changeset 0:6dd524f61e62

add dwt win and basic java stuff
author Frank Benoit <benoit@tionex.de>
date Mon, 02 Mar 2009 14:44:16 +0100
parents
children 0e8eed4cac02
files java/src/java/io/BufferedInputStream.d java/src/java/io/ByteArrayInputStream.d java/src/java/io/ByteArrayOutputStream.d java/src/java/io/File.d java/src/java/io/FileInputStream.d java/src/java/io/FileOutputStream.d java/src/java/io/InputStream.d java/src/java/io/OutputStream.d java/src/java/lang/Boolean.d java/src/java/lang/Byte.d java/src/java/lang/Double.d java/src/java/lang/Float.d java/src/java/lang/Integer.d java/src/java/lang/Long.d java/src/java/lang/Runnable.d java/src/java/lang/System.d java/src/java/lang/all.d java/src/java/lang/util.d java/src/java/nonstandard/WeakRef.d java/src/java/nonstandard/XmlTranscode.d java/src/java/util/ResourceBundle.d java/src/java/util/WeakHashMap.d java/src/java/util/zip/InflaterInputStream.d org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ar.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_cs.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_da.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_de.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_el.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_es.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_fi.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_fr.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_hu.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_it.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_iw.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ja.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ko.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_nl.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_no.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pl.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pt.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pt_BR.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ru.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_sv.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_tr.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh_HK.properties org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh_TW.properties org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWT.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTError.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTException.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/ACC.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/Accessible.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/AnimatedProgress.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/Bullet.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BusyIndicator.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CBanner.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CBannerLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CCombo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLabel.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLayoutData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Adapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Listener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ControlEditor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/DefaultContent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PopupList.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ST.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashForm.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashFormData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashFormLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ScrolledComposite.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ScrolledCompositeLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StackLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyleRange.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextContent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextPrintOptions.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextRenderer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableCursor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableEditor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTree.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeEditor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangeListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangedEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangingEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TreeEditor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/VerifyKeyListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewForm.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewFormLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ByteArrayTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Clipboard.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DND.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DNDEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DNDListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSource.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTarget.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/FileTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/HTMLTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ImageTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/OleEnumFORMATETC.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/RTFTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDragSourceEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDropTargetEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TextTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Transfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TransferData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDragSourceEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDropTargetEffect.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/URLTransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DragDetectEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DragDetectListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/HelpEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/HelpListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ModifyEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ModifyListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseMoveListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseTrackAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseTrackListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseWheelListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/PaintEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/PaintListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeAdapter.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TypedEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/VerifyEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/VerifyListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Color.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Cursor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Device.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/DeviceData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Drawable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Font.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontMetrics.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GC.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GCData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GlyphMetrics.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Image.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageDataLoader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/LineAttributes.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/PaletteData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Path.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/PathData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Pattern.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Point.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/RGB.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Rectangle.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Region.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Resource.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextStyle.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Transform.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/BidiUtil.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/C.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/CloneableCompatibility.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Compatibility.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ImageList.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Library.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Lock.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Platform.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SWTEventListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SWTEventObject.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SerializableCompatibility.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/gdip/Gdip.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/gdip/native.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/FileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/GIFFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGAppn.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGComment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGDecoder.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGEndOfImage.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFrameHeader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGHuffmanTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGQuantizationTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGRestartInterval.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGScanHeader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGSegment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGStartOfImage.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LEDataInputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LEDataOutputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LZWCodec.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LZWNode.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/OS2BMPFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PNGFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngChunkReader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngDecodingDataStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngDeflater.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngEncoder.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngFileReadState.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngHuffmanTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngHuffmanTables.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIdatChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIendChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIhdrChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngInputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngLzBlockReader.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngPlteChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngTrnsChunk.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFDirectory.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFRandomFileAccess.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/WinBMPFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/WinICOFileFormat.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/Common.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/XPCOM.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/XPCOMInit.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/gfxIImageFrame.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/imgIContainer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/imgIContainerObserver.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsEmbedString.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsError.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAppShell.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAtom.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthInformation.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthPrompt.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthPromptCallback.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBaseWindow.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBinaryInputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBinaryOutputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICancelable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICategoryManager.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIChannel.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIChromeEventHandler.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICollection.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIComponentManager.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIComponentRegistrar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContentViewer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookie.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookie2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookieManager.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookieManager2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsID.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMAbstractView.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMAttr.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMBarProp.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMCDATASection.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMCharacterData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMComment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDOMImplementation.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocument.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentFragment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentType.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentView.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMElement.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEntityReference.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventGroup.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventTarget.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMKeyEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMMouseEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNamedNodeMap.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNode.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNodeList.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMProcessingInstruction.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMRange.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer_1_7.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMStorage.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMStorageItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMText.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMUIEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindowCollection.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDebug.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDirectoryService.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShell.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellLoadInfo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellTreeItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellTreeOwner.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocumentCharsetInfo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDownload.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDownload_1_8.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEnumerator.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEventQueue.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEventTarget.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFactory.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFile.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFilePicker.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFilePicker_1_8.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFileURL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog_1_9.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_8.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_9.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHistoryEntry.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIIOService.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIIOService2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIInputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIInterfaceRequestor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIJSContextStack.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsILoadGroup.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsILocalFile.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIMIMEInfo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIMemory.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIModule.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObjectInputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObjectOutputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObserver.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObserverService.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIOutputStream.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefLocalizedString.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefService.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog_1_8.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrompt.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPromptService.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPromptService2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProperties.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProtocolHandler.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIRequest.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIRequestObserver.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHEntry.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHistory.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHistoryListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISecureBrowserUI.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISelection.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISerializable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIServiceManager.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISimpleEnumerator.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIStreamListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIStringEnumerator.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISupports.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISupportsArray.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITooltipListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITraceRefcnt.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITransfer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURI.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURIContentListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWeakReference.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowser.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChrome.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChromeFocus.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserFocus.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebNavigation.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebNavigationInfo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgress.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator2.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowWatcher.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsStringAPI.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prinrval.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prio.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prlink.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prtime.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COM.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COMAPI.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COMTYPES.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/DOCOBJ.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/EXDISP.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/MSHTMHST.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OAIDL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OBJIDL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OLEIDL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/extras.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/ifs.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/opengl/win32/WGL.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/opengl/win32/native.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/OS.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/WINAPI.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/WINTYPES.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FillData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FillLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormAttachment.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowLayout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OLE.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleAutomation.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleClientSite.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleControlSite.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEvent.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventSink.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFrame.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFunctionDescription.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleParameterDescription.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyDescription.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/Variant.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLCanvas.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrintDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/Printer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrinterData.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/Program.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/all.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/std.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Button.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Canvas.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Caret.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ColorDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Combo.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Composite.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Control.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/CoolBar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/CoolItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/DateTime.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Decorations.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Dialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/DirectoryDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Display.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Event.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/EventTable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ExpandBar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ExpandItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FileDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FontDialog.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Group.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/IME.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Item.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Label.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Layout.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Link.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/List.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Listener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Menu.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/MenuItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/MessageBox.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Monitor.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ProgressBar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/RunnableLock.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Sash.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Scale.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ScrollBar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Scrollable.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Shell.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Slider.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Spinner.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Synchronizer.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TabFolder.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TabItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Table.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TableColumn.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TableItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Text.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolBar.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolTip.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tracker.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tray.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TrayItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tree.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TreeColumn.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TreeItem.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TypedListener.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Widget.d org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/all.d
diffstat 555 files changed, 216095 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/BufferedInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,109 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.BufferedInputStream;
+
+import java.io.InputStream;
+import java.lang.all;
+
+import tango.core.Exception;
+
+public class BufferedInputStream : java.io.InputStream.InputStream {
+
+    alias java.io.InputStream.InputStream.read read;
+
+    private const int defaultSize = 8192;
+    protected byte[] buf;
+    protected int count = 0; /// The index one greater than the index of the last valid byte in the buffer.
+    protected int pos   = 0; /// The current position in the buffer.
+    protected int markpos = (-1);
+    protected int marklimit;
+    java.io.InputStream.InputStream istr;
+
+    public this ( java.io.InputStream.InputStream istr ){
+        this( istr, defaultSize );
+    }
+
+    public this ( java.io.InputStream.InputStream istr, int size ){
+        this.istr = istr;
+        if( size <= 0 ){
+            throw new IllegalArgumentException( "Buffer size <= 0" );
+        }
+        buf.length = size;
+    }
+
+    private InputStream getAndCheckIstr(){
+        InputStream res = istr;
+        if( res is null ){
+            throw new IOException( "Stream closed" );
+        }
+        return res;
+    }
+    private byte[] getAndCheckBuf(){
+        byte[] res = buf;
+        if( res is null ){
+            throw new IOException( "Stream closed" );
+        }
+        return res;
+    }
+    private void fill(){
+        assert( pos == count );
+        pos = 0;
+        count = 0;
+        count = getAndCheckIstr().read( buf );
+        if( count < 0 ){
+            count = 0;
+            istr = null;
+        }
+    }
+    public synchronized int read(){
+        if( pos >= count ){
+            fill();
+            if( pos >= count ){
+                return -1;
+            }
+        }
+        return getAndCheckBuf()[pos++] & 0xFF;
+    }
+
+    public synchronized int read( byte[] b, int off, int len ){
+        return super.read( b, off, len );
+    }
+
+    public synchronized long skip( long n ){
+        return this.istr.skip(n);
+    }
+
+    public synchronized int available(){
+        int istr_avail = 0;
+        if( istr !is null ){
+            istr_avail = istr.available();
+        }
+        return istr_avail + (count - pos);
+    }
+
+    public synchronized void mark( int readlimit ){
+        implMissing( __FILE__, __LINE__ );
+        this.istr.mark( readlimit );
+    }
+
+    public synchronized void reset(){
+        implMissing( __FILE__, __LINE__ );
+        this.istr.reset();
+    }
+
+    public bool markSupported(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public void close(){
+        if (this.istr !is null) {
+            this.istr.close();
+        }
+    }
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/ByteArrayInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/* language convertion www.dsource.org/project/tioport */
+module java.io.ByteArrayInputStream;
+
+import java.io.InputStream;
+
+public class ByteArrayInputStream : java.io.InputStream.InputStream {
+
+    alias java.io.InputStream.InputStream.read read;
+    alias java.io.InputStream.InputStream.skip skip;
+    alias java.io.InputStream.InputStream.available available;
+    alias java.io.InputStream.InputStream.close close;
+    alias java.io.InputStream.InputStream.mark mark;
+    alias java.io.InputStream.InputStream.reset reset;
+    alias java.io.InputStream.InputStream.markSupported markSupported;
+
+    protected byte[] buf;
+    protected int pos;
+    protected int fld_mark = 0;
+    //protected int count;
+    public this ( byte[] aBuf ){
+        this.buf = aBuf;
+    }
+
+    public this ( byte[] aBuf, int offset, int length_ESCAPE ){
+        this.buf = aBuf[ offset .. offset+length_ESCAPE ];
+    }
+
+    public synchronized int read(){
+        if( pos >= this.buf.length ){
+            return -1;
+        }
+        int result = this.buf[pos];
+        pos++;
+        return result & 0xFF;
+    }
+
+    public synchronized int read( byte[] b, int off, int len ){
+        return super.read( b, off, len );
+    }
+
+    public synchronized long skip( long n ){
+        pos += n;
+        return 0L;
+    }
+
+    public synchronized int available(){
+        if( pos >= this.buf.length ){
+            return 0;
+        }
+        return this.buf.length - pos;
+    }
+
+    public bool markSupported(){
+        return false;
+    }
+
+    public void mark( int readAheadLimit ){
+    }
+
+    public synchronized void reset(){
+        pos = 0;
+    }
+
+    public void close(){
+    }
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/ByteArrayOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,73 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.ByteArrayOutputStream;
+
+public import java.io.OutputStream;
+import java.lang.all;
+import tango.io.device.Array;
+
+public class ByteArrayOutputStream : java.io.OutputStream.OutputStream {
+
+    protected Array buffer;
+
+    public this (){
+        buffer = new Array();
+    }
+
+    public this ( int par_size ){
+        buffer = new Array(par_size);
+    }
+
+    public synchronized override void write( int b ){
+        byte[1] a;
+        a[0] = b & 0xFF;
+        buffer.append(a);
+    }
+
+    public synchronized override void write( byte[] b, int off, int len ){
+        buffer.append( b[ off .. off + len ]);
+    }
+
+    public synchronized override void write( byte[] b ){
+        buffer.append( b );
+    }
+
+    public synchronized void writeTo( java.io.OutputStream.OutputStream out_KEYWORDESCAPE ){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public synchronized void reset(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public synchronized byte[] toByteArray(){
+        return cast(byte[])buffer.slice();
+    }
+
+    public int size(){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public override String toString(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public String toString( String enc ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public String toString( int hibyte ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public  override void close(){
+        implMissing( __FILE__, __LINE__ );
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/File.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,203 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.File;
+
+import java.lang.all;
+
+static import tango.io.model.IFile;
+static import tango.io.FilePath;
+static import tango.io.Path;
+static import tango.io.FileSystem;
+
+public class File {
+
+    public static char separatorChar;
+    public static String separator;
+    public static char pathSeparatorChar;
+    public static String pathSeparator;
+
+    private tango.io.FilePath.FilePath mFilePath;
+
+    static this(){
+        separator = tango.io.model.IFile.FileConst.PathSeparatorString;
+        separatorChar = tango.io.model.IFile.FileConst.PathSeparatorChar;
+        pathSeparator = tango.io.model.IFile.FileConst.SystemPathString;
+        pathSeparatorChar = tango.io.model.IFile.FileConst.SystemPathChar;
+    }
+
+    public this ( String pathname ){
+        mFilePath = new tango.io.FilePath.FilePath( tango.io.Path.standard( pathname ));
+    }
+
+    public this ( String parent, String child ){
+        mFilePath = new tango.io.FilePath.FilePath( tango.io.FilePath.FilePath.join( parent, child ) );
+    }
+
+    public this ( java.io.File.File parent, String child ){
+        mFilePath = new tango.io.FilePath.FilePath( tango.io.FilePath.FilePath.join( parent.mFilePath.toString, child ) );
+    }
+
+    public int getPrefixLength(){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public String getName(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public String getParent(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public java.io.File.File getParentFile(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public String getPath(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public bool isAbsolute(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public String getAbsolutePath(){
+        return tango.io.FileSystem.FileSystem.toAbsolute( mFilePath ).toString;
+    }
+
+    public java.io.File.File getAbsoluteFile(){
+        return new File( getAbsolutePath() );
+    }
+
+    public String getCanonicalPath(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public java.io.File.File getCanonicalFile(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public bool canRead(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool canWrite(){
+        return mFilePath.isWritable;
+    }
+
+    public bool exists(){
+        return mFilePath.exists;
+    }
+
+    public bool isDirectory(){
+        return mFilePath.isFolder;
+    }
+
+    public bool isFile(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool isHidden(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public long lastModified(){
+        implMissing( __FILE__, __LINE__ );
+        return 0L;
+    }
+
+    public long length(){
+        implMissing( __FILE__, __LINE__ );
+        return 0L;
+    }
+
+    public bool createNewFile(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool delete_KEYWORDESCAPE(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public void deleteOnExit(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public String[] list(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public java.io.File.File[] listFiles(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public bool mkdir(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool mkdirs(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool renameTo( java.io.File.File dest ){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool setLastModified( long time ){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public bool setReadOnly(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public static java.io.File.File[] listRoots(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public static java.io.File.File createTempFile( String prefix, String suffix, java.io.File.File directory ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public static java.io.File.File createTempFile( String prefix, String suffix ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public int compareTo( java.io.File.File pathname ){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public String toString(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/FileInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,80 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.FileInputStream;
+
+import java.lang.all;
+import java.io.File;
+import java.io.InputStream;
+
+version(TANGOSVN){
+import TangoFile = tango.io.device.File;
+} else {
+import TangoFile = tango.io.FileConduit;
+}
+import tango.core.Exception;
+import tango.text.convert.Format;
+
+public class FileInputStream : java.io.InputStream.InputStream {
+
+    alias java.io.InputStream.InputStream.read read;
+
+    private TangoFile.File conduit;
+    private ubyte[] buffer;
+    private int buf_pos;
+    private int buf_size;
+    private const int BUFFER_SIZE = 0x10000;
+    private bool eof;
+
+    public this ( String name ){
+        conduit = new TangoFile.File( name );
+        buffer = new ubyte[]( BUFFER_SIZE );
+    }
+
+    public this ( java.io.File.File file ){
+        implMissing( __FILE__, __LINE__ );
+        conduit = new TangoFile.File( file.getAbsolutePath(), TangoFile.File.ReadExisting );
+        buffer = new ubyte[]( BUFFER_SIZE );
+    }
+
+    public override int read(){
+        if( eof ){
+            return -1;
+        }
+        try{
+            if( buf_pos == buf_size ){
+                buf_pos = 0;
+                buf_size = conduit.input.read( buffer );
+            }
+            if( buf_size <= 0 ){
+                eof = true;
+                return -1;
+            }
+            assert( buf_pos < BUFFER_SIZE, Format( "{0} {1}", buf_pos, buf_size ) );
+            assert( buf_size <= BUFFER_SIZE );
+            int res = cast(int) buffer[ buf_pos ];
+            buf_pos++;
+            return res;
+        }
+        catch( IOException e ){
+            eof = true;
+            return -1;
+        }
+    }
+
+    public long skip( long n ){
+        implMissing( __FILE__, __LINE__ );
+        return 0L;
+    }
+
+    public int available(){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public override void close(){
+        conduit.close();
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/FileOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,56 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.FileOutputStream;
+
+public import java.io.File;
+public import java.io.OutputStream;
+
+import java.lang.all;
+
+version(TANGOSVN){
+import TangoFile = tango.io.device.File;
+} else {
+import TangoFile = tango.io.FileConduit;
+}
+
+public class FileOutputStream : java.io.OutputStream.OutputStream {
+
+    alias java.io.OutputStream.OutputStream.write write;
+    alias java.io.OutputStream.OutputStream.close close;
+    TangoFile.File fc;
+    
+    public this ( String name ){
+        fc = new TangoFile.File( name, TangoFile.File.WriteCreate );
+    }
+
+    public this ( String name, bool append ){
+        fc = new TangoFile.File( name, append ? TangoFile.File.WriteAppending : TangoFile.File.WriteCreate );
+    }
+
+    public this ( java.io.File.File file ){
+        this( file.toString );
+    }
+
+    public this ( java.io.File.File file, bool append ){
+        this( file.toString, append );
+    }
+
+    public override void write( int b ){
+        ubyte[1] a;
+        a[0] = b & 0xFF;
+        fc.write(a);
+    }
+
+    public override void close(){
+        fc.close();
+    }
+
+    public void finalize(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/InputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,61 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+
+module java.io.InputStream;
+
+import java.lang.all;
+
+public abstract class InputStream {
+
+
+    public this (){
+    }
+
+    public abstract int read();
+
+    public int read( byte[] b ){
+        foreach( uint idx, inout byte val; b ){
+            int c = read();
+            if( c == -1 ){
+                return ( idx == 0 ) ? -1 : idx;
+            }
+            b[ idx] = cast(byte)( c & 0xFF );
+        }
+        return b.length;
+    }
+
+    public int read( byte[] b, int off, int len ){
+        return read( b[ off .. off+len ] );
+    }
+
+    public long skip( long n ){
+        implMissing( __FILE__, __LINE__ );
+        return 0L;
+    }
+
+    public int available(){
+        return 0;
+    }
+
+    public void close(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public synchronized void mark( int readlimit ){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public synchronized void reset(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public bool markSupported(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/io/OutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.io.OutputStream;
+
+import java.lang.all;
+
+public abstract class OutputStream {
+
+    public this(){
+    }
+
+    public abstract void write( int b );
+
+    public void write( byte[] b ){
+        foreach( bv; b ){
+            write(bv);
+        }
+    }
+
+    public void write( byte[] b, int off, int len ){
+        write(b[off .. off+len]);
+    }
+
+    public void flush(){
+    }
+
+    public void close(){
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Boolean.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,45 @@
+module java.lang.Boolean;
+
+import java.lang.util;
+import java.lang.System;
+
+class Boolean : ValueWrapperT!(bool) {
+    public static Boolean TRUE;
+    public static Boolean FALSE;
+
+    static this(){
+        TRUE  = new Boolean(true);
+        FALSE = new Boolean(false);
+    }
+    public this( bool v ){
+        super(v);
+    }
+
+    alias ValueWrapperT!(bool).opEquals opEquals;
+    public int opEquals( int other ){
+        return value == ( other !is 0 );
+    }
+    public int opEquals( Object other ){
+        if( auto o = cast(Boolean)other ){
+            return value == o.value;
+        }
+        return false;
+    }
+    public bool booleanValue(){
+        return value;
+    }
+    public static Boolean valueOf( String s ){
+        if( s == "yes" || s == "true" ){
+            return TRUE;
+        }
+        return FALSE;
+    }
+    public static Boolean valueOf( bool b ){
+        return b ? TRUE : FALSE;
+    }
+    public static bool getBoolean(String name){
+        return tango.text.Ascii.icompare(System.getProperty(name, "false"), "true" ) is 0;
+    }
+}
+
+alias Boolean    ValueWrapperBool;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Byte.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module java.lang.Byte;
+
+import java.lang.util;
+
+class Byte : ValueWrapperT!(byte) {
+    public static byte parseByte( String s ){
+        try{
+            int res = tango.text.convert.Integer.parse( s );
+            if( res < byte.min || res > byte.max ){
+                throw new NumberFormatException( "out of range" );
+            }
+            return res;
+        }
+        catch( IllegalArgumentException e ){
+            throw new NumberFormatException( e );
+        }
+    }
+    this( byte value ){
+        super( value );
+    }
+
+    public static String toString( byte i ){
+        return tango.text.convert.Integer.toString(i);
+    }
+
+}
+alias Byte ValueWrapperByte;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Double.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module java.lang.Double;
+
+import java.lang.util;
+
+class Double : ValueWrapperT!(double) {
+    public static double MAX_VALUE = double.max;
+    public static double MIN_VALUE = double.min;
+    this( double value ){
+        super(value);
+    }
+    this( String str ){
+        implMissing( __FILE__, __LINE__ );
+        super(0.0);
+    }
+    public double doubleValue(){
+        return value;
+    }
+    public static String toString( double value ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+    public static double parseDouble(String s){
+        implMissing( __FILE__, __LINE__ );
+        return 0.0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Float.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,37 @@
+module java.lang.Float;
+
+import java.lang.util;
+
+class Float : ValueWrapperT!(float) {
+
+    public static float POSITIVE_INFINITY = (1.0f / 0.0f);
+    public static float NEGATIVE_INFINITY = ((-1.0f) / 0.0f);
+    public static float NaN = (0.0f / 0.0f);
+    public static float MAX_VALUE = 3.4028235e+38f;
+    public static float MIN_VALUE = 1.4e-45f;
+    public static int SIZE = 32;
+
+    this( float value ){
+        super(value);
+    }
+    this( String str ){
+        implMissing( __FILE__, __LINE__ );
+        super(0.0);
+    }
+    public float floatValue(){
+        return value;
+    }
+    public static String toString( float value ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+    public static float parseFloat( String s ){
+        try{
+            return tango.text.convert.Float.toFloat( s );
+        }
+        catch( IllegalArgumentException e ){
+            throw new NumberFormatException( e );
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Integer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,115 @@
+module java.lang.Integer;
+
+import java.lang.util;
+
+class Integer : ValueWrapperT!(int) {
+
+    public static const int MIN_VALUE = 0x80000000;
+    public static const int MAX_VALUE = 0x7fffffff;
+    public static const int SIZE = 32;
+
+    public this ( int value ){
+        super( value );
+    }
+
+    public this ( String s ){
+        super(parseInt(s));
+    }
+
+    public static String toString( int i, int radix ){
+        switch( radix ){
+        case 2:
+            return toBinaryString(i);
+        case 8:
+            return toOctalString(i);
+        case 10:
+            return toString(i);
+        case 16:
+            return toHexString(i);
+        default:
+            implMissing( __FILE__, __LINE__ );
+            return null;
+        }
+    }
+
+    public static String toHexString( int i ){
+        return tango.text.convert.Integer.toString(i, "x" );
+    }
+
+    public static String toOctalString( int i ){
+        return tango.text.convert.Integer.toString(i, "o" );
+    }
+
+    public static String toBinaryString( int i ){
+        return tango.text.convert.Integer.toString(i, "b" );
+    }
+
+    public static String toString( int i ){
+        return tango.text.convert.Integer.toString(i);
+    }
+
+    public static int parseInt( String s, int radix ){
+        try{
+            return tango.text.convert.Integer.toLong( s, radix );
+        }
+        catch( IllegalArgumentException e ){
+            throw new NumberFormatException( e );
+        }
+    }
+
+    public static int parseInt( String s ){
+        try{
+            return tango.text.convert.Integer.toLong( s );
+        }
+        catch( IllegalArgumentException e ){
+            throw new NumberFormatException( e );
+        }
+    }
+
+    public static Integer valueOf( String s, int radix ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+
+    public static Integer valueOf( String s ){
+        return valueOf( parseInt(s));
+    }
+
+    public static Integer valueOf( int i ){
+        return new Integer(i);
+    }
+
+    public byte byteValue(){
+        return cast(byte)value;
+    }
+
+    public short shortValue(){
+        return cast(short)value;
+    }
+
+    public int intValue(){
+        return value;
+    }
+
+    public long longValue(){
+        return cast(long)value;
+    }
+
+    public float floatValue(){
+        return cast(float)value;
+    }
+
+    public double doubleValue(){
+        return cast(double)value;
+    }
+
+    public override  hash_t toHash(){
+        return intValue();
+    }
+
+    public override String toString(){
+        return tango.text.convert.Integer.toString( value );
+    }
+}
+alias Integer ValueWrapperInt;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Long.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module java.lang.Long;
+
+import java.lang.util;
+
+class Long : ValueWrapperT!(long) {
+    public static const long MIN_VALUE = long.min;
+    public static const long MAX_VALUE = long.max;
+    this( long value ){
+        super(value);
+    }
+    this( String str ){
+        implMissing( __FILE__, __LINE__ );
+        super(0);
+    }
+    public long longValue(){
+        return value;
+    }
+    public static long parseLong(String s){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+    public static String toString( double value ){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+}
+alias Long ValueWrapperLong;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/Runnable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,39 @@
+/**
+ * Authors: Frank Benoit <benoit@tionex.de>
+ */
+module java.lang.Runnable;
+
+
+import tango.core.Tuple;
+import tango.core.Traits;
+
+public interface Runnable  {
+
+    public abstract void run();
+
+}
+
+class _DgRunnableT(Dg,T...) : Runnable {
+
+    alias ParameterTupleOf!(Dg) DgArgs;
+    static assert( is(DgArgs == Tuple!(T)),
+                "Delegate args not correct: "~DgArgs.stringof~" vs "~T.stringof );
+
+    Dg dg;
+    T t;
+
+    private this( Dg dg, T t ){
+        this.dg = dg;
+        static if( T.length > 0 ){
+            this.t = t;
+        }
+    }
+
+    void run( ){
+        dg(t);
+    }
+}
+
+_DgRunnableT!(Dg,T) dgRunnable(Dg,T...)( Dg dg, T args ){
+    return new _DgRunnableT!(Dg,T)(dg,args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/System.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,209 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.lang.System;
+
+import java.lang.util;
+
+import tango.sys.Environment;
+import tango.core.Exception;
+import tango.io.model.IFile : FileConst;
+import tango.time.Clock;
+import tango.stdc.stdlib : exit;
+
+template SimpleType(T) {
+    debug{
+        static void validCheck(uint SrcLen, uint DestLen, uint copyLen){
+            if(SrcLen < copyLen || DestLen < copyLen|| SrcLen < 0 || DestLen < 0){
+                //Util.trace("Error : SimpleType.arraycopy(), out of bounds.");
+                assert(0);
+            }
+        }
+    }
+
+    static void remove(inout T[] items, int index) {
+        if(items.length == 0)
+            return;
+
+        if(index < 0 || index >= items.length){
+            throw new ArrayBoundsException(__FILE__, __LINE__);
+        }
+
+        T element = items[index];
+
+        int length = items.length;
+        if(length == 1){
+            items.length = 0;
+            return;// element;
+        }
+
+        if(index == 0)
+            items = items[1 .. $];
+        else if(index == length - 1)
+            items = items[0 .. index];
+        else
+            items = items[0 .. index] ~ items[index + 1 .. $];
+    }
+
+    static void insert(inout T[] items, T item, int index = -1) {
+        if(index == -1)
+            index = items.length;
+
+        if(index < 0 || index > items.length ){
+            throw new ArrayBoundsException(__FILE__, __LINE__);
+        }
+
+        if(index == items.length){
+            items ~= item;
+        }else if(index == 0){
+            T[] newVect;
+            newVect ~= item;
+            items = newVect ~ items;
+        }else if(index < items.length ){
+            T[] arr1 = items[0 .. index];
+            T[] arr2 = items[index .. $];
+
+            // Important : if you write like the following commented,
+            // you get wrong data
+            // code:  T[] arr1 = items[0..index];
+            //        T[] arr2 = items[index..$];
+            //        items = arr1 ~ item;      // error, !!!
+            //        items ~= arr2;            // item replace the arrr2[0] here
+            items = arr1 ~ item ~ arr2;
+        }
+    }
+
+    static void arraycopy(T[] src, uint srcPos, T[] dest, uint destPos, uint len)
+    {
+        if(len == 0) return;
+
+        assert(src);
+        assert(dest);
+        debug{validCheck(src.length - srcPos, dest.length - destPos, len);}
+
+        if(src is dest){
+            if( destPos < srcPos ){
+                for(int i=0; i<len; ++i){
+                    dest[destPos+i] = src[srcPos+i];
+                }
+            }
+            else{
+                for(int i=len-1; i>=0; --i){
+                    dest[destPos+i] = src[srcPos+i];
+                }
+            }
+        }else{
+            dest[destPos..(len+destPos)] = src[srcPos..(len+srcPos)];
+        }
+    }
+}
+
+
+class System {
+
+    alias SimpleType!(int).arraycopy arraycopy;
+    alias SimpleType!(byte).arraycopy arraycopy;
+    alias SimpleType!(double).arraycopy arraycopy;
+    alias SimpleType!(float).arraycopy arraycopy;
+    alias SimpleType!(short).arraycopy arraycopy;
+    alias SimpleType!(long).arraycopy arraycopy;
+    alias SimpleType!(uint).arraycopy arraycopy;
+    alias SimpleType!(ushort).arraycopy arraycopy;
+    alias SimpleType!(ubyte).arraycopy arraycopy;
+    alias SimpleType!(ulong).arraycopy arraycopy;
+    alias SimpleType!(char).arraycopy arraycopy;
+    alias SimpleType!(wchar).arraycopy arraycopy;
+    alias SimpleType!(Object).arraycopy arraycopy;
+    alias SimpleType!(void*).arraycopy arraycopy;
+
+    alias SimpleType!(int[]).arraycopy arraycopy;
+    alias SimpleType!(byte[]).arraycopy arraycopy;
+    alias SimpleType!(double[]).arraycopy arraycopy;
+    alias SimpleType!(float[]).arraycopy arraycopy;
+    alias SimpleType!(short[]).arraycopy arraycopy;
+    alias SimpleType!(long[]).arraycopy arraycopy;
+    alias SimpleType!(uint[]).arraycopy arraycopy;
+    alias SimpleType!(ushort[]).arraycopy arraycopy;
+    alias SimpleType!(ubyte[]).arraycopy arraycopy;
+    alias SimpleType!(ulong[]).arraycopy arraycopy;
+    alias SimpleType!(String).arraycopy arraycopy;
+    alias SimpleType!(wchar[]).arraycopy arraycopy;
+    alias SimpleType!(Object[]).arraycopy arraycopy;
+    alias SimpleType!(void*[]).arraycopy arraycopy;
+    alias SimpleType!(void*[]).arraycopy arraycopy;
+
+    static long currentTimeMillis(){
+        return Clock.now().ticks() / 10000;
+    }
+
+    static void exit( int code ){
+        .exit(code);
+    }
+    public static int identityHashCode(Object x){
+        if( x is null ){
+            return 0;
+        }
+        return (*cast(Object *)&x).toHash();
+    }
+
+    public static String getProperty( String key, String defval ){
+        String res = getProperty(key);
+        if( res ){
+            return res;
+        }
+        return defval;
+    }
+    public static String getProperty( String key ){
+        /* Get values for local org.eclipse.swt specific keys */
+        String* p;
+        if (key[0..3] == "org.eclipse.swt") {
+            return ((p = key in localProperties) != null) ? *p : null;
+        /* else get values for global system keys (environment) */
+        } else {
+            switch( key ){
+                case "os.name": return "linux";
+                case "user.name": return "";
+                case "user.home": return "";
+                case "user.dir" : return "";
+                case "file.separator" : return FileConst.PathSeparatorString ;
+                default: return null;
+            }
+        }
+    }
+
+    public static void setProperty ( String key, String value ) {
+        /* set property for local org.eclipse.swt keys */
+        if (key[0..3] == "org.eclipse.swt") {
+            if (key !is null && value !is null)
+                localProperties[ key ] = value;
+        /* else set properties for global system keys (environment) */
+        } else {
+
+        }
+
+    }
+
+    static class Output {
+        public void println( String str ){
+            implMissing( __FILE__, __LINE__ );
+        }
+    }
+
+    private static Output err__;
+    public static Output err(){
+        if( err__ is null ){
+            err__ = new Output();
+        }
+        return err__;
+    }
+    private static Output out__;
+    public static Output out_(){
+        if( out__ is null ){
+            out__ = new Output();
+        }
+        return out__;
+    }
+
+    private static String[String] localProperties;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,16 @@
+module java.lang.all;
+
+
+public import java.lang.System;
+public import java.lang.Boolean;
+public import java.lang.Byte;
+public import java.lang.Integer;
+public import java.lang.Long;
+public import java.lang.Float;
+public import java.lang.Double;
+public import java.lang.Runnable;
+
+public import java.lang.util;
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/lang/util.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1076 @@
+module java.lang.util;
+
+void implMissing( String file, uint line ){
+    Stderr.formatln( "implementation missing in file {} line {}", file, line );
+    Stderr.formatln( "exiting ..." );
+    exit(1);
+}
+
+alias char[] String;
+public import Math = tango.math.Math;
+
+public import tango.core.Exception : IllegalArgumentException, IOException;
+
+import tango.io.Stdout;
+import tango.io.stream.Format;
+static import tango.stdc.stringz;
+static import tango.text.Util;
+static import tango.text.Text;
+static import tango.text.Ascii;
+import tango.text.Unicode;
+import tango.text.convert.Utf;
+import tango.core.Exception;
+import tango.stdc.stdlib : exit;
+
+import tango.util.log.Trace;
+import tango.util.log.Log;
+import tango.text.UnicodeData;
+Logger getDwtLogger(){
+    return Log.lookup( "org.eclipse.swt" );
+}
+
+alias tango.text.Text.Text!(char) StringBuffer;
+
+alias ArrayBoundsException ArrayIndexOutOfBoundsException;
+
+abstract class ArrayWrapper{
+}
+abstract class ValueWrapper{
+}
+
+class ArrayWrapperT(T) : ArrayWrapper {
+    public T[] array;
+    public this( T[] data ){
+        array = data;
+    }
+    public override int opEquals( Object o ){
+        if( auto other = cast(ArrayWrapperT!(T))o){
+            return array == other.array;
+        }
+        return false;
+    }
+    public override hash_t toHash(){
+        return (typeid(T[])).getHash(&array);
+    }
+    static if( is( T == char )){
+        public override char[] toString(){
+            return array;
+        }
+    }
+}
+
+class ValueWrapperT(T) : ValueWrapper {
+    public T value;
+    public this( T data ){
+        value = data;
+    }
+    static if( is(T==class) || is(T==interface)){
+        public int opEquals( Object other ){
+            if( auto o = cast(ValueWrapperT!(T))other ){
+                return value == o.value;
+            }
+            if( auto o = cast(T)other ){
+                if( value is o ){
+                    return true;
+                }
+                if( value is null || o is null ){
+                    return false;
+                }
+                return value == o;
+            }
+            return false;
+        }
+    }
+    else{
+        public int opEquals( Object other ){
+            if( auto o = cast(ValueWrapperT!(T))other ){
+                return value == o.value;
+            }
+            return false;
+        }
+        public int opEquals( T other ){
+            return value == other;
+        }
+    }
+    public override hash_t toHash(){
+        return (typeid(T)).getHash(&value);
+    }
+}
+
+alias ArrayWrapperT!(byte)    ArrayWrapperByte;
+alias ArrayWrapperT!(int)     ArrayWrapperInt;
+alias ArrayWrapperT!(Object)  ArrayWrapperObject;
+alias ArrayWrapperT!(char)    ArrayWrapperString;
+alias ArrayWrapperT!(String)  ArrayWrapperString2;
+
+Object[] StringArrayToObjectArray( String[] strs ){
+    Object[] res = new Object[strs.length];
+    foreach( idx, str; strs ){
+        res[idx] = new ArrayWrapperString(str);
+    }
+    return res;
+}
+int codepointIndexToIndex( String str, int cpIndex ){
+    int cps = cpIndex;
+    int res = 0;
+    while( cps > 0 ){
+        cps--;
+        if( str[res] < 0x80 ){
+            res+=1;
+        }
+        else if( str[res] < 0xE0 ){
+            res+=2;
+        }
+        else if( str[res] & 0xF0 ){
+            res+=3;
+        }
+        else{
+            res+=4;
+        }
+    }
+    return res;
+}
+
+/++
+ +
+ +/
+int indexToCodepointIndex( String str, int index ){
+    if( index < 0 ) return index;
+    int i = 0;
+    int res = 0;
+    while( i < index ){
+        if( i >= str.length ){
+            break;
+        }
+        if( str[i] < 0x80 ){
+            i+=1;
+        }
+        else if( str[i] < 0xE0 ){
+            i+=2;
+        }
+        else if( str[i] & 0xF0 ){
+            i+=3;
+        }
+        else{
+            i+=4;
+        }
+        res++;
+    }
+    return res;
+}
+
+/++
+ + Get that String, that contains the next codepoint of a String.
+ +/
+String firstCodePointStr( String str, out int consumed ){
+    dchar[1] buf;
+    uint ate;
+    dchar[] res = str.toString32( buf, &ate );
+    consumed = ate;
+    return str[ 0 .. ate ];
+}
+
+/++
+ + Get first codepoint of a String. If an offset is needed, simply use a slice:
+ + ---
+ + dchar res = str[ offset .. $ ].firstCodePoint();
+ + ---
+ +/
+dchar firstCodePoint( String str ){
+    int dummy;
+    return firstCodePoint( str, dummy );
+}
+dchar firstCodePoint( String str, out int consumed ){
+    dchar[1] buf;
+    uint ate;
+    dchar[] res = str.toString32( buf, &ate );
+    consumed = ate;
+    if( ate is 0 || res.length is 0 ){
+        Trace.formatln( "dwthelper.utils {}: str.length={} str={:X2}", __LINE__, str.length, cast(ubyte[])str );
+    }
+    assert( ate > 0 );
+    assert( res.length is 1 );
+    return res[0];
+}
+dchar firstCodePoint( wchar[] str, out int consumed ){
+    dchar[1] buf;
+    uint ate;
+    dchar[] res = str.toString32( buf, &ate );
+    consumed = ate;
+    if( ate is 0 || res.length is 0 ){
+        Trace.formatln( "dwthelper.utils {}: str.length={} str={:X2}", __LINE__, str.length, cast(ubyte[])str );
+    }
+    assert( ate > 0 );
+    assert( res.length is 1 );
+    return res[0];
+}
+
+String dcharToString( dchar key ){
+    dchar[1] buf;
+    buf[0] = key;
+    return tango.text.convert.Utf.toString( buf );
+}
+
+int codepointCount( String str ){
+    scope dchar[] buf = new dchar[]( str.length );
+    uint ate;
+    dchar[] res = tango.text.convert.Utf.toString32( str, buf, &ate );
+    assert( ate is str.length );
+    return res.length;
+}
+
+//alias tango.text.convert.Utf.toString16 toString16;
+//alias tango.text.convert.Utf.toString toString;
+
+int toAbsoluteCodePointStartOffset( String str, int index ){
+    //Trace.formatln( "str={}, str.length={}, index={}", str, str.length, index );
+    //Trace.memory( str );
+    if( str.length is index ){
+        return index;
+    }
+    if( ( str[index] & 0x80 ) is 0x00 ) {
+        return index;
+    }
+    else{
+        int steps = 0;
+        while(( str[index] & 0xC0 ) is 0x80 ){
+            index--;
+            steps++;
+            if( steps > 3 || index < 0 ){
+                break;
+            }
+        }
+        if((( str[index] & 0xE0 ) is 0xC0) && ( steps <= 1 )){
+            // ok
+        }
+        else if((( str[index] & 0xF0 ) is 0xE0) && ( steps <= 2 )){
+            // ok
+        }
+        else if((( str[index] & 0xF8 ) is 0xF0) && ( steps <= 3 )){
+            // ok
+        }
+        else{
+            tango.text.convert.Utf.onUnicodeError( "invalid utf8 input to toAbsoluteCodePointStartOffset" );
+        }
+        return index;
+    }
+}
+int getRelativeCodePointOffset( String str, int startIndex, int searchRelCp ){
+    return getAbsoluteCodePointOffset( str, startIndex, searchRelCp ) - startIndex;
+}
+int getAbsoluteCodePointOffset( String str, int startIndex, int searchRelCp ){
+
+    //Trace.formatln( "str={}, str.length={}, startIndex={}, searchRelCp={}", str, str.length, startIndex, searchRelCp );
+    //Trace.memory( str );
+
+    int ignore;
+    int i = startIndex;
+    if( searchRelCp > 0 ){
+        while( searchRelCp !is 0 ){
+
+            if( ( i < str.length )
+            && (( str[i] & 0x80 ) is 0x00 ))
+            {
+                i+=1;
+            }
+            else if( ( i+1 < str.length )
+                && (( str[i+1] & 0xC0 ) is 0x80 )
+                && (( str[i  ] & 0xE0 ) is 0xC0 ))
+            {
+                i+=2;
+            }
+            else if( ( i+2 < str.length )
+                && (( str[i+2] & 0xC0 ) is 0x80 )
+                && (( str[i+1] & 0xC0 ) is 0x80 )
+                && (( str[i  ] & 0xF0 ) is 0xE0 ))
+            {
+                i+=3;
+            }
+            else if(( i+3 < str.length )
+                && (( str[i+3] & 0xC0 ) is 0x80 )
+                && (( str[i+2] & 0xC0 ) is 0x80 )
+                && (( str[i+1] & 0xC0 ) is 0x80 )
+                && (( str[i  ] & 0xF8 ) is 0xF0 ))
+            {
+                i+=4;
+            }
+            else{
+                Trace.formatln( "getAbsoluteCodePointOffset invalid utf8 characters:  {:X2}", cast(ubyte[]) str );
+                tango.text.convert.Utf.onUnicodeError( "invalid utf8 input", i );
+            }
+            searchRelCp--;
+        }
+    }
+    else if( searchRelCp < 0 ){
+        while( searchRelCp !is 0 ){
+            do{
+                i--;
+                if( i < 0 ){
+                    return startIndex-1;
+                }
+            } while(( str[i] & 0xC0 ) is 0x80 );
+            searchRelCp++;
+        }
+    }
+    return i;
+}
+int getAbsoluteCodePointOffset( wchar[] str, int startIndex, int searchRelCp ){
+    int ignore;
+    int i = startIndex;
+    if( searchRelCp > 0 ){
+        while( searchRelCp !is 0 ){
+
+            if( ( i < str.length )
+                && ( str[i] & 0xD800 ) !is 0xD800 )
+            {
+                i+=1;
+            }
+            else if( ( i+1 < str.length )
+                && (( str[i+1] & 0xDC00 ) is 0xDC00 )
+                && (( str[i  ] & 0xDC00 ) is 0xD800 ))
+            {
+                i+=2;
+            }
+            else{
+                Trace.formatln( "invalid utf16 characters:  {:X2}", cast(ubyte[]) str );
+                tango.text.convert.Utf.onUnicodeError( "invalid utf16 input", i );
+            }
+            searchRelCp--;
+        }
+    }
+    else if( searchRelCp < 0 ){
+        while( searchRelCp !is 0 ){
+            do{
+                i--;
+                if( i < 0 ){
+                    return startIndex-1;
+                    //Trace.formatln( "dwthelper.utils getRelativeCodePointOffset {}: str={}, startIndex={}, searchRelCp={}", __LINE__, str, startIndex, searchRelCp );
+                    //tango.text.convert.Utf.onUnicodeError( "invalid utf16 input", i );
+                }
+            } while(( str[i] & 0xDC00 ) is 0xDC00 );
+            searchRelCp++;
+        }
+    }
+    return i;
+}
+dchar getRelativeCodePoint( String str, int startIndex, int searchRelCp ){
+    int dummy;
+    return getRelativeCodePoint( str, startIndex, dummy );
+}
+dchar getRelativeCodePoint( String str, int startIndex, int searchRelCp, out int relIndex ){
+    relIndex = getRelativeCodePointOffset( str, startIndex, searchRelCp );
+    int ignore;
+    return firstCodePoint( str[ startIndex+relIndex .. $ ], ignore );
+}
+
+int utf8AdjustOffset( String str, int offset ){
+    if( str.length <= offset || offset <= 0 ){
+        return offset;
+    }
+    while(( str[offset] & 0xC0 ) is 0x80 ){
+        offset--;
+    }
+    return offset;
+}
+int utf8OffsetIncr( String str, int offset ){
+    int res = offset +1;
+    if( str.length <= res || res <= 0 ){
+        return res;
+    }
+    int tries = 4;
+    while(( str[res] & 0xC0 ) is 0x80 ){
+        res++;
+        assert( tries-- > 0 );
+    }
+    return res;
+}
+int utf8OffsetDecr( String str, int offset ){
+    int res = offset-1;
+    if( str.length <= res || res <= 0 ){
+        return res;
+    }
+    int tries = 4;
+    while(( str[res] & 0xC0 ) is 0x80 ){
+        res--;
+        assert( tries-- > 0 );
+    }
+    Trace.formatln( "utf8OffsetDecr {}->{}", offset, res );
+    Trace.memory( str );
+    return res;
+}
+
+class Character {
+    public static bool isUpperCase( dchar c ){
+        implMissing( __FILE__, __LINE__);
+        return false;
+    }
+    public static dchar toUpperCase( dchar c ){
+        dchar[] r = tango.text.Unicode.toUpper( [c] );
+        return r[0];
+    }
+    public static dchar toLowerCase( dchar c ){
+        dchar[] r = tango.text.Unicode.toLower( [c] );
+        return r[0];
+    }
+    public static bool isWhitespace( dchar c ){
+        return tango.text.Unicode.isWhitespace( c );
+    }
+    public static bool isDigit( dchar c ){
+        return tango.text.Unicode.isDigit( c );
+    }
+    public static bool isLetterOrDigit( dchar c ){
+        return isDigit(c) || isLetter(c);
+    }
+    public static bool isUnicodeIdentifierPart(char ch){
+        implMissing( __FILE__, __LINE__);
+        return false;
+    }
+    public static bool isUnicodeIdentifierStart(char ch){
+        implMissing( __FILE__, __LINE__);
+        return false;
+    }
+    public static bool isIdentifierIgnorable(char ch){
+        implMissing( __FILE__, __LINE__);
+        return false;
+    }
+    public static bool isJavaIdentifierPart(char ch){
+        implMissing( __FILE__, __LINE__);
+        return false;
+    }
+
+    this( char c ){
+        // must be correct for container storage
+        implMissing( __FILE__, __LINE__);
+    }
+}
+
+String new_String( String cont, int offset, int len ){
+    return cont[ offset .. offset+len ].dup;
+}
+String new_String( String cont ){
+    return cont.dup;
+}
+String String_valueOf( bool v ){
+    return v ? "true" : "false";
+}
+String String_valueOf( int v ){
+    return tango.text.convert.Integer.toString(v);
+}
+String String_valueOf( long v ){
+    return tango.text.convert.Integer.toString(v);
+}
+String String_valueOf( float v ){
+    return tango.text.convert.Float.toString(v);
+}
+String String_valueOf( double v ){
+    return tango.text.convert.Float.toString(v);
+}
+String String_valueOf( dchar v ){
+    return dcharToString(v);
+}
+String String_valueOf( char[] v ){
+    return v.dup;
+}
+String String_valueOf( char[] v, int offset, int len ){
+    return v[ offset .. offset+len ].dup;
+}
+String String_valueOf( Object v ){
+    return v is null ? "null" : v.toString();
+}
+bool CharacterIsDefined( dchar ch ){
+    return (ch in tango.text.UnicodeData.unicodeData) !is null;
+}
+dchar CharacterFirstToLower( String str ){
+    int consumed;
+    return CharacterFirstToLower( str, consumed );
+}
+dchar CharacterFirstToLower( String str, out int consumed ){
+    dchar[1] buf;
+    buf[0] = firstCodePoint( str, consumed );
+    dchar[] r = tango.text.Unicode.toLower( buf );
+    return r[0];
+}
+int length( String str ){
+    return str.length;
+}
+dchar CharacterToLower( dchar c ){
+    dchar[] r = tango.text.Unicode.toLower( [c] );
+    return r[0];
+}
+dchar CharacterToUpper( dchar c ){
+    dchar[] r = tango.text.Unicode.toUpper( [c] );
+    return r[0];
+}
+bool CharacterIsWhitespace( dchar c ){
+    return tango.text.Unicode.isWhitespace( c );
+}
+bool CharacterIsDigit( dchar c ){
+    return tango.text.Unicode.isDigit( c );
+}
+bool CharacterIsLetter( dchar c ){
+    return tango.text.Unicode.isLetter( c );
+}
+public String toUpperCase( String str ){
+    return tango.text.Unicode.toUpper( str );
+}
+
+public String replaceFirst( String str, String regex, String replacement ){
+    implMissing(__FILE__,__LINE__);
+    return str;
+}
+
+public int indexOf( String str, char searched ){
+    int res = tango.text.Util.locate( str, searched );
+    if( res is str.length ) res = -1;
+    return res;
+}
+
+public int indexOf( String str, char searched, int startpos ){
+    int res = tango.text.Util.locate( str, searched, startpos );
+    if( res is str.length ) res = -1;
+    return res;
+}
+
+public int indexOf(String str, String ch){
+    return indexOf( str, ch, 0 );
+}
+
+public int indexOf(String str, String ch, int start){
+    int res = tango.text.Util.locatePattern( str, ch, start );
+    if( res is str.length ) res = -1;
+    return res;
+}
+
+public int lastIndexOf(String str, char ch){
+    return lastIndexOf( str, ch, str.length );
+}
+public int lastIndexOf(String str, char ch, int formIndex){
+    int res = tango.text.Util.locatePrior( str, ch, formIndex );
+    if( res is str.length ) res = -1;
+    return res;
+}
+public int lastIndexOf(String str, String ch ){
+    return lastIndexOf( str, ch, str.length );
+}
+public int lastIndexOf(String str, String ch, int start ){
+    int res = tango.text.Util.locatePatternPrior( str, ch, start );
+    if( res is str.length ) res = -1;
+    return res;
+}
+
+public String replaceAll( String str, String regex, String replacement ){
+    implMissing(__FILE__,__LINE__);
+    return null;
+}
+public String replace( String str, char from, char to ){
+    return tango.text.Util.replace( str.dup, from, to );
+}
+
+public String substring( String str, int start ){
+    return str[ start .. $ ].dup;
+}
+
+public String substring( String str, int start, int end ){
+    return str[ start .. end ].dup;
+}
+
+public wchar[] substring( wchar[] str, int start ){
+    return str[ start .. $ ].dup;
+}
+
+public wchar[] substring( wchar[] str, int start, int end ){
+    return str[ start .. end ].dup;
+}
+
+public char charAt( String str, int pos ){
+    return str[ pos ];
+}
+
+public void getChars( String src, int srcBegin, int srcEnd, String dst, int dstBegin){
+    dst[ dstBegin .. dstBegin + srcEnd - srcBegin ] = src[ srcBegin .. srcEnd ];
+}
+
+public wchar[] toWCharArray( String str ){
+    return toString16(str);
+}
+
+public char[] toCharArray( String str ){
+    return str;
+}
+
+public bool endsWith( String src, String pattern ){
+    if( src.length < pattern.length ){
+        return false;
+    }
+    return src[ $-pattern.length .. $ ] == pattern;
+}
+
+public bool equals( String src, String other ){
+    return src == other;
+}
+
+public bool equalsIgnoreCase( String src, String other ){
+    return tango.text.Unicode.toFold(src) == tango.text.Unicode.toFold(other);
+}
+
+public int compareToIgnoreCase( String src, String other ){
+    return compareTo( tango.text.Unicode.toFold(src), tango.text.Unicode.toFold(other));
+}
+public int compareTo( String src, String other ){
+    return typeid(String).compare( cast(void*)&src, cast(void*)&other );
+}
+
+public bool startsWith( String src, String pattern ){
+    if( src.length < pattern.length ){
+        return false;
+    }
+    return src[ 0 .. pattern.length ] == pattern;
+}
+
+public String toLowerCase( String src ){
+    return tango.text.Unicode.toLower( src );
+}
+
+public hash_t toHash( String src ){
+    return typeid(String).getHash(&src);
+}
+
+public String trim( String str ){
+    return tango.text.Util.trim( str ).dup;
+}
+public String intern( String str ){
+    return str;
+}
+
+/++
+ + This is like tango.stdc.stringz.toStringz, but in case of an empty input string,
+ + this function returns a pointer to a null value instead of a null ptr.
+ +/
+public char* toStringzValidPtr( String src ){
+    if( src ){
+        return src.toStringz();
+    }
+    else{
+        static const String nullPtr = "\0";
+        return nullPtr.ptr;
+    }
+}
+
+public alias tango.stdc.stringz.toStringz toStringz;
+public alias tango.stdc.stringz.toString16z toString16z;
+public alias tango.stdc.stringz.fromStringz fromStringz;
+public alias tango.stdc.stringz.fromString16z fromString16z;
+
+static String toHex(uint value, bool prefix = true, int radix = 8){
+    return tango.text.convert.Integer.toString(
+            value,
+            radix is 10 ? "d" :
+            radix is  8 ? "o" :
+            radix is 16 ? "x" :
+                          "d" );
+}
+
+class RuntimeException : Exception {
+    this( char[] file, long line, char[] msg = null){
+        super( msg, file, line );
+    }
+    this( String e = null){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+        next = e;
+    }
+    public Exception getCause() {
+        return next;
+    }
+
+}
+class IndexOutOfBoundsException : Exception {
+    this( String e = null){
+        super(e);
+    }
+}
+
+class UnsupportedOperationException : RuntimeException {
+    this( String e = null){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+    }
+}
+class NumberFormatException : IllegalArgumentException {
+    this( String e ){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+    }
+}
+class NullPointerException : Exception {
+    this( String e = null ){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+    }
+}
+class IllegalStateException : Exception {
+    this( String e = null ){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+    }
+}
+class InterruptedException : Exception {
+    this( String e = null ){
+        super(e);
+    }
+    this( Exception e ){
+        super(e.toString);
+    }
+}
+class InvocationTargetException : Exception {
+    Exception cause;
+    this( Exception e = null, String msg = null ){
+        super(msg);
+        cause = e;
+    }
+
+    alias getCause getTargetException;
+    Exception getCause(){
+        return cause;
+    }
+}
+class MissingResourceException : Exception {
+    String classname;
+    String key;
+    this( String msg, String classname, String key ){
+        super(msg);
+        this.classname = classname;
+        this.key = key;
+    }
+}
+class ParseException : Exception {
+    this( String e = null ){
+        super(e);
+    }
+}
+class ClassCastException : Exception {
+    this( String e = null ){
+        super(e);
+    }
+}
+
+interface Cloneable{
+}
+
+interface Comparable {
+    int compareTo(Object o);
+}
+interface Comparator {
+    int compare(Object o1, Object o2);
+}
+interface EventListener{
+}
+
+class EventObject {
+    protected Object source;
+
+    public this(Object source) {
+        if (source is null)
+        throw new IllegalArgumentException( "null arg" );
+        this.source = source;
+    }
+
+    public Object getSource() {
+        return source;
+    }
+
+    public override String toString() {
+        return this.classinfo.name ~ "[source=" ~ source.toString() ~ "]";
+    }
+}
+
+private struct GCStats {
+    size_t poolsize;        // total size of pool
+    size_t usedsize;        // bytes allocated
+    size_t freeblocks;      // number of blocks marked FREE
+    size_t freelistsize;    // total of memory on free lists
+    size_t pageblocks;      // number of blocks marked PAGE
+}
+private extern(C) GCStats gc_stats();
+
+size_t RuntimeTotalMemory(){
+    GCStats s = gc_stats();
+    return s.poolsize;
+}
+
+String ExceptionGetLocalizedMessage( Exception e ){
+    return e.msg;
+}
+
+void ExceptionPrintStackTrace( Exception e ){
+    ExceptionPrintStackTrace( e, Stderr );
+}
+void ExceptionPrintStackTrace( Exception e, FormatOutput!(char) print ){
+    Exception exception = e;
+    while( exception !is null ){
+        print.formatln( "Exception in {}({}): {}", exception.file, exception.line, exception.msg );
+        if( exception.info !is null ){
+            foreach( msg; exception.info ){
+                print.formatln( "trc {}", msg );
+            }
+        }
+        exception = exception.next;
+    }
+}
+
+class Reader{
+    protected Object   lock;
+    protected this(){
+        implMissing(__FILE__,__LINE__);
+    }
+    protected this(Object lock){
+        implMissing(__FILE__,__LINE__);
+    }
+    abstract  void  close();
+    void mark(int readAheadLimit){
+        implMissing(__FILE__,__LINE__);
+    }
+    bool markSupported(){
+        implMissing(__FILE__,__LINE__);
+        return false;
+    }
+    int read(){
+        implMissing(__FILE__,__LINE__);
+        return 0;
+    }
+    int read(char[] cbuf){
+        implMissing(__FILE__,__LINE__);
+        return 0;
+    }
+    abstract int read(char[] cbuf, int off, int len);
+    bool ready(){
+        implMissing(__FILE__,__LINE__);
+        return false;
+    }
+    void reset(){
+        implMissing(__FILE__,__LINE__);
+    }
+    long skip(long n){
+        implMissing(__FILE__,__LINE__);
+        return 0;
+    }
+}
+interface Writer{
+}
+
+
+class Collator : Comparator {
+    public static Collator getInstance(){
+        implMissing( __FILE__, __LINE__ );
+        return null;
+    }
+    private this(){
+    }
+    int compare(Object o1, Object o2){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+}
+
+template arraycast(T) {
+    T[] arraycast(U) (U[] u) {
+        static if (
+            (is (T == interface ) && is (U == interface )) ||
+            (is (T == class ) && is (U == class ))) {
+            return(cast(T[])u);
+        }
+        else {
+            int l = u.length;
+            T[] res;
+            res.length = l;
+            for (int i = 0; i < l; i++) {
+                res[i] = cast(T)u[i];
+            }
+            return(res);
+        }
+    }
+}
+
+String stringcast( Object o ){
+    if( auto str = cast(ArrayWrapperString) o ){
+        return str.array;
+    }
+    return null;
+}
+String[] stringcast( Object[] objs ){
+    String[] res = new String[](objs.length);
+    foreach( idx, obj; objs ){
+        res[idx] = stringcast(obj);
+    }
+    return res;
+}
+ArrayWrapperString stringcast( String str ){
+    return new ArrayWrapperString( str );
+}
+ArrayWrapperString[] stringcast( String[] strs ){
+    ArrayWrapperString[] res = new ArrayWrapperString[ strs.length ];
+    foreach( idx, str; strs ){
+        res[idx] = stringcast(str);
+    }
+    return res;
+}
+
+String[] stringArrayFromObject( Object obj ){
+    if( auto wrapper = cast(ArrayWrapperString2)obj ){
+        return wrapper.array;
+    }
+    if( auto wrapper = cast(ArrayWrapperObject)obj ){
+        String[] res = new String[ wrapper.array.length ];
+        foreach( idx, o; wrapper.array ){
+            if( auto swrapper = cast(ArrayWrapperString) o ){
+                res[idx] = swrapper.array;
+            }
+        }
+        return res;
+    }
+    assert( obj is null ); // if not null, it was the wrong type
+    return null;
+}
+
+T[] arrayFromObject(T)( Object obj ){
+    if( auto wrapper = cast(ArrayWrapperObject)obj ){
+        T[] res = new T[ wrapper.array.length ];
+        foreach( idx, o; wrapper.array ){
+            res[idx] = cast(T)o;
+        }
+        return res;
+    }
+    assert( obj is null ); // if not null, it was the wrong type
+    return null;
+}
+
+
+bool ArrayEquals(T)( T[] a, T[] b ){
+    if( a.length !is b.length ){
+        return false;
+    }
+    for( int i = 0; i < a.length; i++ ){
+        static if( is( T==class) || is(T==interface)){
+            if( a[i] !is null && b[i] !is null ){
+                if( a[i] != b[i] ){
+                    return false;
+                }
+            }
+            else if( a[i] is null && b[i] is null ){
+            }
+            else{
+                return false;
+            }
+        }
+        else{
+            if( a[i] != b[i] ){
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/+int SeqIndexOf(T)( tango.util.collection.model.Seq.Seq!(T) s, T src ){
+    int idx;
+    foreach( e; s ){
+        if( e == src ){
+            return idx;
+        }
+        idx++;
+    }
+    return -1;
+}+/
+
+int arrayIndexOf(T)( T[] arr, T v ){
+    int res = -1;
+    int idx = 0;
+    foreach( p; arr ){
+        if( p == v){
+            res = idx;
+            break;
+        }
+        idx++;
+    }
+    return res;
+}
+
+// int seqIndexOf( tango.util.collection.model.Seq.Seq!(Object) seq, Object v ){
+//     int res = -1;
+//     int idx = 0;
+//     foreach( p; seq ){
+//         if( p == v){
+//             res = idx;
+//             break;
+//         }
+//         idx++;
+//     }
+//     return res;
+// }
+
+void PrintStackTrace( int deepth = 100, String prefix = "trc" ){
+    auto e = new Exception( null );
+    int idx = 0;
+    const start = 3;
+    foreach( msg; e.info ){
+        if( idx >= start && idx < start+deepth ) {
+            Trace.formatln( "{}: {}", prefix, msg );
+        }
+        idx++;
+    }
+}
+
+struct ImportData{
+    void[] data;
+    String name;
+
+    public static ImportData opCall( void[] data, String name ){
+        ImportData res;
+        res.data = data;
+        res.name = name;
+        return res;
+    }
+}
+
+template getImportData(String name ){
+    const ImportData getImportData = ImportData( import(name), name );
+}
+
+interface CharSequence {
+    char           charAt(int index);
+    int             length();
+    CharSequence    subSequence(int start, int end);
+    String          toString();
+}
+
+class StringCharSequence : CharSequence {
+    private String str;
+    this( String str ){
+        this.str = str;
+    }
+    char           charAt(int index){
+        return str[index];
+    }
+    int             length(){
+        return str.length;
+    }
+    CharSequence    subSequence(int start, int end){
+        return new StringCharSequence( str[ start .. end ]);
+    }
+    String          toString(){
+        return str;
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/nonstandard/WeakRef.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,88 @@
+/*==========================================================================
+ * weakref.d
+ *    Written in the D Programming Language (http://www.digitalmars.com/d)
+ */
+/***************************************************************************
+ * Creates a weak reference to a class instance.
+ *
+ * A weak reference lets you hold onto a pointer to an object without
+ * preventing the garbage collector from collecting it.
+ * If the garbage collector collects the object then the weak pointer will
+ * become 'null'.  Thus one should always check a weak pointer for null
+ * before doing anything that depends upon it having a value.
+ *
+ * Tested with:
+ *    DMD 1.025 / Phobos 1.025
+ *    DMD 1.025 / Tango 0.99.4
+ *
+ * Usage example:
+---
+ class Something {}
+
+ auto a = new Something();
+ auto wa = new WeakRef!(Something)(a);
+ std.gc.fullCollect();
+
+ // Reference 'a' prevents collection so wa.ptr is non-null
+ assert(wa.ptr is a);
+
+ delete a;
+
+ // 'a' is gone now, so wa.ptr magically becomes null
+ assert(wa.ptr is null);
+---
+ *
+ *
+ * Author:  William V. Baxter III
+ * Contributors:
+ * Date: 21 Jan 2008
+ * Copyright: (C) 2008  William Baxter
+ * License: Public Domain where allowed by law, ZLIB/PNG otherwise.
+ */
+//===========================================================================
+
+module java.nonstandard.WeakRef;
+
+private {
+    alias void delegate(Object) DisposeEvt;
+    extern (C) void  rt_attachDisposeEvent( Object obj, DisposeEvt evt );
+    extern (C) void  rt_detachDisposeEvent( Object obj, DisposeEvt evt );
+}
+
+class WeakRef(T : Object) {
+private:
+    size_t cast_ptr_;
+    void unhook(Object o) {
+        if (cast(size_t)cast(void*)o == cast_ptr_) {
+            rt_detachDisposeEvent(o, &unhook);
+            cast_ptr_ = 0;
+        }
+    }
+public:
+
+    this(T tptr) {
+        cast_ptr_ = cast(size_t)cast(void*)tptr;
+        rt_attachDisposeEvent(tptr, &unhook);
+    }
+    ~this() {
+        T p = ptr();
+        if (p) {
+            rt_detachDisposeEvent(p, &unhook);
+        }
+    }
+    T ptr() {
+        return cast(T)cast(void*)cast_ptr_;
+    }
+    WeakRef dup() {
+        return new WeakRef(ptr());
+    }
+    int opEquals( Object o ){
+        if( auto other = cast( WeakRef!(T) )o ){
+            return other.cast_ptr_ is cast_ptr_;
+        }
+        return false;
+    }
+    hash_t toHash(){
+        return cast_ptr_;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/nonstandard/XmlTranscode.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,181 @@
+module java.nonstandard.XmlTranscode;
+
+import java.lang.util;
+import tango.core.Exception;
+
+/++
+ + Decode XML entities into UTF8 string.
+ + Eg. "&amp;" -> "&", "&#38;" -> "&", "&#x26;" -> "&"
+ + Throws TextException on failure
+ + The given string is modified.
+ +/
+String xmlUnescape( String str ){
+
+    void error(){
+        throw new TextException( "xmlUnescape" );
+    }
+    // &lt; ...
+    // &#1234;
+    // &#x12AF;
+    String src = str;
+    String trg = str;
+    while( src.length ){
+        if( src[0] !is '&' ){
+            trg[0] = src[0];
+            trg = trg[1..$];
+            src = src[1..$];
+        }
+        else{
+            src = src[1..$]; //  go past '&'
+            if( src.length < 2 ) error();
+
+            // search semi
+            int len = Math.min( src.length, 10 ); // limit semi search to possible longest entityname
+            int semi = tango.text.Util.locate( src[0 .. len ], ';' );
+            if( semi is len ) error(); // no semi found
+
+            String entityName = src[ 0 .. semi ]; // name without semi
+            dchar entityValue = 0;
+            switch( entityName ){
+                case "lt":   entityValue = '<'; break;
+                case "gt":   entityValue = '>'; break;
+                case "amp":  entityValue = '&'; break;
+                case "quot": entityValue = '\"'; break;
+                case "apos": entityValue = '\''; break;
+                default:
+                    if( entityName[0] is 'x' ){
+                        if( semi < 2 ) error();
+                        if( semi > 9 ) error();
+                        foreach( hex; entityName[1..$] ){
+                            entityValue <<= 4;
+                            if( hex >= '0' && hex <= '9' ){
+                                entityValue |= ( hex - '0' );
+                            }
+                            else if( hex >= 'a' && hex <= 'f' ){
+                                entityValue |= ( hex - 'a' );
+                            }
+                            else if( hex >= 'A' && hex <= 'F' ){
+                                entityValue |= ( hex - 'A' );
+                            }
+                            else{
+                                error();
+                            }
+                        }
+                    }
+                    else{
+                        if( semi < 1 ) error();
+                        if( semi > 9 ) error();
+                        foreach( dec; entityName[1..$] ){
+                            if( dec >= '0' && dec <= '9' ){
+                                entityValue *= 10;
+                                entityValue += ( dec - '0' );
+                            }
+                            else{
+                                error();
+                            }
+                        }
+                    }
+            }
+            dchar[1] arr;
+            arr[0] = entityValue;
+            uint ate = 0;
+            String res = tango.text.convert.Utf.toString( arr, trg, &ate );
+            trg = trg[ res.length .. $ ];
+            src = src[ semi +1 .. $ ]; // go past semi
+        }
+    }
+    return str[ 0 .. trg.ptr-str.ptr ];
+}
+
+
+/++
+ + Encode XML entities into UTF8 string.
+ + First checks if processing is needed.
+ + If not, the original string is returned.
+ + If processing is needed, a new string is allocated.
+ +/
+String xmlEscape( String xml ){
+    bool needsReplacement( dchar c ){
+        switch( c ){
+            case '<':
+            case '>':
+            case '&':
+            case '\"':
+            case '\'':
+            case '\r':
+            case '\n':
+            case '\u0009':
+                return true;
+            default:
+                return c > 0x7F;
+        }
+    }
+
+    // Check if processing is needed
+    foreach( char c; xml ){
+        if( needsReplacement( c )){
+            goto Lprocess;
+        }
+    }
+    return xml;
+Lprocess:
+
+    // yes, do a new string, start with +20 chars
+    String res = new char[ xml.length + 20 ];
+    res.length = 0;
+
+    foreach( dchar c; xml ){
+
+        if( !needsReplacement( c )){
+            res ~= c;
+        }
+        else{
+            res ~= '&';
+            switch( c ){
+                case '<': res ~= "lt"; break;
+                case '>': res ~= "gt"; break;
+                case '&': res ~= "amp"; break;
+                case '\"': res ~= "quot"; break;
+                case '\'': res ~= "apos"; break;
+                case '\r': case '\n': case '\u0009':
+                default:
+                    char toHexDigit( int i ){
+                        if( i < 10 ) return '0'+i;
+                        return 'A'+i-10;
+                    }
+                    res ~= "#x";
+                    if( c <= 0xFF ){
+                        res ~= toHexDigit(( c >> 4 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 0 ) & 0x0F );
+                    }
+                    else if( c <= 0xFFFF ){
+                        res ~= toHexDigit(( c >> 12 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 8 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 4 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 0 ) & 0x0F );
+                    }
+                    else if( c <= 0xFFFFFF ){
+                        res ~= toHexDigit(( c >> 20 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 16 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 12 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 8 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 4 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 0 ) & 0x0F );
+                    }
+                    else {
+                        res ~= toHexDigit(( c >> 28 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 24 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 20 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 16 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 12 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 8 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 4 ) & 0x0F );
+                        res ~= toHexDigit(( c >> 0 ) & 0x0F );
+                    }
+                    break;
+            }
+            res ~= ';';
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/util/ResourceBundle.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,181 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.util.ResourceBundle;
+
+import tango.text.Util;
+import tango.io.Stdout;
+
+import java.lang.util;
+import java.lang.Integer;
+import tango.io.device.File;
+import tango.text.locale.Core;
+
+class ResourceBundle {
+
+    String[ String ] map;
+
+    /++
+     + First entry is the default entry if no maching locale is found
+     +/
+    public this( ImportData[] data ){
+        char[] name = Culture.current().name.dup;
+        if( name.length is 5 && name[2] is '-' ){
+            name[2] = '_';
+            char[] end = "_" ~ name ~ ".properties";
+            foreach( entry; data ){
+                if( entry.name.length > end.length && entry.name[ $-end.length .. $ ] == end ){
+                    //Trace.formatln( "ResourceBundle {}", entry.name );
+                    initialize( cast(char[])entry.data );
+                    return;
+                }
+            }
+        }
+        char[] end = "_" ~ name[0..2] ~ ".properties";
+        foreach( entry; data ){
+            if( entry.name.length > end.length && entry.name[ $-end.length .. $ ] == end ){
+                //Trace.formatln( "ResourceBundle {}", entry.name );
+                initialize( cast(char[])entry.data );
+                return;
+            }
+        }
+        //Trace.formatln( "ResourceBundle default" );
+        initialize( cast(char[])data[0].data );
+    }
+    public this( ImportData data ){
+        initialize( cast(char[])data.data );
+    }
+    public this( String data ){
+        initialize( data );
+    }
+    private void initialize( String data ){
+        String line;
+        int dataIndex;
+
+        //tango.io.Stdout.Stdout.formatln( "properties put ..." );
+        void readLine(){
+            line.length = 0;
+            char i = data[ dataIndex++ ];
+            while( dataIndex < data.length && i !is '\n' && i !is '\r' ){
+                line ~= i;
+                i = data[ dataIndex++ ];
+            }
+        }
+
+        //tango.io.Stdout.Stdout.formatln( "properties put {}", __LINE__ );
+        bool linecontinue = false;
+        bool iskeypart = true;
+        String key;
+        String value;
+nextline:
+        while( dataIndex < data.length ){
+            //tango.io.Stdout.Stdout.formatln( "properties put {} startline", __LINE__ );
+            readLine();
+            line = java.lang.util.trim(line);
+            if( line.length is 0 ){
+                //tango.io.Stdout.Stdout.formatln( "properties put {} was 0 length", __LINE__ );
+                continue;
+            }
+            if( line[0] == '#' ){
+                //tango.io.Stdout.Stdout.formatln( "properties put {} was comment", __LINE__ );
+                continue;
+            }
+            int pos = 0;
+            bool esc = false;
+            if( !linecontinue ){
+                iskeypart = true;
+                key = null;
+                value = null;
+            }
+            else{
+                linecontinue = false;
+            }
+            while( pos < line.length ){
+                char[] c = line[pos .. pos +1];
+                if( esc ){
+                    esc = false;
+                    switch( c[0] ){
+                    case 't' : c[0] = '\t'; break;
+                    case 'n' : c[0] = '\n'; break;
+                    case '\\': c[0] = '\\'; break;
+                    case '\"': c[0] = '\"'; break;
+                    case 'u' :
+                        dchar d = Integer.parseInt( line[ pos+1 .. pos+5 ], 16 );
+                        c = dcharToString(d);
+                        pos += 4;
+                       break;
+                    default: break;
+                    }
+                }
+                else{
+                    if( c == "\\" ){
+                        if( pos == line.length -1 ){
+                            linecontinue = true;
+                            goto nextline;
+                        }
+                        esc = true;
+                        pos++;
+                        continue;
+                    }
+                    else if( iskeypart && c == "=" ){
+                        pos++;
+                        iskeypart = false;
+                        continue;
+                    }
+                }
+                pos++;
+                if( iskeypart ){
+                    key ~= c;
+                }
+                else{
+                    value ~= c;
+                }
+            }
+            if( iskeypart ){
+                throw new RuntimeException( __FILE__, __LINE__, "Cannot find = in record" );
+            }
+            key = java.lang.util.trim(key);
+            value = java.lang.util.trim(value);
+            //tango.io.Stdout.Stdout.formatln( "properties put {}=>{}", key, value );
+
+            map[ key.dup ] = value.dup;
+            //tango.io.Stdout.Stdout.formatln( "properties put {}", __LINE__ );
+        }
+    }
+
+    public bool hasString( String key ){
+        return ( key in map ) !is null;
+    }
+
+    public String getString( String key ){
+        if( auto v = key in map ){
+            return (*v).dup;
+        }
+        throw new MissingResourceException( "key not found", this.classinfo.name, key );
+    }
+
+    public String[] getKeys(){
+        return map.keys;
+    }
+
+    public static ResourceBundle getBundle( ImportData[] data ){
+        return new ResourceBundle( data );
+    }
+    public static ResourceBundle getBundle( ImportData data ){
+        return new ResourceBundle( data );
+    }
+    public static ResourceBundle getBundle( String name ){
+        try{
+            return new ResourceBundle( cast(String) File.get(name) );
+        }
+        catch( IOException e){
+            e.msg ~= " file:" ~ name;
+            throw e;
+        }
+    }
+    public static ResourceBundle getBundleFromData( String data ){
+        return new ResourceBundle( data );
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/util/WeakHashMap.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,68 @@
+module java.util.WeakHashMap;
+
+
+private {
+    alias void delegate(Object) DisposeEvt;
+    extern (C) void  rt_attachDisposeEvent( Object obj, DisposeEvt evt );
+    extern (C) void  rt_detachDisposeEvent( Object obj, DisposeEvt evt );
+}
+
+
+/+
+    Is not yet 'weak'
++/
+class WeakHashMap {
+
+    static class Ref {
+        size_t ptr;
+        this(Object k){
+            ptr = cast(size_t)cast(void*)k;
+        }
+        override hash_t toHash(){
+            return cast(hash_t)ptr;
+        }
+        override int opEquals( Object o ){
+            if( auto other = cast(Ref)o ){
+                return ptr is other.ptr;
+            }
+            return false;
+        }
+    }
+
+    private Ref unhookKey;
+
+    private void unhook(Object o) {
+        unhookKey.ptr = cast(size_t)cast(void*)o;
+        if( auto p = unhookKey in data ){
+            rt_detachDisposeEvent(o, &unhook);
+            data.remove( unhookKey );
+        }
+    }
+
+    Object[ Ref ] data;
+    ClassInfo gcLock;
+    this(){
+        unhookKey = new Ref(null);
+        gcLock = ClassInfo.find( "gcx.GCLock" );
+    }
+
+    public void put (Object key, Object element){
+        auto k = new Ref(key);
+        rt_attachDisposeEvent(key, &unhook);
+        data[ k ] = element;
+    }
+    public void remove (Object key){
+        scope k = new Ref(key);
+        if( auto p = k in data ){
+            data.remove( k );
+            rt_detachDisposeEvent(key, &unhook);
+        }
+    }
+    public Object get(Object key){
+        scope k = new Ref(key);
+        if( auto p = k in data ){
+            return *p;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/java/util/zip/InflaterInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,122 @@
+/**
+ * Authors: Frank Benoit <keinfarbton@googlemail.com>
+ */
+module java.util.zip.InflaterInputStream;
+
+public import java.io.InputStream;
+import java.lang.all;
+import tango.io.Stdout;
+import tango.io.compress.ZlibStream;
+version(Windows){
+    version(build){
+        pragma(link,"zlib");
+    }
+}
+version(TANGOSVN){
+    import tango.io.device.Conduit;
+} else {
+    import tango.io.Conduit;
+}
+
+class InputStreamWrapper : tango.io.model.IConduit.InputStream {
+
+    java.io.InputStream.InputStream istr;
+
+    this( java.io.InputStream.InputStream istr ){
+        this.istr = istr;
+    }
+
+    uint read (void[] dst){
+        int res = istr.read( cast(byte[])dst );
+        return res;
+    }
+    void[] load (void[] dst = null) {
+            return Conduit.load (this, dst);
+    }
+
+    tango.io.model.IConduit.InputStream clear (){
+        return this;
+    }
+
+    tango.io.model.IConduit.IConduit conduit (){
+        return null;
+    }
+
+    void close (){
+        istr.close();
+    }
+    tango.io.model.IConduit.InputStream input (){
+        return null;
+    }
+    long seek (long offset, Anchor anchor = Anchor.Begin){
+        return 0;
+    }
+}
+
+public class InflaterInputStream : java.io.InputStream.InputStream {
+
+    alias java.io.InputStream.InputStream.read read;
+    alias java.io.InputStream.InputStream.skip skip;
+    alias java.io.InputStream.InputStream.available available;
+    alias java.io.InputStream.InputStream.close close;
+    alias java.io.InputStream.InputStream.mark mark;
+    alias java.io.InputStream.InputStream.reset reset;
+    alias java.io.InputStream.InputStream.markSupported markSupported;
+
+    protected byte[] buf;
+    protected int len;
+    package bool usesDefaultInflater = false;
+
+    ZlibInput tangoIstr;
+
+    public this ( java.io.InputStream.InputStream istr ){
+        tangoIstr = new ZlibInput( new InputStreamWrapper(istr ));
+    }
+
+    public int read(){
+        ubyte[1] data;
+        uint res = tangoIstr.read( data );
+        if( res !is 1 ){
+            return data[0] & 0xFF;
+        }
+        return -1;
+    }
+
+    public int read( byte[] b, int off, int len ){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public int available(){
+        implMissing( __FILE__, __LINE__ );
+        return 0;
+    }
+
+    public long skip( long n ){
+        implMissing( __FILE__, __LINE__ );
+        return 0L;
+    }
+
+    public void close(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public void fill(){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public bool markSupported(){
+        implMissing( __FILE__, __LINE__ );
+        return false;
+    }
+
+    public synchronized void mark( int readlimit ){
+        implMissing( __FILE__, __LINE__ );
+    }
+
+    public synchronized void reset(){
+        implMissing( __FILE__, __LINE__ );
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,75 @@
+###############################################################################
+# 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
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+SWT_Yes=Yes
+SWT_No=No
+SWT_OK=OK
+SWT_Cancel=Cancel
+SWT_Abort=Abort
+SWT_Retry=Retry
+SWT_Ignore=Ignore
+SWT_Sample=Sample
+SWT_A_Sample_Text=A Sample Text
+SWT_Selection=Selection
+SWT_Current_Selection=Current Selection
+SWT_Font=Font
+SWT_Color=Color
+SWT_Extended_style=Extended style
+SWT_Size=Size
+SWT_Style=Style
+SWT_Save=Save
+SWT_Character_set=Character set
+SWT_ColorDialog_Title=Colors
+SWT_FontDialog_Title=Fonts
+SWT_FontSet=Font Set
+SWT_NewFont=New Font
+SWT_Remove=Remove
+SWT_Up=Up
+SWT_Down=Down
+SWT_Selection=Selection
+SWT_Charset_Western=western
+SWT_Charset_EastEuropean=eastern
+SWT_Charset_SouthEuropean=southern
+SWT_Charset_NorthEuropean=northern
+SWT_Charset_Cyrillic=cyrillic
+SWT_Charset_Arabic=arabic
+SWT_Charset_Greek=greek
+SWT_Charset_Hebrew=hebrew
+SWT_Charset_Turkish=turkish
+SWT_Charset_Nordic=nordic
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=baltic rim
+SWT_Charset_Celtic=celtic
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=romanian
+SWT_Charset_SimplifiedChinese=simp. chinese
+SWT_Charset_TraditionalChinese=trad. chinese
+SWT_Charset_Japanese=japanese
+SWT_Charset_Korean=korean
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Input Methods
+SWT_Password=Password:
+SWT_Username=User Name:
+SWT_Switch=Switch
+SWT_Press=Press
+SWT_Open=Open
+SWT_Close=Close
+SWT_Minimize=Minimize
+SWT_Maximize=Maximize
+SWT_Restore=Restore
+SWT_ShowList=Show List
+SWT_FileDownload=File Download
+SWT_Download_File=Download: {0}
+SWT_Download_Location=Saving {0} from {1}
+SWT_Download_Started=Downloading...
+SWT_Download_Status=Download: {0,number,integer} KB of {1,number,integer} KB
+SWT_Authentication_Required=Authentication Required
+SWT_Enter_Username_and_Password=Enter user name and password for {0} at {1}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ar.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 05:04:05 EDT 2006
+SWT_Yes=\u0646\u0639\u0645
+SWT_No=\u0644\u0627
+SWT_OK=\u062D\u0633\u0646\u0627
+SWT_Cancel=\u0627\u0644\u063A\u0627\u0621
+SWT_Abort=\u0627\u0646\u0647\u0627\u0621
+SWT_Retry=\u0627\u0639\u0627\u062F\u0629 \u0627\u0644\u0645\u062D\u0627\u0648\u0644\u0629
+SWT_Ignore=\u062A\u062C\u0627\u0647\u0644
+SWT_Sample=\u0646\u0645\u0648\u0630\u062C
+SWT_A_Sample_Text=\u0646\u0645\u0648\u0630\u062C \u0644\u0644\u0646\u0635
+SWT_Selection=\u0627\u0644\u0627\u062E\u062A\u064A\u0627\u0631
+SWT_Current_Selection=\u0627\u0644\u0627\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u062D\u0627\u0644\u064A
+SWT_Font=\u0637\u0627\u0642\u0645 \u0627\u0644\u0637\u0628\u0627\u0639\u0629
+SWT_Color=\u0627\u0644\u0644\u0648\u0646
+SWT_Extended_style=\u0627\u0644\u0646\u0645\u0637 \u0627\u0644\u0645\u0645\u062A\u062F
+SWT_Size=\u062A\u063A\u064A\u064A\u0631 \u062D\u062C\u0645
+SWT_Style=\u0627\u0644\u0646\u0645\u0637
+SWT_Save=\u062D\u0641\u0638
+SWT_Character_set=\u0641\u0626\u0629 \u0627\u0644\u062D\u0631\u0648\u0641
+SWT_ColorDialog_Title=\u0627\u0644\u0623\u0644\u0648\u0627\u0646
+SWT_FontDialog_Title=\u0623\u0637\u0642\u0645 \u0627\u0644\u0637\u0628\u0627\u0639\u0629
+SWT_FontSet=\u0637\u0627\u0642\u0645 \u0627\u0644\u0637\u0628\u0627\u0639\u0629 \u0627\u0644\u0645\u062D\u062F\u062F
+SWT_NewFont=\u0637\u0627\u0642\u0645 \u0627\u0644\u0637\u0628\u0627\u0639\u0629 \u0627\u0644\u062C\u062F\u064A\u062F
+SWT_Remove=\u0627\u0632\u0627\u0644\u0629
+SWT_Up=\u0644\u0623\u0639\u0644\u0649
+SWT_Down=\u0644\u0623\u0633\u0641\u0644
+SWT_Selection=\u0627\u0644\u0627\u062E\u062A\u064A\u0627\u0631
+SWT_Charset_Western=western
+SWT_Charset_EastEuropean=eastern
+SWT_Charset_SouthEuropean=southern
+SWT_Charset_NorthEuropean=northern
+SWT_Charset_Cyrillic=cyrillic
+SWT_Charset_Arabic=arabic
+SWT_Charset_Greek=greek
+SWT_Charset_Hebrew=hebrew
+SWT_Charset_Turkish=turkish
+SWT_Charset_Nordic=nordic
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=baltic rim
+SWT_Charset_Celtic=celtic
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=romanian
+SWT_Charset_SimplifiedChinese=simp. chinese
+SWT_Charset_TraditionalChinese=trad. chinese
+SWT_Charset_Japanese=japanese
+SWT_Charset_Korean=korean
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u0637\u0631\u0642 \u0627\u0644\u0645\u062F\u062E\u0644\u0627\u062A
+SWT_Password=\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631\u064A\u0629\:
+SWT_Username=\u0627\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\:
+SWT_Switch=\u062A\u0628\u062F\u064A\u0644
+SWT_Press=\u0636\u063A\u0637
+SWT_Open=\u0641\u062A\u062D
+SWT_Close=\u0627\u063A\u0644\u0627\u0642
+SWT_Minimize=\u062A\u0635\u063A\u064A\u0631
+SWT_Maximize=\u062A\u0643\u0628\u064A\u0631
+SWT_Restore=\u0627\u0633\u062A\u0639\u0627\u062F\u0629
+SWT_ShowList=\u0639\u0631\u0636 \u0643\u0634\u0641
+SWT_FileDownload=\u062A\u062D\u0645\u064A\u0644 \u0627\u0644\u0645\u0644\u0641
+SWT_Download_File=\u062A\u062D\u0645\u064A\u0644\: {0}
+SWT_Download_Location=\u062D\u0641\u0638 {0} \u0645\u0646 {1}
+SWT_Download_Started=\u062A\u062D\u0645\u064A\u0644...
+SWT_Download_Status=\u062A\u062D\u0645\u064A\u0644\: {0,number,integer} KB \u0645\u0646 {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_cs.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 02:30:38 EDT 2006
+SWT_Yes=Ano
+SWT_No=Ne
+SWT_OK=OK
+SWT_Cancel=Storno
+SWT_Abort=P\u0159ed\u010Dasn\u011B ukon\u010Dit
+SWT_Retry=Zopakovat
+SWT_Ignore=Ignorovat
+SWT_Sample=Uk\u00E1zka
+SWT_A_Sample_Text=Vzorov\u00FD text
+SWT_Selection=V\u00FDb\u011Br
+SWT_Current_Selection=Aktu\u00E1ln\u00ED v\u00FDb\u011Br
+SWT_Font=P\u00EDsmo
+SWT_Color=Barva
+SWT_Extended_style=Roz\u0161\u00ED\u0159en\u00FD styl
+SWT_Size=Velikost
+SWT_Style=Styl
+SWT_Save=Ulo\u017Eit
+SWT_Character_set=Znakov\u00E1 sada
+SWT_ColorDialog_Title=Barvy
+SWT_FontDialog_Title=P\u00EDsma
+SWT_FontSet=Sada p\u00EDsem
+SWT_NewFont=Nov\u00E9 p\u00EDsmo
+SWT_Remove=Odebrat
+SWT_Up=Nahoru
+SWT_Down=Dol\u016F
+SWT_Selection=V\u00FDb\u011Br
+SWT_Charset_Western=z\u00E1padn\u00ED
+SWT_Charset_EastEuropean=v\u00FDchodn\u00ED
+SWT_Charset_SouthEuropean=ji\u017En\u00ED
+SWT_Charset_NorthEuropean=severn\u00ED
+SWT_Charset_Cyrillic=azbuka
+SWT_Charset_Arabic=arab\u0161tina
+SWT_Charset_Greek=\u0159e\u010Dtina
+SWT_Charset_Hebrew=hebrej\u0161tina
+SWT_Charset_Turkish=ture\u010Dtina
+SWT_Charset_Nordic=seversk\u00E9 jazyky
+SWT_Charset_Thai=thaj\u0161tina
+SWT_Charset_BalticRim=pobaltsk\u00E9 jazyky
+SWT_Charset_Celtic=kelt\u0161tina
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rumun\u0161tina
+SWT_Charset_SimplifiedChinese=zjedn. \u010D\u00EDn\u0161tina
+SWT_Charset_TraditionalChinese=trad. \u010D\u00EDn\u0161tina
+SWT_Charset_Japanese=japon\u0161tina
+SWT_Charset_Korean=korej\u0161tina
+SWT_Charset_Unicode=unik\u00F3d
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Metody vstupu
+SWT_Password=Heslo\:
+SWT_Username=Jm\u00E9no u\u017Eivatele\:
+SWT_Switch=P\u0159epnout
+SWT_Press=Stisknout
+SWT_Open=Otev\u0159\u00EDt
+SWT_Close=Zav\u0159\u00EDt
+SWT_Minimize=Minimalizovat
+SWT_Maximize=Maximalizovat
+SWT_Restore=Obnovit
+SWT_ShowList=Zobrazit seznam
+SWT_FileDownload=Sta\u017Een\u00ED souboru
+SWT_Download_File=St\u00E1hnout\: {0}
+SWT_Download_Location=Ukl\u00E1d\u00E1n\u00ED {0} z {1}
+SWT_Download_Started=Prob\u00EDh\u00E1 stahov\u00E1n\u00ED...
+SWT_Download_Status=Sta\u017Eeno\: {0,number,integer} kB z {1,number,integer} kB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_da.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Ja
+SWT_No=Nej
+SWT_OK=OK
+SWT_Cancel=Annull\u00E9r
+SWT_Abort=Afbryd
+SWT_Retry=Pr\u00F8v igen
+SWT_Ignore=Ignor\u00E9r
+SWT_Sample=Eksempel
+SWT_A_Sample_Text=Eksempeltekst
+SWT_Selection=Valg
+SWT_Current_Selection=Aktuelt valg
+SWT_Font=Font
+SWT_Color=Farve
+SWT_Extended_style=Udvidet typografi
+SWT_Size=St\u00F8rrelse
+SWT_Style=Type
+SWT_Save=Gem
+SWT_Character_set=Tegns\u00E6t
+SWT_ColorDialog_Title=Farver
+SWT_FontDialog_Title=Fonte
+SWT_FontSet=Fonts\u00E6t
+SWT_NewFont=Ny font
+SWT_Remove=Fjern
+SWT_Up=Op
+SWT_Down=Ned
+SWT_Selection=Valg
+SWT_Charset_Western=vestligt
+SWT_Charset_EastEuropean=\u00F8steurop\u00E6isk
+SWT_Charset_SouthEuropean=sydeurop\u00E6isk
+SWT_Charset_NorthEuropean=nordeurop\u00E6isk
+SWT_Charset_Cyrillic=kyrillisk
+SWT_Charset_Arabic=arabisk
+SWT_Charset_Greek=gr\u00E6sk
+SWT_Charset_Hebrew=hebraisk
+SWT_Charset_Turkish=tyrkisk
+SWT_Charset_Nordic=nordisk
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=baltisk
+SWT_Charset_Celtic=keltisk
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rum\u00E6nsk
+SWT_Charset_SimplifiedChinese=fork. kinesisk
+SWT_Charset_TraditionalChinese=ufork. kinesisk
+SWT_Charset_Japanese=japansk
+SWT_Charset_Korean=koreansk
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Inputmetoder
+SWT_Password=Kodeord\:
+SWT_Username=Brugernavn\:
+SWT_Switch=Skift
+SWT_Press=Tryk p\u00E5
+SWT_Open=\u00C5bn
+SWT_Close=Luk
+SWT_Minimize=Minim\u00E9r
+SWT_Maximize=Maksim\u00E9r
+SWT_Restore=Gendan
+SWT_ShowList=Vis liste
+SWT_FileDownload=Filoverf\u00F8rsel
+SWT_Download_File=Overf\u00F8r\: {0}
+SWT_Download_Location=Gemmer {0} fra {1}
+SWT_Download_Started=Overf\u00F8rer...
+SWT_Download_Status=Overf\u00F8r\: {0,number,integer} KB af {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_de.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=Ja
+SWT_No=Nein
+SWT_OK=OK
+SWT_Cancel=Abbrechen
+SWT_Abort=Stoppen
+SWT_Retry=Erneut versuchen
+SWT_Ignore=Ignorieren
+SWT_Sample=Beispiel
+SWT_A_Sample_Text=Beispieltext
+SWT_Selection=Auswahl
+SWT_Current_Selection=Aktuelle Auswahl
+SWT_Font=Schriftart
+SWT_Color=Farbe
+SWT_Extended_style=Erweiterte Darstellung
+SWT_Size=Gr\u00F6\u00DFe
+SWT_Style=Darstellung
+SWT_Save=Speichern
+SWT_Character_set=Zeichensatz
+SWT_ColorDialog_Title=Farben
+SWT_FontDialog_Title=Schriftarten
+SWT_FontSet=Schriftartenangebot
+SWT_NewFont=Neue Schriftart
+SWT_Remove=Entfernen
+SWT_Up=Nach oben
+SWT_Down=Nach unten
+SWT_Selection=Auswahl
+SWT_Charset_Western=Westlich
+SWT_Charset_EastEuropean=\u00D6stlich
+SWT_Charset_SouthEuropean=S\u00FCdlich
+SWT_Charset_NorthEuropean=Nordisch
+SWT_Charset_Cyrillic=Kyrillisch
+SWT_Charset_Arabic=Arabisch
+SWT_Charset_Greek=Griechisch
+SWT_Charset_Hebrew=Hebr\u00E4isch
+SWT_Charset_Turkish=T\u00FCrkisch
+SWT_Charset_Nordic=Nordisch
+SWT_Charset_Thai=Thai
+SWT_Charset_BalticRim=Baltisch
+SWT_Charset_Celtic=Keltisch
+SWT_Charset_Euro=Euro
+SWT_Charset_Romanian=Rum\u00E4nisch
+SWT_Charset_SimplifiedChinese=Vereinfachtes Chinesisch
+SWT_Charset_TraditionalChinese=Traditionelles Chinesisch
+SWT_Charset_Japanese=Japanisch
+SWT_Charset_Korean=Koreanisch
+SWT_Charset_Unicode=Unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Eingabemethoden
+SWT_Password=Kennwort\:
+SWT_Username=Benutzername\:
+SWT_Switch=Umschalten
+SWT_Press=Dr\u00FCcken
+SWT_Open=\u00D6ffnen
+SWT_Close=Schlie\u00DFen
+SWT_Minimize=Minimieren
+SWT_Maximize=Maximieren
+SWT_Restore=Wiederherstellen
+SWT_ShowList=Liste anzeigen
+SWT_FileDownload=Datei herunterladen
+SWT_Download_File=Herunterladen\: {0}
+SWT_Download_Location=Speichern von {0} von {1}
+SWT_Download_Started=Herunterladen...
+SWT_Download_Status=Herunterladen\: {0,number,integer} KB von {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_el.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=\u039D\u03B1\u03B9
+SWT_No=\u038C\u03C7\u03B9
+SWT_OK=OK
+SWT_Cancel=\u0391\u03BA\u03CD\u03C1\u03C9\u03C3\u03B7
+SWT_Abort=\u039C\u03B1\u03C4\u03B1\u03AF\u03C9\u03C3\u03B7
+SWT_Retry=\u0395\u03C0\u03B1\u03BD\u03AC\u03BB\u03B7\u03C8\u03B7
+SWT_Ignore=\u03A0\u03B1\u03C1\u03AC\u03B2\u03BB\u03B5\u03C8\u03B7
+SWT_Sample=\u0394\u03B5\u03AF\u03B3\u03BC\u03B1
+SWT_A_Sample_Text=\u0394\u03B5\u03AF\u03B3\u03BC\u03B1 \u03BA\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
+SWT_Selection=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
+SWT_Current_Selection=\u03A4\u03C1\u03AD\u03C7\u03BF\u03C5\u03C3\u03B1 \u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
+SWT_Font=\u0393\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03AC
+SWT_Color=\u03A7\u03C1\u03CE\u03BC\u03B1
+SWT_Extended_style=\u0395\u03BA\u03C4\u03B5\u03C4\u03B1\u03BC\u03AD\u03BD\u03BF \u03C3\u03C4\u03C5\u03BB
+SWT_Size=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2
+SWT_Style=\u03A3\u03C4\u03C5\u03BB
+SWT_Save=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
+SWT_Character_set=\u03A3\u03CD\u03BD\u03BF\u03BB\u03BF \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD
+SWT_ColorDialog_Title=\u03A7\u03C1\u03CE\u03BC\u03B1\u03C4\u03B1
+SWT_FontDialog_Title=\u0393\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03AD\u03C2
+SWT_FontSet=\u039F\u03C1\u03B9\u03C3\u03BC\u03CC\u03C2 \u03B3\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03AC\u03C2
+SWT_NewFont=\u039D\u03AD\u03B1 \u03B3\u03C1\u03B1\u03BC\u03BC\u03B1\u03C4\u03BF\u03C3\u03B5\u03B9\u03C1\u03AC
+SWT_Remove=\u0391\u03C6\u03B1\u03AF\u03C1\u03B5\u03C3\u03B7
+SWT_Up=\u03A0\u03AC\u03BD\u03C9
+SWT_Down=\u039A\u03AC\u03C4\u03C9
+SWT_Selection=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
+SWT_Charset_Western=\u03B4\u03C5\u03C4\u03B9\u03BA\u03CC
+SWT_Charset_EastEuropean=\u03B1\u03BD\u03B1\u03C4\u03BF\u03BB\u03B9\u03BA\u03CC
+SWT_Charset_SouthEuropean=\u03BD\u03CC\u03C4\u03B9\u03BF
+SWT_Charset_NorthEuropean=\u03B2\u03CC\u03C1\u03B5\u03B9\u03BF
+SWT_Charset_Cyrillic=\u03BA\u03C5\u03C1\u03B9\u03BB\u03BB\u03B9\u03BA\u03CC
+SWT_Charset_Arabic=\u03B1\u03C1\u03B1\u03B2\u03B9\u03BA\u03CC
+SWT_Charset_Greek=\u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03CC
+SWT_Charset_Hebrew=\u03B5\u03B2\u03C1\u03B1\u03CA\u03BA\u03CC
+SWT_Charset_Turkish=\u03C4\u03BF\u03CD\u03C1\u03BA\u03B9\u03BA\u03BF
+SWT_Charset_Nordic=\u03BD\u03BF\u03C1\u03B4\u03B9\u03BA\u03CC
+SWT_Charset_Thai=\u03C4\u03B1\u03CA\u03BB\u03B1\u03BD\u03B4\u03B9\u03BA\u03CC
+SWT_Charset_BalticRim=\u03B1\u03BA\u03C4\u03AE \u03C4\u03B7\u03C2 \u03B2\u03B1\u03BB\u03C4\u03B9\u03BA\u03AE\u03C2
+SWT_Charset_Celtic=\u03BA\u03B5\u03BB\u03C4\u03B9\u03BA\u03CC
+SWT_Charset_Euro=\u03B5\u03C5\u03C1\u03C9\u03C0\u03B1\u03CA\u03BA\u03CC
+SWT_Charset_Romanian=\u03C1\u03BF\u03C5\u03BC\u03AC\u03BD\u03B9\u03BA\u03BF
+SWT_Charset_SimplifiedChinese=\u03B1\u03C0\u03BB\u03BF\u03C0. \u03BA\u03B9\u03BD\u03B5\u03B6\u03B9\u03BA\u03CC
+SWT_Charset_TraditionalChinese=\u03C0\u03B1\u03C1\u03B1\u03B4\u03BF\u03C3. \u03BA\u03B9\u03BD\u03B5\u03B6\u03B9\u03BA\u03CC
+SWT_Charset_Japanese=\u03B9\u03B1\u03C0\u03C9\u03BD\u03B9\u03BA\u03CC
+SWT_Charset_Korean=\u03BA\u03BF\u03C1\u03B5\u03B1\u03C4\u03B9\u03BA\u03CC
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u039C\u03AD\u03B8\u03BF\u03B4\u03BF\u03B9 \u03B5\u03B9\u03C3\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2
+SWT_Password=\u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2 \:
+SWT_Username=\u038C\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7\:
+SWT_Switch=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE
+SWT_Press=\u03A0\u03AC\u03C4\u03B7\u03BC\u03B1
+SWT_Open=\u0386\u03BD\u03BF\u03B9\u03B3\u03BC\u03B1
+SWT_Close=\u039A\u03BB\u03B5\u03AF\u03C3\u03B9\u03BC\u03BF
+SWT_Minimize=\u0395\u03BB\u03B1\u03C7\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7
+SWT_Maximize=\u039C\u03B5\u03B3\u03B9\u03C3\u03C4\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7
+SWT_Restore=\u0395\u03C0\u03B1\u03BD\u03B1\u03C6\u03BF\u03C1\u03AC
+SWT_ShowList=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03BB\u03AF\u03C3\u03C4\u03B1\u03C2
+SWT_FileDownload=\u039C\u03B5\u03C4\u03B1\u03C6\u03CC\u03C1\u03C4\u03C9\u03C3\u03B7 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
+SWT_Download_File=\u039C\u03B5\u03C4\u03B1\u03C6\u03CC\u03C1\u03C4\u03C9\u03C3\u03B7\: {0}
+SWT_Download_Location=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7 {0} \u03B1\u03C0\u03CC {1}
+SWT_Download_Started=\u039C\u03B5\u03C4\u03B1\u03C6\u03CC\u03C1\u03C4\u03C9\u03C3\u03B7...
+SWT_Download_Status=\u039C\u03B5\u03C4\u03B1\u03C6\u03CC\u03C1\u03C4\u03C9\u03C3\u03B7\: {0,number,integer} KB \u03B1\u03C0\u03CC {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_es.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=S\u00ED
+SWT_No=No
+SWT_OK=Aceptar
+SWT_Cancel=Cancelar
+SWT_Abort=Terminar anormalmente
+SWT_Retry=Reintentar
+SWT_Ignore=Omitir
+SWT_Sample=Ejemplo
+SWT_A_Sample_Text=Ejemplo de texto
+SWT_Selection=Selecci\u00F3n
+SWT_Current_Selection=Selecci\u00F3n actual
+SWT_Font=Font
+SWT_Color=Color
+SWT_Extended_style=Estilo ampliado
+SWT_Size=Tama\u00F1o
+SWT_Style=Estilo
+SWT_Save=Guardar
+SWT_Character_set=Juego de caracteres
+SWT_ColorDialog_Title=Colores
+SWT_FontDialog_Title=Fonts
+SWT_FontSet=Conjunto de fonts
+SWT_NewFont=Font nuevo
+SWT_Remove=Eliminar
+SWT_Up=Subir
+SWT_Down=Bajar
+SWT_Selection=Selecci\u00F3n
+SWT_Charset_Western=occidental
+SWT_Charset_EastEuropean=oriental
+SWT_Charset_SouthEuropean=meridional
+SWT_Charset_NorthEuropean=septentrional
+SWT_Charset_Cyrillic=cir\u00EDlico
+SWT_Charset_Arabic=\u00E1rabe
+SWT_Charset_Greek=griego
+SWT_Charset_Hebrew=hebreo
+SWT_Charset_Turkish=turco
+SWT_Charset_Nordic=n\u00F3rdico
+SWT_Charset_Thai=tailand\u00E9s
+SWT_Charset_BalticRim=pa\u00EDses b\u00E1lticos
+SWT_Charset_Celtic=celta
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rumano
+SWT_Charset_SimplifiedChinese=chino simplificado
+SWT_Charset_TraditionalChinese=chino tradicional
+SWT_Charset_Japanese=japon\u00E9s
+SWT_Charset_Korean=coreano
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=M\u00E9todos de entrada
+SWT_Password=Contrase\u00F1a\:
+SWT_Username=Nombre de usuario\:
+SWT_Switch=Pasar
+SWT_Press=Pulsar
+SWT_Open=Abrir
+SWT_Close=Cerrar
+SWT_Minimize=Minimizar
+SWT_Maximize=Maximizar
+SWT_Restore=Restaurar
+SWT_ShowList=Mostrar lista
+SWT_FileDownload=Descarga de archivos
+SWT_Download_File=Descargar\: {0}
+SWT_Download_Location=Guardando {0} de {1}
+SWT_Download_Started=Descargando...
+SWT_Download_Status=Descargar\: {0,number,integer} KB de {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_fi.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Kyll\u00E4
+SWT_No=Ei
+SWT_OK=OK
+SWT_Cancel=Peruuta
+SWT_Abort=Keskeyt\u00E4
+SWT_Retry=Yrit\u00E4 uudelleen
+SWT_Ignore=Ohita
+SWT_Sample=Malli
+SWT_A_Sample_Text=Malliteksti
+SWT_Selection=Valinta
+SWT_Current_Selection=Nykyinen valinta
+SWT_Font=Fontti
+SWT_Color=V\u00E4ri
+SWT_Extended_style=Laajennettu tyyli
+SWT_Size=Koko
+SWT_Style=Tyyli
+SWT_Save=Tallenna
+SWT_Character_set=Merkist\u00F6
+SWT_ColorDialog_Title=V\u00E4rit
+SWT_FontDialog_Title=Fontit
+SWT_FontSet=Fontisto
+SWT_NewFont=Uusi fontti
+SWT_Remove=Poista
+SWT_Up=Yl\u00F6s
+SWT_Down=Alas
+SWT_Selection=Valinta
+SWT_Charset_Western=l\u00E4nsieurooppalainen
+SWT_Charset_EastEuropean=it\u00E4eurooppalainen
+SWT_Charset_SouthEuropean=etel\u00E4eurooppalainen
+SWT_Charset_NorthEuropean=pohjoiseurooppalainen
+SWT_Charset_Cyrillic=kyrillinen
+SWT_Charset_Arabic=arabialainen
+SWT_Charset_Greek=kreikkalainen
+SWT_Charset_Hebrew=heprealainen
+SWT_Charset_Turkish=turkkilainen
+SWT_Charset_Nordic=pohjoismaalainen
+SWT_Charset_Thai=thaimaalainen
+SWT_Charset_BalticRim=balttilainen
+SWT_Charset_Celtic=kelttil\u00E4inen
+SWT_Charset_Euro=eurooppalainen
+SWT_Charset_Romanian=romanialainen
+SWT_Charset_SimplifiedChinese=yksinkertaistettu kiinalainen
+SWT_Charset_TraditionalChinese=perinteinen kiinalainen
+SWT_Charset_Japanese=japanilainen
+SWT_Charset_Korean=korealainen
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Sy\u00F6tt\u00F6metodit
+SWT_Password=Salasana\:
+SWT_Username=K\u00E4ytt\u00E4j\u00E4tunnus\:
+SWT_Switch=Vaihda
+SWT_Press=Paina
+SWT_Open=Avaa
+SWT_Close=Sulje
+SWT_Minimize=Pienenn\u00E4
+SWT_Maximize=Suurenna
+SWT_Restore=Palauta
+SWT_ShowList=N\u00E4yt\u00E4 luettelo
+SWT_FileDownload=Tiedoston lataus
+SWT_Download_File=Ladataan kohdetta\: {0}
+SWT_Download_Location=Tallennetaan kohdetta {0} kohteesta {1}
+SWT_Download_Started=Lataus on meneill\u00E4\u00E4n...
+SWT_Download_Status=Lataus\: {0,number,integer} kt / {1,number,integer} kt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_fr.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=Oui
+SWT_No=Non
+SWT_OK=OK
+SWT_Cancel=Annuler
+SWT_Abort=Abandonner
+SWT_Retry=Recommencer
+SWT_Ignore=Ignorer
+SWT_Sample=Exemple
+SWT_A_Sample_Text=Exemple de texte
+SWT_Selection=S\u00E9lection
+SWT_Current_Selection=S\u00E9lection actuelle
+SWT_Font=Font
+SWT_Color=Couleur
+SWT_Extended_style=Style \u00E9tendu
+SWT_Size=Taille
+SWT_Style=Style
+SWT_Save=Enregistrer
+SWT_Character_set=Jeu de caract\u00E8res
+SWT_ColorDialog_Title=Couleurs
+SWT_FontDialog_Title=Polices
+SWT_FontSet=Ensemble de polices
+SWT_NewFont=Nouvelle police
+SWT_Remove=Supprimer
+SWT_Up=Monter
+SWT_Down=Descendre
+SWT_Selection=S\u00E9lection
+SWT_Charset_Western=western
+SWT_Charset_EastEuropean=eastern
+SWT_Charset_SouthEuropean=southern
+SWT_Charset_NorthEuropean=northern
+SWT_Charset_Cyrillic=cyrillique
+SWT_Charset_Arabic=arabe
+SWT_Charset_Greek=grec
+SWT_Charset_Hebrew=h\u00E9breu
+SWT_Charset_Turkish=turc
+SWT_Charset_Nordic=nordique
+SWT_Charset_Thai=tha\u00EF
+SWT_Charset_BalticRim=baltique rim
+SWT_Charset_Celtic=celtique
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=roumain
+SWT_Charset_SimplifiedChinese=chinois simp.
+SWT_Charset_TraditionalChinese=chinois trad.
+SWT_Charset_Japanese=japonais
+SWT_Charset_Korean=cor\u00E9en
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=M\u00E9thodes d'entr\u00E9e
+SWT_Password=Mot de passe \:
+SWT_Username=Nom d'utilisateur \:
+SWT_Switch=Basculer
+SWT_Press=Appuyer
+SWT_Open=Ouverture
+SWT_Close=Fermer
+SWT_Minimize=R\u00E9duire
+SWT_Maximize=Agrandir
+SWT_Restore=Restaurer
+SWT_ShowList=Afficher la liste
+SWT_FileDownload=T\u00E9l\u00E9chargement de fichier
+SWT_Download_File=T\u00E9l\u00E9chargement \: {0}
+SWT_Download_Location=Sauvegarde de {0} \u00E0 partir de {1}
+SWT_Download_Started=T\u00E9l\u00E9chargement en cours...
+SWT_Download_Status=T\u00E9l\u00E9chargement \: {0,number,integer} ko sur {1,number,integer} ko
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_hu.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 02:30:38 EDT 2006
+SWT_Yes=Igen
+SWT_No=Nem
+SWT_OK=OK
+SWT_Cancel=M\u00E9gse
+SWT_Abort=Megszak\u00EDt\u00E1s
+SWT_Retry=\u00DAjra
+SWT_Ignore=Mell\u0151z\u00E9s
+SWT_Sample=Minta
+SWT_A_Sample_Text=Mintasz\u00F6veg
+SWT_Selection=Kijel\u00F6l\u00E9s
+SWT_Current_Selection=Jelenlegi kijel\u00F6l\u00E9s
+SWT_Font=Bet\u0171t\u00EDpus
+SWT_Color=Sz\u00EDn
+SWT_Extended_style=Kiterjesztett st\u00EDlus
+SWT_Size=M\u00E9ret
+SWT_Style=St\u00EDlus
+SWT_Save=Ment\u00E9s
+SWT_Character_set=Karakterk\u00E9szlet
+SWT_ColorDialog_Title=Sz\u00EDnek
+SWT_FontDialog_Title=Bet\u0171t\u00EDpusok
+SWT_FontSet=Bet\u0171k\u00E9szlet
+SWT_NewFont=\u00DAj bet\u0171t\u00EDpus
+SWT_Remove=Elt\u00E1vol\u00EDt\u00E1s
+SWT_Up=Fel
+SWT_Down=Le
+SWT_Selection=Kijel\u00F6l\u00E9s
+SWT_Charset_Western=nyugati
+SWT_Charset_EastEuropean=keleti
+SWT_Charset_SouthEuropean=d\u00E9li
+SWT_Charset_NorthEuropean=\u00E9szaki
+SWT_Charset_Cyrillic=cirill
+SWT_Charset_Arabic=arab
+SWT_Charset_Greek=g\u00F6r\u00F6g
+SWT_Charset_Hebrew=h\u00E9ber
+SWT_Charset_Turkish=t\u00F6r\u00F6k
+SWT_Charset_Nordic=skandin\u00E1v
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=balti
+SWT_Charset_Celtic=kelta
+SWT_Charset_Euro=eur\u00F3
+SWT_Charset_Romanian=rom\u00E1n
+SWT_Charset_SimplifiedChinese=egysz. k\u00EDnai
+SWT_Charset_TraditionalChinese=hagy. k\u00EDnai
+SWT_Charset_Japanese=jap\u00E1n
+SWT_Charset_Korean=koreai
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Beviteli m\u00F3dszerek
+SWT_Password=Jelsz\u00F3\:
+SWT_Username=Felhaszn\u00E1l\u00F3n\u00E9v\:
+SWT_Switch=\u00C1tkapcsol\u00E1s
+SWT_Press=Megnyom\u00E1s
+SWT_Open=Megnyit\u00E1s
+SWT_Close=Bez\u00E1r\u00E1s
+SWT_Minimize=Kis m\u00E9ret
+SWT_Maximize=Teljes m\u00E9ret
+SWT_Restore=Vissza\u00E1ll\u00EDt\u00E1s
+SWT_ShowList=Lista megjelen\u00EDt\u00E9se
+SWT_FileDownload=F\u00E1jllet\u00F6lt\u00E9s
+SWT_Download_File=Let\u00F6lt\u00E9s\: {0}
+SWT_Download_Location={0} ment\u00E9se a k\u00F6vetkez\u0151 helyr\u0151l\: {1}
+SWT_Download_Started=Let\u00F6lt\u00E9s...
+SWT_Download_Status=Let\u00F6lt\u00E9s\: {0,number,integer} / {1,number,integer} KByte
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_it.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=S\u00EC
+SWT_No=No
+SWT_OK=OK
+SWT_Cancel=Annulla
+SWT_Abort=Interrompi
+SWT_Retry=Riprova
+SWT_Ignore=Ignora
+SWT_Sample=Esempio
+SWT_A_Sample_Text=Testo di esempio
+SWT_Selection=Selezione
+SWT_Current_Selection=Selezione corrente
+SWT_Font=Tipo di carattere
+SWT_Color=Colore
+SWT_Extended_style=Stile esteso
+SWT_Size=Dimensione
+SWT_Style=Stile
+SWT_Save=Salva
+SWT_Character_set=Insieme di caratteri
+SWT_ColorDialog_Title=Colori
+SWT_FontDialog_Title=Tipi di carattere
+SWT_FontSet=Insieme di tipi di carattere
+SWT_NewFont=Nuovo tipo di carattere
+SWT_Remove=Rimuovi
+SWT_Up=Su
+SWT_Down=Gi\u00F9
+SWT_Selection=Selezione
+SWT_Charset_Western=occidentali
+SWT_Charset_EastEuropean=orientali
+SWT_Charset_SouthEuropean=area del Mediterraneo
+SWT_Charset_NorthEuropean=area settentrionale
+SWT_Charset_Cyrillic=cirillici
+SWT_Charset_Arabic=arabi
+SWT_Charset_Greek=greci
+SWT_Charset_Hebrew=ebraici
+SWT_Charset_Turkish=turchi
+SWT_Charset_Nordic=nordici
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=del Baltico
+SWT_Charset_Celtic=celtici
+SWT_Charset_Euro=europei
+SWT_Charset_Romanian=rumeni
+SWT_Charset_SimplifiedChinese=cinesi sempl.
+SWT_Charset_TraditionalChinese=cinesi trad.
+SWT_Charset_Japanese=giapponesi
+SWT_Charset_Korean=coreani
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Metodi di input
+SWT_Password=Password\:
+SWT_Username=Nome utente\:
+SWT_Switch=Passa a
+SWT_Press=Premi
+SWT_Open=Apri
+SWT_Close=Chiudi
+SWT_Minimize=Riduci a icona
+SWT_Maximize=Ingrandisci
+SWT_Restore=Ripristina
+SWT_ShowList=Mostra elenco
+SWT_FileDownload=Download file
+SWT_Download_File=Download\: {0}
+SWT_Download_Location=Salvataggio di {0} da {1}
+SWT_Download_Started=Download in corso...
+SWT_Download_Status=Download\: {0,number,integer} KB di {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_iw.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 05:04:05 EDT 2006
+SWT_Yes=\u05DB\u05DF
+SWT_No=\u05DC\u05D0
+SWT_OK=\u05D0\u05D9\u05E9\u05D5\u05E8
+SWT_Cancel=\u05D1\u05D9\u05D8\u05D5\u05DC
+SWT_Abort=\u05E0\u05D8\u05D9\u05E9\u05D4
+SWT_Retry=\u05E0\u05E1\u05D9\u05D5\u05DF \u05D7\u05D5\u05D6\u05E8
+SWT_Ignore=\u05D4\u05EA\u05E2\u05DC\u05DE\u05D5\u05EA
+SWT_Sample=\u05D3\u05D5\u05D2\u05DE\u05D4
+SWT_A_Sample_Text=\u05EA\u05DE\u05DC\u05D9\u05DC \u05DC\u05D3\u05D5\u05D2\u05DE\u05D4
+SWT_Selection=\u05D1\u05D7\u05D9\u05E8\u05D4
+SWT_Current_Selection=\u05D1\u05D7\u05D9\u05E8\u05D4 \u05E0\u05D5\u05DB\u05D7\u05D9\u05EA
+SWT_Font=\u05D2\u05D5\u05E4\u05DF
+SWT_Color=\u05E6\u05D1\u05E2
+SWT_Extended_style=\u05E1\u05D2\u05E0\u05D5\u05DF \u05DE\u05D5\u05E8\u05D7\u05D1
+SWT_Size=\u05D2\u05D5\u05D3\u05DC
+SWT_Style=\u05E1\u05D2\u05E0\u05D5\u05DF
+SWT_Save=\u05E9\u05DE\u05D9\u05E8\u05D4
+SWT_Character_set=\u05DE\u05E2\u05E8\u05DB\u05EA \u05EA\u05D5\u05D5\u05D9\u05DD
+SWT_ColorDialog_Title=\u05E6\u05D1\u05E2\u05D9\u05DD
+SWT_FontDialog_Title=\u05D2\u05D5\u05E4\u05E0\u05D9\u05DD
+SWT_FontSet=\u05E7\u05D1\u05D5\u05E6\u05EA \u05D2\u05D5\u05E4\u05E0\u05D9\u05DD
+SWT_NewFont=\u05D2\u05D5\u05E4\u05DF \u05D7\u05D3\u05E9
+SWT_Remove=\u05E1\u05D9\u05DC\u05D5\u05E7
+SWT_Up=\u05DC\u05DE\u05E2\u05DC\u05D4
+SWT_Down=\u05DC\u05DE\u05D8\u05D4
+SWT_Selection=\u05D1\u05D7\u05D9\u05E8\u05D4
+SWT_Charset_Western=\u05DE\u05E2\u05E8\u05D1\u05D9
+SWT_Charset_EastEuropean=\u05DE\u05D6\u05E8\u05D7\u05D9
+SWT_Charset_SouthEuropean=\u05D3\u05E8\u05D5\u05DE\u05D9
+SWT_Charset_NorthEuropean=\u05E6\u05E4\u05D5\u05E0\u05D9
+SWT_Charset_Cyrillic=\u05E7\u05D9\u05E8\u05D9\u05DC\u05D9\u05EA
+SWT_Charset_Arabic=\u05E2\u05E8\u05D1\u05D9\u05EA
+SWT_Charset_Greek=\u05D9\u05D5\u05D5\u05E0\u05D9\u05EA
+SWT_Charset_Hebrew=\u05E2\u05D1\u05E8\u05D9\u05EA
+SWT_Charset_Turkish=\u05D8\u05D5\u05E8\u05E7\u05D9\u05EA
+SWT_Charset_Nordic=\u05E9\u05E4\u05D5\u05EA \u05E0\u05D5\u05E8\u05D3\u05D9\u05D5\u05EA
+SWT_Charset_Thai=\u05EA\u05D0\u05D9\u05DC\u05E0\u05D3\u05D9\u05EA
+SWT_Charset_BalticRim=\u05D4\u05D0\u05E8\u05E6\u05D5\u05EA \u05D4\u05D1\u05DC\u05D8\u05D9\u05D5\u05EA
+SWT_Charset_Celtic=\u05E7\u05DC\u05D8\u05D9\u05EA
+SWT_Charset_Euro=\u05D0\u05D9\u05E8\u05D5
+SWT_Charset_Romanian=\u05E8\u05D5\u05DE\u05E0\u05D9\u05EA
+SWT_Charset_SimplifiedChinese=\u05E1\u05D9\u05E0\u05D9\u05EA \u05E4\u05E9\u05D5\u05D8\u05D4
+SWT_Charset_TraditionalChinese=\u05E1\u05D9\u05E0\u05D9\u05EA \u05DE\u05E1\u05D5\u05E8\u05EA\u05D9\u05EA
+SWT_Charset_Japanese=\u05D9\u05E4\u05E0\u05D9\u05EA
+SWT_Charset_Korean=\u05E7\u05D5\u05E8\u05D9\u05D0\u05E0\u05D9\u05EA
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u05E9\u05D9\u05D8\u05D5\u05EA \u05E7\u05DC\u05D8
+SWT_Password=\u05E1\u05D9\u05E1\u05DE\u05D4\:
+SWT_Username=\u05E9\u05DD \u05DE\u05E9\u05EA\u05DE\u05E9\:
+SWT_Switch=\u05D4\u05D7\u05DC\u05E4\u05D4
+SWT_Press=\u05DC\u05D7\u05D9\u05E6\u05D4
+SWT_Open=\u05E4\u05EA\u05D9\u05D7\u05D4
+SWT_Close=\u05E1\u05D2\u05D9\u05E8\u05D4
+SWT_Minimize=\u05DE\u05D6\u05E2\u05D5\u05E8
+SWT_Maximize=\u05D4\u05D2\u05D3\u05DC\u05D4
+SWT_Restore=\u05E9\u05D7\u05D6\u05D5\u05E8
+SWT_ShowList=\u05D4\u05E6\u05D2\u05EA \u05E8\u05E9\u05D9\u05DE\u05D4
+SWT_FileDownload=\u05D4\u05D5\u05E8\u05D3\u05EA \u05E7\u05D5\u05D1\u05E5
+SWT_Download_File=\u05D4\u05D5\u05E8\u05D3\u05D4\:\u200F {0}
+SWT_Download_Location={0} \u05DE\u05DE\u05D9\u05E7\u05D5\u05DD {1} \u05E0\u05E9\u05DE\u05E8 \u05DB\u05E2\u05EA
+SWT_Download_Started=\u05D4\u05D5\u05E8\u05D3\u05D4 \u05DE\u05EA\u05D1\u05E6\u05E2\u05EA...\u200F
+SWT_Download_Status=\u05D4\u05D5\u05E8\u05D3\u05D4\: {0,number,integer} \u05E7"\u05D1 \u05DE\u05EA\u05D5\u05DA {1,number,integer} \u05E7"\u05D1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ja.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=\u306F\u3044
+SWT_No=\u3044\u3044\u3048
+SWT_OK=OK
+SWT_Cancel=\u30AD\u30E3\u30F3\u30BB\u30EB
+SWT_Abort=\u4E2D\u65AD
+SWT_Retry=\u518D\u8A66\u884C
+SWT_Ignore=\u7121\u8996
+SWT_Sample=\u30B5\u30F3\u30D7\u30EB
+SWT_A_Sample_Text=\u30B5\u30F3\u30D7\u30EB\u30FB\u30C6\u30AD\u30B9\u30C8
+SWT_Selection=\u9078\u629E
+SWT_Current_Selection=\u73FE\u5728\u306E\u9078\u629E\u9805\u76EE
+SWT_Font=\u30D5\u30A9\u30F3\u30C8
+SWT_Color=\u8272
+SWT_Extended_style=\u62E1\u5F35\u30B9\u30BF\u30A4\u30EB
+SWT_Size=\u30B5\u30A4\u30BA
+SWT_Style=\u30B9\u30BF\u30A4\u30EB
+SWT_Save=\u4FDD\u7BA1
+SWT_Character_set=\u6587\u5B57\u30BB\u30C3\u30C8
+SWT_ColorDialog_Title=\u8272
+SWT_FontDialog_Title=\u30D5\u30A9\u30F3\u30C8
+SWT_FontSet=\u30D5\u30A9\u30F3\u30C8\u30FB\u30BB\u30C3\u30C8
+SWT_NewFont=\u65B0\u898F\u30D5\u30A9\u30F3\u30C8
+SWT_Remove=\u9664\u53BB
+SWT_Up=\u4E0A\u3078
+SWT_Down=\u4E0B\u3078
+SWT_Selection=\u9078\u629E
+SWT_Charset_Western=\u897F\u30E8\u30FC\u30ED\u30C3\u30D1\u8A00\u8A9E
+SWT_Charset_EastEuropean=\u6771\u30E8\u30FC\u30ED\u30C3\u30D1\u8A00\u8A9E
+SWT_Charset_SouthEuropean=\u5357\u30E8\u30FC\u30ED\u30C3\u30D1\u8A00\u8A9E
+SWT_Charset_NorthEuropean=\u5317\u30E8\u30FC\u30ED\u30C3\u30D1\u8A00\u8A9E
+SWT_Charset_Cyrillic=\u30AD\u30EA\u30EB\u6587\u5B57
+SWT_Charset_Arabic=\u30A2\u30E9\u30D3\u30A2\u8A9E
+SWT_Charset_Greek=\u30AE\u30EA\u30B7\u30E3\u8A9E
+SWT_Charset_Hebrew=\u30D8\u30D6\u30E9\u30A4\u8A9E
+SWT_Charset_Turkish=\u30C8\u30EB\u30B3\u8A9E
+SWT_Charset_Nordic=\u5317\u6B27\u30B2\u30EB\u30DE\u30F3\u7CFB\u8A00\u8A9E
+SWT_Charset_Thai=\u30BF\u30A4\u8A9E
+SWT_Charset_BalticRim=\u30D0\u30EB\u30C8\u8A9E
+SWT_Charset_Celtic=\u30B1\u30EB\u30C8\u8A9E
+SWT_Charset_Euro=\u30E6\u30FC\u30ED
+SWT_Charset_Romanian=\u30EB\u30FC\u30DE\u30CB\u30A2\u8A9E
+SWT_Charset_SimplifiedChinese=\u4E2D\u56FD\u8A9E (\u7C21\u4F53\u5B57)
+SWT_Charset_TraditionalChinese=\u4E2D\u56FD\u8A9E (\u7E41\u4F53\u5B57)
+SWT_Charset_Japanese=\u65E5\u672C\u8A9E
+SWT_Charset_Korean=\u97D3\u56FD\u8A9E
+SWT_Charset_Unicode=\u30E6\u30CB\u30B3\u30FC\u30C9
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u5165\u529B\u30E1\u30BD\u30C3\u30C9
+SWT_Password=\u30D1\u30B9\u30EF\u30FC\u30C9\:
+SWT_Username=\u30E6\u30FC\u30B6\u30FC\u540D\:
+SWT_Switch=\u5207\u308A\u66FF\u3048
+SWT_Press=\u62BC\u3059
+SWT_Open=\u958B\u304F
+SWT_Close=\u9589\u3058\u308B
+SWT_Minimize=\u6700\u5C0F\u5316
+SWT_Maximize=\u6700\u5927\u5316
+SWT_Restore=\u5FA9\u5143
+SWT_ShowList=\u30EA\u30B9\u30C8\u306E\u8868\u793A
+SWT_FileDownload=\u30D5\u30A1\u30A4\u30EB\u30FB\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9
+SWT_Download_File=\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\: {0}
+SWT_Download_Location={1} \u306E {0} \u3092\u4FDD\u7BA1\u4E2D
+SWT_Download_Started=\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u4E2D...
+SWT_Download_Status=\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\: {1,number,integer} KB \u306E\u3046\u3061 {0,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ko.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=\uC608
+SWT_No=\uC544\uB2C8\uC624
+SWT_OK=\uD655\uC778
+SWT_Cancel=\uCDE8\uC18C
+SWT_Abort=\uC911\uB2E8
+SWT_Retry=\uC7AC\uC2DC\uB3C4
+SWT_Ignore=\uBB34\uC2DC
+SWT_Sample=\uC0D8\uD50C
+SWT_A_Sample_Text=\uC0D8\uD50C \uD14D\uC2A4\uD2B8
+SWT_Selection=\uC120\uD0DD\uC0AC\uD56D
+SWT_Current_Selection=\uD604\uC7AC \uC120\uD0DD\uC0AC\uD56D
+SWT_Font=\uAE00\uAF34
+SWT_Color=\uC0C9\uC0C1
+SWT_Extended_style=\uD655\uC7A5 \uC2A4\uD0C0\uC77C
+SWT_Size=\uD06C\uAE30
+SWT_Style=\uC2A4\uD0C0\uC77C
+SWT_Save=\uC800\uC7A5
+SWT_Character_set=\uBB38\uC790 \uC138\uD2B8
+SWT_ColorDialog_Title=\uC0C9\uC0C1
+SWT_FontDialog_Title=\uAE00\uAF34
+SWT_FontSet=\uAE00\uAF34 \uC138\uD2B8
+SWT_NewFont=\uC0C8 \uAE00\uAF34
+SWT_Remove=\uC81C\uAC70
+SWT_Up=\uC704\uB85C
+SWT_Down=\uC544\uB798\uB85C
+SWT_Selection=\uC120\uD0DD\uC0AC\uD56D
+SWT_Charset_Western=\uC11C\uC720\uB7FD
+SWT_Charset_EastEuropean=\uB3D9\uC720\uB7FD
+SWT_Charset_SouthEuropean=\uB0A8\uC720\uB7FD
+SWT_Charset_NorthEuropean=\uBD81\uC720\uB7FD
+SWT_Charset_Cyrillic=\uC2DC\uB9B4\uC5B4
+SWT_Charset_Arabic=\uC544\uB78D\uC5B4
+SWT_Charset_Greek=\uADF8\uB9AC\uC2A4\uC5B4
+SWT_Charset_Hebrew=\uD5E4\uBE0C\uB8E8\uC5B4
+SWT_Charset_Turkish=\uD130\uD0A4\uC5B4
+SWT_Charset_Nordic=\uC2A4\uCE78\uB514\uB098\uBE44\uC544\uC5B4
+SWT_Charset_Thai=\uD0DC\uAD6D\uC5B4
+SWT_Charset_BalticRim=\uBC1C\uD2B8\uC5B4
+SWT_Charset_Celtic=\uCF08\uD2B8\uC5B4
+SWT_Charset_Euro=\uC720\uB85C
+SWT_Charset_Romanian=\uB8E8\uB9C8\uB2C8\uC544\uC5B4
+SWT_Charset_SimplifiedChinese=\uC911\uAD6D\uC5B4
+SWT_Charset_TraditionalChinese=\uB300\uB9CC\uC5B4
+SWT_Charset_Japanese=\uC77C\uBCF8\uC5B4
+SWT_Charset_Korean=\uD55C\uAD6D\uC5B4
+SWT_Charset_Unicode=\uC720\uB2C8\uCF54\uB4DC
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\uC785\uB825 \uBA54\uC18C\uB4DC
+SWT_Password=\uC554\uD638\:
+SWT_Username=\uC0AC\uC6A9\uC790 \uC774\uB984\:
+SWT_Switch=\uC804\uD658
+SWT_Press=\uB204\uB974\uAE30
+SWT_Open=\uC5F4\uAE30
+SWT_Close=\uB2EB\uAE30
+SWT_Minimize=\uCD5C\uC18C\uD654
+SWT_Maximize=\uCD5C\uB300\uD654
+SWT_Restore=\uBCF5\uC6D0
+SWT_ShowList=\uBAA9\uB85D \uD45C\uC2DC
+SWT_FileDownload=\uD30C\uC77C \uB2E4\uC6B4\uB85C\uB4DC
+SWT_Download_File=\uB2E4\uC6B4\uB85C\uB4DC\: {0}
+SWT_Download_Location={1}\uC5D0\uC11C {0} \uC800\uC7A5 \uC911
+SWT_Download_Started=\uB2E4\uC6B4\uB85C\uB4DC \uC911...
+SWT_Download_Status=\uB2E4\uC6B4\uB85C\uB4DC\: {0,number,integer} KB / {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_nl.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Ja
+SWT_No=Nee
+SWT_OK=OK
+SWT_Cancel=Annuleren
+SWT_Abort=Afbreken
+SWT_Retry=Opnieuw proberen
+SWT_Ignore=Negeren
+SWT_Sample=Voorbeeld
+SWT_A_Sample_Text=Een voorbeeldtekst
+SWT_Selection=Selectie
+SWT_Current_Selection=Huidige selectie
+SWT_Font=Lettertype
+SWT_Color=Kleur
+SWT_Extended_style=Uitgebreide stijl
+SWT_Size=Formaat
+SWT_Style=Opmaakprofiel
+SWT_Save=Opslaan
+SWT_Character_set=Tekenset
+SWT_ColorDialog_Title=Kleuren
+SWT_FontDialog_Title=Lettertypen
+SWT_FontSet=Lettertypeset
+SWT_NewFont=Nieuw lettertype
+SWT_Remove=Verwijderen
+SWT_Up=Omhoog
+SWT_Down=Omlaag
+SWT_Selection=Selectie
+SWT_Charset_Western=westers
+SWT_Charset_EastEuropean=oost
+SWT_Charset_SouthEuropean=zuid
+SWT_Charset_NorthEuropean=noord
+SWT_Charset_Cyrillic=Cyrillisch
+SWT_Charset_Arabic=Arabisch
+SWT_Charset_Greek=Grieks
+SWT_Charset_Hebrew=Hebreeuws
+SWT_Charset_Turkish=Turks
+SWT_Charset_Nordic=Noords
+SWT_Charset_Thai=Thai
+SWT_Charset_BalticRim=Baltisch gebied
+SWT_Charset_Celtic=Keltisch
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=Roemeens
+SWT_Charset_SimplifiedChinese=Vereenv. Chinees
+SWT_Charset_TraditionalChinese=Trad. Chinees
+SWT_Charset_Japanese=Japans
+SWT_Charset_Korean=Koreaans
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Invoermethoden
+SWT_Password=Wachtwoord\:
+SWT_Username=Gebruikersnaam\:
+SWT_Switch=Overschakelen
+SWT_Press=Drukken
+SWT_Open=Openen
+SWT_Close=Sluiten
+SWT_Minimize=Minimaliseren
+SWT_Maximize=Maximaliseren
+SWT_Restore=Herstellen
+SWT_ShowList=Lijst afbeelden
+SWT_FileDownload=Bestand downloaden
+SWT_Download_File=Downloaden\: {0}
+SWT_Download_Location={0} uit {1} opslaan
+SWT_Download_Started=Downloaden...
+SWT_Download_Status=Downloaden\: {0,number,integer} kB van {1,number,integer} kB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_no.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Ja
+SWT_No=Nei
+SWT_OK=OK
+SWT_Cancel=Avbryt
+SWT_Abort=Avbryt
+SWT_Retry=Pr\u00F8v p\u00E5 nytt
+SWT_Ignore=Ignorer
+SWT_Sample=Eksempel
+SWT_A_Sample_Text=En eksempeltekst
+SWT_Selection=Valg
+SWT_Current_Selection=Gjeldende valg
+SWT_Font=Font
+SWT_Color=Farge
+SWT_Extended_style=Utvidet stil
+SWT_Size=St\u00F8rrelse
+SWT_Style=Stil
+SWT_Save=Lagre
+SWT_Character_set=Tegnsett
+SWT_ColorDialog_Title=Farger
+SWT_FontDialog_Title=Fonter
+SWT_FontSet=Fontsett
+SWT_NewFont=Ny font
+SWT_Remove=Fjern
+SWT_Up=Opp
+SWT_Down=Ned
+SWT_Selection=Valg
+SWT_Charset_Western=vestlig
+SWT_Charset_EastEuropean=\u00F8stlig
+SWT_Charset_SouthEuropean=s\u00F8rlig
+SWT_Charset_NorthEuropean=nordlig
+SWT_Charset_Cyrillic=kyrillisk
+SWT_Charset_Arabic=arabisk
+SWT_Charset_Greek=gresk
+SWT_Charset_Hebrew=hebraisk
+SWT_Charset_Turkish=tyrkisk
+SWT_Charset_Nordic=nordisk
+SWT_Charset_Thai=thai
+SWT_Charset_BalticRim=baltisk
+SWT_Charset_Celtic=keltisk
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rumensk
+SWT_Charset_SimplifiedChinese=foren. kinesisk
+SWT_Charset_TraditionalChinese=trad. kinesisk
+SWT_Charset_Japanese=japansk
+SWT_Charset_Korean=koreansk
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Inndatametoder
+SWT_Password=Passord\:
+SWT_Username=Brukernavn\:
+SWT_Switch=Bytt
+SWT_Press=Trykk p\u00E5
+SWT_Open=\u00C5pne
+SWT_Close=Lukk
+SWT_Minimize=Minimer
+SWT_Maximize=Maksimer
+SWT_Restore=Gjenopprett
+SWT_ShowList=Vis liste
+SWT_FileDownload=Filnedlasting
+SWT_Download_File=Last ned\: {0}
+SWT_Download_Location=Lagrer {0} fra {1}
+SWT_Download_Started=Laster ned...
+SWT_Download_Status=Last ned\: {0,number,integer} kB av {1,number,integer} kB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pl.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 02:30:38 EDT 2006
+SWT_Yes=Tak
+SWT_No=Nie
+SWT_OK=OK
+SWT_Cancel=Anuluj
+SWT_Abort=Przerwij
+SWT_Retry=Pon\u00F3w
+SWT_Ignore=Ignoruj
+SWT_Sample=Przyk\u0142ad
+SWT_A_Sample_Text=Przyk\u0142adowy tekst
+SWT_Selection=Wyb\u00F3r
+SWT_Current_Selection=Bie\u017C\u0105cy wyb\u00F3r
+SWT_Font=Czcionka
+SWT_Color=Kolor
+SWT_Extended_style=Styl rozszerzony
+SWT_Size=Wielko\u015B\u0107
+SWT_Style=Styl
+SWT_Save=Zapisz
+SWT_Character_set=Zestaw znak\u00F3w
+SWT_ColorDialog_Title=Kolory
+SWT_FontDialog_Title=Czcionki
+SWT_FontSet=Zestaw czcionek
+SWT_NewFont=Nowa czcionka
+SWT_Remove=Usu\u0144
+SWT_Up=W g\u00F3r\u0119
+SWT_Down=W d\u00F3\u0142
+SWT_Selection=Wyb\u00F3r
+SWT_Charset_Western=zachodni
+SWT_Charset_EastEuropean=wschodni
+SWT_Charset_SouthEuropean=po\u0142udniowy
+SWT_Charset_NorthEuropean=p\u00F3\u0142nocny
+SWT_Charset_Cyrillic=cyrylica
+SWT_Charset_Arabic=arabski
+SWT_Charset_Greek=grecki
+SWT_Charset_Hebrew=hebrajski
+SWT_Charset_Turkish=turecki
+SWT_Charset_Nordic=nordycki
+SWT_Charset_Thai=tajski
+SWT_Charset_BalticRim=ba\u0142tycki
+SWT_Charset_Celtic=celtycki
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rumu\u0144ski
+SWT_Charset_SimplifiedChinese=chi\u0144ski uproszczony
+SWT_Charset_TraditionalChinese=chi\u0144ski tradycyjny
+SWT_Charset_Japanese=japo\u0144ski
+SWT_Charset_Korean=korea\u0144ski
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Metody wej\u015Bcia
+SWT_Password=Has\u0142o\:
+SWT_Username=Nazwa u\u017Cytkownika\:
+SWT_Switch=Prze\u0142\u0105cz
+SWT_Press=Naci\u015Bnij
+SWT_Open=Otw\u00F3rz
+SWT_Close=Zamknij
+SWT_Minimize=Minimalizuj
+SWT_Maximize=Maksymalizuj
+SWT_Restore=Odtw\u00F3rz
+SWT_ShowList=Poka\u017C list\u0119
+SWT_FileDownload=Pobieranie pliku
+SWT_Download_File=Pobierz\: {0}
+SWT_Download_Location=Zapisywanie {0} z {1}
+SWT_Download_Started=Pobieranie...
+SWT_Download_Status=Pobrano\: {0,number,integer} kB z {1,number,integer} kB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pt.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Sim
+SWT_No=N\u00E3o
+SWT_OK=OK
+SWT_Cancel=Cancelar
+SWT_Abort=Abortar
+SWT_Retry=Tentar de novo
+SWT_Ignore=Ignorar
+SWT_Sample=Exemplo
+SWT_A_Sample_Text=Exemplo de texto
+SWT_Selection=Selec\u00E7\u00E3o
+SWT_Current_Selection=Selec\u00E7\u00E3o actual
+SWT_Font=Tipo de letra
+SWT_Color=Cor
+SWT_Extended_style=Estilo alargado
+SWT_Size=Tamanho
+SWT_Style=Estilo
+SWT_Save=Guardar
+SWT_Character_set=Conjunto de caracteres
+SWT_ColorDialog_Title=Cores
+SWT_FontDialog_Title=Tipos de letra
+SWT_FontSet=Conjunto de tipos de letra
+SWT_NewFont=Novo tipo de letra
+SWT_Remove=Remover
+SWT_Up=Para cima
+SWT_Down=Para baixo
+SWT_Selection=Selec\u00E7\u00E3o
+SWT_Charset_Western=ocidental
+SWT_Charset_EastEuropean=oriental
+SWT_Charset_SouthEuropean=meridional
+SWT_Charset_NorthEuropean=setentrional
+SWT_Charset_Cyrillic=cir\u00EDlico
+SWT_Charset_Arabic=\u00E1rabe
+SWT_Charset_Greek=grego
+SWT_Charset_Hebrew=hebreu
+SWT_Charset_Turkish=turco
+SWT_Charset_Nordic=n\u00F3rdico
+SWT_Charset_Thai=tailand\u00EAs
+SWT_Charset_BalticRim=pa\u00EDses b\u00E1lticos
+SWT_Charset_Celtic=celta
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=romeno
+SWT_Charset_SimplifiedChinese=chin\u00EAs trad.
+SWT_Charset_TraditionalChinese=chin\u00EAs trad.
+SWT_Charset_Japanese=japon\u00EAs
+SWT_Charset_Korean=coreano
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=M\u00E9todos de introdu\u00E7\u00E3o de dados
+SWT_Password=Palavra-passe\:
+SWT_Username=Nome do utilizador\:
+SWT_Switch=Comutar
+SWT_Press=Premir
+SWT_Open=Abrir
+SWT_Close=Fechar
+SWT_Minimize=Minimizar
+SWT_Maximize=Maximizar
+SWT_Restore=Restaurar
+SWT_ShowList=Mostrar lista
+SWT_FileDownload=Descarregamento de ficheiros
+SWT_Download_File=Descarregar\: {0}
+SWT_Download_Location=Guardar {0} de {1}
+SWT_Download_Started=A descarregar...
+SWT_Download_Status=Descarregar\: {0,number,integer} KB de {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_pt_BR.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=Sim
+SWT_No=N\u00E3o   
+SWT_OK=OK
+SWT_Cancel=Cancelar
+SWT_Abort=Interromper
+SWT_Retry=Tentar Novamente
+SWT_Ignore=Ignorar
+SWT_Sample=Exemplo
+SWT_A_Sample_Text=Um texto de amostra
+SWT_Selection=Sele\u00E7\u00E3o
+SWT_Current_Selection=Sele\u00E7\u00E3o atual
+SWT_Font=Fonte
+SWT_Color=Cor
+SWT_Extended_style=Estilo Estendido
+SWT_Size=Tamanho
+SWT_Style=Estilo
+SWT_Save=Salvar
+SWT_Character_set=Conjunto de Caracteres
+SWT_ColorDialog_Title=Cores
+SWT_FontDialog_Title=Fontes
+SWT_FontSet=Defini\u00E7\u00E3o de Fonte
+SWT_NewFont=Nova Fonte
+SWT_Remove=Remover
+SWT_Up=Para Cima
+SWT_Down=Para Baixo
+SWT_Selection=Sele\u00E7\u00E3o
+SWT_Charset_Western=ocidental
+SWT_Charset_EastEuropean=oriental
+SWT_Charset_SouthEuropean=meridional
+SWT_Charset_NorthEuropean=setentrional
+SWT_Charset_Cyrillic=cir\u00EDlico
+SWT_Charset_Arabic=\u00E1rabe
+SWT_Charset_Greek=grego
+SWT_Charset_Hebrew=hebraico
+SWT_Charset_Turkish=turco
+SWT_Charset_Nordic=n\u00F3rdico
+SWT_Charset_Thai=tai
+SWT_Charset_BalticRim=margem b\u00E1ltica
+SWT_Charset_Celtic=celta
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=romeno
+SWT_Charset_SimplifiedChinese=chin\u00EAs simplificado
+SWT_Charset_TraditionalChinese=chin\u00EAs simplificado
+SWT_Charset_Japanese=japon\u00EAs
+SWT_Charset_Korean=coreano
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=M\u00E9todos de Entrada
+SWT_Password=Senha\:
+SWT_Username=Nome do Usu\u00E1rio\:
+SWT_Switch=Chave
+SWT_Press=Pressione
+SWT_Open=Abrir
+SWT_Close=Fechar
+SWT_Minimize=Minimizar
+SWT_Maximize=Maximizar
+SWT_Restore=Restaurar
+SWT_ShowList=Mostrar Lista
+SWT_FileDownload=Download de Arquivo
+SWT_Download_File=Download\: {0}
+SWT_Download_Location=Salvando {0} de {1}
+SWT_Download_Started=Fazendo download...
+SWT_Download_Status=Download\: {0,number,integer} KB de {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_ru.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 02:30:38 EDT 2006
+SWT_Yes=\u0414\u0430
+SWT_No=\u041D\u0435\u0442
+SWT_OK=OK
+SWT_Cancel=\u041E\u0442\u043C\u0435\u043D\u0430
+SWT_Abort=\u041F\u0440\u0435\u0440\u0432\u0430\u0442\u044C
+SWT_Retry=\u041F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C
+SWT_Ignore=\u0418\u0433\u043D\u043E\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C
+SWT_Sample=\u041F\u0440\u0438\u043C\u0435\u0440
+SWT_A_Sample_Text=\u041F\u0440\u0438\u043C\u0435\u0440 \u0442\u0435\u043A\u0441\u0442\u0430
+SWT_Selection=\u0412\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442
+SWT_Current_Selection=\u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0444\u0440\u0430\u0433\u043C\u0435\u043D\u0442
+SWT_Font=\u0428\u0440\u0438\u0444\u0442
+SWT_Color=\u0426\u0432\u0435\u0442
+SWT_Extended_style=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u043D\u044B\u0439 \u0441\u0442\u0438\u043B\u044C
+SWT_Size=\u0420\u0430\u0437\u043C\u0435\u0440
+SWT_Style=\u0421\u0442\u0438\u043B\u044C
+SWT_Save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
+SWT_Character_set=\u041A\u043E\u0434\u0438\u0440\u043E\u0432\u043A\u0430
+SWT_ColorDialog_Title=\u0426\u0432\u0435\u0442\u0430
+SWT_FontDialog_Title=\u0428\u0440\u0438\u0444\u0442\u044B
+SWT_FontSet=\u0421\u0435\u043C\u0435\u0439\u0441\u0442\u0432\u043E \u0448\u0440\u0438\u0444\u0442\u043E\u0432
+SWT_NewFont=\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0448\u0440\u0438\u0444\u0442
+SWT_Remove=\u0423\u0434\u0430\u043B\u0438\u0442\u044C
+SWT_Up=\u0412\u0432\u0435\u0440\u0445
+SWT_Down=\u0412\u043D\u0438\u0437
+SWT_Selection=\u0412\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0439 \u044D\u043B\u0435\u043C\u0435\u043D\u0442
+SWT_Charset_Western=\u0437\u0430\u043F\u0430\u0434\u043D\u043E\u0435\u0432\u0440\u043E\u043F\u0435\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_EastEuropean=\u0432\u043E\u0441\u0442\u043E\u0447\u043D\u043E\u0435\u0432\u0440\u043E\u043F\u0435\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_SouthEuropean=\u044E\u0436\u043D\u043E\u0435\u0432\u0440\u043E\u043F\u0435\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_NorthEuropean=\u0441\u0435\u0432\u0435\u0440\u043D\u043E\u0435\u0432\u0440\u043E\u043F\u0435\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_Cyrillic=\u043A\u0438\u0440\u0438\u043B\u043B\u0438\u0446\u0430
+SWT_Charset_Arabic=\u0430\u0440\u0430\u0431\u0441\u043A\u0430\u044F
+SWT_Charset_Greek=\u0433\u0440\u0435\u0447\u0435\u0441\u043A\u0430\u044F
+SWT_Charset_Hebrew=\u0438\u0432\u0440\u0438\u0442
+SWT_Charset_Turkish=\u0442\u0443\u0440\u0435\u0446\u043A\u0430\u044F
+SWT_Charset_Nordic=\u0441\u043A\u0430\u043D\u0434\u0438\u043D\u0430\u0432\u0441\u043A\u0430\u044F
+SWT_Charset_Thai=\u0442\u0430\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_BalticRim=\u0431\u0430\u043B\u0442\u0438\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_Celtic=\u043A\u0435\u043B\u044C\u0442\u0441\u043A\u0430\u044F
+SWT_Charset_Euro=\u0435\u0432\u0440\u043E
+SWT_Charset_Romanian=\u0440\u0443\u043C\u044B\u043D\u0441\u043A\u0430\u044F
+SWT_Charset_SimplifiedChinese=\u043A\u0438\u0442\u0430\u0439\u0441\u043A\u0430\u044F (\u041A\u041D\u0420) 
+SWT_Charset_TraditionalChinese=\u043A\u0438\u0442\u0430\u0439\u0441\u043A\u0430\u044F (\u0422\u0430\u0439\u0432\u0430\u043D\u044C) 
+SWT_Charset_Japanese=\u044F\u043F\u043E\u043D\u0441\u043A\u0430\u044F
+SWT_Charset_Korean=\u043A\u043E\u0440\u0435\u0439\u0441\u043A\u0430\u044F
+SWT_Charset_Unicode=\u044E\u043D\u0438\u043A\u043E\u0434
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u041C\u0435\u0442\u043E\u0434\u044B \u0432\u0432\u043E\u0434\u0430
+SWT_Password=\u041F\u0430\u0440\u043E\u043B\u044C\:
+SWT_Username=\u0418\u043C\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F\:
+SWT_Switch=\u041F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C
+SWT_Press=\u041D\u0430\u0436\u0430\u0442\u044C
+SWT_Open=\u041E\u0442\u043A\u0440\u044B\u0442\u044C
+SWT_Close=\u0417\u0430\u043A\u0440\u044B\u0442\u044C
+SWT_Minimize=\u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C
+SWT_Maximize=\u0420\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C
+SWT_Restore=\u0412\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C
+SWT_ShowList=\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0441\u043F\u0438\u0441\u043E\u043A
+SWT_FileDownload=\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0444\u0430\u0439\u043B\u0430
+SWT_Download_File=\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\: {0}
+SWT_Download_Location=\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 {0} \u0438\u0437 {1}
+SWT_Download_Started=\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430...
+SWT_Download_Status=\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\: {0,number,integer} \u0438\u0437 {1,number,integer} \u041A\u0431
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_sv.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Ja
+SWT_No=Nej
+SWT_OK=OK
+SWT_Cancel=Avbryt
+SWT_Abort=Avbryt
+SWT_Retry=F\u00F6rs\u00F6k igen
+SWT_Ignore=Ignorera
+SWT_Sample=Exempel
+SWT_A_Sample_Text=En exempeltext
+SWT_Selection=Urval
+SWT_Current_Selection=Aktuellt urval
+SWT_Font=Teckensnitt
+SWT_Color=F\u00E4rg
+SWT_Extended_style=Ut\u00F6kat format
+SWT_Size=Storlek
+SWT_Style=Format
+SWT_Save=Spara
+SWT_Character_set=Teckenupps\u00E4ttning
+SWT_ColorDialog_Title=F\u00E4rger
+SWT_FontDialog_Title=Teckensnitt
+SWT_FontSet=Teckensnittsupps\u00E4ttning
+SWT_NewFont=Nytt teckensnitt
+SWT_Remove=Ta bort
+SWT_Up=Upp
+SWT_Down=Ned
+SWT_Selection=Urval
+SWT_Charset_Western=v\u00E4steuropeiska
+SWT_Charset_EastEuropean=\u00F6steuropeiska
+SWT_Charset_SouthEuropean=sydeuropeiska
+SWT_Charset_NorthEuropean=nordeuropeiska
+SWT_Charset_Cyrillic=kyrilliska
+SWT_Charset_Arabic=arabiska
+SWT_Charset_Greek=grekiska
+SWT_Charset_Hebrew=hebreiska
+SWT_Charset_Turkish=turkiska
+SWT_Charset_Nordic=nordiska
+SWT_Charset_Thai=thail\u00E4ndska
+SWT_Charset_BalticRim=baltiska
+SWT_Charset_Celtic=keltiska
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=rum\u00E4nska
+SWT_Charset_SimplifiedChinese=f\u00F6renklad kinesiska
+SWT_Charset_TraditionalChinese=traditionell kinesiska
+SWT_Charset_Japanese=japanska
+SWT_Charset_Korean=koreanska
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Inmatningsmetoder
+SWT_Password=L\u00F6senord\:
+SWT_Username=Anv\u00E4ndarnamn\:
+SWT_Switch=V\u00E4xla
+SWT_Press=Tryck p\u00E5
+SWT_Open=\u00D6ppna
+SWT_Close=St\u00E4ng
+SWT_Minimize=Minimera
+SWT_Maximize=Maximera
+SWT_Restore=\u00C5terst\u00E4ll
+SWT_ShowList=Visa lista
+SWT_FileDownload=Filh\u00E4mtning
+SWT_Download_File=H\u00E4mtning\: {0}
+SWT_Download_Location=Spara {0} fr\u00E5n {1}
+SWT_Download_Started=H\u00E4mtar...
+SWT_Download_Status=H\u00E4mtning\: {0,number,integer} KB av {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_tr.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 03:45:44 EDT 2006
+SWT_Yes=Evet
+SWT_No=Hay\u0131r
+SWT_OK=Tamam
+SWT_Cancel=\u0130ptal
+SWT_Abort=Durdur
+SWT_Retry=Yeniden Dene
+SWT_Ignore=Yoksay
+SWT_Sample=\u00D6rnek
+SWT_A_Sample_Text=\u00D6rnek Metin
+SWT_Selection=Se\u00E7im
+SWT_Current_Selection=Y\u00FCr\u00FCrl\u00FCkteki Se\u00E7im
+SWT_Font=Yaz\u0131y\u00FCz\u00FC
+SWT_Color=Renk
+SWT_Extended_style=Ek Bi\u00E7em
+SWT_Size=B\u00FCy\u00FCkl\u00FCk
+SWT_Style=Bi\u00E7em
+SWT_Save=Sakla
+SWT_Character_set=Karakter k\u00FCmesi
+SWT_ColorDialog_Title=Renkler
+SWT_FontDialog_Title=Yaz\u0131y\u00FCzleri
+SWT_FontSet=Yaz\u0131y\u00FCz\u00FC K\u00FCmesi
+SWT_NewFont=Yeni Yaz\u0131y\u00FCz\u00FC
+SWT_Remove=Kald\u0131r
+SWT_Up=Yukar\u0131
+SWT_Down=A\u015Fa\u011F\u0131
+SWT_Selection=Se\u00E7im
+SWT_Charset_Western=bat\u0131
+SWT_Charset_EastEuropean=do\u011Fu
+SWT_Charset_SouthEuropean=g\u00FCney
+SWT_Charset_NorthEuropean=kuzey
+SWT_Charset_Cyrillic=kiril
+SWT_Charset_Arabic=arap\u00E7a
+SWT_Charset_Greek=yunanca
+SWT_Charset_Hebrew=ibranice
+SWT_Charset_Turkish=t\u00FCrk\u00E7e
+SWT_Charset_Nordic=kuzey avrupa dilleri
+SWT_Charset_Thai=tay
+SWT_Charset_BalticRim=balt\u0131k
+SWT_Charset_Celtic=kelt
+SWT_Charset_Euro=euro
+SWT_Charset_Romanian=romence
+SWT_Charset_SimplifiedChinese=yal\u0131n. \u00E7ince
+SWT_Charset_TraditionalChinese=gelenk. \u00E7ince
+SWT_Charset_Japanese=japonca
+SWT_Charset_Korean=korece
+SWT_Charset_Unicode=unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=Giri\u015F Y\u00F6ntemleri
+SWT_Password=Parola\:
+SWT_Username=Kullan\u0131c\u0131 Ad\u0131\:
+SWT_Switch=Ge\u00E7
+SWT_Press=Bas
+SWT_Open=A\u00E7
+SWT_Close=Kapat
+SWT_Minimize=Simge Durumuna K\u00FC\u00E7\u00FClt
+SWT_Maximize=Ekran Boyutuna Getir
+SWT_Restore=Geri Y\u00FCkle
+SWT_ShowList=Listeyi G\u00F6ster
+SWT_FileDownload=Dosya A\u015Fa\u011F\u0131 Y\u00FCkle
+SWT_Download_File=A\u015Fa\u011F\u0131 y\u00FCkle\: {0}
+SWT_Download_Location={0} saklan\u0131yor ({1})
+SWT_Download_Started=A\u015Fa\u011F\u0131 y\u00FCkleniyor...
+SWT_Download_Status=A\u015Fa\u011F\u0131 y\u00FCkle\: {0,number,integer} KB / {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=\u662F
+SWT_No=\u5426
+SWT_OK=\u786E\u5B9A
+SWT_Cancel=\u53D6\u6D88
+SWT_Abort=\u653E\u5F03
+SWT_Retry=\u91CD\u8BD5
+SWT_Ignore=\u5FFD\u7565
+SWT_Sample=\u6837\u672C
+SWT_A_Sample_Text=\u6837\u672C\u6587\u672C
+SWT_Selection=\u6240\u9009\u9879
+SWT_Current_Selection=\u5F53\u524D\u9009\u62E9
+SWT_Font=\u5B57\u4F53
+SWT_Color=\u989C\u8272
+SWT_Extended_style=\u6269\u5C55\u6837\u5F0F
+SWT_Size=\u5927\u5C0F
+SWT_Style=\u6837\u5F0F
+SWT_Save=\u4FDD\u5B58
+SWT_Character_set=\u5B57\u7B26\u96C6
+SWT_ColorDialog_Title=\u989C\u8272
+SWT_FontDialog_Title=\u5B57\u4F53
+SWT_FontSet=\u5B57\u4F53\u96C6
+SWT_NewFont=\u65B0\u5B57\u4F53
+SWT_Remove=\u9664\u53BB
+SWT_Up=\u4E0A\u79FB
+SWT_Down=\u4E0B\u79FB
+SWT_Selection=\u6240\u9009\u9879
+SWT_Charset_Western=\u897F\u65B9
+SWT_Charset_EastEuropean=\u4E1C\u6B27
+SWT_Charset_SouthEuropean=\u5357\u6B27
+SWT_Charset_NorthEuropean=\u5317\u6B27
+SWT_Charset_Cyrillic=Cyrillic
+SWT_Charset_Arabic=\u963F\u62C9\u4F2F\u8BED
+SWT_Charset_Greek=\u5E0C\u814A\u8BED
+SWT_Charset_Hebrew=\u5E0C\u4F2F\u83B1\u8BED
+SWT_Charset_Turkish=\u571F\u8033\u5176\u8BED
+SWT_Charset_Nordic=\u65E5\u8033\u66FC\u8BED
+SWT_Charset_Thai=\u6CF0\u56FD\u8BED
+SWT_Charset_BalticRim=\u6CBF\u6CE2\u7F57\u7684\u6D77\u8BED
+SWT_Charset_Celtic=\u51EF\u5C14\u7279\u8BED
+SWT_Charset_Euro=\u6B27\u5143\u7B26\u53F7
+SWT_Charset_Romanian=\u7F57\u9A6C\u5C3C\u4E9A\u8BED
+SWT_Charset_SimplifiedChinese=\u7B80\u4F53\u4E2D\u6587
+SWT_Charset_TraditionalChinese=\u7E41\u4F53\u4E2D\u6587
+SWT_Charset_Japanese=\u65E5\u8BED
+SWT_Charset_Korean=\u97E9\u56FD\u8BED
+SWT_Charset_Unicode=Unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u8F93\u5165\u65B9\u6CD5
+SWT_Password=\u5BC6\u7801\uFF1A
+SWT_Username=\u7528\u6237\u540D\uFF1A
+SWT_Switch=\u5207\u6362
+SWT_Press=\u6309
+SWT_Open=\u6253\u5F00
+SWT_Close=\u5173\u95ED
+SWT_Minimize=\u6700\u5C0F\u5316
+SWT_Maximize=\u6700\u5927\u5316
+SWT_Restore=\u6062\u590D
+SWT_ShowList=\u663E\u793A\u5217\u8868
+SWT_FileDownload=\u6587\u4EF6\u4E0B\u8F7D
+SWT_Download_File=\u4E0B\u8F7D\uFF1A{0}
+SWT_Download_Location=\u6B63\u5728\u4FDD\u5B58 {1} \u4E2D\u7684 {0}
+SWT_Download_Started=\u6B63\u5728\u4E0B\u8F7D...
+SWT_Download_Status=\u4E0B\u8F7D\uFF1A{0,number,integer} KB\uFF0C\u603B\u5171 {1,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh_HK.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=\u662F
+SWT_No=\u5426
+SWT_OK=\u78BA\u5B9A
+SWT_Cancel=\u53D6\u6D88
+SWT_Abort=\u4E2D\u6B62
+SWT_Retry=\u91CD\u8A66
+SWT_Ignore=\u5FFD\u7565
+SWT_Sample=\u7BC4\u4F8B
+SWT_A_Sample_Text=\u6A23\u672C\u6587\u5B57
+SWT_Selection=\u9078\u53D6
+SWT_Current_Selection=\u76EE\u524D\u6240\u9078\u7684\u9805\u76EE
+SWT_Font=\u5B57\u578B
+SWT_Color=\u984F\u8272
+SWT_Extended_style=\u64F4\u5145\u6A23\u5F0F
+SWT_Size=\u5927\u5C0F
+SWT_Style=\u6A23\u5F0F
+SWT_Save=\u5132\u5B58
+SWT_Character_set=\u5B57\u96C6
+SWT_ColorDialog_Title=\u984F\u8272
+SWT_FontDialog_Title=\u5B57\u578B
+SWT_FontSet=\u5B57\u578B\u8A2D\u5B9A
+SWT_NewFont=\u65B0\u5EFA\u5B57\u578B
+SWT_Remove=\u79FB\u9664
+SWT_Up=\u4E0A
+SWT_Down=\u4E0B
+SWT_Selection=\u9078\u53D6
+SWT_Charset_Western=\u897F\u6B50
+SWT_Charset_EastEuropean=\u6771\u6B50
+SWT_Charset_SouthEuropean=\u5357\u6B50
+SWT_Charset_NorthEuropean=\u5317\u6B50
+SWT_Charset_Cyrillic=\u65AF\u62C9\u592B\u6587
+SWT_Charset_Arabic=\u963F\u62C9\u4F2F\u6587
+SWT_Charset_Greek=\u5E0C\u81D8\u6587
+SWT_Charset_Hebrew=\u5E0C\u4F2F\u4F86\u6587
+SWT_Charset_Turkish=\u571F\u8033\u5176\u6587
+SWT_Charset_Nordic=\u65AF\u582A\u7684\u7D0D\u7DAD\u4E9E\u8A9E
+SWT_Charset_Thai=\u6CF0\u6587
+SWT_Charset_BalticRim=\u6CE2\u7F85\u7684\u6D77\u5468\u570D\u570B\u5BB6
+SWT_Charset_Celtic=\u51F1\u723E\u7279\u8A9E
+SWT_Charset_Euro=\u6B50\u6D32
+SWT_Charset_Romanian=\u7F85\u99AC\u5C3C\u4E9E\u6587
+SWT_Charset_SimplifiedChinese=\u7C21\u9AD4\u4E2D\u6587
+SWT_Charset_TraditionalChinese=\u7E41\u9AD4\u4E2D\u6587
+SWT_Charset_Japanese=\u65E5\u6587
+SWT_Charset_Korean=\u97D3\u6587
+SWT_Charset_Unicode=Unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u8F38\u5165\u65B9\u6CD5
+SWT_Password=\u5BC6\u78BC\uFF1A
+SWT_Username=\u4F7F\u7528\u8005\u540D\u7A31\uFF1A
+SWT_Switch=\u5207\u63DB
+SWT_Press=\u6309
+SWT_Open=\u958B\u555F
+SWT_Close=\u95DC\u9589
+SWT_Minimize=\u6700\u5C0F\u5316
+SWT_Maximize=\u6700\u5927\u5316
+SWT_Restore=\u9084\u539F
+SWT_ShowList=\u986F\u793A\u6E05\u55AE
+SWT_FileDownload=\u6A94\u6848\u4E0B\u8F09
+SWT_Download_File=\u4E0B\u8F09\uFF1A{0}
+SWT_Download_Location=\u6B63\u5728\u5F9E {1} \u5132\u5B58 {0}
+SWT_Download_Started=\u6B63\u5728\u4E0B\u8F09...
+SWT_Download_Status=\u4E0B\u8F09\uFF1A{1,number,integer} KB \u4E2D\u7684 {0,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/res/swt.internal.SWTMessages_zh_TW.properties	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+#Thu Jun 22 01:01:55 EDT 2006
+SWT_Yes=\u662F
+SWT_No=\u5426
+SWT_OK=\u78BA\u5B9A
+SWT_Cancel=\u53D6\u6D88
+SWT_Abort=\u4E2D\u6B62
+SWT_Retry=\u91CD\u8A66
+SWT_Ignore=\u5FFD\u7565
+SWT_Sample=\u7BC4\u4F8B
+SWT_A_Sample_Text=\u6A23\u672C\u6587\u5B57
+SWT_Selection=\u9078\u53D6
+SWT_Current_Selection=\u76EE\u524D\u6240\u9078\u7684\u9805\u76EE
+SWT_Font=\u5B57\u578B
+SWT_Color=\u984F\u8272
+SWT_Extended_style=\u64F4\u5145\u6A23\u5F0F
+SWT_Size=\u5927\u5C0F
+SWT_Style=\u6A23\u5F0F
+SWT_Save=\u5132\u5B58
+SWT_Character_set=\u5B57\u96C6
+SWT_ColorDialog_Title=\u984F\u8272
+SWT_FontDialog_Title=\u5B57\u578B
+SWT_FontSet=\u5B57\u578B\u8A2D\u5B9A
+SWT_NewFont=\u65B0\u5EFA\u5B57\u578B
+SWT_Remove=\u79FB\u9664
+SWT_Up=\u4E0A
+SWT_Down=\u4E0B
+SWT_Selection=\u9078\u53D6
+SWT_Charset_Western=\u897F\u6B50
+SWT_Charset_EastEuropean=\u6771\u6B50
+SWT_Charset_SouthEuropean=\u5357\u6B50
+SWT_Charset_NorthEuropean=\u5317\u6B50
+SWT_Charset_Cyrillic=\u65AF\u62C9\u592B\u6587
+SWT_Charset_Arabic=\u963F\u62C9\u4F2F\u6587
+SWT_Charset_Greek=\u5E0C\u81D8\u6587
+SWT_Charset_Hebrew=\u5E0C\u4F2F\u4F86\u6587
+SWT_Charset_Turkish=\u571F\u8033\u5176\u6587
+SWT_Charset_Nordic=\u65AF\u582A\u7684\u7D0D\u7DAD\u4E9E\u8A9E
+SWT_Charset_Thai=\u6CF0\u6587
+SWT_Charset_BalticRim=\u6CE2\u7F85\u7684\u6D77\u5468\u570D\u570B\u5BB6
+SWT_Charset_Celtic=\u51F1\u723E\u7279\u8A9E
+SWT_Charset_Euro=\u6B50\u6D32
+SWT_Charset_Romanian=\u7F85\u99AC\u5C3C\u4E9E\u6587
+SWT_Charset_SimplifiedChinese=\u7C21\u9AD4\u4E2D\u6587
+SWT_Charset_TraditionalChinese=\u7E41\u9AD4\u4E2D\u6587
+SWT_Charset_Japanese=\u65E5\u6587
+SWT_Charset_Korean=\u97D3\u6587
+SWT_Charset_Unicode=Unicode
+SWT_Charset_ASCII=ASCII
+SWT_InputMethods=\u8F38\u5165\u65B9\u6CD5
+SWT_Password=\u5BC6\u78BC\uFF1A
+SWT_Username=\u4F7F\u7528\u8005\u540D\u7A31\uFF1A
+SWT_Switch=\u5207\u63DB
+SWT_Press=\u6309
+SWT_Open=\u958B\u555F
+SWT_Close=\u95DC\u9589
+SWT_Minimize=\u6700\u5C0F\u5316
+SWT_Maximize=\u6700\u5927\u5316
+SWT_Restore=\u9084\u539F
+SWT_ShowList=\u986F\u793A\u6E05\u55AE
+SWT_FileDownload=\u6A94\u6848\u4E0B\u8F09
+SWT_Download_File=\u4E0B\u8F09\uFF1A{0}
+SWT_Download_Location=\u6B63\u5728\u5F9E {1} \u5132\u5B58 {0}
+SWT_Download_Started=\u6B63\u5728\u4E0B\u8F09...
+SWT_Download_Status=\u4E0B\u8F09\uFF1A{1,number,integer} KB \u4E2D\u7684 {0,number,integer} KB
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWT.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3849 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D Programming language:
+ *      Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.SWT;
+
+
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.Library;
+import org.eclipse.swt.internal.Platform;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+
+import tango.core.Exception;
+import java.lang.all;
+
+version(build){
+    pragma(link, "advapi32");
+    pragma(link, "comctl32");
+    pragma(link, "comdlg32");
+    pragma(link, "gdi32");
+    pragma(link, "kernel32");
+    pragma(link, "shell32");
+    pragma(link, "ole32");
+    pragma(link, "oleaut32");
+    pragma(link, "olepro32");
+    pragma(link, "oleacc");
+    pragma(link, "user32");
+    pragma(link, "usp10");
+    pragma(link, "msimg32");
+    pragma(link, "opengl32");
+    pragma(link, "shlwapi");
+    //pragma(link, "gdiplus"); // load dynamic
+    //pragma(link, "uxtheme"); // load dynamic
+}
+
+/**
+ * This class provides access to a small number of SWT system-wide
+ * methods, and in addition defines the public constants provided
+ * by SWT.
+ * <p>
+ * By defining constants like UP and DOWN in a single class, SWT
+ * can share common names and concepts at the same time minimizing
+ * the number of classes, names and constants for the application
+ * programmer.
+ * </p><p>
+ * Note that some of the constants provided by this class represent
+ * optional, appearance related aspects of widgets which are available
+ * either only on some window systems, or for a differing set of
+ * widgets on each window system. These constants are marked
+ * as <em>HINT</em>s. The set of widgets which support a particular
+ * <em>HINT</em> may change from release to release, although we typically
+ * will not withdraw support for a <em>HINT</em> once it is made available.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+/* NOTE:
+ *   Good javadoc coding style is to put the values of static const
+ *   constants in the comments. This reinforces the fact that
+ *   consumers are allowed to rely on the value (and they must
+ *   since the values are compiled inline in their code). We
+ *   can <em>not</em> change the values of these constants between
+ *   releases.
+ */
+public class SWT {
+
+    /* Widget Event Constants */
+
+    /**
+     * The null event type (value is 0).
+     *
+     * @since 3.0
+     */
+    public static const int None = 0;
+
+    /**
+     * The key down event type (value is 1).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addKeyListener
+     * @see org.eclipse.swt.widgets.Tracker#addKeyListener
+     * @see org.eclipse.swt.events.KeyListener#keyPressed
+     * @see org.eclipse.swt.events.KeyEvent
+     */
+    public static const int KeyDown = 1;
+
+    /**
+     * The key up event type (value is 2).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addKeyListener
+     * @see org.eclipse.swt.widgets.Tracker#addKeyListener
+     * @see org.eclipse.swt.events.KeyListener#keyReleased
+     * @see org.eclipse.swt.events.KeyEvent
+     */
+    public static const int KeyUp = 2;
+
+    /**
+     * The mouse down event type (value is 3).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseListener
+     * @see org.eclipse.swt.events.MouseListener#mouseDown
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseDown = 3;
+
+    /**
+     * The mouse up event type (value is 4).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseListener
+     * @see org.eclipse.swt.events.MouseListener#mouseUp
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseUp = 4;
+
+    /**
+     * The mouse move event type (value is 5).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseMoveListener
+     * @see org.eclipse.swt.events.MouseMoveListener#mouseMove
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseMove = 5;
+
+    /**
+     * The mouse enter event type (value is 6).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseTrackListener
+     * @see org.eclipse.swt.events.MouseTrackListener#mouseEnter
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseEnter = 6;
+
+    /**
+     * The mouse exit event type (value is 7).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseTrackListener
+     * @see org.eclipse.swt.events.MouseTrackListener#mouseExit
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseExit = 7;
+
+    /**
+     * The mouse double click event type (value is 8).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseListener
+     * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseDoubleClick = 8;
+
+    /**
+     * The paint event type (value is 9).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addPaintListener
+     * @see org.eclipse.swt.events.PaintListener#paintControl
+     * @see org.eclipse.swt.events.PaintEvent
+     */
+    public static const int Paint = 9;
+
+    /**
+     * The move event type (value is 10).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addControlListener
+     * @see org.eclipse.swt.widgets.TableColumn#addControlListener
+     * @see org.eclipse.swt.widgets.Tracker#addControlListener
+     * @see org.eclipse.swt.widgets.TreeColumn#addControlListener
+     * @see org.eclipse.swt.events.ControlListener#controlMoved
+     * @see org.eclipse.swt.events.ControlEvent
+     */
+    public static const int Move = 10;
+
+    /**
+     * The resize event type (value is 11).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addControlListener
+     * @see org.eclipse.swt.widgets.TableColumn#addControlListener
+     * @see org.eclipse.swt.widgets.Tracker#addControlListener
+     * @see org.eclipse.swt.widgets.TreeColumn#addControlListener
+     * @see org.eclipse.swt.events.ControlListener#controlResized
+     * @see org.eclipse.swt.events.ControlEvent
+     */
+    public static const int Resize = 11;
+
+    /**
+     * The dispose event type (value is 12).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Widget#addDisposeListener
+     * @see org.eclipse.swt.events.DisposeListener#widgetDisposed
+     * @see org.eclipse.swt.events.DisposeEvent
+     */
+    public static const int Dispose = 12;
+
+    /**
+     * The selection event type (value is 13).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Button#addSelectionListener
+     * @see org.eclipse.swt.widgets.Combo#addSelectionListener
+     * @see org.eclipse.swt.widgets.CoolItem#addSelectionListener
+     * @see org.eclipse.swt.widgets.Link#addSelectionListener
+     * @see org.eclipse.swt.widgets.List#addSelectionListener
+     * @see org.eclipse.swt.widgets.MenuItem#addSelectionListener
+     * @see org.eclipse.swt.widgets.Sash#addSelectionListener
+     * @see org.eclipse.swt.widgets.Scale#addSelectionListener
+     * @see org.eclipse.swt.widgets.ScrollBar#addSelectionListener
+     * @see org.eclipse.swt.widgets.Slider#addSelectionListener
+     * @see org.eclipse.swt.widgets.TabFolder#addSelectionListener
+     * @see org.eclipse.swt.widgets.Table#addSelectionListener
+     * @see org.eclipse.swt.widgets.TableColumn#addSelectionListener
+     * @see org.eclipse.swt.widgets.ToolItem#addSelectionListener
+     * @see org.eclipse.swt.widgets.TrayItem#addSelectionListener
+     * @see org.eclipse.swt.widgets.Tree#addSelectionListener
+     * @see org.eclipse.swt.widgets.TreeColumn#addSelectionListener
+     * @see org.eclipse.swt.events.SelectionListener#widgetSelected
+     * @see org.eclipse.swt.events.SelectionEvent
+     */
+    public static const int Selection = 13;
+
+    /**
+     * The default selection event type (value is 14).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Combo#addSelectionListener
+     * @see org.eclipse.swt.widgets.List#addSelectionListener
+     * @see org.eclipse.swt.widgets.Spinner#addSelectionListener
+     * @see org.eclipse.swt.widgets.Table#addSelectionListener
+     * @see org.eclipse.swt.widgets.Text#addSelectionListener
+     * @see org.eclipse.swt.widgets.TrayItem#addSelectionListener
+     * @see org.eclipse.swt.widgets.Tree#addSelectionListener
+     * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected
+     * @see org.eclipse.swt.events.SelectionEvent
+     */
+    public static const int DefaultSelection = 14;
+
+    /**
+     * The focus in event type (value is 15).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addFocusListener
+     * @see org.eclipse.swt.events.FocusListener#focusGained
+     * @see org.eclipse.swt.events.FocusEvent
+     */
+    public static const int FocusIn = 15;
+
+    /**
+     * The focus out event type (value is 16).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addFocusListener
+     * @see org.eclipse.swt.events.FocusListener#focusLost
+     * @see org.eclipse.swt.events.FocusEvent
+     */
+    public static const int FocusOut = 16;
+
+    /**
+     * The expand event type (value is 17).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Tree#addTreeListener
+     * @see org.eclipse.swt.events.TreeListener#treeExpanded
+     * @see org.eclipse.swt.events.TreeEvent
+     */
+    public static const int Expand = 17;
+
+    /**
+     * The collapse event type (value is 18).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Tree#addTreeListener
+     * @see org.eclipse.swt.events.TreeListener#treeCollapsed
+     * @see org.eclipse.swt.events.TreeEvent
+     */
+    public static const int Collapse = 18;
+
+    /**
+     * The iconify event type (value is 19).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Shell#addShellListener
+     * @see org.eclipse.swt.events.ShellListener#shellIconified
+     * @see org.eclipse.swt.events.ShellEvent
+     */
+    public static const int Iconify = 19;
+
+    /**
+     * The de-iconify event type (value is 20).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Shell#addShellListener
+     * @see org.eclipse.swt.events.ShellListener#shellDeiconified
+     * @see org.eclipse.swt.events.ShellEvent
+     */
+    public static const int Deiconify = 20;
+
+    /**
+     * The close event type (value is 21).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Shell#addShellListener
+     * @see org.eclipse.swt.events.ShellListener#shellClosed
+     * @see org.eclipse.swt.events.ShellEvent
+     */
+    public static const int Close = 21;
+
+    /**
+     * The show event type (value is 22).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Menu#addMenuListener
+     * @see org.eclipse.swt.events.MenuListener#menuShown
+     * @see org.eclipse.swt.events.MenuEvent
+     */
+    public static const int Show = 22;
+
+    /**
+     * The hide event type (value is 23).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Menu#addMenuListener
+     * @see org.eclipse.swt.events.MenuListener#menuHidden
+     * @see org.eclipse.swt.events.MenuEvent
+     */
+    public static const int Hide = 23;
+
+    /**
+     * The modify event type (value is 24).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Combo#addModifyListener
+     * @see org.eclipse.swt.widgets.Spinner#addModifyListener
+     * @see org.eclipse.swt.widgets.Text#addModifyListener
+     * @see org.eclipse.swt.events.ModifyListener#modifyText
+     * @see org.eclipse.swt.events.ModifyEvent
+     */
+    public static const int Modify = 24;
+
+    /**
+     * The verify event type (value is 25).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.custom.CCombo#addVerifyListener
+     * @see org.eclipse.swt.widgets.Combo#addVerifyListener
+     * @see org.eclipse.swt.custom.StyledText#addVerifyListener
+     * @see org.eclipse.swt.widgets.Text#addVerifyListener
+     * @see org.eclipse.swt.events.VerifyListener#verifyText
+     * @see org.eclipse.swt.events.VerifyEvent
+     */
+    public static const int Verify = 25;
+
+    /**
+     * The activate event type (value is 26).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Shell#addShellListener
+     * @see org.eclipse.swt.events.ShellListener#shellActivated
+     * @see org.eclipse.swt.events.ShellEvent
+     */
+    public static const int Activate = 26;
+
+    /**
+     * The deactivate event type (value is 27).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Shell#addShellListener
+     * @see org.eclipse.swt.events.ShellListener#shellDeactivated
+     * @see org.eclipse.swt.events.ShellEvent
+     */
+    public static const int Deactivate = 27;
+
+    /**
+     * The help event type (value is 28).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addHelpListener
+     * @see org.eclipse.swt.widgets.Menu#addHelpListener
+     * @see org.eclipse.swt.widgets.MenuItem#addHelpListener
+     * @see org.eclipse.swt.events.HelpListener#helpRequested
+     * @see org.eclipse.swt.events.HelpEvent
+     */
+    public static const int Help = 28;
+
+    /**
+     * The drag detect event type (value is 29).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.dnd.DragSource
+     */
+    public static const int DragDetect = 29;
+
+    /**
+     * The arm event type (value is 30).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.MenuItem#addArmListener
+     * @see org.eclipse.swt.events.ArmListener#widgetArmed
+     * @see org.eclipse.swt.events.ArmEvent
+     */
+    public static const int Arm = 30;
+
+    /**
+     * The traverse event type (value is 31).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addTraverseListener
+     * @see org.eclipse.swt.events.TraverseListener#keyTraversed
+     * @see org.eclipse.swt.events.TraverseEvent
+     */
+    public static const int Traverse = 31;
+
+    /**
+     * The mouse hover event type (value is 32).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Control#addMouseTrackListener
+     * @see org.eclipse.swt.events.MouseTrackListener#mouseHover
+     * @see org.eclipse.swt.events.MouseEvent
+     */
+    public static const int MouseHover = 32;
+
+    /**
+     * The hardware key down event type (value is 33).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     */
+    public static const int HardKeyDown = 33;
+
+    /**
+     * The hardware key up event type (value is 34).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     */
+    public static const int HardKeyUp = 34;
+
+    /**
+     * The menu detect event type (value is 35).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.0
+     */
+    public static const int MenuDetect = 35;
+
+    /**
+     * The set data event type (value is 36).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @see org.eclipse.swt.widgets.Table
+     * @see org.eclipse.swt.widgets.Tree
+     *
+     * @since 3.0
+     */
+    public static const int SetData = 36;
+
+    /**
+     * The mouse wheel event type (value is 37).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.1
+     */
+    public static const int MouseWheel = 37;
+
+    /**
+     * The settings changed event type (value is 39).
+     * <p>
+     * The settings changed event is sent when an operating system
+     * property, such as a system font or color, has been changed.
+     * The event occurs after the property has been changed, but
+     * before any widget is redrawn.  Applications that cache operating
+     * system properties can use this event to update their caches.
+     * A specific property change can be detected by querying the
+     * new value of a property and comparing it with the equivalent
+     * cached value.  The operating system automatically redraws and
+     * lays out all widgets after this event is sent.
+     * </p>
+     *
+     * @see org.eclipse.swt.widgets.Display#addListener
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.2
+     */
+    public static const int Settings = 39;
+
+    /**
+     * The erase item event type (value is 40).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.2
+     */
+    public static const int EraseItem = 40;
+
+    /**
+     * The measure item event type (value is 41).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.2
+     */
+    public static const int MeasureItem = 41;
+
+    /**
+     * The paint item event type (value is 42).
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.widgets.Event
+     *
+     * @since 3.2
+     */
+    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 SWT#COMPOSITION_CHANGED}</li>
+     * <li>{@link SWT#COMPOSITION_OFFSET}</li>
+     * <li>{@link SWT#COMPOSITION_SELECTION}</li>
+     * </ul></p>
+     *
+     * @see org.eclipse.swt.widgets.Widget#addListener
+     * @see org.eclipse.swt.widgets.Display#addFilter
+     * @see org.eclipse.swt.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 SWT#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 SWT#ImeComposition
+     * @see org.eclipse.swt.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 SWT#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).
+     */
+    public static const int DRAG = 1;
+
+    /**
+     * Event detail field that indicates a user-interface component
+     * state is selected (value is 1&lt;&lt;1).
+     *
+     * @since 3.2
+     */
+    public static const int SELECTED = 1 << 1;
+
+    /**
+     * Event detail field that indicates a user-interface component
+     * state is focused (value is 1&lt;&lt;2).
+     *
+     * @since 3.2
+     */
+    public static const int FOCUSED = 1 << 2;
+
+    /**
+     * Event detail field that indicates a user-interface component
+     * draws the background (value is 1&lt;&lt;3).
+     *
+     * @since 3.2
+     */
+    public static const int BACKGROUND = 1 << 3;
+
+    /**
+     * Event detail field that indicates a user-interface component
+     * draws the foreground (value is 1&lt;&lt;4).
+     *
+     * @since 3.2
+     */
+    public static const int FOREGROUND = 1 << 4;
+
+    /**
+     * Event detail field that indicates a user-interface component
+     * state is hot (value is 1&lt;&lt;5).
+     *
+     * @since 3.3
+     */
+    public static const int HOT = 1 << 5;
+
+    /* This code is intentionally commented */
+    //public static const int PRESSED = 1 << 3;
+    //public static const int ACTIVE = 1 << 4;
+    //public static const int DISABLED = 1 << 5;
+    //public static const int HOT = 1 << 6;
+    //public static const int DEFAULTED = 1 << 7;
+
+    /**
+     * Traversal event detail field value indicating that no
+     * traversal action should be taken
+     * (value is 0).
+     */
+    public static const int TRAVERSE_NONE = 0;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that a dialog should be cancelled was
+     * pressed; typically, this is the ESC key
+     * (value is 1&lt;&lt;1).
+     */
+    public static const int TRAVERSE_ESCAPE = 1 << 1;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which activates the default button in a dialog was
+     * pressed; typically, this is the ENTER key
+     * (value is 1&lt;&lt;2).
+     */
+    public static const int TRAVERSE_RETURN = 1 << 2;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that focus should be given to the
+     * previous tab group was pressed; typically, this is the
+     * SHIFT-TAB key sequence
+     * (value is 1&lt;&lt;3).
+     */
+    public static const int TRAVERSE_TAB_PREVIOUS = 1 << 3;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that focus should be given to the
+     * next tab group was pressed; typically, this is the
+     * TAB key
+     * (value is 1&lt;&lt;4).
+     */
+    public static const int TRAVERSE_TAB_NEXT = 1 << 4;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that focus should be given to the
+     * previous tab item was pressed; typically, this is either
+     * the LEFT-ARROW or UP-ARROW keys
+     * (value is 1&lt;&lt;5).
+     */
+    public static const int TRAVERSE_ARROW_PREVIOUS = 1 << 5;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that focus should be given to the
+     * previous tab item was pressed; typically, this is either
+     * the RIGHT-ARROW or DOWN-ARROW keys
+     * (value is 1&lt;&lt;6).
+     */
+    public static const int TRAVERSE_ARROW_NEXT = 1 << 6;
+
+    /**
+     * Traversal event detail field value indicating that a
+     * mnemonic key sequence was pressed
+     * (value is 1&lt;&lt;7).
+     */
+    public static const int TRAVERSE_MNEMONIC = 1 << 7;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that the previous page of a multi-page
+     * window should be shown was pressed; typically, this
+     * is the CTRL-PAGEUP key sequence
+     * (value is 1&lt;&lt;8).
+     */
+    public static const int TRAVERSE_PAGE_PREVIOUS = 1 << 8;
+
+    /**
+     * Traversal event detail field value indicating that the
+     * key which designates that the next page of a multi-page
+     * window should be shown was pressed; typically, this
+     * is the CTRL-PAGEDOWN key sequence
+     * (value is 1&lt;&lt;9).
+     */
+    public static const int TRAVERSE_PAGE_NEXT = 1 << 9;
+
+    /**
+     * A constant known to be zero (0), typically used in operations
+     * which take bit flags to indicate that "no bits are set".
+     */
+    public static const int NONE = 0;
+
+    /**
+     * A constant known to be zero (0), used in operations which
+     * take pointers to indicate a null argument.
+     */
+    public static const int NULL = 0;
+
+    /**
+     * Indicates that a default should be used (value is -1).
+     */
+    public static const int DEFAULT = -1;
+
+    /**
+     * Indicates that a property is off (value is 0).
+     *
+     * @since 3.1
+     */
+    public static const int OFF = 0;
+
+    /**
+     * Indicates that a property is on (value is 1).
+     *
+     * @since 3.1
+     */
+    public static const int ON = 1;
+
+    /**
+     * Indicates low quality (value is 1).
+     *
+     * @since 3.1
+     */
+    public static const int LOW = 1;
+
+    /**
+     * Indicates high quality (value is 2).
+     *
+     * @since 3.1
+     */
+    public static const int HIGH = 2;
+
+    /**
+     * Style constant for menu bar behavior (value is 1&lt;&lt;1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Menu</code></li>
+     * </ul></p>
+     */
+    public static const int BAR = 1 << 1;
+
+    /**
+     * Style constant for drop down menu/list behavior (value is 1&lt;&lt;2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Menu</code></li>
+     * <li><code>ToolItem</code></li>
+     * <li><code>CoolItem</code></li>
+     * <li><code>Combo</code></li>
+     * </ul></p>
+     */
+    public static const int DROP_DOWN = 1 << 2;
+
+    /**
+     * Style constant for pop up menu behavior (value is 1&lt;&lt;3).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Menu</code></li>
+     * </ul></p>
+     */
+    public static const int POP_UP = 1 << 3;
+
+    /**
+     * Style constant for line separator behavior (value is 1&lt;&lt;1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>MenuItem</code></li>
+     * <li><code>ToolItem</code></li>
+     * </ul></p>
+     */
+    public static const int SEPARATOR = 1 << 1;
+
+    /**
+     * Style constant for toggle button behavior (value is 1&lt;&lt;1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * </ul></p>
+     */
+    public static const int TOGGLE = 1 << 1;
+
+    /**
+     * Style constant for arrow button behavior (value is 1&lt;&lt;2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * </ul></p>
+     */
+    public static const int ARROW = 1 << 2;
+
+    /**
+     * Style constant for push button behavior (value is 1&lt;&lt;3).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>MenuItem</code></li>
+     * <li><code>ToolItem</code></li>
+     * </ul></p>
+     */
+    public static const int PUSH = 1 << 3;
+
+    /**
+     * Style constant for radio button behavior (value is 1&lt;&lt;4).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>MenuItem</code></li>
+     * <li><code>ToolItem</code></li>
+     * </ul></p>
+     */
+    public static const int RADIO = 1 << 4;
+
+    /**
+     * Style constant for check box behavior (value is 1&lt;&lt;5).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>MenuItem</code></li>
+     * <li><code>ToolItem</code></li>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
+     * </ul></p>
+     */
+    public static const int CHECK = 1 << 5;
+
+    /**
+     * Style constant for cascade behavior (value is 1&lt;&lt;6).
+     * <p><b>Used By:</b><ul>
+     * <li><code>MenuItem</code></li>
+     * </ul></p>
+     */
+    public static const int CASCADE = 1 << 6;
+
+    /**
+     * Style constant for multi-selection behavior in lists
+     * and multiple line support on text fields (value is 1&lt;&lt;1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Text</code></li>
+     * <li><code>List</code></li>
+     * <li><code>FileDialog</code></li>
+     * </ul></p>
+     */
+    public static const int MULTI = 1 << 1;
+
+    /**
+     * Style constant for single selection behavior in lists
+     * and single line support on text fields (value is 1&lt;&lt;2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Text</code></li>
+     * <li><code>List</code></li>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
+     * </ul></p>
+     */
+    public static const int SINGLE = 1 << 2;
+
+    /**
+     * Style constant for read-only behavior (value is 1&lt;&lt;3).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Combo</code></li>
+     * <li><code>Text</code></li>
+     * </ul></p>
+     */
+    public static const int READ_ONLY = 1 << 3;
+
+    /**
+     * Style constant for automatic line wrap behavior (value is 1&lt;&lt;6).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>Text</code></li>
+     * <li><code>ToolBar</code></li>
+     * <li><code>Spinner</code></li>
+     * </ul></p>
+     */
+    public static const int WRAP = 1 << 6;
+
+    /**
+     * Style constant for search behavior (value is 1&lt;&lt;7).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Text</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int SEARCH = 1 << 7;
+
+    /**
+     * Style constant for simple (not drop down) behavior (value is 1&lt;&lt;6).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Combo</code></li>
+     * </ul></p>
+     */
+    public static const int SIMPLE = 1 << 6;
+
+    /**
+     * Style constant for password behavior (value is 1&lt;&lt;22).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Text</code></li>
+     * </ul></p>
+     *
+     * @since 3.0
+     */
+    public static const int PASSWORD = 1 << 22;
+
+    /**
+     * Style constant for shadow in behavior (value is 1&lt;&lt;2).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>Group</code></li>
+     * </ul></p>
+     */
+    public static const int SHADOW_IN = 1 << 2;
+
+    /**
+     * Style constant for shadow out behavior (value is 1&lt;&lt;3).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>Group</code></li>
+     * <li><code>ToolBar</code></li>
+     * </ul></p>
+     */
+    public static const int SHADOW_OUT = 1 << 3;
+
+    /**
+     * Style constant for shadow etched in behavior (value is 1&lt;&lt;4).
+     * <br>Note that this is a <em>HINT</em>. It is ignored on all platforms except Motif.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Group</code></li>
+     * </ul></p>
+     */
+    public static const int SHADOW_ETCHED_IN = 1 << 4;
+
+    /**
+     * Style constant for shadow etched out behavior (value is 1&lt;&lt;6).
+     * <br>Note that this is a <em>HINT</em>. It is ignored on all platforms except Motif.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Group</code></li>
+     * </ul></p>
+     */
+    public static const int SHADOW_ETCHED_OUT = 1 << 6;
+
+    /**
+     * Style constant for no shadow behavior (value is 1&lt;&lt;5).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>Group</code></li>
+     * </ul></p>
+     */
+    public static const int SHADOW_NONE = 1 << 5;
+
+    /**
+     * Style constant for progress bar behavior (value is 1&lt;&lt;1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>ProgressBar</code></li>
+     * </ul></p>
+     */
+    public static const int INDETERMINATE = 1 << 1;
+
+    /**
+     * Style constant for tool window behavior (value is 1&lt;&lt;2).
+     * <p>
+     * A tool window is a window intended to be used as a floating toolbar.
+     * It typically has a title bar that is shorter than a normal title bar,
+     * and the window title is typically drawn using a smaller font.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p><p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int TOOL = 1 << 2;
+
+    /**
+     * Style constant to ensure no trimmings are used (value is 1&lt;&lt;3).
+     * <br>Note that this overrides all other trim styles.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int NO_TRIM = 1 << 3;
+
+    /**
+     * Style constant for resize box trim (value is 1&lt;&lt;4).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * <li><code>Tracker</code></li>
+     * </ul></p>
+     */
+    public static const int RESIZE = 1 << 4;
+
+    /**
+     * Style constant for title area trim (value is 1&lt;&lt;5).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int TITLE = 1 << 5;
+
+    /**
+     * Style constant for close box trim (value is 1&lt;&lt;6,
+     * since we do not distinguish between CLOSE style and MENU style).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int CLOSE = 1 << 6;
+
+    /**
+     * Style constant for shell menu trim (value is 1&lt;&lt;6,
+     * since we do not distinguish between CLOSE style and MENU style).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int MENU = CLOSE;
+
+    /**
+     * Style constant for minimize box trim (value is 1&lt;&lt;7).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int MIN = 1 << 7;
+
+    /**
+     * Style constant for maximize box trim (value is 1&lt;&lt;10).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Decorations</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int MAX = 1 << 10;
+
+    /**
+     * Style constant for horizontal scrollbar behavior (value is 1&lt;&lt;8).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Scrollable</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int H_SCROLL = 1 << 8;
+
+    /**
+     * Style constant for vertical scrollbar behavior (value is 1&lt;&lt;9).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Scrollable</code> and subclasses</li>
+     * </ul></p>
+     */
+    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>
+     * <li><code>Control</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int BORDER = 1 << 11;
+
+    /**
+     * Style constant indicating that the window manager should clip
+     * a widget's children with respect to its viewable area. (value is 1&lt;&lt;12).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int CLIP_CHILDREN = 1 << 12;
+
+    /**
+     * Style constant indicating that the window manager should clip
+     * a widget's siblings with respect to its viewable area. (value is 1&lt;&lt;13).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int CLIP_SIBLINGS = 1 << 13;
+
+    /**
+     * Style constant for always on top behavior (value is 1&lt;&lt;14).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Shell</code> and subclasses</li>
+     * </ul></p>
+     */
+    public static const int ON_TOP = 1 << 14;
+
+    /**
+     * Trim style convenience constant for the most common top level shell appearance
+     * (value is CLOSE|TITLE|MIN|MAX|RESIZE).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int SHELL_TRIM = CLOSE | TITLE | MIN | MAX | RESIZE;
+
+    /**
+     * Trim style convenience constant for the most common dialog shell appearance
+     * (value is CLOSE|TITLE|BORDER).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int DIALOG_TRIM = TITLE | CLOSE | BORDER;
+
+    /**
+     * Style constant for modeless behavior (value is 0).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Dialog</code></li>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int MODELESS = 0;
+
+    /**
+     * Style constant for primary modal behavior (value is 1&lt;&lt;15).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Dialog</code></li>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int PRIMARY_MODAL = 1 << 15;
+
+    /**
+     * Style constant for application modal behavior (value is 1&lt;&lt;16).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Dialog</code></li>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int APPLICATION_MODAL = 1 << 16;
+
+    /**
+     * Style constant for system modal behavior (value is 1&lt;&lt;17).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Dialog</code></li>
+     * <li><code>Shell</code></li>
+     * </ul></p>
+     */
+    public static const int SYSTEM_MODAL = 1 << 17;
+
+    /**
+     * Style constant for selection hiding behavior when the widget loses focus (value is 1&lt;&lt;15).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Table</code></li>
+     * </ul></p>
+     */
+    public static const int HIDE_SELECTION = 1 << 15;
+
+    /**
+     * Style constant for full row selection behavior and
+     * selection constant indicating that a full line should be
+     * drawn. (value is 1&lt;&lt;16).
+     * <br>Note that for some widgets this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
+     * <li><code>StyledText</code></li>
+     * <li><code>TextLayout</code></li>
+     * </ul></p>
+     */
+    public static const int FULL_SELECTION = 1 << 16;
+
+    /**
+     * Style constant for flat appearance. (value is 1&lt;&lt;23).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>ToolBar</code></li>
+     * </ul></p>
+     */
+    public static const int FLAT = 1 << 23;
+
+    /**
+     * Style constant for smooth appearance. (value is 1&lt;&lt;16).
+     * <br>Note that this is a <em>HINT</em>.
+     * <p><b>Used By:</b><ul>
+     * <li><code>ProgressBar</code></li>
+     * <li><code>Sash</code></li>
+     * </ul></p>
+     */
+    public static const int SMOOTH = 1 << 16;
+
+    /**
+     * Style constant for no background behavior (value is 1&lt;&lt;18).
+     * <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 the application is responsible
+     * for filling every pixel of the client area.
+     * This style might be used as an alternative to "double-buffering" in order to reduce flicker.
+     * This style does not mean "transparent" - widgets that are obscured will not draw through.
+     * </p><p><b>Used By:</b><ul>
+     * <li><code>Composite</code></li>
+     * </ul></p>
+     */
+    public static const int NO_BACKGROUND = 1 << 18;
+
+    /**
+     * 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>
+     */
+    public static const int NO_FOCUS = 1 << 19;
+
+    /**
+     * Style constant for no redraw on resize behavior (value is 1&lt;&lt;20).
+     * <p>
+     * This style stops the entire client area from being invalidated when the size
+     * of the Canvas changes. Specifically, when the size of the Canvas gets smaller,
+     * the SWT.Paint event is not sent. When it gets bigger, an SWT.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>
+     */
+    public static const int NO_REDRAW_RESIZE = 1 << 20;
+
+    /**
+     * 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>
+     */
+    public static const int NO_MERGE_PAINTS = 1 << 21;
+
+    /**
+     * Style constant for preventing child radio group behavior (value is 1&lt;&lt;22).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Composite</code></li>
+     * </ul></p>
+     */
+    public static const int NO_RADIO_GROUP = 1 << 22;
+
+    /**
+     * Style constant for left to right orientation (value is 1&lt;&lt;25).
+     * <p>
+     * When orientation is not explicitly specified, orientation is
+     * inherited.  This means that children will be assigned the
+     * orientation of their parent.  To override this behavior and
+     * force an orientation for a child, explicitly set the orientation
+     * of the child when that child is created.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * <li><code>Menu</code></li>
+     * <li><code>GC</code></li>
+     * </ul></p>
+     *
+     * @since 2.1.2
+     */
+    public static const int LEFT_TO_RIGHT = 1 << 25;
+
+    /**
+     * Style constant for right to left orientation (value is 1&lt;&lt;26).
+     * <p>
+     * When orientation is not explicitly specified, orientation is
+     * inherited.  This means that children will be assigned the
+     * orientation of their parent.  To override this behavior and
+     * force an orientation for a child, explicitly set the orientation
+     * of the child when that child is created.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * <li><code>Menu</code></li>
+     * <li><code>GC</code></li>
+     * </ul></p>
+     *
+     * @since 2.1.2
+     */
+    public static const int RIGHT_TO_LEFT = 1 << 26;
+
+    /**
+     * Style constant to indicate coordinate mirroring (value is 1&lt;&lt;27).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * <li><code>Menu</code></li>
+     * </ul></p>
+     *
+     * @since 2.1.2
+     */
+    public static const int MIRRORED = 1 << 27;
+
+    /**
+     * Style constant to allow embedding (value is 1&lt;&lt;24).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Composite</code></li>
+     * </ul></p>
+     *
+     * @since 3.0
+     */
+    public static const int EMBEDDED = 1 << 24;
+
+    /**
+     * Style constant to allow virtual data (value is 1&lt;&lt;28).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
+     * </ul></p>
+     *
+     * @since 3.0
+     */
+    public static const int VIRTUAL = 1 << 28;
+
+    /**
+     * Style constant to indicate double buffering (value is 1&lt;&lt;29).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * </ul></p>
+     *
+     * @since 3.1
+     */
+    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>
+     * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+     * </ul></p>
+     */
+    public static const int TOP = UP;
+
+    /**
+     * Style constant for align down behavior (value is 1&lt;&lt;10,
+     * since align DOWN and align BOTTOM 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 DOWN               = 1 << 10;
+
+    /**
+     * Style constant for align bottom behavior (value is 1&lt;&lt;10,
+     * since align DOWN and align BOTTOM are considered the same).
+     * <p><b>Used By:</b><ul>
+     * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+     * </ul></p>
+     */
+    public static const int BOTTOM             = DOWN;
+
+    /**
+     * Style constant for leading alignment (value is 1&lt;&lt;14).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>Label</code></li>
+     * <li><code>TableColumn</code></li>
+     * <li><code>Tracker</code></li>
+     * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+     * </ul></p>
+     *
+     * @since 2.1.2
+     */
+    public static const int LEAD               = 1 << 14;
+
+    /**
+     * Style constant for align left behavior (value is 1&lt;&lt;14).
+     * This is a synonym for LEAD (value is 1&lt;&lt;14).  Newer
+     * applications should use LEAD instead of LEFT to make code more
+     * understandable on right-to-left platforms.
+     */
+    public static const int LEFT               = LEAD;
+
+    /**
+     * Style constant for trailing alignment (value is 1&lt;&lt;17).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>Label</code></li>
+     * <li><code>TableColumn</code></li>
+     * <li><code>Tracker</code></li>
+     * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+     * </ul></p>
+     *
+     * @since 2.1.2
+     */
+    public static const int TRAIL              = 1 << 17;
+
+    /**
+     * Style constant for align right behavior (value is 1&lt;&lt;17).
+     * This is a synonym for TRAIL (value is 1&lt;&lt;17).  Newer
+     * applications should use TRAIL instead of RIGHT to make code more
+     * understandable on right-to-left platforms.
+     */
+    public static const int RIGHT              = TRAIL;
+
+    /**
+     * Style constant for align center behavior (value is 1&lt;&lt;24).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Button</code></li>
+     * <li><code>Label</code></li>
+     * <li><code>TableColumn</code></li>
+     * <li><code>FormAttachment</code> in a <code>FormLayout</code></li>
+     * </ul></p>
+     */
+    public static const int CENTER = 1 << 24;
+
+    /**
+     * Style constant for horizontal alignment or orientation behavior (value is 1&lt;&lt;8).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>ProgressBar</code></li>
+     * <li><code>Sash</code></li>
+     * <li><code>Scale</code></li>
+     * <li><code>ScrollBar</code></li>
+     * <li><code>Slider</code></li>
+     * <li><code>ToolBar</code></li>
+     * <li><code>FillLayout</code> type</li>
+     * <li><code>RowLayout</code> type</li>
+     * </ul></p>
+     */
+    public static const int HORIZONTAL = 1 << 8;
+
+    /**
+     * Style constant for vertical alignment or orientation behavior (value is 1&lt;&lt;9).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Label</code></li>
+     * <li><code>ProgressBar</code></li>
+     * <li><code>Sash</code></li>
+     * <li><code>Scale</code></li>
+     * <li><code>ScrollBar</code></li>
+     * <li><code>Slider</code></li>
+     * <li><code>ToolBar</code></li>
+     * <li><code>CoolBar</code></li>
+     * <li><code>FillLayout</code> type</li>
+     * <li><code>RowLayout</code> type</li>
+     * </ul></p>
+     */
+    public static const int VERTICAL = 1 << 9;
+
+    /**
+     * Style constant for date display (value is 1&lt;&lt;5).
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int DATE = 1 << 5;
+
+    /**
+     * Style constant for time display (value is 1&lt;&lt;7).
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int TIME = 1 << 7;
+
+    /**
+     * Style constant for calendar display (value is 1&lt;&lt;10).
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int CALENDAR = 1 << 10;
+
+    /**
+     * Style constant for short date/time format (value is 1&lt;&lt;15).
+     * <p>
+     * A short date displays the month and year.
+     * A short time displays hours and minutes.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int SHORT = 1 << 15;
+
+    /**
+     * Style constant for medium date/time format (value is 1&lt;&lt;16).
+     * <p>
+     * A medium date displays the day, month and year.
+     * A medium time displays hours, minutes, and seconds.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int MEDIUM = 1 << 16;
+
+    /**
+     * Style constant for long date/time format (value is 1&lt;&lt;28).
+     * <p>
+     * A long date displays the day, month and year.
+     * A long time displays hours, minutes, and seconds.
+     * The day and month names may be displayed.
+     * <br>Note that this is a <em>HINT</em>.
+     * </p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>DateTime</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int LONG = 1 << 28;
+
+    /**
+     * Style constant specifying that a Browser should use a Mozilla GRE
+     * for rendering its content (value is 1&lt;&lt;15).
+     * <p>
+     * <p><b>Used By:</b><ul>
+     * <li><code>Browser</code></li>
+     * </ul></p>
+     *
+     * @since 3.3
+     */
+    public static const int MOZILLA = 1 << 15;
+
+    /**
+     * Style constant for balloon behavior (value is 1&lt;&lt;12).
+     * <p><b>Used By:</b><ul>
+     * <li><code>ToolTip</code></li>
+     * </ul></p>
+     *
+     * @since 3.2
+     */
+    public static const int BALLOON = 1 << 12;
+
+    /**
+     * Style constant for vertical alignment or orientation behavior (value is 1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>GridLayout</code> type</li>
+     * </ul></p>
+     */
+    public static const int BEGINNING = 1;
+
+    /**
+     * Style constant for vertical alignment or orientation behavior (value is 4).
+     * <p><b>Used By:</b><ul>
+     * <li><code>GridLayout</code> type</li>
+     * </ul></p>
+     */
+    public static const int FILL = 4;
+
+    /**
+     * Input Method Editor style constant for double byte
+     * input behavior (value is 1&lt;&lt;1).
+     */
+    public static const int DBCS = 1 << 1;
+
+    /**
+     * Input Method Editor style constant for alpha
+     * input behavior (value is 1&lt;&lt;2).
+     */
+    public static const int ALPHA = 1 << 2;
+
+    /**
+     * Input Method Editor style constant for native
+     * input behavior (value is 1&lt;&lt;3).
+     */
+    public static const int NATIVE = 1 << 3;
+
+    /**
+     * Input Method Editor style constant for phonetic
+     * input behavior (value is 1&lt;&lt;4).
+     */
+    public static const int PHONETIC = 1 << 4;
+
+    /**
+     * Input Method Editor style constant for romanicized
+     * input behavior (value is 1&lt;&lt;5).
+     */
+    public static const int ROMAN = 1 << 5;
+
+    /**
+     * ASCII character convenience constant for the backspace character
+     * (value is the <code>char</code> '\b').
+     */
+    public static const char BS = '\b';
+
+    /**
+     * ASCII character convenience constant for the carriage return character
+     * (value is the <code>char</code> '\r').
+     */
+    public static const char CR = '\r';
+
+    /**
+     * ASCII character convenience constant for the delete character
+     * (value is the <code>char</code> with value 127).
+     */
+    public static const char DEL = 0x7F;
+
+    /**
+     * ASCII character convenience constant for the escape character
+     * (value is the <code>char</code> with value 27).
+     */
+    public static const char ESC = 0x1B;
+
+    /**
+     * ASCII character convenience constant for the line feed character
+     * (value is the <code>char</code> '\n').
+     */
+    public static const char LF = '\n';
+
+    /**
+     * ASCII character convenience constant for the tab character
+     * (value is the <code>char</code> '\t').
+     *
+     * @since 2.1
+     */
+    public static const char TAB = '\t';
+
+    /**
+     * keyboard and/or mouse event mask indicating that the ALT key
+     * was pushed on the keyboard when the event was generated
+     * (value is 1&lt;&lt;16).
+     */
+    public static const int ALT = 1 << 16;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the SHIFT key
+     * was pushed on the keyboard when the event was generated
+     * (value is 1&lt;&lt;17).
+     */
+    public static const int SHIFT = 1 << 17;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the CTRL key
+     * was pushed on the keyboard when the event was generated
+     * (value is 1&lt;&lt;18).
+     */
+    public static const int CTRL = 1 << 18;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the CTRL key
+     * was pushed on the keyboard when the event was generated. This
+     * is a synonym for CTRL (value is 1&lt;&lt;18).
+     */
+    public static const int CONTROL = CTRL;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the COMMAND key
+     * was pushed on the keyboard when the event was generated
+     * (value is 1&lt;&lt;22).
+     *
+     * @since 2.1
+     */
+    public static const int COMMAND = 1 << 22;
+
+    /**
+     * Keyboard and/or mouse event mask indicating all possible
+     * keyboard modifiers.
+     *
+     * To allow for the future, this mask  is intended to be used in
+     * place of code that references  each individual keyboard mask.
+     *  For example, the following expression will determine whether
+     * any modifier is pressed and will continue to work as new modifier
+     * masks are added.
+     *
+     * <code>(stateMask & SWT.MODIFIER_MASK) !is 0</code>.
+     *
+     * @since 2.1
+     */
+    public static const int MODIFIER_MASK = ALT | SHIFT | CTRL | COMMAND;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that mouse button one
+     * was pushed when the event was generated. (value is 1&lt;&lt;19).
+     */
+    public static const int BUTTON1 = 1 << 19;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that mouse button two
+     * was pushed when the event was generated. (value is 1&lt;&lt;20).
+     */
+    public static const int BUTTON2 = 1 << 20;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that mouse button three
+     * was pushed when the event was generated. (value is 1&lt;&lt;21).
+     */
+    public static const int BUTTON3 = 1 << 21;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that mouse button four
+     * was pushed when the event was generated. (value is 1&lt;&lt;23).
+     *
+     * @since 3.1
+     */
+    public static const int BUTTON4 = 1 << 23;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that mouse button five
+     * was pushed when the event was generated. (value is 1&lt;&lt;25).
+     *
+     * @since 3.1
+     */
+    public static const int BUTTON5 = 1 << 25;
+
+    /**
+     * Keyboard and/or mouse event mask indicating all possible
+     * mouse buttons.
+     *
+     * To allow for the future, this mask  is intended to be used
+     * in place of code that references each individual button mask.
+     * For example, the following expression will determine whether
+     * any button is pressed and will continue to work as new button
+     * masks are added.
+     *
+     * <code>(stateMask & SWT.BUTTON_MASK) !is 0</code>.
+     *
+     * @since 2.1
+     */
+    public static const int BUTTON_MASK = BUTTON1 | BUTTON2 | BUTTON3 | BUTTON4 | BUTTON5;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the MOD1 key
+     * was pushed on the keyboard when the event was generated.
+     *
+     * This is the primary keyboard modifier for the platform.
+     *
+     * @since 2.1
+     */
+    public static const int MOD1 = CONTROL;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the MOD2 key
+     * was pushed on the keyboard when the event was generated.
+     *
+     * This is the secondary keyboard modifier for the platform.
+     *
+     * @since 2.1
+     */
+    public static const int MOD2 = SHIFT;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the MOD3 key
+     * was pushed on the keyboard when the event was generated.
+     *
+     * @since 2.1
+     */
+    public static const int MOD3 = ALT;
+
+    /**
+     * Keyboard and/or mouse event mask indicating that the MOD4 key
+     * was pushed on the keyboard when the event was generated.
+     *
+     * @since 2.1
+     */
+    public static const int MOD4 = 0;
+
+    /**
+     * Constants to indicate line scrolling (value is 1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * </ul></p>
+     *
+     * @since 3.1
+     */
+    public static const int SCROLL_LINE = 1;
+
+    /**
+     * Constants to indicate page scrolling (value is 2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>Control</code></li>
+     * </ul></p>
+     *
+     * @since 3.1
+     */
+    public static const int SCROLL_PAGE = 2;
+
+    /**
+     * Accelerator constant used to differentiate a key code from a
+     * unicode character.
+     *
+     * If this bit is set, then the key stroke
+     * portion of an accelerator represents a key code.  If this bit
+     * is not set, then the key stroke portion of an accelerator is
+     * a unicode character.
+     *
+     * The following expression is false:
+     *
+     * <code>((SWT.MOD1 | SWT.MOD2 | 'T') & SWT.KEYCODE_BIT) !is 0</code>.
+     *
+     * The following expression is true:
+     *
+     * <code>((SWT.MOD3 | SWT.F2) & SWT.KEYCODE_BIT) !is 0</code>.
+     *
+     * (value is (1&lt;&lt;24))
+     *
+     * @since 2.1
+     */
+    public static const int KEYCODE_BIT = (1 << 24);
+
+    /**
+     * Accelerator constant used to extract the key stroke portion of
+     * an accelerator.
+     *
+     * The key stroke may be a key code or a unicode
+     * value.  If the key stroke is a key code <code>KEYCODE_BIT</code>
+     * will be set.
+     *
+     * @since 2.1
+     */
+    public static const int KEY_MASK = KEYCODE_BIT + 0xFFFF;
+
+    /**
+     * Keyboard event constant representing the UP ARROW key
+     * (value is (1&lt;&lt;24)+1).
+     */
+    public static const int ARROW_UP = KEYCODE_BIT + 1;
+
+    /**
+     * Keyboard event constant representing the DOWN ARROW key
+     * (value is (1&lt;&lt;24)+2).
+     */
+    public static const int ARROW_DOWN = KEYCODE_BIT + 2;
+
+    /**
+     * Keyboard event constant representing the LEFT ARROW key
+     * (value is (1&lt;&lt;24)+3).
+     */
+    public static const int ARROW_LEFT = KEYCODE_BIT + 3;
+
+    /**
+     * Keyboard event constant representing the RIGHT ARROW key
+     * (value is (1&lt;&lt;24)+4).
+     */
+    public static const int ARROW_RIGHT = KEYCODE_BIT + 4;
+
+    /**
+     * Keyboard event constant representing the PAGE UP key
+     * (value is (1&lt;&lt;24)+5).
+     */
+    public static const int PAGE_UP = KEYCODE_BIT + 5;
+
+    /**
+     * Keyboard event constant representing the PAGE DOWN key
+     * (value is (1&lt;&lt;24)+6).
+     */
+    public static const int PAGE_DOWN = KEYCODE_BIT + 6;
+
+    /**
+     * Keyboard event constant representing the HOME key
+     * (value is (1&lt;&lt;24)+7).
+     */
+    public static const int HOME = KEYCODE_BIT + 7;
+
+    /**
+     * Keyboard event constant representing the END key
+     * (value is (1&lt;&lt;24)+8).
+     */
+    public static const int END = KEYCODE_BIT + 8;
+
+    /**
+     * Keyboard event constant representing the INSERT key
+     * (value is (1&lt;&lt;24)+9).
+     */
+    public static const int INSERT = KEYCODE_BIT + 9;
+
+    /**
+     * Keyboard event constant representing the F1 key
+     * (value is (1&lt;&lt;24)+10).
+     */
+    public static const int F1 = KEYCODE_BIT + 10;
+
+    /**
+     * Keyboard event constant representing the F2 key
+     * (value is (1&lt;&lt;24)+11).
+     */
+    public static const int F2 = KEYCODE_BIT + 11;
+
+    /**
+     * Keyboard event constant representing the F3 key
+     * (value is (1&lt;&lt;24)+12).
+     */
+    public static const int F3 = KEYCODE_BIT + 12;
+
+    /**
+     * Keyboard event constant representing the F4 key
+     * (value is (1&lt;&lt;24)+13).
+     */
+    public static const int F4 = KEYCODE_BIT + 13;
+
+    /**
+     * Keyboard event constant representing the F5 key
+     * (value is (1&lt;&lt;24)+14).
+     */
+    public static const int F5 = KEYCODE_BIT + 14;
+
+    /**
+     * Keyboard event constant representing the F6 key
+     * (value is (1&lt;&lt;24)+15).
+     */
+    public static const int F6 = KEYCODE_BIT + 15;
+
+    /**
+     * Keyboard event constant representing the F7 key
+     * (value is (1&lt;&lt;24)+16).
+     */
+    public static const int F7 = KEYCODE_BIT + 16;
+
+    /**
+     * Keyboard event constant representing the F8 key
+     * (value is (1&lt;&lt;24)+17).
+     */
+    public static const int F8 = KEYCODE_BIT + 17;
+
+    /**
+     * Keyboard event constant representing the F9 key
+     * (value is (1&lt;&lt;24)+18).
+     */
+    public static const int F9 = KEYCODE_BIT + 18;
+
+    /**
+     * Keyboard event constant representing the F10 key
+     * (value is (1&lt;&lt;24)+19).
+     */
+    public static const int F10 = KEYCODE_BIT + 19;
+
+    /**
+     * Keyboard event constant representing the F11 key
+     * (value is (1&lt;&lt;24)+20).
+     */
+    public static const int F11 = KEYCODE_BIT + 20;
+
+    /**
+     * Keyboard event constant representing the F12 key
+     * (value is (1&lt;&lt;24)+21).
+     */
+    public static const int F12 = KEYCODE_BIT + 21;
+
+    /**
+     * Keyboard event constant representing the F13 key
+     * (value is (1&lt;&lt;24)+22).
+     *
+     * @since 3.0
+     */
+    public static const int F13 = KEYCODE_BIT + 22;
+
+    /**
+     * Keyboard event constant representing the F14 key
+     * (value is (1&lt;&lt;24)+23).
+     *
+     * @since 3.0
+     */
+    public static const int F14 = KEYCODE_BIT + 23;
+
+    /**
+     * Keyboard event constant representing the F15 key
+     * (value is (1&lt;&lt;24)+24).
+     *
+     * @since 3.0
+     */
+    public static const int F15 = KEYCODE_BIT + 24;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad multiply key (value is (1&lt;&lt;24)+42).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_MULTIPLY = KEYCODE_BIT + 42;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad add key (value is (1&lt;&lt;24)+43).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_ADD = KEYCODE_BIT + 43;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad subtract key (value is (1&lt;&lt;24)+45).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_SUBTRACT = KEYCODE_BIT + 45;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad decimal key (value is (1&lt;&lt;24)+46).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_DECIMAL = KEYCODE_BIT + 46;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad divide key (value is (1&lt;&lt;24)+47).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_DIVIDE = KEYCODE_BIT + 47;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad zero key (value is (1&lt;&lt;24)+48).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_0 = KEYCODE_BIT + 48;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad one key (value is (1&lt;&lt;24)+49).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_1 = KEYCODE_BIT + 49;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad two key (value is (1&lt;&lt;24)+50).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_2 = KEYCODE_BIT + 50;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad three key (value is (1&lt;&lt;24)+51).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_3 = KEYCODE_BIT + 51;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad four key (value is (1&lt;&lt;24)+52).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_4 = KEYCODE_BIT + 52;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad five key (value is (1&lt;&lt;24)+53).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_5 = KEYCODE_BIT + 53;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad six key (value is (1&lt;&lt;24)+54).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_6 = KEYCODE_BIT + 54;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad seven key (value is (1&lt;&lt;24)+55).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_7 = KEYCODE_BIT + 55;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad eight key (value is (1&lt;&lt;24)+56).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_8 = KEYCODE_BIT + 56;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad nine key (value is (1&lt;&lt;24)+57).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_9 = KEYCODE_BIT + 57;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad equal key (value is (1&lt;&lt;24)+61).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_EQUAL = KEYCODE_BIT + 61;
+
+    /**
+     * Keyboard event constant representing the numeric key
+     * pad enter key (value is (1&lt;&lt;24)+80).
+     *
+     * @since 3.0
+     */
+    public static const int KEYPAD_CR = KEYCODE_BIT + 80;
+
+    /**
+     * Keyboard event constant representing the help
+     * key (value is (1&lt;&lt;24)+81).
+     *
+     * NOTE: The HELP key maps to the key labeled "help",
+     * not "F1". If your keyboard does not have a HELP key,
+     * you will never see this key press.  To listen for
+     * help on a control, use SWT.Help.
+     *
+     * @since 3.0
+     *
+     * @see SWT#Help
+     */
+    public static const int HELP = KEYCODE_BIT + 81;
+
+    /**
+     * Keyboard event constant representing the caps
+     * lock key (value is (1&lt;&lt;24)+82).
+     *
+     * @since 3.0
+     */
+    public static const int CAPS_LOCK = KEYCODE_BIT + 82;
+
+    /**
+     * Keyboard event constant representing the num
+     * lock key (value is (1&lt;&lt;24)+83).
+     *
+     * @since 3.0
+     */
+    public static const int NUM_LOCK = KEYCODE_BIT + 83;
+
+    /**
+     * Keyboard event constant representing the scroll
+     * lock key (value is (1&lt;&lt;24)+84).
+     *
+     * @since 3.0
+     */
+    public static const int SCROLL_LOCK = KEYCODE_BIT + 84;
+
+    /**
+     * Keyboard event constant representing the pause
+     * key (value is (1&lt;&lt;24)+85).
+     *
+     * @since 3.0
+     */
+    public static const int PAUSE = KEYCODE_BIT + 85;
+
+    /**
+     * Keyboard event constant representing the break
+     * key (value is (1&lt;&lt;24)+86).
+     *
+     * @since 3.0
+     */
+    public static const int BREAK = KEYCODE_BIT + 86;
+
+    /**
+     * Keyboard event constant representing the print screen
+     * key (value is (1&lt;&lt;24)+87).
+     *
+     * @since 3.0
+     */
+    public static const int PRINT_SCREEN = KEYCODE_BIT + 87;
+
+    /**
+     * The <code>MessageBox</code> style constant for error icon
+     * behavior (value is 1).
+     */
+    public static const int ICON_ERROR = 1;
+
+    /**
+     * The <code>MessageBox</code> style constant for information icon
+     * behavior (value is 1&lt;&lt;1).
+     */
+    public static const int ICON_INFORMATION = 1 << 1;
+
+    /**
+     * The <code>MessageBox</code> style constant for question icon
+     * behavior (value is 1&lt;&lt;2).
+     */
+    public static const int ICON_QUESTION = 1 << 2;
+
+    /**
+     * The <code>MessageBox</code> style constant for warning icon
+     * behavior (value is 1&lt;&lt;3).
+     */
+    public static const int ICON_WARNING = 1 << 3;
+
+    /**
+     * The <code>MessageBox</code> style constant for "working" icon
+     * behavior (value is 1&lt;&lt;4).
+     */
+    public static const int ICON_WORKING = 1 << 4;
+
+    /**
+     * The <code>MessageBox</code> style constant for an OK button;
+     * valid combinations are OK, OK|CANCEL
+     * (value is 1&lt;&lt;5).
+     */
+    public static const int OK = 1 << 5;
+
+    /**
+     * The <code>MessageBox</code> style constant for YES button;
+     * valid combinations are YES|NO, YES|NO|CANCEL
+     * (value is 1&lt;&lt;6).
+     */
+    public static const int YES = 1 << 6;
+
+    /**
+     * The <code>MessageBox</code> style constant for NO button;
+     * valid combinations are YES|NO, YES|NO|CANCEL
+     * (value is 1&lt;&lt;7).
+     */
+    public static const int NO = 1 << 7;
+
+    /**
+     * The <code>MessageBox</code> style constant for a CANCEL button;
+     * valid combinations are OK|CANCEL, YES|NO|CANCEL, RETRY|CANCEL
+     * (value is 1&lt;&lt;8).  This style constant is also used with
+     * <code>Text</code> in combination with SEARCH.
+     *
+     * <p><b>Used By:</b><ul>
+     * <li><code>MessageBox</code></li>
+     * <li><code>Text</code></li>
+     * </ul></p>
+     */
+    public static const int CANCEL = 1 << 8;
+
+    /**
+     * The <code>MessageBox</code> style constant for an ABORT button;
+     * the only valid combination is ABORT|RETRY|IGNORE
+     * (value is 1&lt;&lt;9).
+     */
+    public static const int ABORT = 1 << 9;
+
+    /**
+     * The <code>MessageBox</code> style constant for a RETRY button;
+     *  valid combinations are ABORT|RETRY|IGNORE, RETRY|CANCEL
+     * (value is 1&lt;&lt;10).
+     */
+    public static const int RETRY = 1 << 10;
+
+    /**
+     * The <code>MessageBox</code> style constant for an IGNORE button;
+     * the only valid combination is ABORT|RETRY|IGNORE
+     * (value is 1&lt;&lt;11).
+     */
+    public static const int IGNORE = 1 << 11;
+
+    /**
+     * The <code>FileDialog</code> style constant for open file dialog behavior
+     * (value is 1&lt;&lt;12).
+     */
+    public static const int OPEN = 1 << 12;
+
+    /**
+     * The <code>FileDialog</code> style constant for save file dialog behavior
+     * (value is 1&lt;&lt;13).
+     */
+    public static const int SAVE = 1 << 13;
+
+    /**
+     * The <code>Composite</code> constant to indicate that
+     * an attribute (such as background) is not inherited
+     * by the children (value is 0).
+     *
+     * @since 3.2
+     */
+    public static const int INHERIT_NONE = 0;
+
+    /**
+     * The <code>Composite</code> constant to indicate that
+     * an attribute (such as background) is inherited by
+     * children who choose this value as their "default"
+     * (value is 1).  For example, a label child will
+     * typically choose to inherit the background color
+     * of a composite while a list or table will not.
+     *
+     * @since 3.2
+     */
+    public static const int INHERIT_DEFAULT = 1;
+
+    /**
+     * The <code>Composite</code> constant to indicate that
+     * an attribute (such as background) is inherited by
+     * all children.
+     *
+     * @since 3.2
+     */
+    public static const int INHERIT_FORCE = 2;
+
+    /**
+     * Default color white (value is 1).
+     */
+    public static const int COLOR_WHITE = 1;
+
+    /**
+     * Default color black (value is 2).
+     */
+    public static const int COLOR_BLACK = 2;
+
+    /**
+     * Default color red (value is 3).
+     */
+    public static const int COLOR_RED = 3;
+
+    /**
+     * Default color dark red (value is 4).
+     */
+    public static const int COLOR_DARK_RED = 4;
+
+    /**
+     * Default color green (value is 5).
+     */
+    public static const int COLOR_GREEN = 5;
+
+    /**
+     * Default color dark green (value is 6).
+     */
+    public static const int COLOR_DARK_GREEN = 6;
+
+    /**
+     * Default color yellow (value is 7).
+     */
+    public static const int COLOR_YELLOW = 7;
+
+    /**
+     * Default color dark yellow (value is 8).
+     */
+    public static const int COLOR_DARK_YELLOW = 8;
+
+    /**
+     * Default color blue (value is 9).
+     */
+    public static const int COLOR_BLUE = 9;
+
+    /**
+     * Default color dark blue (value is 10).
+     */
+    public static const int COLOR_DARK_BLUE = 10;
+
+    /**
+     * Default color magenta (value is 11).
+     */
+    public static const int COLOR_MAGENTA = 11;
+
+    /**
+     * Default color dark magenta (value is 12).
+     */
+    public static const int COLOR_DARK_MAGENTA = 12;
+
+    /**
+     * Default color cyan (value is 13).
+     */
+    public static const int COLOR_CYAN = 13;
+
+    /**
+     * Default color dark cyan (value is 14).
+     */
+    public static const int COLOR_DARK_CYAN = 14;
+
+    /**
+     * Default color gray (value is 15).
+     */
+    public static const int COLOR_GRAY = 15;
+
+    /**
+     * Default color dark gray (value is 16).
+     */
+    public static const int COLOR_DARK_GRAY = 16;
+
+    /*
+     * System Colors
+     *
+     * Dealing with system colors is an area where there are
+     * many platform differences.  On some platforms, system
+     * colors can change dynamically while the program is
+     * running.  On other platforms, system colors can be
+     * changed for all instances of a particular widget.
+     * Therefore, the only truly portable method to obtain
+     * a widget color query is to query the color from an
+     * instance of the widget.
+     *
+     *  It is expected that the list of supported colors
+     * will grow over time.
+     */
+
+    /**
+     * System color used to paint dark shadow areas (value is 17).
+     */
+    public static const int COLOR_WIDGET_DARK_SHADOW = 17;
+
+    /**
+     * System color used to paint normal shadow areas (value is 18).
+     */
+    public static const int COLOR_WIDGET_NORMAL_SHADOW = 18;
+
+    /**
+     * System color used to paint light shadow areas (value is 19).
+     */
+    public static const int COLOR_WIDGET_LIGHT_SHADOW = 19;
+
+    /**
+     * System color used to paint highlight shadow areas (value is 20).
+     */
+    public static const int COLOR_WIDGET_HIGHLIGHT_SHADOW = 20;
+
+    /**
+     * System color used to paint foreground areas (value is 21).
+     */
+    public static const int COLOR_WIDGET_FOREGROUND = 21;
+
+    /**
+     * System color used to paint background areas (value is 22).
+     */
+    public static const int COLOR_WIDGET_BACKGROUND = 22;
+
+    /**
+     * System color used to paint border areas (value is 23).
+     */
+    public static const int COLOR_WIDGET_BORDER = 23;
+
+    /**
+     * System color used to paint list foreground areas (value is 24).
+     */
+    public static const int COLOR_LIST_FOREGROUND = 24;
+
+    /**
+     * System color used to paint list background areas (value is 25).
+     */
+    public static const int COLOR_LIST_BACKGROUND = 25;
+
+    /**
+     * System color used to paint list selection background areas (value is 26).
+     */
+    public static const int COLOR_LIST_SELECTION = 26;
+
+    /**
+     * System color used to paint list selected text (value is 27).
+     */
+    public static const int COLOR_LIST_SELECTION_TEXT = 27;
+
+    /**
+     * System color used to paint tooltip text (value is 28).
+     */
+    public static const int COLOR_INFO_FOREGROUND = 28;
+
+    /**
+     * System color used to paint tooltip background areas (value is 29).
+     */
+    public static const int COLOR_INFO_BACKGROUND = 29;
+
+    /**
+     * System color used to paint title text (value is 30).
+     */
+    public static const int COLOR_TITLE_FOREGROUND = 30;
+
+    /**
+     * System color used to paint title background areas (value is 31).
+     */
+    public static const int COLOR_TITLE_BACKGROUND = 31;
+
+    /**
+     * System color used to paint title background gradient (value is 32).
+     */
+    public static const int COLOR_TITLE_BACKGROUND_GRADIENT = 32;
+
+    /**
+     * System color used to paint inactive title text (value is 33).
+     */
+    public static const int COLOR_TITLE_INACTIVE_FOREGROUND = 33;
+
+    /**
+     * System color used to paint inactive title background areas (value is 34).
+     */
+    public static const int COLOR_TITLE_INACTIVE_BACKGROUND = 34;
+
+    /**
+     * System color used to paint inactive title background gradient (value is 35).
+     */
+    public static const int COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = 35;
+
+    /**
+     * Draw constant indicating whether the drawing operation
+     * should fill the background (value is 1&lt;&lt;0).
+     */
+    public static const int DRAW_TRANSPARENT = 1 << 0;
+
+    /**
+     * Draw constant indicating whether the string drawing operation
+     * should handle line-delimiters (value is 1&lt;&lt;1).
+     */
+    public static const int DRAW_DELIMITER = 1 << 1;
+
+    /**
+     * Draw constant indicating whether the string drawing operation
+     * should expand TAB characters (value is 1&lt;&lt;2).
+     */
+    public static const int DRAW_TAB = 1 << 2;
+
+    /**
+     * Draw constant indicating whether the string drawing operation
+     * should handle mnemonics (value is 1&lt;&lt;3).
+     */
+    public static const int DRAW_MNEMONIC = 1 << 3;
+
+
+    /**
+     * Selection constant indicating that a line delimiter should be
+     * drawn (value is 1&lt;&lt;17).
+     *
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextLayout</code></li>
+     * </ul></p>
+     *
+     * @see #FULL_SELECTION
+     * @see #LAST_LINE_SELECTION
+     *
+     * @since 3.3
+     */
+    public static const int DELIMITER_SELECTION = 1 << 17;
+
+    /**
+     * Selection constant indicating that the last line is selected
+     * to the end and should be drawn using either a line delimiter
+     * or full line selection (value is 1&lt;&lt;20).
+     *
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextLayout</code></li>
+     * </ul></p>
+     *
+     * @see #DELIMITER_SELECTION
+     * @see #FULL_SELECTION
+     *
+     * @since 3.3
+     */
+    public static const int LAST_LINE_SELECTION = 1 << 20;
+
+    /**
+     * SWT error constant indicating that no error number was specified
+     * (value is 1).
+     */
+    public static const int ERROR_UNSPECIFIED = 1;
+
+    /**
+     * SWT error constant indicating that no more handles for an
+     * operating system resource are available
+     * (value is 2).
+     */
+    public static const int ERROR_NO_HANDLES = 2;
+
+    /**
+     * SWT error constant indicating that no more callback resources are available
+     * (value is 3).
+     */
+    public static const int ERROR_NO_MORE_CALLBACKS = 3;
+
+    /**
+     * SWT error constant indicating that a null argument was passed in
+     * (value is 4).
+     */
+    public static const int ERROR_NULL_ARGUMENT = 4;
+
+    /**
+     * SWT error constant indicating that an invalid argument was passed in
+     * (value is 5).
+     */
+    public static const int ERROR_INVALID_ARGUMENT = 5;
+
+    /**
+     * SWT error constant indicating that a value was found to be
+     * outside the allowable range
+     * (value is 6).
+     */
+    public static const int ERROR_INVALID_RANGE = 6;
+
+    /**
+     * SWT error constant indicating that a value which can not be
+     * zero was found to be
+     * (value is 7).
+     */
+    public static const int ERROR_CANNOT_BE_ZERO = 7;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide the value of an item
+     * (value is 8).
+     */
+    public static const int ERROR_CANNOT_GET_ITEM = 8;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide the selection
+     * (value is 9).
+     */
+    public static const int ERROR_CANNOT_GET_SELECTION = 9;
+
+    /**
+     * SWT error constant indicating that the matrix is not invertible
+     * (value is 10).
+     *
+     * @since 3.1
+     */
+    public static const int ERROR_CANNOT_INVERT_MATRIX = 10;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide the height of an item
+     * (value is 11).
+     */
+    public static const int ERROR_CANNOT_GET_ITEM_HEIGHT = 11;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide the text of a widget
+     * (value is 12).
+     */
+    public static const int ERROR_CANNOT_GET_TEXT = 12;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to set the text of a widget
+     * (value is 13).
+     */
+    public static const int ERROR_CANNOT_SET_TEXT = 13;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to add an item
+     * (value is 14).
+     */
+    public static const int ERROR_ITEM_NOT_ADDED = 14;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to remove an item
+     * (value is 15).
+     */
+    public static const int ERROR_ITEM_NOT_REMOVED = 15;
+
+    /**
+     * SWT error constant indicating that the graphics library
+     * is not available
+     * (value is 16).
+     */
+    public static const int ERROR_NO_GRAPHICS_LIBRARY = 16;
+
+    /**
+     * SWT error constant indicating that a particular feature has
+     * not been implemented on this platform
+     * (value is 20).
+     */
+    public static const int ERROR_NOT_IMPLEMENTED = 20;
+
+    /**
+     * SWT error constant indicating that a menu which needed
+     * to have the drop down style had some other style instead
+     * (value is 21).
+     */
+    public static const int ERROR_MENU_NOT_DROP_DOWN = 21;
+
+    /**
+     * SWT error constant indicating that an attempt was made to
+     * invoke an SWT operation which can only be executed by the
+     * user-interface thread from some other thread
+     * (value is 22).
+     */
+    public static const int ERROR_THREAD_INVALID_ACCESS = 22;
+
+    /**
+     * SWT error constant indicating that an attempt was made to
+     * invoke an SWT operation using a widget which had already
+     * been disposed
+     * (value is 24).
+     */
+    public static const int ERROR_WIDGET_DISPOSED = 24;
+
+    /**
+     * SWT error constant indicating that a menu item which needed
+     * to have the cascade style had some other style instead
+     * (value is 27).
+     */
+    public static const int ERROR_MENUITEM_NOT_CASCADE = 27;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to set the selection of a widget
+     * (value is 28).
+     */
+    public static const int ERROR_CANNOT_SET_SELECTION = 28;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to set the menu
+     * (value is 29).
+     */
+    public static const int ERROR_CANNOT_SET_MENU = 29;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to set the enabled state
+     * (value is 30).
+     */
+    public static const int ERROR_CANNOT_SET_ENABLED = 30;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide enabled/disabled state information
+     * (value is 31).
+     */
+    public static const int ERROR_CANNOT_GET_ENABLED = 31;
+
+    /**
+     * SWT error constant indicating that a provided widget can
+     * not be used as a parent in the current operation
+     * (value is 32).
+     */
+    public static const int ERROR_INVALID_PARENT = 32;
+
+    /**
+     * SWT error constant indicating that a menu which needed
+     * to have the menu bar style had some other style instead
+     * (value is 33).
+     */
+    public static const int ERROR_MENU_NOT_BAR = 33;
+
+    /**
+     * SWT error constant indicating that the underlying operating
+     * system was unable to provide count information
+     * (value is 36).
+     */
+    public static const int ERROR_CANNOT_GET_COUNT = 36;
+
+    /**
+     * SWT error constant indicating that a menu which needed
+     * to have the pop up menu style had some other style instead
+     * (value is 37).
+     */
+    public static const int ERROR_MENU_NOT_POP_UP = 37;
+
+    /**
+     * SWT error constant indicating that a graphics operation
+     * was attempted with an image of an unsupported depth
+     * (value is 38).
+     */
+    public static const int ERROR_UNSUPPORTED_DEPTH = 38;
+
+    /**
+     * SWT error constant indicating that an input/output operation
+     * failed during the execution of an SWT operation
+     * (value is 39).
+     */
+    public static const int ERROR_IO = 39;
+
+    /**
+     * SWT error constant indicating that a graphics operation
+     * was attempted with an image having an invalid format
+     * (value is 40).
+     */
+    public static const int ERROR_INVALID_IMAGE = 40;
+
+    /**
+     * SWT error constant indicating that a graphics operation
+     * was attempted with an image having a valid but unsupported
+     * format
+     * (value is 42).
+     */
+    public static const int ERROR_UNSUPPORTED_FORMAT = 42;
+
+    /**
+     * SWT error constant indicating that an attempt was made
+     * to subclass an SWT widget class without implementing the
+     * <code>checkSubclass()</code> method
+     * (value is 43).
+     *
+     * For additional information see the comment in
+     * <code>Widget.checkSubclass()</code>.
+     *
+     * @see org.eclipse.swt.widgets.Widget#checkSubclass
+     */
+    public static const int ERROR_INVALID_SUBCLASS = 43;
+
+    /**
+     * SWT error constant indicating that an attempt was made to
+     * invoke an SWT operation using a graphics object which had
+     * already been disposed
+     * (value is 44).
+     */
+    public static const int ERROR_GRAPHIC_DISPOSED = 44;
+
+    /**
+     * SWT error constant indicating that an attempt was made to
+     * invoke an SWT operation using a device which had already
+     * been disposed
+     * (value is 45).
+     */
+    public static const int ERROR_DEVICE_DISPOSED = 45;
+
+    /**
+     * SWT error constant indicating that an exception happened
+     * when executing a runnable
+     * (value is 46).
+     */
+    public static const int ERROR_FAILED_EXEC = 46;
+
+    /**
+     * SWT error constant indicating that an unsatisfied link
+     * error occurred while attempting to load a library
+     * (value is 47).
+     *
+     * @since 3.1
+     */
+    public static const int ERROR_FAILED_LOAD_LIBRARY = 47;
+
+    /**
+     * SWT error constant indicating that a font is not valid
+     * (value is 48).
+     *
+     * @since 3.1
+     */
+    public static const int ERROR_INVALID_FONT = 48;
+
+    /**
+     * Constant indicating that an image or operation is of type bitmap  (value is 0).
+     */
+    public static const int BITMAP = 0;
+
+    /**
+     * Constant indicating that an image or operation is of type icon  (value is 1).
+     */
+    public static const int ICON = 1;
+
+    /**
+     * The <code>Image</code> constructor argument indicating that
+     * the new image should be a copy of the image provided as
+     * an argument  (value is 0).
+     */
+    public static const int IMAGE_COPY = 0;
+
+    /**
+     * The <code>Image</code> constructor argument indicating that
+     * the new image should have the appearance of a "disabled"
+     * (using the platform's rules for how this should look)
+     * copy of the image provided as an argument  (value is 1).
+     */
+    public static const int IMAGE_DISABLE = 1;
+
+    /**
+     * The <code>Image</code> constructor argument indicating that
+     * the new image should have the appearance of a "gray scaled"
+     * copy of the image provided as an argument  (value is 2).
+     */
+    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). 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;
+
+    /**
+     * The font style constant indicating a bold weight font
+     * (value is 1&lt;&lt;0).
+     */
+    public static const int BOLD = 1 << 0;
+
+    /**
+     * The font style constant indicating an italic font
+     * (value is 1&lt;&lt;1).
+     */
+    public static const int ITALIC = 1 << 1;
+
+    /**
+     * System arrow cursor  (value is 0).
+     */
+    public static const int CURSOR_ARROW = 0;
+
+    /**
+     * System wait cursor  (value is 1).
+     */
+    public static const int CURSOR_WAIT = 1;
+
+    /**
+     * System cross hair cursor  (value is 2).
+     */
+    public static const int CURSOR_CROSS = 2;
+
+    /**
+     * System app startup cursor  (value is 3).
+     */
+    public static const int CURSOR_APPSTARTING = 3;
+
+    /**
+     * System help cursor  (value is 4).
+     */
+    public static const int CURSOR_HELP = 4;
+
+    /**
+     * System resize all directions cursor (value is 5).
+     */
+    public static const int CURSOR_SIZEALL = 5;
+
+    /**
+     * System resize north-east-south-west cursor  (value is 6).
+     */
+    public static const int CURSOR_SIZENESW = 6;
+
+    /**
+     * System resize north-south cursor  (value is 7).
+     */
+    public static const int CURSOR_SIZENS = 7;
+
+    /**
+     * System resize north-west-south-east cursor  (value is 8).
+     */
+    public static const int CURSOR_SIZENWSE = 8;
+
+    /**
+     * System resize west-east cursor  (value is 9).
+     */
+    public static const int CURSOR_SIZEWE = 9;
+
+    /**
+     * System resize north cursor  (value is 10).
+     */
+    public static const int CURSOR_SIZEN = 10;
+
+    /**
+     * System resize south cursor  (value is 11).
+     */
+    public static const int CURSOR_SIZES = 11;
+
+    /**
+     * System resize east cursor  (value is 12).
+     */
+    public static const int CURSOR_SIZEE = 12;
+
+    /**
+     * System resize west cursor  (value is 13).
+     */
+    public static const int CURSOR_SIZEW = 13;
+
+    /**
+     * System resize north-east cursor (value is 14).
+     */
+    public static const int CURSOR_SIZENE = 14;
+
+    /**
+     * System resize south-east cursor (value is 15).
+     */
+    public static const int CURSOR_SIZESE = 15;
+
+    /**
+     * System resize south-west cursor (value is 16).
+     */
+    public static const int CURSOR_SIZESW = 16;
+
+    /**
+     * System resize north-west cursor (value is 17).
+     */
+    public static const int CURSOR_SIZENW = 17;
+
+    /**
+     * System up arrow cursor  (value is 18).
+     */
+    public static const int CURSOR_UPARROW = 18;
+
+    /**
+     * System i-beam cursor (value is 19).
+     */
+    public static const int CURSOR_IBEAM = 19;
+
+    /**
+     * System "not allowed" cursor (value is 20).
+     */
+    public static const int CURSOR_NO = 20;
+
+    /**
+     * System hand cursor (value is 21).
+     */
+    public static const int CURSOR_HAND = 21;
+
+    /**
+     * Line drawing style for flat end caps (value is 1).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineCap(int)
+     * @see org.eclipse.swt.graphics.GC#getLineCap()
+     *
+     * @since 3.1
+     */
+    public static const int CAP_FLAT = 1;
+
+    /**
+     * Line drawing style for rounded end caps (value is 2).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineCap(int)
+     * @see org.eclipse.swt.graphics.GC#getLineCap()
+     *
+     * @since 3.1
+     */
+    public static const int CAP_ROUND = 2;
+
+    /**
+     * Line drawing style for square end caps (value is 3).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineCap(int)
+     * @see org.eclipse.swt.graphics.GC#getLineCap()
+     *
+     * @since 3.1
+     */
+    public static const int CAP_SQUARE = 3;
+
+    /**
+     * Line drawing style for miter joins (value is 1).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineJoin(int)
+     * @see org.eclipse.swt.graphics.GC#getLineJoin()
+     *
+     * @since 3.1
+     */
+    public static const int JOIN_MITER = 1;
+
+    /**
+     * Line drawing  style for rounded joins (value is 2).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineJoin(int)
+     * @see org.eclipse.swt.graphics.GC#getLineJoin()
+     *
+     * @since 3.1
+     */
+    public static const int JOIN_ROUND = 2;
+
+    /**
+     * Line drawing style for bevel joins (value is 3).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineJoin(int)
+     * @see org.eclipse.swt.graphics.GC#getLineJoin()
+     *
+     * @since 3.1
+     */
+    public static const int JOIN_BEVEL = 3;
+
+    /**
+     * Line drawing style for solid lines  (value is 1).
+     */
+    public static const int LINE_SOLID = 1;
+
+    /**
+     * Line drawing style for dashed lines (value is 2).
+     */
+    public static const int LINE_DASH = 2;
+
+    /**
+     * Line drawing style for dotted lines (value is 3).
+     */
+    public static const int LINE_DOT = 3;
+
+    /**
+     * Line drawing style for alternating dash-dot lines (value is 4).
+     */
+    public static const int LINE_DASHDOT = 4;
+
+    /**
+     * Line drawing style for dash-dot-dot lines (value is 5).
+     */
+    public static const int LINE_DASHDOTDOT = 5;
+
+    /**
+     * Line drawing style for custom dashed lines (value is 6).
+     *
+     * @see org.eclipse.swt.graphics.GC#setLineDash(int[])
+     * @see org.eclipse.swt.graphics.GC#getLineDash()
+     *
+     * @since 3.1
+     */
+    public static const int LINE_CUSTOM = 6;
+
+    /**
+     * Path constant that represents a "move to" operation (value is 1).
+     *
+     * @since 3.1
+     */
+    public static const int PATH_MOVE_TO = 1;
+
+    /**
+     * Path constant that represents a "line to" operation (value is 2).
+     *
+     * @since 3.1
+     */
+    public static const int PATH_LINE_TO = 2;
+
+    /**
+     * Path constant that represents a "quadratic curve to" operation (value is 3).
+     *
+     * @since 3.1
+     */
+    public static const int PATH_QUAD_TO = 3;
+
+    /**
+     * Path constant that represents a "cubic curve to" operation (value is 4).
+     *
+     * @since 3.1
+     */
+    public static const int PATH_CUBIC_TO = 4;
+
+    /**
+     * Path constant that represents a "close" operation (value is 5).
+     *
+     * @since 3.1
+     */
+    public static const int PATH_CLOSE = 5;
+
+    /**
+     * Even odd rule for filling operations (value is 1).
+     *
+     * @since 3.1
+     */
+    public static const int FILL_EVEN_ODD = 1;
+
+    /**
+     * Winding rule for filling operations (value is 2).
+     *
+     * @since 3.1
+     */
+    public static const int FILL_WINDING = 2;
+
+    /**
+     * Image format constant indicating an unknown image type (value is -1).
+     */
+    public static const int IMAGE_UNDEFINED = -1;
+
+    /**
+     * Image format constant indicating a Windows BMP format image (value is 0).
+     */
+    public static const int IMAGE_BMP = 0;
+
+    /**
+     * Image format constant indicating a run-length encoded
+     * Windows BMP format image (value is 1).
+     */
+    public static const int IMAGE_BMP_RLE = 1;
+
+    /**
+     * Image format constant indicating a GIF format image (value is 2).
+     */
+    public static const int IMAGE_GIF = 2;
+
+    /**
+     * Image format constant indicating a ICO format image (value is 3).
+     */
+    public static const int IMAGE_ICO = 3;
+
+    /**
+     * Image format constant indicating a JPEG format image (value is 4).
+     */
+    public static const int IMAGE_JPEG = 4;
+
+    /**
+     * Image format constant indicating a PNG format image (value is 5).
+     */
+    public static const int IMAGE_PNG = 5;
+
+    /**
+     * Image format constant indicating a TIFF format image (value is 6).
+     */
+    public static const int IMAGE_TIFF = 6;
+
+    /**
+     * Image format constant indicating an OS/2 BMP format image (value is 7).
+     */
+    public static const int IMAGE_OS2_BMP = 7;
+
+    /**
+     * GIF image disposal method constants indicating that the
+     * disposal method is unspecified (value is 0).
+     */
+    public static const int DM_UNSPECIFIED = 0x0;
+
+    /**
+     * GIF image disposal method constants indicating that the
+     * disposal method is to do nothing; that is, to leave the
+     * previous image in place (value is 1).
+     */
+    public static const int DM_FILL_NONE = 0x1;
+
+    /**
+     * GIF image disposal method constants indicating that the
+     * the previous images should be covered with the background
+     * color before displaying the next image (value is 2).
+     */
+    public static const int DM_FILL_BACKGROUND = 0x2;
+
+    /**
+     * GIF image disposal method constants indicating that the
+     * disposal method is to restore the previous picture
+     * (value is 3).
+     */
+    public static const int DM_FILL_PREVIOUS = 0x3;
+
+    /**
+     * Image transparency constant indicating that the image
+     * contains no transparency information (value is 0).
+     */
+    public static const int TRANSPARENCY_NONE = 0x0;
+
+    /**
+     * Image transparency constant indicating that the image
+     * contains alpha transparency information (value is 1&lt;&lt;0).
+     */
+    public static const int TRANSPARENCY_ALPHA = 1 << 0;
+
+    /**
+     * Image transparency constant indicating that the image
+     * contains a transparency mask (value is 1&lt;&lt;1).
+     */
+    public static const int TRANSPARENCY_MASK = 1 << 1;
+
+    /**
+     * Image transparency constant indicating that the image
+     * contains a transparent pixel (value is 1&lt;&lt;2).
+     */
+    public static const int TRANSPARENCY_PIXEL = 1 << 2;
+
+    /**
+     * The character movement type (value is 1&lt;&lt;0).
+     * This constant is used to move a text offset over a character.
+     *
+     * @see org.eclipse.swt.graphics.TextLayout#getNextOffset(int, int)
+     * @see org.eclipse.swt.graphics.TextLayout#getPreviousOffset(int, int)
+     *
+     * @since 3.0
+     */
+    public static const int MOVEMENT_CHAR = 1 << 0;
+
+    /**
+     * The cluster movement type (value is 1&lt;&lt;1).
+     * This constant is used to move a text offset over a cluster.
+     * A cluster groups one or more characters. A cluster is
+     * undivisible, this means that a caret offset can not be placed in the
+     * middle of a cluster.
+     *
+     * @see org.eclipse.swt.graphics.TextLayout#getNextOffset(int, int)
+     * @see org.eclipse.swt.graphics.TextLayout#getPreviousOffset(int, int)
+     *
+     * @since 3.0
+     */
+    public static const int MOVEMENT_CLUSTER = 1 << 1;
+
+    /**
+     * The word movement type (value is 1&lt;&lt;2).
+     * This constant is used to move a text offset over a word.
+     * The behavior of this constant depends on the platform and on the
+     * direction of the movement. For example, on Windows the stop is
+     * always at the start of the word. On GTK and Mac the stop is at the end
+     * of the word if the direction is next and at the start of the word if the
+     * direction is previous.
+     *
+     * @see org.eclipse.swt.graphics.TextLayout#getNextOffset(int, int)
+     * @see org.eclipse.swt.graphics.TextLayout#getPreviousOffset(int, int)
+     *
+     * @since 3.0
+     */
+    public static const int MOVEMENT_WORD = 1 << 2;
+
+    /**
+     * The word end movement type (value is 1&lt;&lt;3).
+     * This constant is used to move a text offset to the next or previous
+     * word end. The behavior of this constant does not depend on the platform.
+     *
+     *
+     * @see org.eclipse.swt.graphics.TextLayout#getNextOffset(int, int)
+     * @see org.eclipse.swt.graphics.TextLayout#getPreviousOffset(int, int)
+     *
+     * @since 3.3
+     */
+    public static const int MOVEMENT_WORD_END = 1 << 3;
+
+    /**
+     * The word start movement type (value is 1&lt;&lt;4).
+     * This constant is used to move a text offset to the next or previous
+     * word start. The behavior of this constant does not depend on the platform.
+     *
+     * @see org.eclipse.swt.graphics.TextLayout#getNextOffset(int, int)
+     * @see org.eclipse.swt.graphics.TextLayout#getPreviousOffset(int, int)
+     *
+     * @since 3.3
+     */
+    public static const int MOVEMENT_WORD_START = 1 << 4;
+
+
+/**
+ * Answers a concise, human readable description of the error code.
+ *
+ * @param code the SWT error code.
+ * @return a description of the error code.
+ *
+ * @see SWT
+ */
+static String findErrorText (int code) {
+    switch (code) {
+        case ERROR_UNSPECIFIED:            return "Unspecified error"; //$NON-NLS-1$
+        case ERROR_NO_HANDLES:             return "No more handles"; //$NON-NLS-1$
+        case ERROR_NO_MORE_CALLBACKS:      return "No more callbacks"; //$NON-NLS-1$
+        case ERROR_NULL_ARGUMENT:          return "Argument cannot be null"; //$NON-NLS-1$
+        case ERROR_INVALID_ARGUMENT:       return "Argument not valid"; //$NON-NLS-1$
+        case ERROR_INVALID_RANGE:          return "Index out of bounds"; //$NON-NLS-1$
+        case ERROR_CANNOT_BE_ZERO:         return "Argument cannot be zero"; //$NON-NLS-1$
+        case ERROR_CANNOT_GET_ITEM:        return "Cannot get item"; //$NON-NLS-1$
+        case ERROR_CANNOT_GET_SELECTION:   return "Cannot get selection"; //$NON-NLS-1$
+        case ERROR_CANNOT_GET_ITEM_HEIGHT: return "Cannot get item height"; //$NON-NLS-1$
+        case ERROR_CANNOT_GET_TEXT:        return "Cannot get text"; //$NON-NLS-1$
+        case ERROR_CANNOT_SET_TEXT:        return "Cannot set text"; //$NON-NLS-1$
+        case ERROR_ITEM_NOT_ADDED:         return "Item not added"; //$NON-NLS-1$
+        case ERROR_ITEM_NOT_REMOVED:       return "Item not removed"; //$NON-NLS-1$
+        case ERROR_NOT_IMPLEMENTED:        return "Not implemented"; //$NON-NLS-1$
+        case ERROR_MENU_NOT_DROP_DOWN:     return "Menu must be a drop down"; //$NON-NLS-1$
+        case ERROR_THREAD_INVALID_ACCESS:  return "Invalid thread access"; //$NON-NLS-1$
+        case ERROR_WIDGET_DISPOSED:        return "Widget is disposed"; //$NON-NLS-1$
+        case ERROR_MENUITEM_NOT_CASCADE:   return "Menu item is not a CASCADE"; //$NON-NLS-1$
+        case ERROR_CANNOT_SET_SELECTION:   return "Cannot set selection";  //$NON-NLS-1$
+        case ERROR_CANNOT_SET_MENU:        return "Cannot set menu";  //$NON-NLS-1$
+        case ERROR_CANNOT_SET_ENABLED:     return "Cannot set the enabled state";  //$NON-NLS-1$
+        case ERROR_CANNOT_GET_ENABLED:     return "Cannot get the enabled state";  //$NON-NLS-1$
+        case ERROR_INVALID_PARENT:         return "Widget has the wrong parent";  //$NON-NLS-1$
+        case ERROR_MENU_NOT_BAR:           return "Menu is not a BAR";  //$NON-NLS-1$
+        case ERROR_CANNOT_GET_COUNT:       return "Cannot get count"; //$NON-NLS-1$
+        case ERROR_MENU_NOT_POP_UP:        return "Menu is not a POP_UP"; //$NON-NLS-1$
+        case ERROR_UNSUPPORTED_DEPTH:      return "Unsupported color depth"; //$NON-NLS-1$
+        case ERROR_IO:                     return "i/o error"; //$NON-NLS-1$
+        case ERROR_INVALID_IMAGE:          return "Invalid image"; //$NON-NLS-1$
+        case ERROR_UNSUPPORTED_FORMAT:     return "Unsupported or unrecognized format"; //$NON-NLS-1$
+        case ERROR_INVALID_SUBCLASS:       return "Subclassing not allowed"; //$NON-NLS-1$
+        case ERROR_GRAPHIC_DISPOSED:       return "Graphic is disposed"; //$NON-NLS-1$
+        case ERROR_DEVICE_DISPOSED:        return "Device is disposed"; //$NON-NLS-1$
+        case ERROR_FAILED_EXEC:            return "Failed to execute runnable"; //$NON-NLS-1$
+        case ERROR_FAILED_LOAD_LIBRARY:    return "Unable to load library"; //$NON-NLS-1$
+        case ERROR_CANNOT_INVERT_MATRIX:   return "Cannot invert matrix"; //$NON-NLS-1$
+        case ERROR_NO_GRAPHICS_LIBRARY:    return "Unable to load graphics library"; //$NON-NLS-1$
+        case ERROR_INVALID_FONT:           return "Font not valid"; //$NON-NLS-1$
+        default:
+    }
+    return "Unknown error"; //$NON-NLS-1$
+}
+
+/**
+ * Returns the NLS'ed message for the given argument.
+ *
+ * @param key the key to look up
+ * @return the message for the given key
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
+ * </ul>
+ */
+public static String getMessage(String key) {
+    return Compatibility.getMessage(key);
+}
+
+/**
+ * Returns the SWT platform name.
+ * Examples: "win32", "motif", "gtk", "photon", "carbon"
+ *
+ * @return the SWT platform name
+ */
+public static String getPlatform () {
+    return Platform.PLATFORM;
+}
+
+/**
+ * Returns the SWT version number as an integer.
+ * Example: "SWT051" is 51
+ *
+ * @return the SWT version number
+ */
+public static int getVersion () {
+    return Library.SWT_VERSION;
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ *
+ * @param code the SWT error code
+ */
+public static void error (String file, long line, int code) {
+    error (code, null);
+}
+public static void error (int code) {
+    error (code, null);
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ * The <code>throwable</code> argument should be either null, or the
+ * throwable which caused SWT to throw an exception.
+ * <p>
+ * In SWT, errors are reported by throwing one of three exceptions:
+ * <dl>
+ * <dd>java.lang.IllegalArgumentException</dd>
+ * <dt>thrown whenever one of the API methods is invoked with an illegal argument</dt>
+ * <dd>org.eclipse.swt.SWTException (extends java.lang.RuntimeException)</dd>
+ * <dt>thrown whenever a recoverable error happens internally in SWT</dt>
+ * <dd>org.eclipse.swt.SWTError (extends java.lang.Error)</dd>
+ * <dt>thrown whenever a <b>non-recoverable</b> error happens internally in SWT</dt>
+ * </dl>
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ * </p>
+ *
+ * @param code the SWT error code.
+ * @param throwable the exception which caused the error to occur.
+ *
+ * @see SWTError
+ * @see SWTException
+ * @see IllegalArgumentException
+ */
+public static void error (int code, Exception throwable) {
+    error (code, throwable, null);
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ * The <code>throwable</code> argument should be either null, or the
+ * throwable which caused SWT to throw an exception.
+ * <p>
+ * In SWT, errors are reported by throwing one of three exceptions:
+ * <dl>
+ * <dd>java.lang.IllegalArgumentException</dd>
+ * <dt>thrown whenever one of the API methods is invoked with an illegal argument</dt>
+ * <dd>org.eclipse.swt.SWTException (extends java.lang.RuntimeException)</dd>
+ * <dt>thrown whenever a recoverable error happens internally in SWT</dt>
+ * <dd>org.eclipse.swt.SWTError (extends java.lang.Error)</dd>
+ * <dt>thrown whenever a <b>non-recoverable</b> error happens internally in SWT</dt>
+ * </dl>
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ * </p>
+ *
+ * @param code the SWT error code.
+ * @param throwable the exception which caused the error to occur.
+ * @param detail more information about error.
+ *
+ * @see SWTError
+ * @see SWTException
+ * @see IllegalArgumentException
+ *
+ * @since 3.0
+ */
+public static void error (int code, Exception throwable, String detail) {
+
+    /*
+    * This code prevents the creation of "chains" of SWTErrors and
+    * SWTExceptions which in turn contain other SWTErrors and
+    * SWTExceptions as their throwable. This can occur when low level
+    * code throws an exception past a point where a higher layer is
+    * being "safe" and catching all exceptions. (Note that, this is
+    * _a_bad_thing_ which we always try to avoid.)
+    *
+    * On the theory that the low level code is closest to the
+    * original problem, we simply re-throw the original exception here.
+    *
+    * NOTE: Exceptions thrown in syncExec and asyncExec must be
+    * wrapped.
+    */
+    if (code !is SWT.ERROR_FAILED_EXEC) {
+        if (auto t = cast(SWTError)throwable ) throw t;
+        if (auto t = cast(SWTException)throwable ) throw t;
+    }
+
+    String message = findErrorText (code);
+    if (detail != null) message ~= detail;
+    switch (code) {
+
+        /* Illegal Arguments (non-fatal) */
+        case ERROR_NULL_ARGUMENT:
+        case ERROR_CANNOT_BE_ZERO:
+        case ERROR_INVALID_ARGUMENT:
+        case ERROR_MENU_NOT_BAR:
+        case ERROR_MENU_NOT_DROP_DOWN:
+        case ERROR_MENU_NOT_POP_UP:
+        case ERROR_MENUITEM_NOT_CASCADE:
+        case ERROR_INVALID_PARENT:
+        case ERROR_INVALID_RANGE: {
+            throw new IllegalArgumentException (message);
+        }
+
+        /* SWT Exceptions (non-fatal) */
+        case ERROR_INVALID_SUBCLASS:
+        case ERROR_THREAD_INVALID_ACCESS:
+        case ERROR_WIDGET_DISPOSED:
+        case ERROR_GRAPHIC_DISPOSED:
+        case ERROR_DEVICE_DISPOSED:
+        case ERROR_INVALID_IMAGE:
+        case ERROR_UNSUPPORTED_DEPTH:
+        case ERROR_UNSUPPORTED_FORMAT:
+        case ERROR_FAILED_EXEC:
+        case ERROR_CANNOT_INVERT_MATRIX:
+        case ERROR_NO_GRAPHICS_LIBRARY:
+        case ERROR_IO: {
+            auto exception = new SWTException (code, message);
+            exception.throwable = throwable;
+            throw exception;
+        }
+
+        /* Operation System Errors (fatal, may occur only on some platforms) */
+        case ERROR_CANNOT_GET_COUNT:
+        case ERROR_CANNOT_GET_ENABLED:
+        case ERROR_CANNOT_GET_ITEM:
+        case ERROR_CANNOT_GET_ITEM_HEIGHT:
+        case ERROR_CANNOT_GET_SELECTION:
+        case ERROR_CANNOT_GET_TEXT:
+        case ERROR_CANNOT_SET_ENABLED:
+        case ERROR_CANNOT_SET_MENU:
+        case ERROR_CANNOT_SET_SELECTION:
+        case ERROR_CANNOT_SET_TEXT:
+        case ERROR_ITEM_NOT_ADDED:
+        case ERROR_ITEM_NOT_REMOVED:
+        case ERROR_NO_HANDLES:
+        //FALL THROUGH
+
+        /* SWT Errors (fatal, may occur only on some platforms) */
+        case ERROR_FAILED_LOAD_LIBRARY:
+        case ERROR_NO_MORE_CALLBACKS:
+        case ERROR_NOT_IMPLEMENTED:
+        case ERROR_UNSPECIFIED: {
+            auto error = new SWTError (code, message);
+            error.throwable = throwable;
+            throw error;
+        }
+        default:
+    }
+
+    /* Unknown/Undefined Error */
+    SWTError error = new SWTError (code, message);
+    error.throwable = throwable;
+    throw error;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTError.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.SWTError;
+
+import org.eclipse.swt.SWT;
+
+import tango.core.Exception;
+import tango.io.Stdout;
+import java.lang.all;
+
+/**
+ * This error is thrown whenever an unrecoverable error
+ * occurs internally in SWT. The message text and error code
+ * provide a further description of the problem. The exception
+ * has a <code>throwable</code> field which holds the underlying
+ * throwable that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * <p>
+ * SWTErrors are thrown when something fails internally which
+ * either leaves SWT in an unknown state (eg. the o/s call to
+ * remove an item from a list returns an error code) or when SWT
+ * is left in a known-to-be-unrecoverable state (eg. it runs out
+ * of callback resources). SWTErrors should not occur in typical
+ * programs, although "high reliability" applications should
+ * still catch them.
+ * </p><p>
+ * This class also provides support methods used by SWT to match
+ * error codes to the appropriate exception class (SWTError,
+ * SWTException, or IllegalArgumentException) and to provide
+ * human readable strings for SWT error codes.
+ * </p>
+ *
+ * @see SWTException
+ * @see SWT#error(int)
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class SWTError : PlatformException {
+    /**
+     * The SWT error code, one of SWT.ERROR_*.
+     */
+    public int code;
+
+    /**
+     * The underlying throwable that caused the problem,
+     * or null if this information is not available.
+     */
+    public Exception throwable( Exception e ){
+        this.next = e;
+        return this.next;
+    }
+    public Exception throwable(){
+        return this.next;
+    }
+
+    //static final long serialVersionUID = 3833467327105808433L;
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace filled in. The error code is set to an
+ * unspecified value.
+ */
+public this () {
+    this (SWT.ERROR_UNSPECIFIED);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and message filled in. The error code is
+ * set to an unspecified value.  Specifying <code>null</code>
+ * as the message is equivalent to specifying an empty string.
+ *
+ * @param message the detail message for the exception
+ */
+public this (String message) {
+    this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public this (int code) {
+    this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace, error code and message filled in.
+ * Specifying <code>null</code> as the message is
+ * equivalent to specifying an empty string.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public this (int code, String message) {
+    super (message);
+    this.code = code;
+}
+
+/**
+ * Returns the underlying throwable that caused the problem,
+ * or null if this information is not available.
+ * <p>
+ * NOTE: This method overrides Throwable.getCause() that was
+ * added to JDK1.4. It is necessary to override this method
+ * in order for inherited printStackTrace() methods to work.
+ * </p>
+ * @return the underlying throwable
+ *
+ * @since 3.1
+ */
+public Exception getCause() {
+    return throwable;
+}
+
+/**
+ *  Returns the string describing this SWTError object.
+ *  <p>
+ *  It is combined with the message string of the Throwable
+ *  which caused this SWTError (if this information is available).
+ *  </p>
+ *  @return the error message string of this SWTError object
+ */
+public String getMessage () {
+    if (throwable is null)
+        return super.toString();
+    return super.toString () ~ " (" ~ throwable.toString () ~ ")"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+/**
+ * Outputs a printable representation of this error's
+ * stack trace on the standard error stream.
+ * <p>
+ * Note: printStackTrace(PrintStream) and printStackTrace(PrintWriter)
+ * are not provided in order to maintain compatibility with CLDC.
+ * </p>
+ */
+public void printStackTrace () {
+    Stderr.formatln( "stacktrace follows (if feature compiled in)" );
+    foreach( msg; info ){
+        Stderr.formatln( "{}", msg );
+    }
+    if ( throwable !is null) {
+        Stderr.formatln ("*** Stack trace of contained error ***"); //$NON-NLS-1$
+        foreach( msg; throwable.info ){
+            Stderr.formatln( "{}", msg );
+        }
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/SWTException.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.SWTException;
+
+import org.eclipse.swt.SWT;
+
+import tango.core.Exception;
+import tango.io.Stdout;
+import java.lang.all;
+
+/**
+ * This runtime exception is thrown whenever a recoverable error
+ * occurs internally in SWT. The message text and error code
+ * provide a further description of the problem. The exception
+ * has a <code>throwable</code> field which holds the underlying
+ * exception that caused the problem (if this information is
+ * available (i.e. it may be null)).
+ * <p>
+ * SWTExceptions are thrown when something fails internally,
+ * but SWT is left in a known stable state (eg. a widget call
+ * was made from a non-u/i thread, or there is failure while
+ * reading an Image because the source file was corrupt).
+ * </p>
+ *
+ * @see SWTError
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class SWTException : Exception {
+    /**
+     * The SWT error code, one of SWT.ERROR_*.
+     */
+    public int code;
+
+    /**
+     * The underlying throwable that caused the problem,
+     * or null if this information is not available.
+     */
+    public Exception throwable( Exception e ){
+        this.next = e;
+        return this.next;
+    }
+    public Exception throwable(){
+        return this.next;
+    }
+
+
+    //static final long serialVersionUID = 3257282552304842547L;
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace filled in. The error code is set to an
+ * unspecified value.
+ */
+public this () {
+    this (SWT.ERROR_UNSPECIFIED);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and message filled in. The error code is
+ * set to an unspecified value.  Specifying <code>null</code>
+ * as the message is equivalent to specifying an empty string.
+ *
+ * @param message the detail message for the exception
+ */
+public this (String message) {
+    this (SWT.ERROR_UNSPECIFIED, message);
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace and error code filled in.
+ *
+ * @param code the SWT error code
+ */
+public this (int code) {
+    this (code, SWT.findErrorText (code));
+}
+
+/**
+ * Constructs a new instance of this class with its
+ * stack trace, error code and message filled in.
+ * Specifying <code>null</code> as the message is
+ * equivalent to specifying an empty string.
+ *
+ * @param code the SWT error code
+ * @param message the detail message for the exception
+ */
+public this (int code, String message) {
+    super (message);
+    this.code = code;
+}
+
+/**
+ * Returns the underlying throwable that caused the problem,
+ * or null if this information is not available.
+ * <p>
+ * NOTE: This method overrides Throwable.getCause() that was
+ * added to JDK1.4. It is necessary to override this method
+ * in order for inherited printStackTrace() methods to work.
+ * </p>
+ * @return the underlying throwable
+ *
+ * @since 3.1
+ */
+public Exception getCause() {
+    return throwable;
+}
+
+/**
+ *  Returns the string describing this SWTException object.
+ *  <p>
+ *  It is combined with the message string of the Throwable
+ *  which caused this SWTException (if this information is available).
+ *  </p>
+ *  @return the error message string of this SWTException object
+ */
+public String getMessage () {
+    if (throwable is null) return super.toString ();
+    return super.toString () ~ " (" ~ throwable.toString () ~ ")"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+/**
+ * Outputs a printable representation of this exception's
+ * stack trace on the standard error stream.
+ * <p>
+ * Note: printStackTrace(PrintStream) and printStackTrace(PrintWriter)
+ * are not provided in order to maintain compatibility with CLDC.
+ * </p>
+ */
+public void printStackTrace () {
+    Stderr.formatln( "stacktrace follows (if feature compiled in)" );
+    foreach( msg; info ){
+        Stderr.formatln( "{}", msg );
+    }
+    if ( throwable !is null) {
+        Stderr.formatln ("*** Stack trace of contained exception ***"); //$NON-NLS-1$
+        foreach( msg; throwable.info ){
+            Stderr.formatln( "{}", msg );
+        }
+    }
+}
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/ACC.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.ACC;
+
+
+/**
+ * Class ACC contains all the constants used in defining an
+ * Accessible object.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 2.0
+ */
+public class ACC {
+    public static const int STATE_NORMAL = 0x00000000;
+    public static const int STATE_SELECTED = 0x00000002;
+    public static const int STATE_SELECTABLE = 0x00200000;
+    public static const int STATE_MULTISELECTABLE = 0x1000000;
+    public static const int STATE_FOCUSED = 0x00000004;
+    public static const int STATE_FOCUSABLE = 0x00100000;
+    public static const int STATE_PRESSED = 0x8;
+    public static const int STATE_CHECKED = 0x10;
+    public static const int STATE_EXPANDED = 0x200;
+    public static const int STATE_COLLAPSED = 0x400;
+    public static const int STATE_HOTTRACKED = 0x80;
+    public static const int STATE_BUSY = 0x800;
+    public static const int STATE_READONLY = 0x40;
+    public static const int STATE_INVISIBLE = 0x8000;
+    public static const int STATE_OFFSCREEN = 0x10000;
+    public static const int STATE_SIZEABLE = 0x20000;
+    public static const int STATE_LINKED = 0x400000;
+
+    public static const int ROLE_CLIENT_AREA = 0xa;
+    public static const int ROLE_WINDOW = 0x9;
+    public static const int ROLE_MENUBAR = 0x2;
+    public static const int ROLE_MENU = 0xb;
+    public static const int ROLE_MENUITEM = 0xc;
+    public static const int ROLE_SEPARATOR = 0x15;
+    public static const int ROLE_TOOLTIP = 0xd;
+    public static const int ROLE_SCROLLBAR = 0x3;
+    public static const int ROLE_DIALOG = 0x12;
+    public static const int ROLE_LABEL = 0x29;
+    public static const int ROLE_PUSHBUTTON = 0x2b;
+    public static const int ROLE_CHECKBUTTON = 0x2c;
+    public static const int ROLE_RADIOBUTTON = 0x2d;
+    public static const int ROLE_COMBOBOX = 0x2e;
+    public static const int ROLE_TEXT = 0x2a;
+    public static const int ROLE_TOOLBAR = 0x16;
+    public static const int ROLE_LIST = 0x21;
+    public static const int ROLE_LISTITEM = 0x22;
+    public static const int ROLE_TABLE = 0x18;
+    public static const int ROLE_TABLECELL = 0x1d;
+    public static const int ROLE_TABLECOLUMNHEADER = 0x19;
+    /** @deprecated use ROLE_TABLECOLUMNHEADER */
+    public static const int ROLE_TABLECOLUMN = ROLE_TABLECOLUMNHEADER;
+    public static const int ROLE_TABLEROWHEADER = 0x1a;
+    public static const int ROLE_TREE = 0x23;
+    public static const int ROLE_TREEITEM = 0x24;
+    public static const int ROLE_TABFOLDER = 0x3c;
+    public static const int ROLE_TABITEM = 0x25;
+    public static const int ROLE_PROGRESSBAR = 0x30;
+    public static const int ROLE_SLIDER = 0x33;
+    public static const int ROLE_LINK = 0x1e;
+
+    public static const int CHILDID_SELF = -1;
+    public static const int CHILDID_NONE = -2;
+    public static const int CHILDID_MULTIPLE = -3;
+
+    public static const int TEXT_INSERT = 0;
+    public static const int TEXT_DELETE = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/Accessible.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1487 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.Accessible;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.ifs;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleControlListener;
+import org.eclipse.swt.accessibility.AccessibleListener;
+import org.eclipse.swt.accessibility.AccessibleTextListener;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+
+import java.lang.all;
+import tango.core.Array;
+import tango.core.Thread;
+
+/**
+ * Instances of this class provide a bridge between application
+ * code and assistive technology clients. Many platforms provide
+ * default accessible behavior for most widgets, and this class
+ * allows that default behavior to be overridden. Applications
+ * can get the default Accessible object for a control by sending
+ * it <code>getAccessible</code>, and then add an accessible listener
+ * to override simple items like the name and help string, or they
+ * can add an accessible control listener to override complex items.
+ * As a rule of thumb, an application would only want to use the
+ * accessible control listener to implement accessibility for a
+ * custom control.
+ *
+ * @see Control#getAccessible
+ * @see AccessibleListener
+ * @see AccessibleEvent
+ * @see AccessibleControlListener
+ * @see AccessibleControlEvent
+ * @see <a href="http://www.eclipse.org/swt/snippets/#accessibility">Accessibility snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public class Accessible {
+    int refCount = 0, enumIndex = 0;
+    _IAccessibleImpl objIAccessible;
+    _IEnumVARIANTImpl objIEnumVARIANT;
+    IAccessible iaccessible;
+    SWTEventListener[] accessibleListeners;
+    SWTEventListener[] accessibleControlListeners;
+    SWTEventListener[] textListeners;
+    Object[] variants;
+    Control control;
+
+    this(Control control) {
+        this.control = control;
+        int /*long*/[] ppvObject = new int /*long*/[1];
+        /* CreateStdAccessibleObject([in] hwnd, [in] idObject, [in] riidInterface, [out] ppvObject).
+         * AddRef has already been called on ppvObject by the callee and must be released by the caller.
+         */
+        HRESULT result = COM.CreateStdAccessibleObject(control.handle, COM.OBJID_CLIENT, &COM.IIDIAccessible, cast(void**)&iaccessible);
+        /* The object needs to be checked, because if the CreateStdAccessibleObject()
+         * symbol is not found, the return value is S_OK.
+         */
+        if (iaccessible is null) return;
+        if (result !is COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+        objIAccessible = new _IAccessibleImpl(this);
+
+//PORTING_FIXME: i don't understand this...
+/+
+        int /*long*/ ppVtable = objIAccessible.ppVtable;
+        int /*long*/[] pVtable = new int /*long*/[1];
+        COM.MoveMemory(pVtable, ppVtable, OS.PTR_SIZEOF);
+        int /*long*/[] funcs = new int /*long*/[28];
+        COM.MoveMemory(funcs, pVtable[0], OS.PTR_SIZEOF * funcs.length);
+        funcs[9] = COM.get_accChild_CALLBACK(funcs[9]);
+        funcs[10] = COM.get_accName_CALLBACK(funcs[10]);
+        funcs[11] = COM.get_accValue_CALLBACK(funcs[11]);
+        funcs[12] = COM.get_accDescription_CALLBACK(funcs[12]);
+        funcs[13] = COM.get_accRole_CALLBACK(funcs[13]);
+        funcs[14] = COM.get_accState_CALLBACK(funcs[14]);
+        funcs[15] = COM.get_accHelp_CALLBACK(funcs[15]);
+        funcs[16] = COM.get_accHelpTopic_CALLBACK(funcs[16]);
+        funcs[17] = COM.get_accKeyboardShortcut_CALLBACK(funcs[17]);
+        funcs[20] = COM.get_accDefaultAction_CALLBACK(funcs[20]);
+        funcs[21] = COM.accSelect_CALLBACK(funcs[21]);
+        funcs[22] = COM.accLocation_CALLBACK(funcs[22]);
+        funcs[23] = COM.accNavigate_CALLBACK(funcs[23]);
+        funcs[25] = COM.accDoDefaultAction_CALLBACK(funcs[25]);
+        funcs[26] = COM.put_accName_CALLBACK(funcs[26]);
+        funcs[27] = COM.put_accValue_CALLBACK(funcs[27]);
+        COM.MoveMemory(pVtable[0], funcs, OS.PTR_SIZEOF * funcs.length);
++/
+
+        objIEnumVARIANT = new _IEnumVARIANTImpl(this) ;
+        AddRef();
+    }
+
+    /**
+     * Invokes platform specific functionality to allocate a new accessible object.
+     * <p>
+     * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+     * API for <code>Accessible</code>. It is marked public only so that it
+     * can be shared within the packages provided by SWT. It is not
+     * available on all platforms, and should never be called from
+     * application code.
+     * </p>
+     *
+     * @param control the control to get the accessible object for
+     * @return the platform specific accessible object
+     */
+    public static Accessible internal_new_Accessible(Control control) {
+        return new Accessible(control);
+    }
+
+    /**
+     * Adds the listener to the collection of listeners who will
+     * be notified when an accessible client asks for certain strings,
+     * such as name, description, help, or keyboard shortcut. The
+     * listener is notified by sending it one of the messages defined
+     * in the <code>AccessibleListener</code> interface.
+     *
+     * @param listener the listener that should be notified when the receiver
+     * is asked for a name, description, help, or keyboard shortcut string
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleListener
+     * @see #removeAccessibleListener
+     */
+    public void addAccessibleListener(AccessibleListener listener) {
+        checkWidget();
+        if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+        accessibleListeners ~= listener;
+    }
+
+    /**
+     * Adds the listener to the collection of listeners who will
+     * be notified when an accessible client asks for custom control
+     * specific information. The listener is notified by sending it
+     * one of the messages defined in the <code>AccessibleControlListener</code>
+     * interface.
+     *
+     * @param listener the listener that should be notified when the receiver
+     * is asked for custom control specific information
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleControlListener
+     * @see #removeAccessibleControlListener
+     */
+    public void addAccessibleControlListener(AccessibleControlListener listener) {
+        checkWidget();
+        if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+        accessibleControlListeners ~= listener;
+    }
+
+    /**
+     * Adds the listener to the collection of listeners who will
+     * be notified when an accessible client asks for custom text control
+     * specific information. The listener is notified by sending it
+     * one of the messages defined in the <code>AccessibleTextListener</code>
+     * interface.
+     *
+     * @param listener the listener that should be notified when the receiver
+     * is asked for custom text control specific information
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleTextListener
+     * @see #removeAccessibleTextListener
+     *
+     * @since 3.0
+     */
+    public void addAccessibleTextListener (AccessibleTextListener listener) {
+        checkWidget ();
+        if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+        textListeners ~= listener;
+    }
+
+    /**
+     * Returns the control for this Accessible object.
+     *
+     * @return the receiver's control
+     * @since 3.0
+     */
+    public Control getControl() {
+        return control;
+    }
+
+    /**
+     * Invokes platform specific functionality to dispose an accessible object.
+     * <p>
+     * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+     * API for <code>Accessible</code>. It is marked public only so that it
+     * can be shared within the packages provided by SWT. It is not
+     * available on all platforms, and should never be called from
+     * application code.
+     * </p>
+     */
+    public void internal_dispose_Accessible() {
+        if (iaccessible !is null) {
+            iaccessible.Release();
+        }
+        iaccessible = null;
+        Release();
+    }
+
+    /**
+     * Invokes platform specific functionality to handle a window message.
+     * <p>
+     * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+     * API for <code>Accessible</code>. It is marked public only so that it
+     * can be shared within the packages provided by SWT. It is not
+     * available on all platforms, and should never be called from
+     * application code.
+     * </p>
+     */
+    public int /*long*/ internal_WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) {
+        if (objIAccessible is null) return 0;
+        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.
+             */
+            return COM.LresultFromObject(&COM.IIDIAccessible, wParam, cast(IAccessible)objIAccessible);
+        }
+        return 0;
+    }
+
+    /**
+     * Removes the listener from the collection of listeners who will
+     * be notified when an accessible client asks for certain strings,
+     * such as name, description, help, or keyboard shortcut.
+     *
+     * @param listener the listener that should no longer be notified when the receiver
+     * is asked for a name, description, help, or keyboard shortcut string
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleListener
+     * @see #addAccessibleListener
+     */
+    public void removeAccessibleListener(AccessibleListener listener) {
+        checkWidget();
+        if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+        accessibleListeners.length = accessibleListeners.remove(listener);
+    }
+
+    /**
+     * Removes the listener from the collection of listeners who will
+     * be notified when an accessible client asks for custom control
+     * specific information.
+     *
+     * @param listener the listener that should no longer be notified when the receiver
+     * is asked for custom control specific information
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleControlListener
+     * @see #addAccessibleControlListener
+     */
+    public void removeAccessibleControlListener(AccessibleControlListener listener) {
+        checkWidget();
+        if (listener is null) SWT.error(__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+        accessibleControlListeners.length = accessibleControlListeners.remove(listener);
+    }
+
+    /**
+     * Removes the listener from the collection of listeners who will
+     * be notified when an accessible client asks for custom text control
+     * specific information.
+     *
+     * @param listener the listener that should no longer be notified when the receiver
+     * is asked for custom text control specific information
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+     * </ul>
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see AccessibleTextListener
+     * @see #addAccessibleTextListener
+     *
+     * @since 3.0
+     */
+    public void removeAccessibleTextListener (AccessibleTextListener listener) {
+        checkWidget ();
+        if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+        textListeners.length = textListeners.remove (listener);
+    }
+
+    /**
+     * Sends a message to accessible clients that the child selection
+     * within a custom container control has changed.
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @since 3.0
+     */
+    public void selectionChanged () {
+        checkWidget();
+        COM.NotifyWinEvent (COM.EVENT_OBJECT_SELECTIONWITHIN, control.handle, COM.OBJID_CLIENT, COM.CHILDID_SELF);
+    }
+
+    /**
+     * Sends a message to accessible clients indicating that the focus
+     * has changed within a custom control.
+     *
+     * @param childID an identifier specifying a child of the control
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     */
+    public void setFocus(int childID) {
+        checkWidget();
+        COM.NotifyWinEvent (COM.EVENT_OBJECT_FOCUS, control.handle, COM.OBJID_CLIENT, childIDToOs(childID));
+    }
+
+    /**
+     * Sends a message to accessible clients that the text
+     * caret has moved within a custom control.
+     *
+     * @param index the new caret index within the control
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @since 3.0
+     */
+    public void textCaretMoved (int index) {
+        checkWidget();
+        COM.NotifyWinEvent (COM.EVENT_OBJECT_LOCATIONCHANGE, control.handle, COM.OBJID_CARET, COM.CHILDID_SELF);
+    }
+
+    /**
+     * Sends a message to accessible clients that the text
+     * within a custom control has changed.
+     *
+     * @param type the type of change, one of <code>ACC.NOTIFY_TEXT_INSERT</code>
+     * or <code>ACC.NOTIFY_TEXT_DELETE</code>
+     * @param startIndex the text index within the control where the insertion or deletion begins
+     * @param length the non-negative length in characters of the insertion or deletion
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @see ACC#TEXT_INSERT
+     * @see ACC#TEXT_DELETE
+     *
+     * @since 3.0
+     */
+    public void textChanged (int type, int startIndex, int length) {
+        checkWidget();
+        COM.NotifyWinEvent (COM.EVENT_OBJECT_VALUECHANGE, control.handle, COM.OBJID_CLIENT, COM.CHILDID_SELF);
+    }
+
+    /**
+     * Sends a message to accessible clients that the text
+     * selection has changed within a custom control.
+     *
+     * @exception SWTException <ul>
+     *    <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
+     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
+     * </ul>
+     *
+     * @since 3.0
+     */
+    public void textSelectionChanged () {
+        checkWidget();
+        // not an MSAA event
+    }
+
+    /* QueryInterface([in] iid, [out] ppvObject)
+     * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
+     * must be incremented before returning.  Caller is responsible for releasing ppvObject.
+     */
+    HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+
+        if (COM.IsEqualGUID(riid, &COM.IIDIUnknown)) {
+            *ppvObject = cast(void*)cast(IUnknown)  objIAccessible;
+            AddRef();
+            return COM.S_OK;
+        }
+
+        if (COM.IsEqualGUID(riid, &COM.IIDIDispatch)) {
+            *ppvObject = cast(void*)cast(IDispatch) objIAccessible;
+            AddRef();
+            return COM.S_OK;
+        }
+
+        if (COM.IsEqualGUID(riid, &COM.IIDIAccessible)) {
+            *ppvObject = cast(void*)cast(IAccessible) objIAccessible;
+            AddRef();
+            return COM.S_OK;
+        }
+
+        if (COM.IsEqualGUID(riid, &COM.IIDIEnumVARIANT)) {
+            *ppvObject = cast(void*)cast(IEnumVARIANT) objIEnumVARIANT;
+            AddRef();
+            enumIndex = 0;
+            return COM.S_OK;
+        }
+
+        HRESULT result = iaccessible.QueryInterface(riid, ppvObject);
+        return result;
+    }
+
+    ULONG AddRef() {
+        refCount++;
+        return refCount;
+    }
+
+    ULONG Release() {
+        refCount--;
+
+        if (refCount is 0) {
+            objIAccessible = null;
+            objIEnumVARIANT = null;
+        }
+        return refCount;
+    }
+
+    HRESULT accDoDefaultAction(VARIANT variant) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // Currently, we don't let the application override this. Forward to the proxy.
+        int code = iaccessible.accDoDefaultAction(variant);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    HRESULT accHitTest(LONG xLeft, LONG yTop, VARIANT* pvarChild) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        if (accessibleControlListeners.length is 0) {
+            return iaccessible.accHitTest(xLeft, yTop, pvarChild);
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = ACC.CHILDID_NONE;
+        event.x = xLeft;
+        event.y = yTop;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getChildAtPoint(event);
+        }
+        int childID = event.childID;
+        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;
+    }
+
+    HRESULT accLocation(LONG* pxLeft, LONG* pyTop, LONG* pcxWidth, LONG* pcyHeight, VARIANT variant) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default location from the OS. */
+        int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0;
+        int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, variant);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleControlListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            int[1] pLeft, pTop, pWidth, pHeight;
+            COM.MoveMemory(pLeft.ptr, pxLeft, 4);
+            COM.MoveMemory(pTop.ptr, pyTop, 4);
+            COM.MoveMemory(pWidth.ptr, pcxWidth, 4);
+            COM.MoveMemory(pHeight.ptr, pcyHeight, 4);
+            osLeft = pLeft[0]; osTop = pTop[0]; osWidth = pWidth[0]; osHeight = pHeight[0];
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.x = osLeft;
+        event.y = osTop;
+        event.width = osWidth;
+        event.height = osHeight;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getLocation(event);
+        }
+        OS.MoveMemory(pxLeft, &event.x, 4);
+        OS.MoveMemory(pyTop, &event.y, 4);
+        OS.MoveMemory(pcxWidth, &event.width, 4);
+        OS.MoveMemory(pcyHeight, &event.height, 4);
+        return COM.S_OK;
+    }
+
+    HRESULT accNavigate(LONG navDir, VARIANT variant, VARIANT* pvarEndUpAt) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // Currently, we don't let the application override this. Forward to the proxy.
+        int code = iaccessible.accNavigate(navDir, variant, pvarEndUpAt);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    HRESULT accSelect(LONG flagsSelect, VARIANT variant) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // Currently, we don't let the application override this. Forward to the proxy.
+        int code = iaccessible.accSelect(flagsSelect, variant);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    /* get_accChild([in] varChild, [out] ppdispChild)
+     * Ownership of ppdispChild transfers from callee to caller so reference count on ppdispChild
+     * must be incremented before returning.  The caller is responsible for releasing ppdispChild.
+     */
+    HRESULT get_accChild(VARIANT variant, LPDISPATCH* ppdispChild) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+        if (accessibleControlListeners.length is 0) {
+            int code = iaccessible.get_accChild(variant, ppdispChild);
+            if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+            return code;
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getChild(event);
+        }
+        Accessible accessible = event.accessible;
+        if (accessible !is null) {
+            accessible.AddRef();
+            *ppdispChild = accessible.objIAccessible;
+            return COM.S_OK;
+        }
+        return COM.S_FALSE;
+    }
+
+    HRESULT get_accChildCount(LONG* pcountChildren) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+
+        /* Get the default child count from the OS. */
+        int osChildCount = 0;
+        int code = iaccessible.get_accChildCount(pcountChildren);
+        if (accessibleControlListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            int[1] pChildCount;
+            COM.MoveMemory(pChildCount.ptr, pcountChildren, 4);
+            osChildCount = pChildCount[0];
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = ACC.CHILDID_SELF;
+        event.detail = osChildCount;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getChildCount(event);
+        }
+
+        *pcountChildren = event.detail;
+        return COM.S_OK;
+    }
+
+    HRESULT get_accDefaultAction(VARIANT variant, BSTR* pszDefaultAction) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default defaultAction from the OS. */
+        String osDefaultAction = null;
+        int code = iaccessible.get_accDefaultAction(variant, pszDefaultAction);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleControlListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            osDefaultAction = BSTRToStr( *pszDefaultAction, true );
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osDefaultAction;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getDefaultAction(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszDefaultAction = ptr;
+        return COM.S_OK;
+    }
+
+    HRESULT get_accDescription(VARIANT variant, BSTR* pszDescription) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default description from the OS. */
+        String osDescription = null;
+        int code = iaccessible.get_accDescription(variant, pszDescription);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        // TEMPORARY CODE - process tree even if there are no apps listening
+        if (accessibleListeners.length is 0 && !( null is cast(Tree)control )) return code;
+        if (code is COM.S_OK) {
+            int size = COM.SysStringByteLen(*pszDescription);
+            if (size > 0) {
+                size = (size + 1) /2;
+                osDescription = WCHARzToStr(*pszDescription, size);
+            }
+        }
+
+        AccessibleEvent event = new AccessibleEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osDescription;
+
+        // TEMPORARY CODE
+        /* Currently our tree columns are emulated using custom draw,
+         * so we need to create the description using the tree column
+         * header text and tree item text. */
+        if (v.lVal !is COM.CHILDID_SELF) {
+            if (auto tree = cast(Tree)control ) {
+                int columnCount = tree.getColumnCount ();
+                if (columnCount > 1) {
+                    HWND hwnd = control.handle;
+                    int hItem;
+                    if (OS.COMCTL32_MAJOR >= 6) {
+                        hItem = OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
+                    } else {
+                        hItem = v.lVal;
+                    }
+                    Widget widget = tree.getDisplay ().findWidget (hwnd, hItem);
+                    event.result = "";
+                    if (widget !is null ) if( auto item = cast(TreeItem) widget ) {
+                        for (int i = 1; i < columnCount; i++) {
+                            event.result ~= tree.getColumn(i).getText() ~ ": " ~ item.getText(i);
+                            if (i + 1 < columnCount) event.result ~= ", ";
+                        }
+                    }
+                }
+            }
+        }
+        for (int i = 0; i < accessibleListeners.length; i++) {
+            AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
+            listener.getDescription(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszDescription = ptr;
+        return COM.S_OK;
+    }
+
+    /* get_accFocus([out] int pvarChild)
+     * Ownership of pvarChild transfers from callee to caller so reference count on pvarChild
+     * must be incremented before returning.  The caller is responsible for releasing pvarChild.
+     */
+    HRESULT get_accFocus(VARIANT* pvarChild) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+
+        /* Get the default focus child from the OS. */
+        int osChild = ACC.CHILDID_NONE;
+        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) {
+                int[1] pChild;
+                COM.MoveMemory(pChild.ptr, pvarChild + 8, 4);
+                osChild = osToChildID(pChild[0]);
+            }
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osChild;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getFocus(event);
+        }
+        Accessible accessible = event.accessible;
+        if (accessible !is null) {
+            accessible.AddRef();
+            pvarChild.vt = COM.VT_DISPATCH;
+            pvarChild.byRef = cast(void*)cast(IDispatch)accessible.objIAccessible;
+            return COM.S_OK;
+        }
+        int childID = event.childID;
+        if (childID is ACC.CHILDID_NONE) {
+            pvarChild.vt = COM.VT_EMPTY;
+            return COM.S_FALSE;
+        }
+        if (childID is ACC.CHILDID_SELF) {
+            AddRef();
+            pvarChild.vt = COM.VT_DISPATCH;
+            pvarChild.byRef = cast(void*)cast(IDispatch)objIAccessible;
+            return COM.S_OK;
+        }
+        pvarChild.vt = COM.VT_I4;
+        pvarChild.lVal = childIDToOs(childID);
+        return COM.S_OK;
+    }
+
+    HRESULT get_accHelp(VARIANT variant, BSTR* pszHelp) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default help string from the OS. */
+        String osHelp = null;
+        int code = iaccessible.get_accHelp(variant, pszHelp);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            // the original SysString is clearuped and bstr set to null
+            osHelp = BSTRToStr(*pszHelp, true);
+        }
+
+        AccessibleEvent event = new AccessibleEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osHelp;
+        for (int i = 0; i < accessibleListeners.length; i++) {
+            AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
+            listener.getHelp(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszHelp = ptr;
+        return COM.S_OK;
+    }
+
+    HRESULT get_accHelpTopic(BSTR* pszHelpFile, VARIANT variant, LONG* pidTopic) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // Currently, we don't let the application override this. Forward to the proxy.
+        int code = iaccessible.get_accHelpTopic(pszHelpFile, variant, pidTopic);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    HRESULT get_accKeyboardShortcut(VARIANT variant, BSTR* pszKeyboardShortcut) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default keyboard shortcut from the OS. */
+        String osKeyboardShortcut = null;
+        int code = iaccessible.get_accKeyboardShortcut(variant, pszKeyboardShortcut);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            // the original SysString is clearuped and bstr set to null
+            osKeyboardShortcut = BSTRToStr(*pszKeyboardShortcut, true);
+        }
+
+        AccessibleEvent event = new AccessibleEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osKeyboardShortcut;
+        for (int i = 0; i < accessibleListeners.length; i++) {
+            AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
+            listener.getKeyboardShortcut(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszKeyboardShortcut = ptr;
+        return COM.S_OK;
+    }
+
+    HRESULT get_accName(VARIANT variant, BSTR* pszName) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default name from the OS. */
+        String osName = null;
+        int code = iaccessible.get_accName(variant, pszName);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            // the original SysString is clearuped and bstr set to null
+            osName = BSTRToStr(*pszName, true);
+        }
+
+        AccessibleEvent event = new AccessibleEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osName;
+        for (int i = 0; i < accessibleListeners.length; i++) {
+            AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
+            listener.getName(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszName = ptr;
+        return COM.S_OK;
+    }
+
+    /* get_accParent([out] ppdispParent)
+     * Ownership of ppdispParent transfers from callee to caller so reference count on ppdispParent
+     * must be incremented before returning.  The caller is responsible for releasing ppdispParent.
+     */
+    HRESULT get_accParent(LPDISPATCH* ppdispParent) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // Currently, we don't let the application override this. Forward to the proxy.
+        return iaccessible.get_accParent(ppdispParent);
+    }
+
+    HRESULT get_accRole(VARIANT variant, VARIANT* pvarRole) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default role from the OS. */
+        int osRole = COM.ROLE_SYSTEM_CLIENT;
+        int code = iaccessible.get_accRole(variant, pvarRole);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        // 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) {
+                int[1] pRole;
+                COM.MoveMemory(pRole.ptr, pvarRole + 8, 4);
+                osRole = pRole[0];
+            }
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.detail = osToRole(osRole);
+        // TEMPORARY CODE
+        /* Currently our checkbox table and tree are emulated using state mask
+         * images, so we need to specify 'checkbox' role for the items. */
+        if (v.lVal !is COM.CHILDID_SELF) {
+            if ( null !is cast(Tree)control || null !is cast(Table)control ) {
+                if ((control.getStyle() & SWT.CHECK) !is 0) event.detail = ACC.ROLE_CHECKBUTTON;
+            }
+        }
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getRole(event);
+        }
+        int role = roleToOs(event.detail);
+        pvarRole.vt = COM.VT_I4;
+        pvarRole.lVal = role;
+        return COM.S_OK;
+    }
+
+    /* get_accSelection([out] pvarChildren)
+     * Ownership of pvarChildren transfers from callee to caller so reference count on pvarChildren
+     * must be incremented before returning.  The caller is responsible for releasing pvarChildren.
+     */
+    HRESULT get_accSelection(VARIANT* pvarChildren) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+
+        /* Get the default selection from the OS. */
+        int osChild = ACC.CHILDID_NONE;
+        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) {
+                int[1] pChild;
+                COM.MoveMemory(pChild.ptr, pvarChildren + 8, 4);
+                osChild = osToChildID(pChild[0]);
+            } else if (pvt[0] is COM.VT_UNKNOWN) {
+                osChild = ACC.CHILDID_MULTIPLE;
+                /* Should get IEnumVARIANT from punkVal field, and enumerate children... */
+            }
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osChild;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getSelection(event);
+        }
+        Accessible accessible = event.accessible;
+        if (accessible !is null) {
+            accessible.AddRef();
+            pvarChildren.vt = COM.VT_DISPATCH;
+            pvarChildren.byRef = cast(void*)cast(IDispatch)accessible.objIAccessible;
+            return COM.S_OK;
+        }
+        int childID = event.childID;
+        if (childID is ACC.CHILDID_NONE) {
+            pvarChildren.vt = COM.VT_EMPTY;
+            return COM.S_FALSE;
+        }
+        if (childID is ACC.CHILDID_MULTIPLE) {
+            AddRef();
+            pvarChildren.vt = COM.VT_UNKNOWN;
+            pvarChildren.byRef = cast(void*)cast(IUnknown)objIAccessible;
+            return COM.S_OK;
+        }
+        if (childID is ACC.CHILDID_SELF) {
+            AddRef();
+            pvarChildren.vt = COM.VT_DISPATCH;
+            pvarChildren.byRef = cast(void*)cast(IDispatch)objIAccessible;
+            return COM.S_OK;
+        }
+        pvarChildren.vt = COM.VT_I4;
+        pvarChildren.lVal = childIDToOs(childID);
+        return COM.S_OK;
+    }
+
+    HRESULT get_accState(VARIANT variant, VARIANT* pvarState) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default state from the OS. */
+        int osState = 0;
+        int code = iaccessible.get_accState(variant, pvarState);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        // 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) {
+                int[1] pState;
+                COM.MoveMemory(pState.ptr, pvarState + 8, 4);
+                osState = pState[0];
+            }
+        }
+        bool grayed = false;
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.detail = osToState(osState);
+        // TEMPORARY CODE
+        /* Currently our checkbox table and tree are emulated using state mask
+         * images, so we need to determine if the item state is 'checked'. */
+        if (v.lVal !is COM.CHILDID_SELF) {
+            if (null !is cast(Tree)control && (control.getStyle() & SWT.CHECK) !is 0) {
+                auto hwnd = control.handle;
+                TVITEM tvItem;
+                tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+                if (OS.COMCTL32_MAJOR >= 6) {
+                    tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_MAPACCIDTOHTREEITEM, v.lVal, 0);
+                } else {
+                    tvItem.hItem = cast(HTREEITEM) v.lVal;
+                }
+                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() & SWT.CHECK) !is 0) {
+                Table table = cast(Table) control;
+                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;
+                }
+            }
+        }
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            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;
+    }
+
+    HRESULT get_accValue(VARIANT variant, BSTR* pszValue) {
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        VARIANT* v = &variant;
+        //COM.MoveMemory(v, variant, VARIANT.sizeof);
+        if ((v.vt & 0xFFFF) !is COM.VT_I4) return COM.E_INVALIDARG;
+
+        /* Get the default value string from the OS. */
+        String osValue = null;
+        int code = iaccessible.get_accValue(variant, pszValue);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        if (accessibleControlListeners.length is 0) return code;
+        if (code is COM.S_OK) {
+            int size = COM.SysStringByteLen(*pszValue);
+            if (size > 0) {
+                osValue = WCHARsToStr((*pszValue)[ 0 .. size ]);
+            }
+        }
+
+        AccessibleControlEvent event = new AccessibleControlEvent(this);
+        event.childID = osToChildID(v.lVal);
+        event.result = osValue;
+        for (int i = 0; i < accessibleControlListeners.length; i++) {
+            AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+            listener.getValue(event);
+        }
+        if (event.result is null) return code;
+        auto ptr = COM.SysAllocString(StrToWCHARz(event.result));
+        *pszValue = ptr;
+        return COM.S_OK;
+    }
+
+    HRESULT put_accName(VARIANT variant, BSTR* szName) {
+        // MSAA: this method is no longer supported
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // We don't implement this. Forward to the proxy.
+        int code = iaccessible.put_accName(variant, szName);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    HRESULT put_accValue(VARIANT variant, BSTR* szValue) {
+        // MSAA: this method is typically only used for edit controls
+        if (iaccessible is null) return COM.CO_E_OBJNOTCONNECTED;
+        // We don't implement this. Forward to the proxy.
+        int code = iaccessible.put_accValue(variant, szValue);
+        if (code is COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
+        return code;
+    }
+
+    /* IEnumVARIANT methods: Next, Skip, Reset, Clone */
+    /* Retrieve the next celt items in the enumeration sequence.
+     * If there are fewer than the requested number of elements left
+     * in the sequence, retrieve the remaining elements.
+     * The number of elements actually retrieved is returned in pceltFetched
+     * (unless the caller passed in NULL for that parameter).
+     */
+
+     /* Next([in] celt, [out] rgvar, [in, out] pceltFetched)
+     * Ownership of rgvar transfers from callee to caller so reference count on rgvar
+     * must be incremented before returning.  The caller is responsible for releasing rgvar.
+     */
+    HRESULT Next(ULONG celt, VARIANT *rgvar, ULONG *pceltFetched) {
+        /* If there are no listeners, query the proxy for
+         * its IEnumVariant, and get the Next items from it.
+         */
+        if (accessibleControlListeners.length is 0) {
+            IEnumVARIANT ienumvariant;
+            int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
+            if (code !is COM.S_OK) return code;
+            uint[1] celtFetched;
+            code = ienumvariant.Next(celt, rgvar, celtFetched.ptr);
+            ienumvariant.Release();
+            COM.MoveMemory(pceltFetched, celtFetched.ptr, 4);
+            return code;
+        }
+
+        if (rgvar is null) return COM.E_INVALIDARG;
+        if (pceltFetched is null && celt !is 1) return COM.E_INVALIDARG;
+        if (enumIndex is 0) {
+            AccessibleControlEvent event = new AccessibleControlEvent(this);
+            event.childID = ACC.CHILDID_SELF;
+            for (int i = 0; i < accessibleControlListeners.length; i++) {
+                AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
+                listener.getChildren(event);
+            }
+            variants = event.children;
+        }
+        Object[] nextItems = null;
+        if (variants !is null && celt >= 1) {
+            int endIndex = enumIndex + celt - 1;
+            if (endIndex > (variants.length - 1)) endIndex = variants.length - 1;
+            if (enumIndex <= endIndex) {
+                nextItems = new Object[endIndex - enumIndex + 1];
+                for (int i = 0; i < nextItems.length; i++) {
+                    Object child = variants[enumIndex];
+                    if (auto val = cast(ValueWrapperInt)child ) {
+                        nextItems[i] = new ValueWrapperInt(childIDToOs(val.value));
+                    } else {
+                        nextItems[i] = child;
+                    }
+                    enumIndex++;
+                }
+            }
+        }
+        if (nextItems !is null) {
+            for (int i = 0; i < nextItems.length; i++) {
+                Object nextItem = nextItems[i];
+                if (auto val = cast(ValueWrapperInt)nextItem ) {
+                    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();
+                    rgvar[i].vt = COM.VT_DISPATCH;
+                    rgvar[i].byRef = cast(void*)accessible.objIAccessible;
+                }
+            }
+            if (pceltFetched !is null)
+                *pceltFetched = nextItems.length;
+            if (nextItems.length is celt) return COM.S_OK;
+        } else {
+            if (pceltFetched !is null){
+                int zero = 0;
+                *pceltFetched = 0;
+            }
+        }
+        return COM.S_FALSE;
+    }
+
+    /* Skip over the specified number of elements in the enumeration sequence. */
+    HRESULT Skip(ULONG celt)  {
+        /* If there are no listeners, query the proxy
+         * for its IEnumVariant, and tell it to Skip.
+         */
+        if (accessibleControlListeners.length is 0) {
+            IEnumVARIANT ienumvariant;
+            int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
+            if (code !is COM.S_OK) return code;
+            code = ienumvariant.Skip(celt);
+            ienumvariant.Release();
+            return code;
+        }
+
+        if (celt < 1 ) return COM.E_INVALIDARG;
+        enumIndex += celt;
+        if (enumIndex > (variants.length - 1)) {
+            enumIndex = variants.length - 1;
+            return COM.S_FALSE;
+        }
+        return COM.S_OK;
+    }
+
+    /* Reset the enumeration sequence to the beginning. */
+    HRESULT Reset() {
+        /* If there are no listeners, query the proxy
+         * for its IEnumVariant, and tell it to Reset.
+         */
+        if (accessibleControlListeners.length is 0) {
+            IEnumVARIANT ienumvariant;
+            int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
+            if (code !is COM.S_OK) return code;
+            code = ienumvariant.Reset();
+            ienumvariant.Release();
+            return code;
+        }
+
+        enumIndex = 0;
+        return COM.S_OK;
+    }
+
+     /* Clone([out] ppEnum)
+     * Ownership of ppEnum transfers from callee to caller so reference count on ppEnum
+     * must be incremented before returning.  The caller is responsible for releasing ppEnum.
+     */
+    int Clone(IEnumVARIANT* ppEnum) {
+        /* If there are no listeners, query the proxy for
+         * its IEnumVariant, and get the Clone from it.
+         */
+        if (accessibleControlListeners.length is 0) {
+            IEnumVARIANT ienumvariant;
+            int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
+            if (code !is COM.S_OK) return code;
+            IEnumVARIANT[1] pEnum;
+            code = ienumvariant.Clone(pEnum.ptr);
+            ienumvariant.Release();
+            COM.MoveMemory(ppEnum, pEnum.ptr, (void*).sizeof);
+            return code;
+        }
+
+        if (ppEnum is null) return COM.E_INVALIDARG;
+        *ppEnum = objIEnumVARIANT;
+        AddRef();
+        return COM.S_OK;
+    }
+
+    int childIDToOs(int childID) {
+        if (childID is ACC.CHILDID_SELF) return COM.CHILDID_SELF;
+        /*
+        * Feature of Windows:
+        * In Windows XP, tree item ids are 1-based indices. Previous versions
+        * of Windows use the tree item handle for the accessible child ID.
+        * For backward compatibility, we still take a handle childID for tree
+        * items on XP. All other childIDs are 1-based indices.
+        */
+        if (!(cast(Tree)control )) return childID + 1;
+        if (OS.COMCTL32_MAJOR < 6) return childID;
+        return OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
+    }
+
+    int osToChildID(int osChildID) {
+        if (osChildID is COM.CHILDID_SELF) return ACC.CHILDID_SELF;
+        /*
+        * Feature of Windows:
+        * In Windows XP, tree item ids are 1-based indices. Previous versions
+        * of Windows use the tree item handle for the accessible child ID.
+        * For backward compatibility, we still take a handle childID for tree
+        * items on XP. All other childIDs are 1-based indices.
+        */
+        if (!(cast(Tree)control )) return osChildID - 1;
+        if (OS.COMCTL32_MAJOR < 6) return osChildID;
+        return OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
+    }
+
+    int stateToOs(int state) {
+        int osState = 0;
+        if ((state & ACC.STATE_SELECTED) !is 0) osState |= COM.STATE_SYSTEM_SELECTED;
+        if ((state & ACC.STATE_SELECTABLE) !is 0) osState |= COM.STATE_SYSTEM_SELECTABLE;
+        if ((state & ACC.STATE_MULTISELECTABLE) !is 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE;
+        if ((state & ACC.STATE_FOCUSED) !is 0) osState |= COM.STATE_SYSTEM_FOCUSED;
+        if ((state & ACC.STATE_FOCUSABLE) !is 0) osState |= COM.STATE_SYSTEM_FOCUSABLE;
+        if ((state & ACC.STATE_PRESSED) !is 0) osState |= COM.STATE_SYSTEM_PRESSED;
+        if ((state & ACC.STATE_CHECKED) !is 0) osState |= COM.STATE_SYSTEM_CHECKED;
+        if ((state & ACC.STATE_EXPANDED) !is 0) osState |= COM.STATE_SYSTEM_EXPANDED;
+        if ((state & ACC.STATE_COLLAPSED) !is 0) osState |= COM.STATE_SYSTEM_COLLAPSED;
+        if ((state & ACC.STATE_HOTTRACKED) !is 0) osState |= COM.STATE_SYSTEM_HOTTRACKED;
+        if ((state & ACC.STATE_BUSY) !is 0) osState |= COM.STATE_SYSTEM_BUSY;
+        if ((state & ACC.STATE_READONLY) !is 0) osState |= COM.STATE_SYSTEM_READONLY;
+        if ((state & ACC.STATE_INVISIBLE) !is 0) osState |= COM.STATE_SYSTEM_INVISIBLE;
+        if ((state & ACC.STATE_OFFSCREEN) !is 0) osState |= COM.STATE_SYSTEM_OFFSCREEN;
+        if ((state & ACC.STATE_SIZEABLE) !is 0) osState |= COM.STATE_SYSTEM_SIZEABLE;
+        if ((state & ACC.STATE_LINKED) !is 0) osState |= COM.STATE_SYSTEM_LINKED;
+        return osState;
+    }
+
+    int osToState(int osState) {
+        int state = ACC.STATE_NORMAL;
+        if ((osState & COM.STATE_SYSTEM_SELECTED) !is 0) state |= ACC.STATE_SELECTED;
+        if ((osState & COM.STATE_SYSTEM_SELECTABLE) !is 0) state |= ACC.STATE_SELECTABLE;
+        if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) !is 0) state |= ACC.STATE_MULTISELECTABLE;
+        if ((osState & COM.STATE_SYSTEM_FOCUSED) !is 0) state |= ACC.STATE_FOCUSED;
+        if ((osState & COM.STATE_SYSTEM_FOCUSABLE) !is 0) state |= ACC.STATE_FOCUSABLE;
+        if ((osState & COM.STATE_SYSTEM_PRESSED) !is 0) state |= ACC.STATE_PRESSED;
+        if ((osState & COM.STATE_SYSTEM_CHECKED) !is 0) state |= ACC.STATE_CHECKED;
+        if ((osState & COM.STATE_SYSTEM_EXPANDED) !is 0) state |= ACC.STATE_EXPANDED;
+        if ((osState & COM.STATE_SYSTEM_COLLAPSED) !is 0) state |= ACC.STATE_COLLAPSED;
+        if ((osState & COM.STATE_SYSTEM_HOTTRACKED) !is 0) state |= ACC.STATE_HOTTRACKED;
+        if ((osState & COM.STATE_SYSTEM_BUSY) !is 0) state |= ACC.STATE_BUSY;
+        if ((osState & COM.STATE_SYSTEM_READONLY) !is 0) state |= ACC.STATE_READONLY;
+        if ((osState & COM.STATE_SYSTEM_INVISIBLE) !is 0) state |= ACC.STATE_INVISIBLE;
+        if ((osState & COM.STATE_SYSTEM_OFFSCREEN) !is 0) state |= ACC.STATE_OFFSCREEN;
+        if ((osState & COM.STATE_SYSTEM_SIZEABLE) !is 0) state |= ACC.STATE_SIZEABLE;
+        if ((osState & COM.STATE_SYSTEM_LINKED) !is 0) state |= ACC.STATE_LINKED;
+        return state;
+    }
+
+    int roleToOs(int role) {
+        switch (role) {
+            case ACC.ROLE_CLIENT_AREA: return COM.ROLE_SYSTEM_CLIENT;
+            case ACC.ROLE_WINDOW: return COM.ROLE_SYSTEM_WINDOW;
+            case ACC.ROLE_MENUBAR: return COM.ROLE_SYSTEM_MENUBAR;
+            case ACC.ROLE_MENU: return COM.ROLE_SYSTEM_MENUPOPUP;
+            case ACC.ROLE_MENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
+            case ACC.ROLE_SEPARATOR: return COM.ROLE_SYSTEM_SEPARATOR;
+            case ACC.ROLE_TOOLTIP: return COM.ROLE_SYSTEM_TOOLTIP;
+            case ACC.ROLE_SCROLLBAR: return COM.ROLE_SYSTEM_SCROLLBAR;
+            case ACC.ROLE_DIALOG: return COM.ROLE_SYSTEM_DIALOG;
+            case ACC.ROLE_LABEL: return COM.ROLE_SYSTEM_STATICTEXT;
+            case ACC.ROLE_PUSHBUTTON: return COM.ROLE_SYSTEM_PUSHBUTTON;
+            case ACC.ROLE_CHECKBUTTON: return COM.ROLE_SYSTEM_CHECKBUTTON;
+            case ACC.ROLE_RADIOBUTTON: return COM.ROLE_SYSTEM_RADIOBUTTON;
+            case ACC.ROLE_COMBOBOX: return COM.ROLE_SYSTEM_COMBOBOX;
+            case ACC.ROLE_TEXT: return COM.ROLE_SYSTEM_TEXT;
+            case ACC.ROLE_TOOLBAR: return COM.ROLE_SYSTEM_TOOLBAR;
+            case ACC.ROLE_LIST: return COM.ROLE_SYSTEM_LIST;
+            case ACC.ROLE_LISTITEM: return COM.ROLE_SYSTEM_LISTITEM;
+            case ACC.ROLE_TABLE: return COM.ROLE_SYSTEM_TABLE;
+            case ACC.ROLE_TABLECELL: return COM.ROLE_SYSTEM_CELL;
+            case ACC.ROLE_TABLECOLUMNHEADER: return COM.ROLE_SYSTEM_COLUMNHEADER;
+            case ACC.ROLE_TABLEROWHEADER: return COM.ROLE_SYSTEM_ROWHEADER;
+            case ACC.ROLE_TREE: return COM.ROLE_SYSTEM_OUTLINE;
+            case ACC.ROLE_TREEITEM: return COM.ROLE_SYSTEM_OUTLINEITEM;
+            case ACC.ROLE_TABFOLDER: return COM.ROLE_SYSTEM_PAGETABLIST;
+            case ACC.ROLE_TABITEM: return COM.ROLE_SYSTEM_PAGETAB;
+            case ACC.ROLE_PROGRESSBAR: return COM.ROLE_SYSTEM_PROGRESSBAR;
+            case ACC.ROLE_SLIDER: return COM.ROLE_SYSTEM_SLIDER;
+            case ACC.ROLE_LINK: return COM.ROLE_SYSTEM_LINK;
+            default:
+        }
+        return COM.ROLE_SYSTEM_CLIENT;
+    }
+
+    int osToRole(int osRole) {
+        switch (osRole) {
+            case COM.ROLE_SYSTEM_CLIENT: return ACC.ROLE_CLIENT_AREA;
+            case COM.ROLE_SYSTEM_WINDOW: return ACC.ROLE_WINDOW;
+            case COM.ROLE_SYSTEM_MENUBAR: return ACC.ROLE_MENUBAR;
+            case COM.ROLE_SYSTEM_MENUPOPUP: return ACC.ROLE_MENU;
+            case COM.ROLE_SYSTEM_MENUITEM: return ACC.ROLE_MENUITEM;
+            case COM.ROLE_SYSTEM_SEPARATOR: return ACC.ROLE_SEPARATOR;
+            case COM.ROLE_SYSTEM_TOOLTIP: return ACC.ROLE_TOOLTIP;
+            case COM.ROLE_SYSTEM_SCROLLBAR: return ACC.ROLE_SCROLLBAR;
+            case COM.ROLE_SYSTEM_DIALOG: return ACC.ROLE_DIALOG;
+            case COM.ROLE_SYSTEM_STATICTEXT: return ACC.ROLE_LABEL;
+            case COM.ROLE_SYSTEM_PUSHBUTTON: return ACC.ROLE_PUSHBUTTON;
+            case COM.ROLE_SYSTEM_CHECKBUTTON: return ACC.ROLE_CHECKBUTTON;
+            case COM.ROLE_SYSTEM_RADIOBUTTON: return ACC.ROLE_RADIOBUTTON;
+            case COM.ROLE_SYSTEM_COMBOBOX: return ACC.ROLE_COMBOBOX;
+            case COM.ROLE_SYSTEM_TEXT: return ACC.ROLE_TEXT;
+            case COM.ROLE_SYSTEM_TOOLBAR: return ACC.ROLE_TOOLBAR;
+            case COM.ROLE_SYSTEM_LIST: return ACC.ROLE_LIST;
+            case COM.ROLE_SYSTEM_LISTITEM: return ACC.ROLE_LISTITEM;
+            case COM.ROLE_SYSTEM_TABLE: return ACC.ROLE_TABLE;
+            case COM.ROLE_SYSTEM_CELL: return ACC.ROLE_TABLECELL;
+            case COM.ROLE_SYSTEM_COLUMNHEADER: return ACC.ROLE_TABLECOLUMNHEADER;
+            case COM.ROLE_SYSTEM_ROWHEADER: return ACC.ROLE_TABLEROWHEADER;
+            case COM.ROLE_SYSTEM_OUTLINE: return ACC.ROLE_TREE;
+            case COM.ROLE_SYSTEM_OUTLINEITEM: return ACC.ROLE_TREEITEM;
+            case COM.ROLE_SYSTEM_PAGETABLIST: return ACC.ROLE_TABFOLDER;
+            case COM.ROLE_SYSTEM_PAGETAB: return ACC.ROLE_TABITEM;
+            case COM.ROLE_SYSTEM_PROGRESSBAR: return ACC.ROLE_PROGRESSBAR;
+            case COM.ROLE_SYSTEM_SLIDER: return ACC.ROLE_SLIDER;
+            case COM.ROLE_SYSTEM_LINK: return ACC.ROLE_LINK;
+            default:
+        }
+        return ACC.ROLE_CLIENT_AREA;
+    }
+
+    /* checkWidget was copied from Widget, and rewritten to work in this package */
+    void checkWidget () {
+        if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+        if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
+    }
+
+    /* isValidThread was copied from Widget, and rewritten to work in this package */
+    WINBOOL isValidThread () {
+        return control.getDisplay ().getThread () is Thread.getThis ();
+    }
+}
+
+class _IAccessibleImpl : IAccessible {
+
+    Accessible  parent;
+    this(Accessible p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IDispatch
+    HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
+    HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
+    HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
+    HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) { return COM.E_NOTIMPL; }
+
+    // interface of IAccessible
+    HRESULT get_accParent(LPDISPATCH * ppdispParent) { return parent.get_accParent(ppdispParent); }
+    HRESULT get_accChildCount(LONG* pcountChildren) { return parent.get_accChildCount(pcountChildren); }
+    HRESULT get_accChild(VARIANT varChildID, LPDISPATCH* ppdispChild) {
+        return parent.get_accChild(varChildID, ppdispChild);
+    }
+    HRESULT get_accName(VARIANT varID, BSTR* pszName) {
+        return parent.get_accName(varID, pszName);
+    }
+    HRESULT get_accValue(VARIANT varID, BSTR* pszValue) {
+        return parent.get_accValue(varID, pszValue);
+    }
+    HRESULT get_accDescription(VARIANT varID,BSTR* pszDescription) {
+        return parent.get_accDescription(varID, pszDescription);
+    }
+    HRESULT get_accRole(VARIANT varID, VARIANT* pvarRole) {
+        return parent.get_accRole(varID, pvarRole);
+    }
+    HRESULT get_accState(VARIANT varID, VARIANT* pvarState) {
+        return parent.get_accState(varID, pvarState);
+    }
+    HRESULT get_accHelp(VARIANT varID, BSTR* pszHelp) {
+        return parent.get_accHelp(varID, pszHelp);
+    }
+    HRESULT get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild, LONG* pidTopic) {
+        return parent.get_accHelpTopic(pszHelpFile, varChild, pidTopic);
+    }
+    HRESULT get_accKeyboardShortcut(VARIANT varID, BSTR* pszKeyboardShortcut) {
+        return parent.get_accKeyboardShortcut(varID, pszKeyboardShortcut);
+    }
+    HRESULT get_accFocus(VARIANT* pvarID) { return parent.get_accFocus(pvarID); }
+    HRESULT get_accSelection(VARIANT* pvarChildren) { return parent.get_accSelection(pvarChildren); }
+    HRESULT get_accDefaultAction(VARIANT varID,BSTR* pszDefaultAction) {
+        return parent.get_accDefaultAction(varID, pszDefaultAction);
+    }
+    HRESULT accSelect(LONG flagsSelect, VARIANT varID) {
+        return parent.accSelect(flagsSelect, varID);
+    }
+    HRESULT accLocation(LONG* pxLeft, LONG* pyTop, LONG* pcxWidth, LONG* pcyHeight, VARIANT varID) {
+        return parent.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varID);
+    }
+    HRESULT accNavigate(LONG navDir, VARIANT varStart, VARIANT* pvarEnd) {
+        return parent.accNavigate(navDir, varStart, pvarEnd);
+    }
+    HRESULT accHitTest(LONG xLeft,  LONG yTop, VARIANT* pvarID) {
+        return parent.accHitTest(xLeft, yTop, pvarID);
+    }
+    HRESULT accDoDefaultAction(VARIANT varID) {
+        return parent.accDoDefaultAction(varID);
+    }
+    HRESULT put_accName(VARIANT varID, BSTR* szName) {
+        return parent.put_accName(varID, szName);
+    }
+    HRESULT put_accValue(VARIANT varID, BSTR* szValue) {
+        return parent.put_accValue(varID, szValue);
+    }
+}
+
+class _IEnumVARIANTImpl : IEnumVARIANT {
+
+    Accessible  parent;
+    this(Accessible a) { parent = a; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IEnumVARIANT
+    HRESULT Next(ULONG celt, VARIANT *rgvar, ULONG *pceltFetched) { return parent.Next(celt, rgvar, pceltFetched); }
+    HRESULT Skip(ULONG celt) { return parent.Skip(celt); }
+    HRESULT Reset() { return parent.Reset(); }
+    HRESULT Clone(LPENUMVARIANT * ppenum) { return COM.E_NOTIMPL;}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleAdapter;
+
+import org.eclipse.swt.accessibility.AccessibleListener;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>AccessibleListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleEvent</code>s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * </p>
+ *
+ * @see AccessibleListener
+ * @see AccessibleEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public abstract class AccessibleAdapter : AccessibleListener {
+
+    /**
+     * Sent when an accessibility client requests the name
+     * of the control, or the name of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the name of the control or specified child in the
+     * <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a name, and returning null tells the client
+     * to use the platform name.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested name string, or null</li>
+     * </ul>
+     */
+    public void getName(AccessibleEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the help string
+     * of the control, or the help string of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * The information in this property should be similar to the help
+     * provided by toolTipText. It describes what the control or child
+     * does or how to use it, as opposed to getDescription, which
+     * describes appearance.
+     * </p><p>
+     * Return the help string of the control or specified child in
+     * the <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a help string, and returning null tells the
+     * client to use the platform help string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested help string, or null</li>
+     * </ul>
+     */
+    public void getHelp(AccessibleEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the keyboard shortcut
+     * of the control, or the keyboard shortcut of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * A keyboard shortcut can either be a mnemonic, or an accelerator.
+     * As a general rule, if the control or child can receive keyboard focus,
+     * then you should expose its mnemonic, and if it cannot receive keyboard
+     * focus, then you should expose its accelerator.
+     * </p><p>
+     * Return the keyboard shortcut string of the control or specified child
+     * in the <code>result</code> field of the event object. Returning an
+     * empty string tells the client that the control or child does not
+     * have a keyboard shortcut string, and returning null tells the client
+     * to use the platform keyboard shortcut string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested keyboard shortcut string (example: "ALT+N"), or null</li>
+     * </ul>
+     */
+    public void getKeyboardShortcut(AccessibleEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests a description
+     * of the control, or a description of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * This is a textual description of the control or child's visual
+     * appearance, which is typically only necessary if it cannot be
+     * determined from other properties such as role.
+     * </p><p>
+     * Return the description of the control or specified child in
+     * the <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a description, and returning null tells the
+     * client to use the platform description.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested description string, or null</li>
+     * </ul>
+     */
+    public void getDescription(AccessibleEvent e) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleControlAdapter;
+
+import org.eclipse.swt.accessibility.AccessibleControlListener;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>AccessibleControlListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleControlEvent</code>s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * When returning a child identifier to a client, you may use CHILDID_NONE
+ * to indicate that no child or control has the required information.
+ * </p><p>
+ * Note: This adapter is typically used by implementors of
+ * a custom control to provide very detailed information about
+ * the control instance to accessibility clients.
+ * </p>
+ *
+ * @see AccessibleControlListener
+ * @see AccessibleControlEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public abstract class AccessibleControlAdapter : AccessibleControlListener {
+
+    /**
+     * Sent when an accessibility client requests the identifier
+     * of the control child at the specified display coordinates.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the identifier of the child at display point (x, y)
+     * in the <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if point (x, y) is in the control itself
+     * and not in any child. Return CHILDID_NONE if point (x, y)
+     * is not contained in either the control or any of its children.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>x, y [IN] - the specified point in display coordinates</li>
+     *    <li>childID [Typical OUT] - the ID of the child at point, or CHILDID_SELF, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for the control or child may be returned instead of the childID</li>
+     * </ul>
+     */
+    public void getChildAtPoint(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the location
+     * of the control, or the location of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return a rectangle describing the location of the specified
+     * control or child in the <code>x, y, width, and height</code>
+     * fields of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>x, y, width, height [OUT] - the control or child location in display coordinates</li>
+     * </ul>
+     */
+    public void getLocation(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the accessible object
+     * for a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return an <code>Accessible</code> for the specified control or
+     * child in the <code>accessible</code> field of the event object.
+     * Return null if the specified child does not have its own
+     * <code>Accessible</code>.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>accessible [OUT] - an Accessible for the specified childID, or null if one does not exist</li>
+     * </ul>
+     */
+    public void getChild(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the number of
+     * children in the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the number of child items in the <code>detail</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>detail [OUT] - the number of child items in this control</li>
+     * </ul>
+     */
+    public void getChildCount(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the default action
+     * of the control, or the default action of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * This string is typically a verb describing what the user does to it.
+     * For example, a Push Button's default action is "Press", a Check Button's
+     * is "Check" or "UnCheck", and List items have the default action "Double Click".
+     * </p><p>
+     * Return a string describing the default action of the specified
+     * control or child in the <code>result</code> field of the event object.
+     * Returning null tells the client to use the platform default action string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested default action string, or null</li>
+     * </ul>
+     */
+    public void getDefaultAction(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the identity of
+     * the child or control that has keyboard focus.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the identifier of the child that has focus in the
+     * <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if the control itself has keyboard focus.
+     * Return CHILDID_NONE if neither the control nor any of its children has focus.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [Typical OUT] - the ID of the child with focus, or CHILDID_SELF, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for a child may be returned instead of its childID</li>
+     * </ul>
+     */
+    public void getFocus(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the role
+     * of the control, or the role of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return a role constant (constant defined in ACC beginning with ROLE_)
+     * that describes the role of the specified control or child in the
+     * <code>detail</code> field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>detail [OUT] - a role constant describing the role of the control or child</li>
+     * </ul>
+     */
+    public void getRole(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the identity of
+     * the child or control that is currently selected.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the identifier of the selected child in the
+     * <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if the control itself is selected.
+     * Return CHILDID_MULTIPLE if multiple children are selected, and return an array of childIDs in the <code>children</code> field.
+     * Return CHILDID_NONE if neither the control nor any of its children are selected.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [Typical OUT] - the ID of the selected child, or CHILDID_SELF, or CHILDID_MULTIPLE, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for the control or child may be returned instead of the childID</li>
+     * </ul>
+     */
+    public void getSelection(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the state
+     * of the control, or the state of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return a state mask (mask bit constants defined in ACC beginning with STATE_)
+     * that describes the current state of the specified control or child in the
+     * <code>detail</code> field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>detail [OUT] - a state mask describing the current state of the control or child</li>
+     * </ul>
+     */
+    public void getState(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the value
+     * of the control, or the value of a child of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Many controls do not return a value. Examples of controls
+     * that do are: Combo returns the text string, Text returns
+     * its contents, ProgressBar returns a string representing a
+     * percentage, and Tree items return a string representing
+     * their level in the tree.
+     * </p><p>
+     * Return a string describing the value of the specified control
+     * or child in the <code>result</code> field of the event object.
+     * Returning null tells the client to use the platform value string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested value string, or null</li>
+     * </ul>
+     */
+    public void getValue(AccessibleControlEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the children of the control.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the children as an array of childIDs in the <code>children</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>children [Typical OUT] - an array of childIDs</li>
+     *    <li>accessible [Optional OUT] - an array of accessible objects for the children may be returned instead of the childIDs</li>
+     * </ul>
+     */
+    public void getChildren(AccessibleControlEvent e) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleControlEvent;
+
+import org.eclipse.swt.accessibility.Accessible;
+
+import org.eclipse.swt.internal.SWTEventObject;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * accessibility clients sending messages to controls
+ * asking for detailed information about the implementation
+ * of the control instance. Typically, only implementors
+ * of custom controls need to listen for this event.
+ * <p>
+ * Note: The meaning of each field depends on the
+ * message that was sent.
+ * </p>
+ *
+ * @see AccessibleControlListener
+ * @see AccessibleControlAdapter
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public class AccessibleControlEvent : SWTEventObject {
+    public int childID;         // IN/OUT
+    public Accessible accessible;   // OUT
+    public int x, y;                // IN/OUT
+    public int width, height;       // OUT
+    public int detail;          // IN/OUT
+    public String result;           // OUT
+    public Object children[];       // [OUT]
+
+    //static final long serialVersionUID = 3257281444169529141L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public this(Object source) {
+    super(source);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public String toString () {
+    return Format( "AccessibleControlEvent {childID={} accessible={} x={} y={} width={} heigth={} detail={} result={}",
+        childID, accessible, x, y, width, height, detail, result);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleControlListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleControlListener;
+
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes that implement this interface provide methods
+ * that deal with the events that are generated when an
+ * accessibility client sends a message to a control.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addAccessibleControlListener</code> method and removed
+ * using the <code>removeAccessibleControlListener</code> method.
+ * When a client requests information the appropriate method
+ * will be invoked.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * </p><p>
+ * Note: This interface is typically used by implementors of
+ * a custom control to provide very detailed information about
+ * the control instance to accessibility clients.
+ * </p>
+ *
+ * @see AccessibleControlAdapter
+ * @see AccessibleControlEvent
+ *
+ * @since 2.0
+ */
+public interface AccessibleControlListener : SWTEventListener {
+
+    /**
+     * Sent when an accessibility client requests the identifier
+     * of the control child at the specified display coordinates.
+     * <p>
+     * Return the identifier of the child at display point (x, y)
+     * in the <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if point (x, y) is in the control itself
+     * and not in any child. Return CHILDID_NONE if point (x, y)
+     * is not contained in either the control or any of its children.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>x, y [IN] - the specified point in display coordinates</li>
+     *    <li>childID [Typical OUT] - the ID of the child at point, or CHILDID_SELF, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for the control or child may be returned instead of the childID</li>
+     * </ul>
+     */
+    public void getChildAtPoint(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the location
+     * of the control, or the location of a child of the control.
+     * <p>
+     * Return a rectangle describing the location of the specified
+     * control or child in the <code>x, y, width, and height</code>
+     * fields of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>x, y, width, height [OUT] - the control or child location in display coordinates</li>
+     * </ul>
+     */
+    public void getLocation(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the accessible object
+     * for a child of the control.
+     * <p>
+     * Return an <code>Accessible</code> for the specified control or
+     * child in the <code>accessible</code> field of the event object.
+     * Return null if the specified child does not have its own
+     * <code>Accessible</code>.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>accessible [OUT] - an Accessible for the specified childID, or null if one does not exist</li>
+     * </ul>
+     */
+    public void getChild(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the number of
+     * children in the control.
+     * <p>
+     * Return the number of child items in the <code>detail</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>detail [OUT] - the number of child items in this control</li>
+     * </ul>
+     */
+    public void getChildCount(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the default action
+     * of the control, or the default action of a child of the control.
+     * <p>
+     * This string is typically a verb describing what the user does to it.
+     * For example, a Push Button's default action is "Press", a Check Button's
+     * is "Check" or "UnCheck", and List items have the default action "Double Click".
+     * </p><p>
+     * Return a string describing the default action of the specified
+     * control or child in the <code>result</code> field of the event object.
+     * Returning null tells the client to use the platform default action string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested default action string, or null</li>
+     * </ul>
+     */
+    public void getDefaultAction(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the identity of
+     * the child or control that has keyboard focus.
+     * <p>
+     * Return the identifier of the child that has focus in the
+     * <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if the control itself has keyboard focus.
+     * Return CHILDID_NONE if neither the control nor any of its children has focus.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [Typical OUT] - the ID of the child with focus, or CHILDID_SELF, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for a child may be returned instead of its childID</li>
+     * </ul>
+     */
+    public void getFocus(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the role
+     * of the control, or the role of a child of the control.
+     * <p>
+     * Return a role constant (constant defined in ACC beginning with ROLE_)
+     * that describes the role of the specified control or child in the
+     * <code>detail</code> field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>detail [OUT] - a role constant describing the role of the control or child</li>
+     * </ul>
+     */
+    public void getRole(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the identity of
+     * the child or control that is currently selected.
+     * <p>
+     * Return the identifier of the selected child in the
+     * <code>childID</code> field of the event object.
+     * Return CHILDID_SELF if the control itself is selected.
+     * Return CHILDID_MULTIPLE if multiple children are selected, and return an array of childIDs in the <code>children</code> field.
+     * Return CHILDID_NONE if neither the control nor any of its children are selected.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [Typical OUT] - the ID of the selected child, or CHILDID_SELF, or CHILDID_MULTIPLE, or CHILDID_NONE</li>
+     *    <li>accessible [Optional OUT] - the accessible object for the control or child may be returned instead of the childID</li>
+     * </ul>
+     */
+    public void getSelection(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the state
+     * of the control, or the state of a child of the control.
+     * <p>
+     * Return a state mask (mask bit constants defined in ACC beginning with STATE_)
+     * that describes the current state of the specified control or child in the
+     * <code>detail</code> field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>detail [OUT] - a state mask describing the current state of the control or child</li>
+     * </ul>
+     */
+    public void getState(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the value
+     * of the control, or the value of a child of the control.
+     * <p>
+     * Many controls do not return a value. Examples of controls
+     * that do are: Combo returns the text string, Text returns
+     * its contents, ProgressBar returns a string representing a
+     * percentage, and Tree items return a string representing
+     * their level in the tree.
+     * </p><p>
+     * Return a string describing the value of the specified control
+     * or child in the <code>result</code> field of the event object.
+     * Returning null tells the client to use the platform value string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested value string, or null</li>
+     * </ul>
+     */
+    public void getValue(AccessibleControlEvent e);
+
+    /**
+     * Sent when an accessibility client requests the children of the control.
+     * <p>
+     * Return the children as an array of childIDs in the <code>children</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>children [Typical OUT] - an array of childIDs</li>
+     *    <li>children [Optional OUT] - an array of accessible objects for the children may be returned instead of the childIDs</li>
+     * </ul>
+     */
+    public void getChildren(AccessibleControlEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleEvent;
+
+
+import org.eclipse.swt.internal.SWTEventObject;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * accessibility clients sending messages to controls
+ * asking for information about the control instance.
+ * <p>
+ * Note: The meaning of the result field depends
+ * on the message that was sent.
+ * </p>
+ *
+ * @see AccessibleListener
+ * @see AccessibleAdapter
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public class AccessibleEvent : SWTEventObject {
+    /**
+     * The value of this field is set by an accessibility client
+     * before the accessible listener method is called.
+     * ChildID can be CHILDID_SELF, representing the control itself,
+     * or a 0-based integer representing a specific child of the control.
+     */
+    public int childID;
+
+    /**
+     * The value of this field must be set in the accessible listener
+     * method before returning.
+     * What to set it to depends on the listener method called, and
+     * the childID specified by the client.
+     */
+    public String result;
+
+    //static final long serialVersionUID = 3257567304224026934L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public this(Object source) {
+    super(source);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+override public String toString () {
+    return Format( "AccessibleEvent {childID={} result={}}", childID, result );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleListener;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+
+/**
+ * Classes that implement this interface provide methods
+ * that deal with the events that are generated when an
+ * accessibility client sends a message to a control.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addAccessibleListener</code> method and removed
+ * using the <code>removeAccessibleListener</code> method.
+ * When a client requests information, the appropriate method
+ * will be invoked.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * </p>
+ *
+ * @see AccessibleAdapter
+ * @see AccessibleEvent
+ *
+ * @since 2.0
+ */
+public interface AccessibleListener : SWTEventListener {
+
+    /**
+     * Sent when an accessibility client requests the name
+     * of the control, or the name of a child of the control.
+     * <p>
+     * Return the name of the control or specified child in the
+     * <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a name, and returning null tells the client
+     * to use the platform name.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested name string, or null</li>
+     * </ul>
+     */
+    public void getName(AccessibleEvent e);
+
+    /**
+     * Sent when an accessibility client requests the help string
+     * of the control, or the help string of a child of the control.
+     * <p>
+     * The information in this property should be similar to the help
+     * provided by toolTipText. It describes what the control or child
+     * does or how to use it, as opposed to getDescription, which
+     * describes appearance.
+     * </p><p>
+     * Return the help string of the control or specified child in
+     * the <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a help string, and returning null tells the
+     * client to use the platform help string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested help string, or null</li>
+     * </ul>
+     */
+    public void getHelp(AccessibleEvent e);
+
+    /**
+     * Sent when an accessibility client requests the keyboard shortcut
+     * of the control, or the keyboard shortcut of a child of the control.
+     * <p>
+     * A keyboard shortcut can either be a mnemonic, or an accelerator.
+     * As a general rule, if the control or child can receive keyboard focus,
+     * then you should expose its mnemonic, and if it cannot receive keyboard
+     * focus, then you should expose its accelerator.
+     * </p><p>
+     * Return the keyboard shortcut string of the control or specified child
+     * in the <code>result</code> field of the event object. Returning an
+     * empty string tells the client that the control or child does not
+     * have a keyboard shortcut string, and returning null tells the client
+     * to use the platform keyboard shortcut string.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested keyboard shortcut string (example: "ALT+N"), or null</li>
+     * </ul>
+     */
+    public void getKeyboardShortcut(AccessibleEvent e);
+
+    /**
+     * Sent when an accessibility client requests a description
+     * of the control, or a description of a child of the control.
+     * <p>
+     * This is a textual description of the control or child's visual
+     * appearance, which is typically only necessary if it cannot be
+     * determined from other properties such as role.
+     * </p><p>
+     * Return the description of the control or specified child in
+     * the <code>result</code> field of the event object. Returning
+     * an empty string tells the client that the control or child
+     * does not have a description, and returning null tells the
+     * client to use the platform description.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying the control or one of its children</li>
+     *    <li>result [OUT] - the requested description string, or null</li>
+     * </ul>
+     */
+    public void getDescription(AccessibleEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleTextAdapter;
+
+import org.eclipse.swt.accessibility.AccessibleTextEvent;
+import org.eclipse.swt.accessibility.AccessibleTextListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>AccessibleTextListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>AccessibleTextEvent</code>s can
+ * extend this class and override only the methods that they are
+ * interested in.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * When returning a child identifier to a client, you may use CHILDID_NONE
+ * to indicate that no child or control has the required information.
+ * </p><p>
+ * Note: This adapter is typically used by implementors of
+ * a custom control to provide very detailed information about
+ * the control instance to accessibility clients.
+ * </p>
+ *
+ * @see AccessibleTextListener
+ * @see AccessibleTextEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public abstract class AccessibleTextAdapter : AccessibleTextListener {
+
+    /**
+     * Sent when an accessibility client requests the current character offset
+     * of the text caret.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the caret offset in the <code>offset</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>offset [OUT] - the current offset of the text caret</li>
+     * </ul>
+     */
+    public void getCaretOffset (AccessibleTextEvent e) {
+    }
+
+    /**
+     * Sent when an accessibility client requests the range of the current
+     * text selection.
+     * The default behavior is to do nothing.
+     * <p>
+     * Return the selection start offset and non-negative length in the
+     * <code>offset</code> and <code>length</code> fields of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>offset [OUT] - the offset of the current text selection</li>
+     *    <li>length [OUT] - the length of the current text selection</li>
+     * </ul>
+     */
+    public void getSelectionRange (AccessibleTextEvent e) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleTextEvent;
+
+
+import org.eclipse.swt.internal.SWTEventObject;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * accessibility clients sending messages to controls
+ * asking for detailed information about the implementation
+ * of the control instance. Typically, only implementors
+ * of custom controls need to listen for this event.
+ * <p>
+ * Note: The meaning of each field depends on the
+ * message that was sent.
+ * </p>
+ *
+ * @see AccessibleTextListener
+ * @see AccessibleTextAdapter
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class AccessibleTextEvent : SWTEventObject {
+    public int childID;             // IN
+    public int offset, length;      // OUT
+
+    //static final long serialVersionUID = 3977019530868308275L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object that fired the event
+ */
+public this (Object source) {
+    super (source);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+override public String toString () {
+    return Format( "AccessibleTextEvent {{childID={} offset={} length={}}",
+        childID,
+        offset,
+        length);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/AccessibleTextListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.accessibility.AccessibleTextListener;
+
+import org.eclipse.swt.accessibility.AccessibleTextEvent;
+
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes that implement this interface provide methods
+ * that deal with the events that are generated when an
+ * accessibility client sends a message to a control.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control using the
+ * <code>addAccessibleTextListener</code> method and removed
+ * using the <code>removeAccessibleTextListener</code> method.
+ * When a client requests information the appropriate method
+ * will be invoked.
+ * </p><p>
+ * Note: Accessibility clients use child identifiers to specify
+ * whether they want information about a control or one of its children.
+ * Child identifiers are increasing integers beginning with 0.
+ * The identifier CHILDID_SELF represents the control itself.
+ * </p><p>
+ * Note: This interface is typically used by implementors of
+ * a custom control to provide very detailed information about
+ * the control instance to accessibility clients.
+ * </p>
+ *
+ * @see AccessibleTextAdapter
+ * @see AccessibleTextEvent
+ *
+ * @since 3.0
+ */
+public interface AccessibleTextListener : SWTEventListener {
+
+    /**
+     * Sent when an accessibility client requests the current character offset
+     * of the text caret.
+     * <p>
+     * Return the caret offset in the <code>offset</code>
+     * field of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>offset [OUT] - the current offset of the text caret</li>
+     * </ul>
+     */
+    public void getCaretOffset (AccessibleTextEvent e);
+
+    /**
+     * Sent when an accessibility client requests the range of the current
+     * text selection.
+     * <p>
+     * Return the selection start offset and non-negative length in the
+     * <code>offset</code> and <code>length</code> fields of the event object.
+     * </p>
+     *
+     * @param e an event object containing the following fields:<ul>
+     *    <li>childID [IN] - an identifier specifying a child of the control</li>
+     *    <li>offset [OUT] - the offset of the current text selection</li>
+     *    <li>length [OUT] - the length of the current text selection</li>
+     * </ul>
+     */
+    public void getSelectionRange (AccessibleTextEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/accessibility/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,15 @@
+module org.eclipse.swt.accessibility.all;
+
+public import org.eclipse.swt.accessibility.ACC;
+public import org.eclipse.swt.accessibility.Accessible;
+public import org.eclipse.swt.accessibility.AccessibleAdapter;
+public import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+public import org.eclipse.swt.accessibility.AccessibleControlEvent;
+public import org.eclipse.swt.accessibility.AccessibleControlListener;
+public import org.eclipse.swt.accessibility.AccessibleEvent;
+public import org.eclipse.swt.accessibility.AccessibleListener;
+public import org.eclipse.swt.accessibility.AccessibleTextAdapter;
+public import org.eclipse.swt.accessibility.AccessibleTextEvent;
+public import org.eclipse.swt.accessibility.AccessibleTextListener;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,19 @@
+module org.eclipse.swt.all;
+
+public import org.eclipse.swt.SWT;
+public import org.eclipse.swt.SWTError;
+public import org.eclipse.swt.SWTException;
+
+public import org.eclipse.swt.accessibility.all;
+public import org.eclipse.swt.custom.all;
+public import org.eclipse.swt.dnd.all;
+public import org.eclipse.swt.events.all;
+public import org.eclipse.swt.graphics.all;
+public import org.eclipse.swt.layout.all;
+public import org.eclipse.swt.ole.all;
+//public import org.eclipse.swt.opengl.all; // dependent on existing bindings
+public import org.eclipse.swt.printing.all;
+public import org.eclipse.swt.program.all;
+public import org.eclipse.swt.widgets.all;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/AnimatedProgress.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.AnimatedProgress;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import java.lang.Runnable;
+
+/**
+ * A control for showing progress feedback for a long running operation.
+ *
+ * @deprecated As of Eclipse 2.1, use ProgressBar with the style SWT.INDETERMINATE
+ *
+ * <dl>
+ * <dt><b>Styles:</b><dd>VERTICAL, HORIZONTAL, BORDER
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class AnimatedProgress : Canvas {
+
+    alias Canvas.computeSize computeSize;
+
+    static const int SLEEP = 70;
+    static const int DEFAULT_WIDTH = 160;
+    static const int DEFAULT_HEIGHT = 18;
+    bool active = false;
+    bool showStripes = false;
+    int value;
+    int orientation = SWT.HORIZONTAL;
+    bool showBorder = false;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#VERTICAL
+ * @see SWT#HORIZONTAL
+ * @see SWT#BORDER
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle(style));
+
+    if ((style & SWT.VERTICAL) !is 0) {
+        orientation = SWT.VERTICAL;
+    }
+    showBorder = (style & SWT.BORDER) !is 0;
+
+    addControlListener(new class() ControlAdapter {
+        public void controlResized(ControlEvent e) {
+            redraw();
+        }
+    });
+    addPaintListener(new class() PaintListener {
+        public void paintControl(PaintEvent e) {
+            paint(e);
+        }
+    });
+    addDisposeListener(new class() DisposeListener {
+        public void widgetDisposed(DisposeEvent e){
+            stop();
+        }
+    });
+}
+private static int checkStyle (int style) {
+    int mask = SWT.NONE;
+    return style & mask;
+}
+/**
+ * Stop the animation if it is not already stopped and
+ * reset the presentation to a blank appearance.
+ *
+ * @exception SWTException <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 synchronized void clear(){
+    checkWidget();
+    if (active) stop();
+    showStripes = false;
+    redraw();
+}
+public override Point computeSize(int wHint, int hHint, bool changed) {
+    checkWidget();
+    Point size = null;
+    if (orientation is SWT.HORIZONTAL) {
+        size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    } else {
+        size = new Point(DEFAULT_HEIGHT, DEFAULT_WIDTH);
+    }
+    if (wHint !is SWT.DEFAULT) size.x = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+
+    return size;
+}
+private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
+    gc.setForeground(topleft);
+    gc.drawLine(x, y, x+w-1, y);
+    gc.drawLine(x, y, x, y+h-1);
+
+    gc.setForeground(bottomright);
+    gc.drawLine(x+w, y, x+w, y+h);
+    gc.drawLine(x, y+h, x+w, y+h);
+}
+void paint(PaintEvent event) {
+    GC gc = event.gc;
+    Display disp= getDisplay();
+
+    Rectangle rect= getClientArea();
+    gc.fillRectangle(rect);
+    if (showBorder) {
+        drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1,
+            disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW),
+            disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
+    }
+
+    paintStripes(gc);
+}
+void paintStripes(GC gc) {
+
+    if (!showStripes) return;
+
+    Rectangle rect= getClientArea();
+    // Subtracted border painted by paint.
+    rect = new Rectangle(rect.x+2, rect.y+2, rect.width-4, rect.height-4);
+
+    gc.setLineWidth(2);
+    gc.setClipping(rect);
+    Color color = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+    gc.setBackground(color);
+    gc.fillRectangle(rect);
+    gc.setForeground(this.getBackground());
+    int step = 12;
+    int foregroundValue = value is 0 ? step - 2 : value - 2;
+    if (orientation is SWT.HORIZONTAL) {
+        int y = rect.y - 1;
+        int w = rect.width;
+        int h = rect.height + 2;
+        for (int i= 0; i < w; i+= step) {
+            int x = i + foregroundValue;
+            gc.drawLine(x, y, x, h);
+        }
+    } else {
+        int x = rect.x - 1;
+        int w = rect.width + 2;
+        int h = rect.height;
+
+        for (int i= 0; i < h; i+= step) {
+            int y = i + foregroundValue;
+            gc.drawLine(x, y, w, y);
+        }
+    }
+
+    if (active) {
+        value = (value + 2) % step;
+    }
+}
+/**
+* Start the animation.
+*
+* @exception SWTException <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 synchronized void start() {
+    checkWidget();
+    if (active) return;
+
+    active = true;
+    showStripes = true;
+
+    Display display = getDisplay();
+    Runnable [] timer = new Runnable [1];
+
+    timer [0] = new class( display, timer ) Runnable {
+        Display disp;
+        Runnable [] runs;
+        this( Display disp, Runnable[] runs ){
+            this.disp = disp;
+            this.runs = runs;
+        }
+        public void run () {
+            if (!active) return;
+            GC gc = new GC(this.outer);
+            paintStripes(gc);
+            gc.dispose();
+            disp.timerExec (SLEEP, runs [0]);
+        }
+    };
+    display.timerExec (SLEEP, timer [0]);
+}
+/**
+* Stop the animation.   Freeze the presentation at its current appearance.
+*/
+public synchronized void stop() {
+    //checkWidget();
+    active = false;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.BidiSegmentEvent;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent to BidiSegmentListeners when a line is to
+ * be measured or rendered in a bidi locale.  The segments field is
+ * used to specify text ranges in the line that should be treated as
+ * separate segments for bidi reordering.  Each segment will be reordered
+ * and rendered separately.
+ * <p>
+ * The elements in the segments field specify the start offset of
+ * a segment relative to the start of the line. They must follow
+ * the following rules:
+ * <ul>
+ * <li>first element must be 0
+ * <li>elements must be in ascending order and must not have duplicates
+ * <li>elements must not exceed the line length
+ * </ul>
+ * In addition, the last element may be set to the end of the line
+ * but this is not required.
+ *
+ * The segments field may be left null if the entire line should
+ * be reordered as is.
+ * </p>
+ * A BidiSegmentListener may be used when adjacent segments of
+ * right-to-left text should not be reordered relative to each other.
+ * For example, within a Java editor, you may wish multiple
+ * right-to-left string literals to be reordered differently than the
+ * bidi algorithm specifies.
+ *
+ * Example:
+ * <pre>
+ *  stored line = "R1R2R3" + "R4R5R6"
+ *      R1 to R6 are right-to-left characters. The quotation marks
+ *      are part of the line text. The line is 13 characters long.
+ *
+ *  segments = null:
+ *      entire line will be reordered and thus the two R2L segments
+ *      swapped (as per the bidi algorithm).
+ *      visual line (rendered on screen) = "R6R5R4" + "R3R2R1"
+ *
+ *  segments = [0, 5, 8]
+ *      "R1R2R3" will be reordered, followed by [blank]+[blank] and
+ *      "R4R5R6".
+ *      visual line = "R3R2R1" + "R6R5R4"
+ * </pre>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class BidiSegmentEvent : TypedEvent {
+
+    /**
+     * line start offset
+     */
+    public int lineOffset;
+
+    /**
+     * line text
+     */
+    public String lineText;
+
+    /**
+     * bidi segments, see above
+     */
+    public int[] segments;
+
+this(StyledTextEvent e) {
+    super(cast(Object)e);
+    lineOffset = e.detail;
+    lineText = e.text;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BidiSegmentListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.BidiSegmentListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.BidiSegmentEvent;
+
+/**
+ * This listener interface may be implemented in order to receive
+ * BidiSegmentEvents.
+ * @see BidiSegmentEvent
+ */
+public interface BidiSegmentListener : SWTEventListener {
+
+/**
+ * This method is called when a line needs to be reordered for
+ * measuring or rendering in a bidi locale.
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineOffset line start offset (input)</li>
+ * <li>event.lineText line text (input)</li>
+ * <li>event.segments text segments that should be reordered
+ *  separately. (output)</li>
+ * </ul>
+ *
+ * @param event the given event
+ *  separately. (output)
+ * @see BidiSegmentEvent
+ */
+public void lineGetSegments(BidiSegmentEvent event);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/Bullet.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.Bullet;
+
+import java.lang.all;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.ST;
+import java.lang.System;
+
+/**
+ * Instances of this class represent bullets in the <code>StyledText</code>.
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see StyledText#setLineBullet(int, int, Bullet)
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public class Bullet {
+    /**
+    * The bullet type.  Possible values are:
+    * <ul>
+    * <li><code>ST.BULLET_DOT</code></li>
+    * <li><code>ST.BULLET_NUMBER</code></li>
+    * <li><code>ST.BULLET_LETTER_LOWER</code></li>
+    * <li><code>ST.BULLET_LETTER_UPPER</code></li>
+    * <li><code>ST.BULLET_TEXT</code></li>
+    * <li><code>ST.BULLET_CUSTOM</code></li>
+    * </ul>
+    */
+    public int type;
+
+    /**
+    * The bullet style.
+    */
+    public StyleRange style;
+
+    /**
+    * The bullet text.
+    */
+    public String text;
+
+    int[] linesIndices;
+    int count;
+
+/**
+ * Create a new bullet with the specified style, and type <code>ST.BULLET_DOT</code>. 
+ * The style must have a glyph metrics set.
+ *
+ * @param style the style
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when the style or the glyph metrics are null</li>
+ * </ul>
+ */
+public this(StyleRange style) {
+    this(ST.BULLET_DOT, style);
+}
+/**
+ * Create a new bullet the specified style and type.
+ * The style must have a glyph metrics set.
+ *
+ * @param type the bullet type
+ * @param style the style
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when the style or the glyph metrics are null</li>
+ * </ul>
+ */
+public this(int type, StyleRange style) {
+    if (style is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (style.metrics is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    this.type = type;
+    this.style = style;
+}
+void addIndices (int startLine, int lineCount) {
+    if (linesIndices is null) {
+        linesIndices = new int[lineCount];
+        count = lineCount;
+        for (int i = 0; i < lineCount; i++) linesIndices[i] = startLine + i;
+    } else {
+        int modifyStart = 0;
+        while (modifyStart < count) {
+            if (startLine <= linesIndices[modifyStart]) break;
+            modifyStart++;
+        }
+        int modifyEnd = modifyStart;
+        while (modifyEnd < count) {
+            if (startLine + lineCount <= linesIndices[modifyEnd]) break;
+            modifyEnd++;
+        }
+        int newSize = modifyStart + lineCount + count - modifyEnd;
+        if (newSize > linesIndices.length) {
+            int[] newLinesIndices = new int[newSize];
+            System.arraycopy(linesIndices, 0, newLinesIndices, 0, count);
+            linesIndices = newLinesIndices;
+        }
+        System.arraycopy(linesIndices, modifyEnd, linesIndices, modifyStart + lineCount, count - modifyEnd);
+        for (int i = 0; i < lineCount; i++) linesIndices[modifyStart + i] = startLine + i;
+        count = newSize;
+    }
+}
+int indexOf (int lineIndex) {
+    for (int i = 0; i < count; i++) {
+        if (linesIndices[i] is lineIndex) return i;
+    }
+    return -1;
+}
+public override hash_t toHash() {
+    return style.toHash() ^ type;
+}
+int[] removeIndices (int startLine, int replaceLineCount, int newLineCount, bool update) {
+    if (count is 0) return null;
+    if (startLine > linesIndices[count - 1]) return null;
+    int endLine = startLine + replaceLineCount;
+    int delta = newLineCount - replaceLineCount;
+    for (int i = 0; i < count; i++) {
+        int index = linesIndices[i];
+        if (startLine <= index) {
+            int j = i;
+            while (j < count) {
+                if (linesIndices[j] >= endLine) break;
+                j++;
+            }
+            if (update) {
+                for (int k = j; k < count; k++) linesIndices[k] += delta;
+            }
+            int[] redrawLines = new int[count - j];
+            System.arraycopy(linesIndices, j, redrawLines, 0, count - j);
+            System.arraycopy(linesIndices, j, linesIndices, i, count - j);
+            count -= (j - i);
+            return redrawLines;
+        }
+    }
+    for (int i = 0; i < count; i++) linesIndices[i] += delta;
+    return null;
+}
+int size() {
+    return count;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/BusyIndicator.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.BusyIndicator;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import java.lang.Runnable;
+import java.lang.all;
+
+/**
+ * Support for showing a Busy Cursor during a long running process.
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#busyindicator">BusyIndicator snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class BusyIndicator {
+
+    static int nextBusyId = 1;
+    static const String BUSYID_NAME = "SWT BusyIndicator"; //$NON-NLS-1$
+    static const String BUSY_CURSOR = "SWT BusyIndicator Cursor"; //$NON-NLS-1$
+
+/**
+ * Runs the given <code>Runnable</code> while providing
+ * busy feedback using this busy indicator.
+ *
+ * @param display the display on which the busy feedback should be
+ *        displayed.  If the display is null, the Display for the current
+ *        thread will be used.  If there is no Display for the current thread,
+ *        the runnable code will be executed and no busy feedback will be displayed.
+ * @param runnable the runnable for which busy feedback is to be shown.
+ *        Must not be null.
+ *
+* @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
+ * </ul>
+ */
+
+public static void showWhile(Display display, Runnable runnable) {
+    if (runnable is null)
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (display is null) {
+        display = Display.getCurrent();
+        if (display is null) {
+            runnable.run();
+            return;
+        }
+    }
+
+    Integer busyId = new Integer(nextBusyId);
+    nextBusyId++;
+    Cursor cursor = display.getSystemCursor(SWT.CURSOR_WAIT);
+    Shell[] shells = display.getShells();
+    for (int i = 0; i < shells.length; i++) {
+        Integer id = cast(Integer)shells[i].getData(BUSYID_NAME);
+        if (id is null) {
+            shells[i].setCursor(cursor);
+            shells[i].setData(BUSYID_NAME, busyId);
+        }
+    }
+
+    try {
+        runnable.run();
+    } finally {
+        shells = display.getShells();
+        for (int i = 0; i < shells.length; i++) {
+            Integer id = cast(Integer)shells[i].getData(BUSYID_NAME);
+            if ( id !is null && id == busyId) {
+                shells[i].setCursor(null);
+                shells[i].setData(BUSYID_NAME, null);
+            }
+        }
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CBanner.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,560 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CBanner;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.custom.CBannerLayout;
+
+import Math = tango.math.Math;
+
+
+/**
+ * Instances of this class implement a Composite that lays out its
+ * children and allows programmatic control of the layout. It draws
+ * a separator between the left and right children which can be dragged
+ * to resize the right control.
+ * CBanner is used in the workbench to layout the toolbar area and
+ * perspective switching toolbar.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>NONE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(None)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+
+public class CBanner : Composite {
+
+    Control left;
+    Control right;
+    Control bottom;
+
+    bool simple = true;
+
+    int[] curve;
+    int curveStart = 0;
+    Rectangle curveRect;
+    int curve_width = 5;
+    int curve_indent = -2;
+
+    int rightWidth = SWT.DEFAULT;
+    int rightMinWidth = 0;
+    int rightMinHeight = 0;
+    Cursor resizeCursor;
+    bool dragging = false;
+    int rightDragDisplacement = 0;
+
+    static const int OFFSCREEN = -200;
+    static const int BORDER_BOTTOM = 2;
+    static const int BORDER_TOP = 3;
+    static const int BORDER_STRIPE = 1;
+    static const int CURVE_TAIL = 200;
+    static const int BEZIER_RIGHT = 30;
+    static const int BEZIER_LEFT = 30;
+    static const int MIN_LEFT = 10;
+    static int BORDER1 = SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW;
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ */
+public this(Composite parent, int style) {
+    curveRect = new Rectangle(0, 0, 0, 0);
+    super(parent, checkStyle(style));
+    super.setLayout(new CBannerLayout());
+    resizeCursor = new Cursor(getDisplay(), SWT.CURSOR_SIZEWE);
+
+    Listener listener = new class() Listener {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+                case SWT.Dispose:
+                    onDispose(); break;
+                case SWT.MouseDown:
+                    onMouseDown (e.x, e.y); break;
+                case SWT.MouseExit:
+                    onMouseExit(); break;
+                case SWT.MouseMove:
+                    onMouseMove(e.x, e.y); break;
+                case SWT.MouseUp:
+                    onMouseUp(); break;
+                case SWT.Paint:
+                    onPaint(e.gc); break;
+                case SWT.Resize:
+                    onResize(); break;
+                default:
+            }
+        }
+    };
+    int[] events = [SWT.Dispose, SWT.MouseDown, SWT.MouseExit, SWT.MouseMove, SWT.MouseUp, SWT.Paint, SWT.Resize];
+    for (int i = 0; i < events.length; i++) {
+        addListener(events[i], listener);
+    }
+}
+static int[] bezier(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) {
+    // The parametric equations for a Bezier curve for x[t] and y[t] where  0 <= t <=1 are:
+    // x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^2+(x3-x0+3x1-3x2)t^3
+    // y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3
+    double a0 = x0;
+    double a1 = 3*(x1 - x0);
+    double a2 = 3*(x0 + x2 - 2*x1);
+    double a3 = x3 - x0 + 3*x1 - 3*x2;
+    double b0 = y0;
+    double b1 = 3*(y1 - y0);
+    double b2 = 3*(y0 + y2 - 2*y1);
+    double b3 = y3 - y0 + 3*y1 - 3*y2;
+
+    int[] polygon = new int[2*count + 2];
+    for (int i = 0; i <= count; i++) {
+        double t = cast(double)i / cast(double)count;
+        polygon[2*i] = cast(int)(a0 + a1*t + a2*t*t + a3*t*t*t);
+        polygon[2*i + 1] = cast(int)(b0 + b1*t + b2*t*t + b3*t*t*t);
+    }
+    return polygon;
+}
+static int checkStyle (int style) {
+    return SWT.NONE;
+}
+/**
+* Returns the Control that appears on the bottom side of the banner.
+*
+* @return the control that appears on the bottom side of the banner or null
+*
+* @exception SWTException <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.0
+*/
+public Control getBottom() {
+    checkWidget();
+    return bottom;
+}
+public override Rectangle getClientArea() {
+    return new Rectangle(0, 0, 0, 0);
+}
+
+/**
+* Returns the Control that appears on the left side of the banner.
+*
+* @return the control that appears on the left side of the banner or null
+*
+* @exception SWTException <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.0
+*/
+public Control getLeft() {
+    checkWidget();
+    return left;
+}
+
+/**
+* Returns the Control that appears on the right side of the banner.
+*
+* @return the control that appears on the right side of the banner or null
+*
+* @exception SWTException <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.0
+*/
+public Control getRight() {
+    checkWidget();
+    return right;
+}
+/**
+ * Returns the minimum size of the control that appears on the right of the banner.
+ *
+ * @return the minimum size of the control that appears on the right of the banner
+ *
+ * @since 3.1
+ */
+public Point getRightMinimumSize() {
+    checkWidget();
+    return new Point(rightMinWidth, rightMinHeight);
+}
+/**
+ * Returns the width of the control that appears on the right of the banner.
+ *
+ * @return the width of the control that appears on the right of the banner
+ *
+ * @since 3.0
+ */
+public int getRightWidth() {
+    checkWidget();
+    if (right is null) return 0;
+    if (rightWidth is SWT.DEFAULT) {
+        Point size = right.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
+        return size.x;
+    }
+    return rightWidth;
+}
+/**
+ * Returns <code>true</code> if the CBanner is rendered
+ * with a simple, traditional shape.
+ *
+ * @return <code>true</code> if the CBanner is rendered with a simple shape
+ *
+ * @since 3.0
+ */
+public bool getSimple() {
+    checkWidget();
+    return simple;
+}
+void onDispose() {
+    if (resizeCursor !is null) resizeCursor.dispose();
+    resizeCursor = null;
+    left = null;
+    right = null;
+    bottom = null;
+}
+void onMouseDown (int x, int y) {
+    if (curveRect.contains(x, y)) {
+        dragging = true;
+        rightDragDisplacement = curveStart - x + curve_width - curve_indent;
+    }
+}
+void onMouseExit() {
+    if (!dragging) setCursor(null);
+}
+void onMouseMove(int x, int y) {
+    if (dragging) {
+        Point size = getSize();
+        if (!(0 < x && x < size.x)) return;
+        rightWidth = Math.max(0, size.x - x - rightDragDisplacement);
+        if (rightMinWidth is SWT.DEFAULT) {
+            Point minSize = right.computeSize(rightMinWidth, rightMinHeight);
+            rightWidth = Math.max(minSize.x, rightWidth);
+        } else {
+            rightWidth = Math.max(rightMinWidth, rightWidth);
+        }
+        layout(false);
+        return;
+    }
+    if (curveRect.contains(x, y)) {
+        setCursor(resizeCursor);
+    } else {
+        setCursor(null);
+    }
+}
+void onMouseUp () {
+    dragging = false;
+}
+void onPaint(GC gc) {
+//   Useful for debugging paint problems
+//  {
+//  Point size = getSize();
+//  gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
+//  gc.fillRectangle(-10, -10, size.x+20, size.y+20);
+//  }
+    if (left is null && right is null) return;
+    Point size = getSize();
+    Color border1 = getDisplay().getSystemColor(BORDER1);
+    if (bottom !is null) {
+        int y = bottom.getBounds().y - BORDER_STRIPE - 1;
+        gc.setForeground(border1);
+        gc.drawLine(0, y, size.x, y);
+    }
+    if (left is null || right is null) return;
+    int[] line1 = new int[curve.length+6];
+    int index = 0;
+    int x = curveStart;
+    line1[index++] = x + 1;
+    line1[index++] = size.y - BORDER_STRIPE;
+    for (int i = 0; i < curve.length/2; i++) {
+        line1[index++]=x+curve[2*i];
+        line1[index++]=curve[2*i+1];
+    }
+    line1[index++] = x + curve_width;
+    line1[index++] = 0;
+    line1[index++] = size.x;
+    line1[index++] = 0;
+
+    Color background = getBackground();
+
+    if (getDisplay().getDepth() >= 15) {
+        // Anti- aliasing
+        int[] line2 = new int[line1.length];
+        index = 0;
+        for (int i = 0; i < line1.length/2; i++) {
+            line2[index] = line1[index++]  - 1;
+            line2[index] = line1[index++];
+        }
+        int[] line3 = new int[line1.length];
+        index = 0;
+        for (int i = 0; i < line1.length/2; i++) {
+            line3[index] = line1[index++] + 1;
+            line3[index] = line1[index++];
+        }
+        RGB from = border1.getRGB();
+        RGB to = background.getRGB();
+        int red = from.red + 3*(to.red - from.red)/4;
+        int green = from.green + 3*(to.green - from.green)/4;
+        int blue = from.blue + 3*(to.blue - from.blue)/4;
+        Color color = new Color(getDisplay(), red, green, blue);
+        gc.setForeground(color);
+        gc.drawPolyline(line2);
+        gc.drawPolyline(line3);
+        color.dispose();
+
+        // draw tail fading to background
+        int x1 = Math.max(0, curveStart - CURVE_TAIL);
+        gc.setForeground(background);
+        gc.setBackground(border1);
+        gc.fillGradientRectangle(x1, size.y - BORDER_STRIPE, curveStart-x1+1, 1, false);
+    } else {
+        // draw solid tail
+        int x1 = Math.max(0, curveStart - CURVE_TAIL);
+        gc.setForeground(border1);
+        gc.drawLine(x1, size.y - BORDER_STRIPE, curveStart+1, size.y - BORDER_STRIPE);
+    }
+
+    // draw border
+    gc.setForeground(border1);
+    gc.drawPolyline(line1);
+}
+
+void onResize() {
+    updateCurve(getSize().y);
+}
+/**
+* Set the control that appears on the bottom side of the banner.
+* The bottom control is optional.  Setting the bottom control to null will remove it from
+* the banner - however, the creator of the control must dispose of the control.
+*
+* @param control the control to be displayed on the bottom or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the bottom control was not created as a child of the receiver</li>
+* </ul>
+*
+* @since 3.0
+*/
+public void setBottom(Control control) {
+    checkWidget();
+    if (control !is null && control.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (bottom !is null && !bottom.isDisposed()) {
+        Point size = bottom.getSize();
+        bottom.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    bottom = control;
+    layout(false);
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    checkWidget();
+    return;
+}
+
+/**
+* Set the control that appears on the left side of the banner.
+* The left control is optional.  Setting the left control to null will remove it from
+* the banner - however, the creator of the control must dispose of the control.
+*
+* @param control the control to be displayed on the left or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the left control was not created as a child of the receiver</li>
+* </ul>
+*
+* @since 3.0
+*/
+public void setLeft(Control control) {
+    checkWidget();
+    if (control !is null && control.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (left !is null && !left.isDisposed()) {
+        Point size = left.getSize();
+        left.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    left = control;
+    layout(false);
+}
+/**
+* Set the control that appears on the right side of the banner.
+* The right control is optional.  Setting the right control to null will remove it from
+* the banner - however, the creator of the control must dispose of the control.
+*
+* @param control the control to be displayed on the right or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the right control was not created as a child of the receiver</li>
+* </ul>
+*
+* @since 3.0
+*/
+public void setRight(Control control) {
+    checkWidget();
+    if (control !is null && control.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (right !is null && !right.isDisposed()) {
+        Point size = right.getSize();
+        right.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    right = control;
+    layout(false);
+}
+/**
+ * Set the minimum height of the control that appears on the right side of the banner.
+ *
+ * @param size the minimum size of the control on the right
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the size is null or the values of size are less than SWT.DEFAULT</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setRightMinimumSize(Point size) {
+    checkWidget();
+    if (size is null || size.x < SWT.DEFAULT || size.y < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    rightMinWidth = size.x;
+    rightMinHeight = size.y;
+    layout(false);
+}
+/**
+ * Set the width of the control that appears on the right side of the banner.
+ *
+ * @param width the width of the control on the right
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if width is less than SWT.DEFAULT</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setRightWidth(int width) {
+    checkWidget();
+    if (width < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    rightWidth = width;
+    layout(false);
+}
+/**
+ * Sets the shape that the CBanner will use to render itself.
+ *
+ * @param simple <code>true</code> if the CBanner should render itself in a simple, traditional style
+ *
+ * @exception SWTException <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.0
+ */
+public void setSimple(bool simple) {
+    checkWidget();
+    if (this.simple !is simple) {
+        this.simple = simple;
+        if (simple) {
+            curve_width = 5;
+            curve_indent = -2;
+        } else {
+            curve_width = 50;
+            curve_indent = 5;
+        }
+        updateCurve(getSize().y);
+        layout(false);
+        redraw();
+    }
+}
+void updateCurve(int height) {
+    int h = height - BORDER_STRIPE;
+    if (simple) {
+        curve = [0,h, 1,h, 2,h-1, 3,h-2,
+                                   3,2, 4,1, 5,0];
+    } else {
+        curve = bezier(0, h+1, BEZIER_LEFT, h+1,
+                             curve_width-BEZIER_RIGHT, 0, curve_width, 0,
+                             curve_width);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CBannerLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CBannerLayout;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.custom.CBanner;
+import org.eclipse.swt.custom.CLayoutData;
+
+import Math = tango.math.Math;
+
+/**
+ * This class provides the layout for CBanner
+ *
+ * @see CBanner
+ */
+class CBannerLayout : Layout {
+
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    CBanner banner = cast(CBanner)composite;
+    Control left = banner.left;
+    Control right = banner.right;
+    Control bottom = banner.bottom;
+    bool showCurve = left !is null && right !is null;
+    int height = hHint;
+    int width = wHint;
+
+    // Calculate component sizes
+    Point bottomSize = new Point(0, 0);
+    if (bottom !is null) {
+        int trim = computeTrim(bottom);
+        int w = wHint is SWT.DEFAULT ? SWT.DEFAULT : Math.max(0, width - trim);
+        bottomSize = computeChildSize(bottom, w, SWT.DEFAULT, flushCache);
+    }
+    Point rightSize = new Point(0, 0);
+    if (right !is null) {
+        int trim = computeTrim(right);
+        int w = SWT.DEFAULT;
+        if (banner.rightWidth !is SWT.DEFAULT) {
+            w = banner.rightWidth - trim;
+            if (left !is null) {
+                w = Math.min(w, width - banner.curve_width + 2* banner.curve_indent - CBanner.MIN_LEFT - trim);
+            }
+            w = Math.max(0, w);
+        }
+        rightSize = computeChildSize(right, w, SWT.DEFAULT, flushCache);
+        if (wHint !is SWT.DEFAULT) {
+            width -= rightSize.x + banner.curve_width - 2* banner.curve_indent;
+        }
+    }
+    Point leftSize = new Point(0, 0);
+    if (left !is null) {
+        int trim = computeTrim(left);
+        int w = wHint is SWT.DEFAULT ? SWT.DEFAULT : Math.max(0, width - trim);
+        leftSize = computeChildSize(left, w, SWT.DEFAULT, flushCache);
+    }
+
+    // Add up sizes
+    width = leftSize.x + rightSize.x;
+    height = bottomSize.y;
+    if (bottom !is null && (left !is null || right !is null)) {
+        height += CBanner.BORDER_STRIPE + 2;
+    }
+    if (left !is null) {
+        if (right is null) {
+            height += leftSize.y;
+        } else {
+            height += Math.max(leftSize.y, banner.rightMinHeight is SWT.DEFAULT ? rightSize.y : banner.rightMinHeight);
+        }
+    } else {
+        height += rightSize.y;
+    }
+    if (showCurve) {
+        width += banner.curve_width - 2*banner.curve_indent;
+        height +=  CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2*CBanner.BORDER_STRIPE;
+    }
+
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+
+    return new Point(width, height);
+}
+Point computeChildSize(Control control, int wHint, int hHint, bool flushCache) {
+    Object data = control.getLayoutData();
+    if (data is null || !( null !is cast(CLayoutData)data)) {
+        data = new CLayoutData();
+        control.setLayoutData(data);
+    }
+    return (cast(CLayoutData)data).computeSize(control, wHint, hHint, flushCache);
+}
+int computeTrim(Control c) {
+    if ( auto s = cast(Scrollable)c) {
+        Rectangle rect = s.computeTrim (0, 0, 0, 0);
+        return rect.width;
+    }
+    return c.getBorderWidth () * 2;
+}
+protected override bool flushCache(Control control) {
+    Object data = control.getLayoutData();
+    if ( auto ld = cast(CLayoutData)data ) ld.flushCache();
+    return true;
+}
+protected override void layout(Composite composite, bool flushCache) {
+    CBanner banner = cast(CBanner)composite;
+    Control left = banner.left;
+    Control right = banner.right;
+    Control bottom = banner.bottom;
+
+    Point size = banner.getSize();
+    bool showCurve = left !is null && right !is null;
+    int width = size.x - 2*banner.getBorderWidth();
+    int height = size.y - 2*banner.getBorderWidth();
+
+    Point bottomSize = new Point(0, 0);
+    if (bottom !is null) {
+        int trim = computeTrim(bottom);
+        int w = Math.max(0, width - trim);
+        bottomSize = computeChildSize(bottom, w, SWT.DEFAULT, flushCache);
+        height -= bottomSize.y + CBanner.BORDER_STRIPE + 2;
+    }
+    if (showCurve) height -=  CBanner.BORDER_TOP + CBanner.BORDER_BOTTOM + 2*CBanner.BORDER_STRIPE;
+    height = Math.max(0, height);
+    Point rightSize = new Point(0,0);
+    if (right !is null) {
+        int trim = computeTrim(right);
+        int w = SWT.DEFAULT;
+        if (banner.rightWidth !is SWT.DEFAULT) {
+            w = banner.rightWidth - trim;
+            if (left !is null) {
+                w = Math.min(w, width - banner.curve_width + 2* banner.curve_indent - CBanner.MIN_LEFT - trim);
+            }
+            w = Math.max(0, w);
+        }
+        rightSize = computeChildSize(right, w, SWT.DEFAULT, flushCache);
+        width = width - (rightSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent);
+    }
+    Point leftSize = new Point(0, 0);
+    if (left !is null) {
+        int trim = computeTrim(left);
+        int w = Math.max(0, width - trim);
+        leftSize = computeChildSize(left, w, SWT.DEFAULT, flushCache);
+    }
+
+    int x = 0;
+    int y = 0;
+    int oldStart = banner.curveStart;
+    Rectangle leftRect = null;
+    Rectangle rightRect = null;
+    Rectangle bottomRect = null;
+    if (bottom !is null) {
+        bottomRect = new Rectangle(x, y+size.y-bottomSize.y, bottomSize.x, bottomSize.y);
+    }
+    if (showCurve) y += CBanner.BORDER_TOP + CBanner.BORDER_STRIPE;
+    if(left !is null) {
+        leftRect = new Rectangle(x, y, leftSize.x, leftSize.y);
+        banner.curveStart = x + leftSize.x - banner.curve_indent;
+        x += leftSize.x - banner.curve_indent + banner.curve_width - banner.curve_indent;
+    }
+    if (right !is null) {
+        if (left !is null) {
+            rightSize.y = Math.max(leftSize.y, banner.rightMinHeight is SWT.DEFAULT ? rightSize.y : banner.rightMinHeight);
+        }
+        rightRect = new Rectangle(x, y, rightSize.x, rightSize.y);
+    }
+    if (banner.curveStart < oldStart) {
+        banner.redraw(banner.curveStart - CBanner.CURVE_TAIL, 0, oldStart + banner.curve_width - banner.curveStart + CBanner.CURVE_TAIL + 5, size.y, false);
+    }
+    if (banner.curveStart > oldStart) {
+        banner.redraw(oldStart - CBanner.CURVE_TAIL, 0, banner.curveStart + banner.curve_width - oldStart + CBanner.CURVE_TAIL + 5, size.y, false);
+    }
+    /*
+     * The paint events must be flushed in order to make the curve draw smoothly
+     * while the user drags the divider.
+     * On Windows, it is necessary to flush the paints before the children are
+     * resized because otherwise the children (particularly toolbars) will flash.
+     */
+    banner.update();
+    banner.curveRect = new Rectangle(banner.curveStart, 0, banner.curve_width, size.y);
+    if (bottomRect !is null) bottom.setBounds(bottomRect);
+    if (rightRect !is null) right.setBounds(rightRect);
+    if (leftRect !is null) left.setBounds(leftRect);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CCombo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1806 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CCombo;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.accessibility.AccessibleTextAdapter;
+import org.eclipse.swt.accessibility.AccessibleTextEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Widget;
+
+static import tango.text.convert.Utf;
+static import tango.text.Unicode;
+static import tango.text.convert.Format;
+import java.lang.all;
+import java.lang.Runnable;
+
+/**
+ * The CCombo class represents a selectable user interface object
+ * that combines a text field and a list and issues notification
+ * when an item is selected from the list.
+ * <p>
+ * CCombo was written to work around certain limitations in the native
+ * combo box. Specifically, on win32, the height of a CCombo can be set;
+ * attempts to set the height of a Combo are ignored. CCombo can be used
+ * anywhere that having the increased flexibility is more important than
+ * getting native L&F, but the decision should not be taken lightly.
+ * There is no is no strict requirement that CCombo look or behave
+ * the same as the native combo box.
+ * </p>
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>BORDER, READ_ONLY, FLAT</dd>
+ * <dt><b>Events:</b>
+ * <dd>DefaultSelection, Modify, Selection, Verify</dd>
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ccombo">CCombo snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class CCombo : Composite {
+
+    alias Composite.computeSize computeSize;
+
+    Text text;
+    List list;
+    int visibleItemCount = 5;
+    Shell popup;
+    Button arrow;
+    bool hasFocus;
+    Listener listener, filter;
+    Color foreground, background;
+    Font font;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#READ_ONLY
+ * @see SWT#FLAT
+ * @see Widget#getStyle()
+ */
+public this (Composite parent, int style) {
+    super (parent, style = checkStyle (style));
+
+    int textStyle = SWT.SINGLE;
+    if ((style & SWT.READ_ONLY) !is 0) textStyle |= SWT.READ_ONLY;
+    if ((style & SWT.FLAT) !is 0) textStyle |= SWT.FLAT;
+    text = new Text (this, textStyle);
+    int arrowStyle = SWT.ARROW | SWT.DOWN;
+    if ((style & SWT.FLAT) !is 0) arrowStyle |= SWT.FLAT;
+    arrow = new Button (this, arrowStyle);
+
+    listener = new class() Listener {
+        public void handleEvent (Event event) {
+            if (popup is event.widget) {
+                popupEvent (event);
+                return;
+            }
+            if (text is event.widget) {
+                textEvent (event);
+                return;
+            }
+            if (list is event.widget) {
+                listEvent (event);
+                return;
+            }
+            if (arrow is event.widget) {
+                arrowEvent (event);
+                return;
+            }
+            if (this.outer is event.widget) {
+                comboEvent (event);
+                return;
+            }
+            if (getShell () is event.widget) {
+                getDisplay().asyncExec(new class() Runnable {
+                    public void run() {
+                        if (isDisposed()) return;
+                        handleFocus (SWT.FocusOut);
+                    }
+                });
+            }
+        }
+    };
+    filter = new class() Listener {
+        public void handleEvent(Event event) {
+            Shell shell = (cast(Control)event.widget).getShell ();
+            if (shell is this.outer.getShell ()) {
+                handleFocus (SWT.FocusOut);
+            }
+        }
+    };
+
+    int [] comboEvents = [SWT.Dispose, SWT.FocusIn, SWT.Move, SWT.Resize];
+    for (int i=0; i<comboEvents.length; i++) this.addListener (comboEvents [i], listener);
+
+    int [] textEvents = [SWT.DefaultSelection, SWT.KeyDown, SWT.KeyUp, SWT.MenuDetect, SWT.Modify, SWT.MouseDown, SWT.MouseUp, SWT.MouseDoubleClick, SWT.MouseWheel, SWT.Traverse, SWT.FocusIn, SWT.Verify];
+    for (int i=0; i<textEvents.length; i++) text.addListener (textEvents [i], listener);
+
+    int [] arrowEvents = [SWT.MouseDown, SWT.MouseUp, SWT.Selection, SWT.FocusIn];
+    for (int i=0; i<arrowEvents.length; i++) arrow.addListener (arrowEvents [i], listener);
+
+    createPopup(null, -1);
+    initAccessible();
+}
+static int checkStyle (int style) {
+    int mask = SWT.BORDER | SWT.READ_ONLY | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    return SWT.NO_FOCUS | (style & mask);
+}
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception SWTException <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 #add(String,int)
+ */
+public void add (String string) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    list.add (string);
+}
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ * <p>
+ * Note: To add an item at the end of the list, use the
+ * result of calling <code>getItemCount()</code> as the
+ * index or use <code>add(String)</code>.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 #add(String)
+ */
+public void add (String string, int index) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    list.add (string, index);
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Modify, typedListener);
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the combo's list selection changes.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #removeVerifyListener
+ *
+ * @since 3.3
+ */
+public void addVerifyListener (VerifyListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Verify,typedListener);
+}
+void arrowEvent (Event event) {
+    switch (event.type) {
+        case SWT.FocusIn: {
+            handleFocus (SWT.FocusIn);
+            break;
+        }
+        case SWT.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 (SWT.MouseDown, mouseEvent);
+            event.doit = mouseEvent.doit;
+            break;
+        }
+        case SWT.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 (SWT.MouseUp, mouseEvent);
+            event.doit = mouseEvent.doit;
+            break;
+        }
+        case SWT.Selection: {
+            text.setFocus();
+            dropDown (!isDropped ());
+            break;
+        }
+        default:
+    }
+}
+/**
+ * Sets the selection in the receiver's text field to an empty
+ * selection starting just before the first character. If the
+ * text field is editable, this has the effect of placing the
+ * i-beam at the start of the text.
+ * <p>
+ * Note: To clear the selected items in the receiver's list,
+ * use <code>deselectAll()</code>.
+ * </p>
+ *
+ * @exception SWTException <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 #deselectAll
+ */
+public void clearSelection () {
+    checkWidget ();
+    text.clearSelection ();
+    list.deselectAll ();
+}
+void comboEvent (Event event) {
+    switch (event.type) {
+        case SWT.Dispose:
+            if (popup !is null && !popup.isDisposed ()) {
+                list.removeListener (SWT.Dispose, listener);
+                popup.dispose ();
+            }
+            Shell shell = getShell ();
+            shell.removeListener (SWT.Deactivate, listener);
+            Display display = getDisplay ();
+            display.removeFilter (SWT.FocusIn, filter);
+            popup = null;
+            text = null;
+            list = null;
+            arrow = null;
+            break;
+        case SWT.FocusIn:
+            Control focusControl = getDisplay ().getFocusControl ();
+            if (focusControl is arrow || focusControl is list) return;
+            if (isDropped()) {
+                list.setFocus();
+            } else {
+                text.setFocus();
+            }
+            break;
+        case SWT.Move:
+            dropDown (false);
+            break;
+        case SWT.Resize:
+            internalLayout (false);
+            break;
+        default:
+    }
+}
+
+public override Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    String[] items = list.getItems ();
+    GC gc = new GC (text);
+    int spacer = gc.stringExtent (" ").x; //$NON-NLS-1$
+    int textWidth = gc.stringExtent (text.getText ()).x;
+    for (int i = 0; i < items.length; i++) {
+        textWidth = Math.max (gc.stringExtent (items[i]).x, textWidth);
+    }
+    gc.dispose ();
+    Point textSize = text.computeSize (SWT.DEFAULT, SWT.DEFAULT, changed);
+    Point arrowSize = arrow.computeSize (SWT.DEFAULT, SWT.DEFAULT, changed);
+    Point listSize = list.computeSize (SWT.DEFAULT, SWT.DEFAULT, changed);
+    int borderWidth = getBorderWidth ();
+
+    height = Math.max (textSize.y, arrowSize.y);
+    width = Math.max (textWidth + 2*spacer + arrowSize.x + 2*borderWidth, listSize.x);
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    return new Point (width + 2*borderWidth, height + 2*borderWidth);
+}
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 copy () {
+    checkWidget ();
+    text.copy ();
+}
+void createPopup(String[] items, int selectionIndex) {
+    // create shell and list
+    popup = new Shell (getShell (), SWT.NO_TRIM | SWT.ON_TOP);
+    int style = getStyle ();
+    int listStyle = SWT.SINGLE | SWT.V_SCROLL;
+    if ((style & SWT.FLAT) !is 0) listStyle |= SWT.FLAT;
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) listStyle |= SWT.RIGHT_TO_LEFT;
+    if ((style & SWT.LEFT_TO_RIGHT) !is 0) listStyle |= SWT.LEFT_TO_RIGHT;
+    list = new List (popup, listStyle);
+    if (font !is null) list.setFont (font);
+    if (foreground !is null) list.setForeground (foreground);
+    if (background !is null) list.setBackground (background);
+
+    int [] popupEvents = [SWT.Close, SWT.Paint, SWT.Deactivate];
+    for (int i=0; i<popupEvents.length; i++) popup.addListener (popupEvents [i], listener);
+    int [] listEvents = [SWT.MouseUp, SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn, SWT.Dispose];
+    for (int i=0; i<listEvents.length; i++) list.addListener (listEvents [i], listener);
+
+    if (items !is null) list.setItems (items);
+    if (selectionIndex !is -1) list.setSelection (selectionIndex);
+}
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @exception SWTException <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 cut () {
+    checkWidget ();
+    text.cut ();
+}
+/**
+ * Deselects the item at the given zero-relative index in the receiver's
+ * list.  If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException <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 deselect (int index) {
+    checkWidget ();
+    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.
+ * <p>
+ * Note: To clear the selection in the receiver's text field,
+ * use <code>clearSelection()</code>.
+ * </p>
+ *
+ * @exception SWTException <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 #clearSelection
+ */
+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 () && isFocusControl()) {
+            text.setFocus();
+        }
+        return;
+    }
+    if (!isVisible()) return;
+    if (getShell() !is popup.getParent ()) {
+        String[] items = list.getItems ();
+        int selectionIndex = list.getSelectionIndex ();
+        list.removeListener (SWT.Dispose, listener);
+        popup.dispose();
+        popup = null;
+        list = null;
+        createPopup (items, selectionIndex);
+    }
+
+    Point size = getSize ();
+    int itemCount = list.getItemCount ();
+    itemCount = (itemCount is 0) ? visibleItemCount : Math.min(visibleItemCount, itemCount);
+    int itemHeight = list.getItemHeight () * itemCount;
+    Point listSize = list.computeSize (SWT.DEFAULT, itemHeight, false);
+    list.setBounds (1, 1, Math.max (size.x - 2, listSize.x), listSize.y);
+
+    int index = list.getSelectionIndex ();
+    if (index !is -1) list.setTopIndex (index);
+    Display display = getDisplay ();
+    Rectangle listRect = list.getBounds ();
+    Rectangle parentRect = display.map (getParent (), null, getBounds ());
+    Point comboSize = getSize ();
+    Rectangle displayRect = getMonitor ().getClientArea ();
+    int width = Math.max (comboSize.x, listRect.width + 2);
+    int height = listRect.height + 2;
+    int x = parentRect.x;
+    int y = parentRect.y + comboSize.y;
+    if (y + height > displayRect.y + displayRect.height) y = parentRect.y - height;
+    if (x + width > displayRect.x + displayRect.width) x = displayRect.x + displayRect.width - listRect.width;
+    popup.setBounds (x, y, width, height);
+    popup.setVisible (true);
+    if (isFocusControl()) list.setFocus ();
+}
+/*
+ * Return the lowercase of the first non-'&' character following
+ * an '&' character in the given string. If there are no '&'
+ * characters in the given string, return '\0'.
+ */
+dchar _findMnemonic (String string) {
+    if (string is null) return '\0';
+    int index = 0;
+    int length = string.length;
+    do {
+        while (index < length && string[index] !is '&') index++;
+        if (++index >= length) return '\0';
+        if (string[index] !is '&') {
+            dchar[1] d; uint ate;
+            auto d2 = tango.text.convert.Utf.toString32( string[ index .. Math.min( index +4, string.length )], d, &ate );
+            auto d3 = tango.text.Unicode.toLower( d2, d2 );
+            return d3[0];
+        }
+        index++;
+    } while (index < length);
+    return '\0';
+}
+/*
+ * Return the Label immediately preceding the receiver in the z-order,
+ * or null if none.
+ */
+Label getAssociatedLabel () {
+    Control[] siblings = getParent ().getChildren ();
+    for (int i = 0; i < siblings.length; i++) {
+        if (siblings [i] is this) {
+            if (i > 0 && ( null !is cast(Label)siblings [i-1] )) {
+                return cast(Label) siblings [i-1];
+            }
+        }
+    }
+    return null;
+}
+public override Control [] getChildren () {
+    checkWidget();
+    return new Control [0];
+}
+/**
+ * Gets the editable state.
+ *
+ * @return whether or not the receiver is editable
+ *
+ * @exception SWTException <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.0
+ */
+public bool getEditable () {
+    checkWidget ();
+    return text.getEditable();
+}
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver's list. Throws an exception if the index is out
+ * of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 String getItem (int index) {
+    checkWidget();
+    return list.getItem (index);
+}
+/**
+ * Returns the number of items contained in the receiver's list.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return list.getItemCount ();
+}
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the receiver's list.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException <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 int getItemHeight () {
+    checkWidget ();
+    return list.getItemHeight ();
+}
+/**
+ * Returns an array of <code>String</code>s which are the items
+ * in the receiver's list.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <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 String [] getItems () {
+    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 SWTException <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();
+}
+/**
+ * Returns a <code>Point</code> whose x coordinate is the start
+ * of the selection in the receiver's text field, and whose y
+ * coordinate is the end of the selection. The returned values
+ * are zero-relative. An "empty" selection as indicated by
+ * the the x and y coordinates having the same value.
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException <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 Point getSelection () {
+    checkWidget ();
+    return text.getSelection ();
+}
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver's list, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException <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 int getSelectionIndex () {
+    checkWidget ();
+    return list.getSelectionIndex ();
+}
+public override int getStyle () {
+    int style = super.getStyle ();
+    style &= ~SWT.READ_ONLY;
+    if (!text.getEditable()) style |= SWT.READ_ONLY;
+    return style;
+}
+/**
+ * Returns a string containing a copy of the contents of the
+ * receiver's text field.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    return text.getText ();
+}
+/**
+ * Returns the height of the receivers's text field.
+ *
+ * @return the text height
+ *
+ * @exception SWTException <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 int getTextHeight () {
+    checkWidget ();
+    return text.getLineHeight ();
+}
+/**
+ * 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>Combo.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException <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 int getTextLimit () {
+    checkWidget ();
+    return text.getTextLimit ();
+}
+/**
+ * Gets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ *
+ * @return the number of items that are visible
+ *
+ * @exception SWTException <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.0
+ */
+public int getVisibleItemCount () {
+    checkWidget ();
+    return visibleItemCount;
+}
+void handleFocus (int type) {
+    if (isDisposed ()) return;
+    switch (type) {
+        case SWT.FocusIn: {
+            if (hasFocus) return;
+            if (getEditable ()) text.selectAll ();
+            hasFocus = true;
+            Shell shell = getShell ();
+            shell.removeListener (SWT.Deactivate, listener);
+            shell.addListener (SWT.Deactivate, listener);
+            Display display = getDisplay ();
+            display.removeFilter (SWT.FocusIn, filter);
+            display.addFilter (SWT.FocusIn, filter);
+            Event e = new Event ();
+            notifyListeners (SWT.FocusIn, e);
+            break;
+        }
+        case SWT.FocusOut: {
+            if (!hasFocus) return;
+            Control focusControl = getDisplay ().getFocusControl ();
+            if (focusControl is arrow || focusControl is list || focusControl is text) return;
+            hasFocus = false;
+            Shell shell = getShell ();
+            shell.removeListener(SWT.Deactivate, listener);
+            Display display = getDisplay ();
+            display.removeFilter (SWT.FocusIn, filter);
+            Event e = new Event ();
+            notifyListeners (SWT.FocusOut, e);
+            break;
+        }
+        default:
+    }
+}
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string) {
+    checkWidget ();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return list.indexOf (string);
+}
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to begin the search
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string, int start) {
+    checkWidget ();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return list.indexOf (string, start);
+}
+
+void initAccessible() {
+    AccessibleAdapter accessibleAdapter = new class() AccessibleAdapter {
+        public void getName (AccessibleEvent e) {
+            String name = null;
+            Label label = getAssociatedLabel ();
+            if (label !is null) {
+                name = stripMnemonic (label.getText());
+            }
+            e.result = name;
+        }
+        public void getKeyboardShortcut(AccessibleEvent e) {
+            String shortcut = null;
+            Label label = getAssociatedLabel ();
+            if (label !is null) {
+                String text = label.getText ();
+                if (text !is null) {
+                    dchar mnemonic = _findMnemonic (text);
+                    if (mnemonic !is '\0') {
+                        shortcut = tango.text.convert.Format.Format( "Alt+{}", mnemonic ); //$NON-NLS-1$
+                    }
+                }
+            }
+            e.result = shortcut;
+        }
+        public void getHelp (AccessibleEvent e) {
+            e.result = getToolTipText ();
+        }
+    };
+    getAccessible ().addAccessibleListener (accessibleAdapter);
+    text.getAccessible ().addAccessibleListener (accessibleAdapter);
+    list.getAccessible ().addAccessibleListener (accessibleAdapter);
+
+    arrow.getAccessible ().addAccessibleListener (new class() AccessibleAdapter {
+        public void getName (AccessibleEvent e) {
+            e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+        public void getKeyboardShortcut (AccessibleEvent e) {
+            e.result = "Alt+Down Arrow"; //$NON-NLS-1$
+        }
+        public void getHelp (AccessibleEvent e) {
+            e.result = getToolTipText ();
+        }
+    });
+
+    getAccessible().addAccessibleTextListener (new class() AccessibleTextAdapter {
+        public void getCaretOffset (AccessibleTextEvent e) {
+            e.offset = text.getCaretPosition ();
+        }
+        public void getSelectionRange(AccessibleTextEvent e) {
+            Point sel = text.getSelection();
+            e.offset = sel.x;
+            e.length = sel.y - sel.x;
+        }
+    });
+
+    getAccessible().addAccessibleControlListener (new class() AccessibleControlAdapter {
+        public void getChildAtPoint (AccessibleControlEvent e) {
+            Point testPoint = toControl (e.x, e.y);
+            if (getBounds ().contains (testPoint)) {
+                e.childID = ACC.CHILDID_SELF;
+            }
+        }
+
+        public void getLocation (AccessibleControlEvent e) {
+            Rectangle location = getBounds ();
+            Point pt = getParent().toDisplay (location.x, location.y);
+            e.x = pt.x;
+            e.y = pt.y;
+            e.width = location.width;
+            e.height = location.height;
+        }
+
+        public void getChildCount (AccessibleControlEvent e) {
+            e.detail = 0;
+        }
+
+        public void getRole (AccessibleControlEvent e) {
+            e.detail = ACC.ROLE_COMBOBOX;
+        }
+
+        public void getState (AccessibleControlEvent e) {
+            e.detail = ACC.STATE_NORMAL;
+        }
+
+        public void getValue (AccessibleControlEvent e) {
+            e.result = getText ();
+        }
+    });
+
+    text.getAccessible ().addAccessibleControlListener (new class() AccessibleControlAdapter {
+        public void getRole (AccessibleControlEvent e) {
+            e.detail = text.getEditable () ? ACC.ROLE_TEXT : ACC.ROLE_LABEL;
+        }
+    });
+
+    arrow.getAccessible ().addAccessibleControlListener (new class() AccessibleControlAdapter {
+        public void getDefaultAction (AccessibleControlEvent e) {
+            e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open"); //$NON-NLS-1$ //$NON-NLS-2$
+        }
+    });
+}
+bool isDropped () {
+    return popup.getVisible ();
+}
+public override bool isFocusControl () {
+    checkWidget();
+    if (text.isFocusControl () || arrow.isFocusControl () || list.isFocusControl () || popup.isFocusControl ()) {
+        return true;
+    }
+    return super.isFocusControl ();
+}
+void internalLayout (bool changed) {
+    if (isDropped ()) dropDown (false);
+    Rectangle rect = getClientArea ();
+    int width = rect.width;
+    int height = rect.height;
+    Point arrowSize = arrow.computeSize (SWT.DEFAULT, height, changed);
+    text.setBounds (0, 0, width - arrowSize.x, height);
+    arrow.setBounds (width - arrowSize.x, 0, arrowSize.x, arrowSize.y);
+}
+void listEvent (Event event) {
+    switch (event.type) {
+        case SWT.Dispose:
+            if (getShell () !is popup.getParent ()) {
+                String[] items = list.getItems ();
+                int selectionIndex = list.getSelectionIndex ();
+                popup = null;
+                list = null;
+                createPopup (items, selectionIndex);
+            }
+            break;
+        case SWT.FocusIn: {
+            handleFocus (SWT.FocusIn);
+            break;
+        }
+        case SWT.MouseUp: {
+            if (event.button !is 1) return;
+            dropDown (false);
+            break;
+        }
+        case SWT.Selection: {
+            int index = list.getSelectionIndex ();
+            if (index is -1) return;
+            text.setText (list.getItem (index));
+            text.selectAll ();
+            list.setSelection (index);
+            Event e = new Event ();
+            e.time = event.time;
+            e.stateMask = event.stateMask;
+            e.doit = event.doit;
+            notifyListeners (SWT.Selection, e);
+            event.doit = e.doit;
+            break;
+        }
+        case SWT.Traverse: {
+            switch (event.detail) {
+                case SWT.TRAVERSE_RETURN:
+                case SWT.TRAVERSE_ESCAPE:
+                case SWT.TRAVERSE_ARROW_PREVIOUS:
+                case SWT.TRAVERSE_ARROW_NEXT:
+                    event.doit = false;
+                    break;
+                case SWT.TRAVERSE_TAB_NEXT:
+                case SWT.TRAVERSE_TAB_PREVIOUS:
+                    event.doit = text.traverse(event.detail);
+                    event.detail = SWT.TRAVERSE_NONE;
+                    if (event.doit) dropDown(false);
+                    return;
+                default:
+            }
+            Event e = new Event ();
+            e.time = event.time;
+            e.detail = event.detail;
+            e.doit = event.doit;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            notifyListeners (SWT.Traverse, e);
+            event.doit = e.doit;
+            event.detail = e.detail;
+            break;
+        }
+        case SWT.KeyUp: {
+            Event e = new Event ();
+            e.time = event.time;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            e.stateMask = event.stateMask;
+            notifyListeners (SWT.KeyUp, e);
+            break;
+        }
+        case SWT.KeyDown: {
+            if (event.character is SWT.ESC) {
+                // Escape key cancels popup list
+                dropDown (false);
+            }
+            if ((event.stateMask & SWT.ALT) !is 0 && (event.keyCode is SWT.ARROW_UP || event.keyCode is SWT.ARROW_DOWN)) {
+                dropDown (false);
+            }
+            if (event.character is SWT.CR) {
+                // Enter causes default selection
+                dropDown (false);
+                Event e = new Event ();
+                e.time = event.time;
+                e.stateMask = event.stateMask;
+                notifyListeners (SWT.DefaultSelection, e);
+            }
+            // At this point the widget may have been disposed.
+            // If so, do not continue.
+            if (isDisposed ()) break;
+            Event e = new Event();
+            e.time = event.time;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            e.stateMask = event.stateMask;
+            notifyListeners(SWT.KeyDown, e);
+            break;
+
+        }
+        default:
+    }
+}
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 paste () {
+    checkWidget ();
+    text.paste ();
+}
+void popupEvent(Event event) {
+    switch (event.type) {
+        case SWT.Paint:
+            // draw black rectangle around list
+            Rectangle listRect = list.getBounds();
+            Color black = getDisplay().getSystemColor(SWT.COLOR_BLACK);
+            event.gc.setForeground(black);
+            event.gc.drawRectangle(0, 0, listRect.width + 1, listRect.height + 1);
+            break;
+        case SWT.Close:
+            event.doit = false;
+            dropDown (false);
+            break;
+        case SWT.Deactivate:
+            /*
+             * Bug in GTK. When the arrow button is pressed the popup control receives a
+             * deactivate event and then the arrow button receives a selection event. If
+             * 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 (!"carbon".equals(SWT.getPlatform())) {
+                Point point = arrow.toControl(getDisplay().getCursorLocation());
+                Point size = arrow.getSize();
+                Rectangle rect = new Rectangle(0, 0, size.x, size.y);
+                if (!rect.contains(point)) dropDown (false);
+            } else {
+                dropDown(false);
+            }
+            break;
+        default:
+    }
+}
+public override void redraw () {
+    super.redraw();
+    text.redraw();
+    arrow.redraw();
+    if (popup.isVisible()) list.redraw();
+}
+public override void redraw (int x, int y, int width, int height, bool all) {
+    super.redraw(x, y, width, height, true);
+}
+
+/**
+ * Removes the item from the receiver's list at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int index) {
+    checkWidget();
+    list.remove (index);
+}
+/**
+ * Removes the items from the receiver's list which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int start, int end) {
+    checkWidget();
+    list.remove (start, end);
+}
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li>
+ * </ul>
+ * @exception SWTException <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 remove (String string) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    list.remove (string);
+}
+/**
+ * Removes all of the items from the receiver's list and clear the
+ * contents of receiver's text field.
+ * <p>
+ * @exception SWTException <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 removeAll () {
+    checkWidget();
+    text.setText (""); //$NON-NLS-1$
+    list.removeAll ();
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Modify, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Selection, listener);
+    removeListener(SWT.DefaultSelection,listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #addVerifyListener
+ *
+ * @since 3.3
+ */
+public void removeVerifyListener (VerifyListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Verify, listener);
+}
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list.  If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 select (int index) {
+    checkWidget();
+    if (index is -1) {
+        list.deselectAll ();
+        text.setText (""); //$NON-NLS-1$
+        return;
+    }
+    if (0 <= index && index < list.getItemCount()) {
+        if (index !is getSelectionIndex()) {
+            text.setText (list.getItem (index));
+            text.selectAll ();
+            list.select (index);
+            list.showSelection ();
+        }
+    }
+}
+public override void setBackground (Color color) {
+    super.setBackground(color);
+    background = color;
+    if (text !is null) text.setBackground(color);
+    if (list !is null) list.setBackground(color);
+    if (arrow !is null) arrow.setBackground(color);
+}
+/**
+ * Sets the editable state.
+ *
+ * @param editable the new editable state
+ *
+ * @exception SWTException <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.0
+ */
+public void setEditable (bool editable) {
+    checkWidget ();
+    text.setEditable(editable);
+}
+public override void setEnabled (bool enabled) {
+    super.setEnabled(enabled);
+    if (popup !is null) popup.setVisible (false);
+    if (text !is null) text.setEnabled(enabled);
+    if (arrow !is null) arrow.setEnabled(enabled);
+}
+public override bool setFocus () {
+    checkWidget();
+    if (!isEnabled () || !isVisible ()) return false;
+    if (isFocusControl ()) return true;
+    return text.setFocus ();
+}
+public override void setFont (Font font) {
+    super.setFont (font);
+    this.font = font;
+    text.setFont (font);
+    list.setFont (font);
+    internalLayout (true);
+}
+public override void setForeground (Color color) {
+    super.setForeground(color);
+    foreground = color;
+    if (text !is null) text.setForeground(color);
+    if (list !is null) list.setForeground(color);
+    if (arrow !is null) arrow.setForeground(color);
+}
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument. This is equivalent
+ * to <code>remove</code>'ing the old item at the index, and then
+ * <code>add</code>'ing the new item at that index.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 setItem (int index, String string) {
+    checkWidget();
+    list.setItem (index, string);
+}
+/**
+ * Sets the receiver's list to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li>
+ * </ul>
+ * @exception SWTException <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 setItems (String [] items) {
+    checkWidget ();
+    list.setItems (items);
+    if (!text.getEditable ()) text.setText (""); //$NON-NLS-1$
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    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 SWTException <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);
+}
+/**
+ * Sets the selection in the receiver's text field to the
+ * range specified by the argument whose x coordinate is the
+ * start of the selection and whose y coordinate is the end
+ * of the selection.
+ *
+ * @param selection a point representing the new selection start and end
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSelection (Point selection) {
+    checkWidget();
+    if (selection is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    text.setSelection (selection.x, selection.y);
+}
+
+/**
+ * Sets the contents of the receiver's text field to the
+ * given string.
+ * <p>
+ * Note: The text field in a <code>Combo</code> is typically
+ * only capable of displaying a single line of text. Thus,
+ * setting the text to a string containing line breaks or
+ * other special characters will probably cause it to
+ * display incorrectly.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    int index = list.indexOf (string);
+    if (index is -1) {
+        list.deselectAll ();
+        text.setText (string);
+        return;
+    }
+    text.setText (string);
+    text.selectAll ();
+    list.setSelection (index);
+    list.showSelection ();
+}
+/**
+ * Sets the maximum number of characters that the receiver's
+ * text field is capable of holding to be the argument.
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
+ * </ul>
+ * @exception SWTException <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 setTextLimit (int limit) {
+    checkWidget();
+    text.setTextLimit (limit);
+}
+
+public override void setToolTipText (String string) {
+    checkWidget();
+    super.setToolTipText(string);
+    arrow.setToolTipText (string);
+    text.setToolTipText (string);
+}
+
+public override void setVisible (bool visible) {
+    super.setVisible(visible);
+    /*
+     * At this point the widget may have been disposed in a FocusOut event.
+     * If so then do not continue.
+     */
+    if (isDisposed ()) return;
+    // TEMPORARY CODE
+    if (popup is null || popup.isDisposed ()) return;
+    if (!visible) popup.setVisible (false);
+}
+/**
+ * Sets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ *
+ * @param count the new number of items to be visible
+ *
+ * @exception SWTException <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.0
+ */
+public void setVisibleItemCount (int count) {
+    checkWidget ();
+    if (count < 0) return;
+    visibleItemCount = count;
+}
+String stripMnemonic (String string) {
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while ((index < length_) && (string[index] !is '&')) index++;
+        if (++index >= length_) return string;
+        if (string[index] !is '&') {
+            return string[0 .. index-1] ~ string[index .. length_];
+        }
+        index++;
+    } while (index < length_);
+    return string;
+}
+void textEvent (Event event) {
+    switch (event.type) {
+        case SWT.FocusIn: {
+            handleFocus (SWT.FocusIn);
+            break;
+        }
+        case SWT.DefaultSelection: {
+            dropDown (false);
+            Event e = new Event ();
+            e.time = event.time;
+            e.stateMask = event.stateMask;
+            notifyListeners (SWT.DefaultSelection, e);
+            break;
+        }
+        case SWT.KeyDown: {
+            Event keyEvent = new Event ();
+            keyEvent.time = event.time;
+            keyEvent.character = event.character;
+            keyEvent.keyCode = event.keyCode;
+            keyEvent.stateMask = event.stateMask;
+            notifyListeners (SWT.KeyDown, keyEvent);
+            if (isDisposed ()) break;
+            event.doit = keyEvent.doit;
+            if (!event.doit) break;
+            if (event.keyCode is SWT.ARROW_UP || event.keyCode is SWT.ARROW_DOWN) {
+                event.doit = false;
+                if ((event.stateMask & SWT.ALT) !is 0) {
+                    bool dropped = isDropped ();
+                    text.selectAll ();
+                    if (!dropped) setFocus ();
+                    dropDown (!dropped);
+                    break;
+                }
+
+                int oldIndex = getSelectionIndex ();
+                if (event.keyCode is SWT.ARROW_UP) {
+                    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 (SWT.Selection, e);
+                }
+                if (isDisposed ()) break;
+            }
+
+            // Further work : Need to add support for incremental search in
+            // pop up list as characters typed in text widget
+            break;
+        }
+        case SWT.KeyUp: {
+            Event e = new Event ();
+            e.time = event.time;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            e.stateMask = event.stateMask;
+            notifyListeners (SWT.KeyUp, e);
+            event.doit = e.doit;
+            break;
+        }
+        case SWT.MenuDetect: {
+            Event e = new Event ();
+            e.time = event.time;
+            notifyListeners (SWT.MenuDetect, e);
+            break;
+        }
+        case SWT.Modify: {
+            list.deselectAll ();
+            Event e = new Event ();
+            e.time = event.time;
+            notifyListeners (SWT.Modify, e);
+            break;
+        }
+        case SWT.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 (SWT.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 ();
+            text.selectAll ();
+            if (!dropped) setFocus ();
+            dropDown (!dropped);
+            break;
+        }
+        case SWT.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 (SWT.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 SWT.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 (SWT.MouseDoubleClick, mouseEvent);
+            break;
+        }
+        case SWT.MouseWheel: {
+            Event keyEvent = new Event ();
+            keyEvent.time = event.time;
+            keyEvent.keyCode = event.count > 0 ? SWT.ARROW_UP : SWT.ARROW_DOWN;
+            keyEvent.stateMask = event.stateMask;
+            notifyListeners (SWT.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 (SWT.Selection, e);
+                }
+                if (isDisposed ()) break;
+            }
+            break;
+        }
+        case SWT.Traverse: {
+            switch (event.detail) {
+                case SWT.TRAVERSE_ARROW_PREVIOUS:
+                case SWT.TRAVERSE_ARROW_NEXT:
+                    // The enter causes default selection and
+                    // the arrow keys are used to manipulate the list contents so
+                    // do not use them for traversal.
+                    event.doit = false;
+                    break;
+                case SWT.TRAVERSE_TAB_PREVIOUS:
+                    event.doit = traverse(SWT.TRAVERSE_TAB_PREVIOUS);
+                    event.detail = SWT.TRAVERSE_NONE;
+                    return;
+                default:
+            }
+            Event e = new Event ();
+            e.time = event.time;
+            e.detail = event.detail;
+            e.doit = event.doit;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            notifyListeners (SWT.Traverse, e);
+            event.doit = e.doit;
+            event.detail = e.detail;
+            break;
+        }
+        case SWT.Verify: {
+            Event e = new Event ();
+            e.text = event.text;
+            e.start = event.start;
+            e.end = event.end;
+            e.character = event.character;
+            e.keyCode = event.keyCode;
+            e.stateMask = event.stateMask;
+            notifyListeners (SWT.Verify, e);
+            event.doit = e.doit;
+            break;
+        }
+        default:
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLabel.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,849 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CLabel;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import java.lang.all;
+
+static import tango.text.Unicode;
+static import tango.text.convert.Utf;
+
+/**
+ * A Label which supports aligned text and/or an image and different border styles.
+ * <p>
+ * If there is not enough space a CLabel uses the following strategy to fit the
+ * information into the available space:
+ * <pre>
+ *      ignores the indent in left align mode
+ *      ignores the image and the gap
+ *      shortens the text by replacing the center portion of the label with an ellipsis
+ *      shortens the text by removing the center portion of the label
+ * </pre>
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>LEFT, RIGHT, CENTER, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dt><b>Events:</b>
+ * <dd></dd>
+ * </dl>
+ *
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class CLabel : Canvas {
+
+    alias Canvas.computeSize computeSize;
+
+    /** Gap between icon and text */
+    private static const int GAP = 5;
+    /** Left and right margins */
+    private static const int INDENT = 3;
+    /** a string inserted in the middle of text that has been shortened */
+    private static const String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026"
+    /** the alignment. Either CENTER, RIGHT, LEFT. Default is LEFT*/
+    private int align_ = SWT.LEFT;
+    private int hIndent = INDENT;
+    private int vIndent = INDENT;
+    /** the current text */
+    private String text;
+    /** the current icon */
+    private Image image;
+    // The tooltip is used for two purposes - the application can set
+    // a tooltip or the tooltip can be used to display the full text when the
+    // the text has been truncated due to the label being too short.
+    // The appToolTip stores the tooltip set by the application.  Control.tooltiptext
+    // contains whatever tooltip is currently being displayed.
+    private String appToolTipText;
+
+    private Image backgroundImage;
+    private Color[] gradientColors;
+    private int[] gradientPercents;
+    private bool gradientVertical;
+    private Color background;
+
+    private static int DRAW_FLAGS = SWT.DRAW_MNEMONIC | SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle(style));
+    if ((style & (SWT.CENTER | SWT.RIGHT)) is 0) style |= SWT.LEFT;
+    if ((style & SWT.CENTER) !is 0) align_ = SWT.CENTER;
+    if ((style & SWT.RIGHT) !is 0)  align_ = SWT.RIGHT;
+    if ((style & SWT.LEFT) !is 0)   align_ = SWT.LEFT;
+
+    addPaintListener(new class() PaintListener{
+        public void paintControl(PaintEvent event) {
+            onPaint(event);
+        }
+    });
+
+    addDisposeListener(new class() DisposeListener{
+        public void widgetDisposed(DisposeEvent event) {
+            onDispose(event);
+        }
+    });
+
+    addTraverseListener(new class() TraverseListener {
+        public void keyTraversed(TraverseEvent event) {
+            if (event.detail is SWT.TRAVERSE_MNEMONIC) {
+                onMnemonic(event);
+            }
+        }
+    });
+
+    initAccessible();
+
+}
+/**
+ * Check the style bits to ensure that no invalid styles are applied.
+ */
+private static int checkStyle (int style) {
+    if ((style & SWT.BORDER) !is 0) style |= SWT.SHADOW_IN;
+    int mask = SWT.SHADOW_IN | SWT.SHADOW_OUT | SWT.SHADOW_NONE | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    style = style & mask;
+    return style |= SWT.NO_FOCUS | SWT.DOUBLE_BUFFERED;
+}
+
+//protected void checkSubclass () {
+//  String name = getClass().getName ();
+//  String validName = CLabel.class.getName();
+//  if (!validName.equals(name)) {
+//      SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+//  }
+//}
+
+public override Point computeSize(int wHint, int hHint, bool changed) {
+    checkWidget();
+    Point e = getTotalSize(image, text);
+    if (wHint is SWT.DEFAULT){
+        e.x += 2*hIndent;
+    } else {
+        e.x = wHint;
+    }
+    if (hHint is SWT.DEFAULT) {
+        e.y += 2*vIndent;
+    } else {
+        e.y = hHint;
+    }
+    return e;
+}
+/**
+ * Draw a rectangle in the given colors.
+ */
+private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
+    gc.setForeground(bottomright);
+    gc.drawLine(x+w, y,   x+w, y+h);
+    gc.drawLine(x,   y+h, x+w, y+h);
+
+    gc.setForeground(topleft);
+    gc.drawLine(x, y, x+w-1, y);
+    gc.drawLine(x, y, x,     y+h-1);
+}
+/*
+ * Return the lowercase of the first non-'&' character following
+ * an '&' character in the given string. If there are no '&'
+ * characters in the given string, return '\0'.
+ */
+dchar _findMnemonic (String string) {
+    if (string is null) return '\0';
+    int index = 0;
+    int length = string.length;
+    do {
+        while (index < length && string[index] !is '&') index++;
+        if (++index >= length) return '\0';
+        if (string[index] !is '&') {
+            dchar[1] tmp; uint ate;
+            dchar[] tmp2 = tango.text.convert.Utf.toString32( string[index .. Math.min( index + 4, string.length ) ], tmp, &ate );
+            assert( tmp2.length == 1 );
+            return tango.text.Unicode.toLower( tmp2 )[0];
+        }
+        index++;
+    } while (index < length);
+    return '\0';
+}
+/**
+ * Returns the alignment.
+ * The alignment style (LEFT, CENTER or RIGHT) is returned.
+ *
+ * @return SWT.LEFT, SWT.RIGHT or SWT.CENTER
+ */
+public int getAlignment() {
+    //checkWidget();
+    return align_;
+}
+/**
+ * Return the CLabel's image or <code>null</code>.
+ *
+ * @return the image of the label or null
+ */
+public Image getImage() {
+    //checkWidget();
+    return image;
+}
+/**
+ * Compute the minimum size.
+ */
+private Point getTotalSize(Image image, String text) {
+    Point size = new Point(0, 0);
+
+    if (image !is null) {
+        Rectangle r = image.getBounds();
+        size.x += r.width;
+        size.y += r.height;
+    }
+
+    GC gc = new GC(this);
+    if (text !is null && text.length > 0) {
+        Point e = gc.textExtent(text, DRAW_FLAGS);
+        size.x += e.x;
+        size.y = Math.max(size.y, e.y);
+        if (image !is null) size.x += GAP;
+    } else {
+        size.y = Math.max(size.y, gc.getFontMetrics().getHeight());
+    }
+    gc.dispose();
+
+    return size;
+}
+public override int getStyle () {
+    int style = super.getStyle();
+    switch (align_) {
+        case SWT.RIGHT: style |= SWT.RIGHT; break;
+        case SWT.CENTER: style |= SWT.CENTER; break;
+        case SWT.LEFT: style |= SWT.LEFT; break;
+        default:
+    }
+    return style;
+}
+
+/**
+ * Return the Label's text.
+ *
+ * @return the text of the label or null
+ */
+public String getText() {
+    //checkWidget();
+    return text;
+}
+public override String getToolTipText () {
+    checkWidget();
+    return appToolTipText;
+}
+private void initAccessible() {
+    Accessible accessible = getAccessible();
+    accessible.addAccessibleListener(new class() AccessibleAdapter {
+        public void getName(AccessibleEvent e) {
+            e.result = getText();
+        }
+
+        public void getHelp(AccessibleEvent e) {
+            e.result = getToolTipText();
+        }
+
+        public void getKeyboardShortcut(AccessibleEvent e) {
+            dchar mnemonic = _findMnemonic(this.outer.text);
+            if (mnemonic !is '\0') {
+                dchar[1] d;
+                d[0] = mnemonic;
+                e.result = "Alt+" ~ tango.text.convert.Utf.toString(d); //$NON-NLS-1$
+            }
+        }
+    });
+
+    accessible.addAccessibleControlListener(new class() AccessibleControlAdapter {
+        public void getChildAtPoint(AccessibleControlEvent e) {
+            e.childID = ACC.CHILDID_SELF;
+        }
+
+        public void getLocation(AccessibleControlEvent e) {
+            Rectangle rect = getDisplay().map(getParent(), null, getBounds());
+            e.x = rect.x;
+            e.y = rect.y;
+            e.width = rect.width;
+            e.height = rect.height;
+        }
+
+        public void getChildCount(AccessibleControlEvent e) {
+            e.detail = 0;
+        }
+
+        public void getRole(AccessibleControlEvent e) {
+            e.detail = ACC.ROLE_LABEL;
+        }
+
+        public void getState(AccessibleControlEvent e) {
+            e.detail = ACC.STATE_READONLY;
+        }
+    });
+}
+void onDispose(DisposeEvent event) {
+    gradientColors = null;
+    gradientPercents = null;
+    backgroundImage = null;
+    text = null;
+    image = null;
+    appToolTipText = null;
+}
+void onMnemonic(TraverseEvent event) {
+    dchar mnemonic = _findMnemonic(text);
+    if (mnemonic is '\0') return;
+    dchar[1] d; uint ate;
+    auto r = tango.text.convert.Utf.toString32( [event.character][], d, &ate );
+    if (tango.text.Unicode.toLower(r)[0] !is mnemonic) return;
+    Composite control = this.getParent();
+    while (control !is null) {
+        Control [] children = control.getChildren();
+        int index = 0;
+        while (index < children.length) {
+            if (children [index] is this) break;
+            index++;
+        }
+        index++;
+        if (index < children.length) {
+            if (children [index].setFocus ()) {
+                event.doit = true;
+                event.detail = SWT.TRAVERSE_NONE;
+            }
+        }
+        control = control.getParent();
+    }
+}
+
+void onPaint(PaintEvent event) {
+    Rectangle rect = getClientArea();
+    if (rect.width is 0 || rect.height is 0) return;
+
+    bool shortenText_ = false;
+    String t = text;
+    Image img = image;
+    int availableWidth = Math.max(0, rect.width - 2*hIndent);
+    Point extent = getTotalSize(img, t);
+    if (extent.x > availableWidth) {
+        img = null;
+        extent = getTotalSize(img, t);
+        if (extent.x > availableWidth) {
+            shortenText_ = true;
+        }
+    }
+
+    GC gc = event.gc;
+    String[] lines = text is null ? null : splitString(text);
+
+    // shorten the text
+    if (shortenText_) {
+        extent.x = 0;
+        for(int i = 0; i < lines.length; i++) {
+            Point e = gc.textExtent(lines[i], DRAW_FLAGS);
+            if (e.x > availableWidth) {
+                lines[i] = shortenText(gc, lines[i], availableWidth);
+                extent.x = Math.max(extent.x, getTotalSize(null, lines[i]).x);
+            } else {
+                extent.x = Math.max(extent.x, e.x);
+            }
+        }
+        if (appToolTipText is null) {
+            super.setToolTipText(text);
+        }
+    } else {
+        super.setToolTipText(appToolTipText);
+    }
+
+    // determine horizontal position
+    int x = rect.x + hIndent;
+    if (align_ is SWT.CENTER) {
+        x = (rect.width - extent.x)/2;
+    }
+    if (align_ is SWT.RIGHT) {
+        x = rect.width - hIndent - extent.x;
+    }
+
+    // draw a background image behind the text
+    try {
+        if (backgroundImage !is null) {
+            // draw a background image behind the text
+            Rectangle imageRect = backgroundImage.getBounds();
+            // tile image to fill space
+            gc.setBackground(getBackground());
+            gc.fillRectangle(rect);
+            int xPos = 0;
+            while (xPos < rect.width) {
+                int yPos = 0;
+                while (yPos < rect.height) {
+                    gc.drawImage(backgroundImage, xPos, yPos);
+                    yPos += imageRect.height;
+                }
+                xPos += imageRect.width;
+            }
+        } else if (gradientColors !is null) {
+            // draw a gradient behind the text
+            final Color oldBackground = gc.getBackground();
+            if (gradientColors.length is 1) {
+                if (gradientColors[0] !is null) gc.setBackground(gradientColors[0]);
+                gc.fillRectangle(0, 0, rect.width, rect.height);
+            } else {
+                final Color oldForeground = gc.getForeground();
+                Color lastColor = gradientColors[0];
+                if (lastColor is null) lastColor = oldBackground;
+                int pos = 0;
+                for (int i = 0; i < gradientPercents.length; ++i) {
+                    gc.setForeground(lastColor);
+                    lastColor = gradientColors[i + 1];
+                    if (lastColor is null) lastColor = oldBackground;
+                    gc.setBackground(lastColor);
+                    if (gradientVertical) {
+                        final int gradientHeight = (gradientPercents[i] * rect.height / 100) - pos;
+                        gc.fillGradientRectangle(0, pos, rect.width, gradientHeight, true);
+                        pos += gradientHeight;
+                    } else {
+                        final int gradientWidth = (gradientPercents[i] * rect.width / 100) - pos;
+                        gc.fillGradientRectangle(pos, 0, gradientWidth, rect.height, false);
+                        pos += gradientWidth;
+                    }
+                }
+                if (gradientVertical && pos < rect.height) {
+                    gc.setBackground(getBackground());
+                    gc.fillRectangle(0, pos, rect.width, rect.height - pos);
+                }
+                if (!gradientVertical && pos < rect.width) {
+                    gc.setBackground(getBackground());
+                    gc.fillRectangle(pos, 0, rect.width - pos, rect.height);
+                }
+                gc.setForeground(oldForeground);
+            }
+            gc.setBackground(oldBackground);
+        } else {
+            if (background !is null || (getStyle() & SWT.DOUBLE_BUFFERED) is 0) {
+                gc.setBackground(getBackground());
+                gc.fillRectangle(rect);
+            }
+        }
+    } catch (SWTException e) {
+        if ((getStyle() & SWT.DOUBLE_BUFFERED) is 0) {
+            gc.setBackground(getBackground());
+            gc.fillRectangle(rect);
+        }
+    }
+
+    // draw border
+    int style = getStyle();
+    if ((style & SWT.SHADOW_IN) !is 0 || (style & SWT.SHADOW_OUT) !is 0) {
+        paintBorder(gc, rect);
+    }
+
+    // draw the image
+    if (img !is null) {
+        Rectangle imageRect = img.getBounds();
+        gc.drawImage(img, 0, 0, imageRect.width, imageRect.height,
+                        x, (rect.height-imageRect.height)/2, imageRect.width, imageRect.height);
+        x +=  imageRect.width + GAP;
+        extent.x -= imageRect.width + GAP;
+    }
+    // draw the text
+    if (lines !is null) {
+        int lineHeight = gc.getFontMetrics().getHeight();
+        int textHeight = lines.length * lineHeight;
+        int lineY = Math.max(vIndent, rect.y + (rect.height - textHeight) / 2);
+        gc.setForeground(getForeground());
+        for (int i = 0; i < lines.length; i++) {
+            int lineX = x;
+            if (lines.length > 1) {
+                if (align_ is SWT.CENTER) {
+                    int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+                    lineX = x + Math.max(0, (extent.x - lineWidth) / 2);
+                }
+                if (align_ is SWT.RIGHT) {
+                    int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
+                    lineX = Math.max(x, rect.x + rect.width - hIndent - lineWidth);
+                }
+            }
+            gc.drawText(lines[i], lineX, lineY, DRAW_FLAGS);
+            lineY += lineHeight;
+        }
+    }
+}
+/**
+ * Paint the Label's border.
+ */
+private void paintBorder(GC gc, Rectangle r) {
+    Display disp= getDisplay();
+
+    Color c1 = null;
+    Color c2 = null;
+
+    int style = getStyle();
+    if ((style & SWT.SHADOW_IN) !is 0) {
+        c1 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+        c2 = disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+    }
+    if ((style & SWT.SHADOW_OUT) !is 0) {
+        c1 = disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
+        c2 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+    }
+
+    if (c1 !is null && c2 !is null) {
+        gc.setLineWidth(1);
+        drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
+    }
+}
+/**
+ * Set the alignment of the CLabel.
+ * Use the values LEFT, CENTER and RIGHT to align image and text within the available space.
+ *
+ * @param align the alignment style of LEFT, RIGHT or CENTER
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the value of align is not one of SWT.LEFT, SWT.RIGHT or SWT.CENTER</li>
+ * </ul>
+ */
+public void setAlignment(int align_) {
+    checkWidget();
+    if (align_ !is SWT.LEFT && align_ !is SWT.RIGHT && align_ !is SWT.CENTER) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (this.align_ !is align_) {
+        this.align_ = align_;
+        redraw();
+    }
+}
+
+public override void setBackground (Color color) {
+    super.setBackground (color);
+    // Are these settings the same as before?
+    if (backgroundImage is null &&
+        gradientColors is null &&
+        gradientPercents is null) {
+        if (color is null) {
+            if (background is null) return;
+        } else {
+            if (color ==/*eq*/ background) return;
+        }
+    }
+    background = color;
+    backgroundImage = null;
+    gradientColors = null;
+    gradientPercents = null;
+    redraw ();
+}
+
+/**
+ * Specify a gradient of colours to be drawn in the background of the CLabel.
+ * <p>For example, to draw a gradient that varies from dark blue to blue and then to
+ * white and stays white for the right half of the label, use the following call
+ * to setBackground:</p>
+ * <pre>
+ *  clabel.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                     new int[] {25, 50, 100});
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance from left to right;  The value <code>null</code>
+ *               clears the background gradient; the value <code>null</code> can be used
+ *               inside the array of Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ *                 of the widget at which the color should change; the size of the percents
+ *                 array must be one less than the size of the colors array.
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the values of colors and percents are not consistent</li>
+ * </ul>
+ */
+public void setBackground(Color[] colors, int[] percents) {
+    setBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colours to be drawn in the background of the CLabel.
+ * <p>For example, to draw a gradient that varies from dark blue to white in the vertical,
+ * direction use the following call
+ * to setBackground:</p>
+ * <pre>
+ *  clabel.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                       new int[] {100}, true);
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance from left/top to right/bottom;  The value <code>null</code>
+ *               clears the background gradient; the value <code>null</code> can be used
+ *               inside the array of Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width/height
+ *                 of the widget at which the color should change; the size of the percents
+ *                 array must be one less than the size of the colors array.
+ * @param vertical indicate the direction of the gradient.  True is vertical and false is horizontal.
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the values of colors and percents are not consistent</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setBackground(Color[] colors, int[] percents, bool vertical) {
+    checkWidget();
+    if (colors !is null) {
+        if (percents is null || percents.length !is colors.length - 1) {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        if (getDisplay().getDepth() < 15) {
+            // Don't use gradients on low color displays
+            colors = [colors[colors.length - 1]];
+            percents = null;
+        }
+        for (int i = 0; i < percents.length; i++) {
+            if (percents[i] < 0 || percents[i] > 100) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            if (i > 0 && percents[i] < percents[i-1]) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+        }
+    }
+
+    // Are these settings the same as before?
+    final Color background = getBackground();
+    if (backgroundImage is null) {
+        if ((gradientColors !is null) && (colors !is null) &&
+            (gradientColors.length is colors.length)) {
+            bool same = false;
+            for (int i = 0; i < gradientColors.length; i++) {
+                same = (gradientColors[i] is colors[i]) ||
+                    ((gradientColors[i] is null) && (colors[i] is background)) ||
+                    ((gradientColors[i] is background) && (colors[i] is null));
+                if (!same) break;
+            }
+            if (same) {
+                for (int i = 0; i < gradientPercents.length; i++) {
+                    same = gradientPercents[i] is percents[i];
+                    if (!same) break;
+                }
+            }
+            if (same && this.gradientVertical is vertical) return;
+        }
+    } else {
+        backgroundImage = null;
+    }
+    // Store the new settings
+    if (colors is null) {
+        gradientColors = null;
+        gradientPercents = null;
+        gradientVertical = false;
+    } else {
+        gradientColors = new Color[colors.length];
+        for (int i = 0; i < colors.length; ++i)
+            gradientColors[i] = (colors[i] !is null) ? colors[i] : background;
+        gradientPercents = new int[percents.length];
+        for (int i = 0; i < percents.length; ++i)
+            gradientPercents[i] = percents[i];
+        gradientVertical = vertical;
+    }
+    // Refresh with the new settings
+    redraw();
+}
+/**
+ * Set the image to be drawn in the background of the label.
+ *
+ * @param image the image to be drawn in the background
+ *
+ * @exception SWTException <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 setBackground(Image image) {
+    checkWidget();
+    if (image is backgroundImage) return;
+    if (image !is null) {
+        gradientColors = null;
+        gradientPercents = null;
+    }
+    backgroundImage = image;
+    redraw();
+
+}
+public override void setFont(Font font) {
+    super.setFont(font);
+    redraw();
+}
+/**
+ * Set the label's Image.
+ * The value <code>null</code> clears it.
+ *
+ * @param image the image to be displayed in the label or null
+ *
+ * @exception SWTException <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 setImage(Image image) {
+    checkWidget();
+    if (image !is this.image) {
+        this.image = image;
+        redraw();
+    }
+}
+/**
+ * Set the label's text.
+ * The value <code>null</code> clears it.
+ *
+ * @param text the text to be displayed in the label or null
+ *
+ * @exception SWTException <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 setText(String text) {
+    checkWidget();
+    if (text is null) text = ""; //$NON-NLS-1$
+    if ( text !=/*eq*/ this.text) {
+        this.text = text;
+        redraw();
+    }
+}
+public override void setToolTipText (String string) {
+    super.setToolTipText (string);
+    appToolTipText = super.getToolTipText();
+}
+/**
+ * Shorten the given text <code>t</code> so that its length doesn't exceed
+ * the given width. The default implementation replaces characters in the
+ * center of the original string with an ellipsis ("...").
+ * Override if you need a different strategy.
+ *
+ * @param gc the gc to use for text measurement
+ * @param t the text to shorten
+ * @param width the width to shorten the text to, in pixels
+ * @return the shortened text
+ */
+protected String shortenText(GC gc, String t, int width) {
+    if (t is null) return null;
+    int w = gc.textExtent(ELLIPSIS, DRAW_FLAGS).x;
+    if (width<=w) return t;
+    int l = t.length;
+    int max = l/2;
+    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.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 = validateOffset(layout, (max+min)/2);
+        } else if (l1+w+l2 < width) {
+            min = mid;
+            mid = validateOffset(layout, (max+min)/2);
+        } else {
+            min = max;
+        }
+    }
+    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, SWT.MOVEMENT_CLUSTER);
+    if (nextOffset !is offset) return layout.getPreviousOffset(nextOffset, SWT.MOVEMENT_CLUSTER);
+    return offset;
+}
+private String[] splitString(String text) {
+    String[] lines = new String[1];
+    int start = 0, pos;
+    do {
+        pos = tango.text.Util.locate( text, '\n', start);
+        if (pos is text.length ) {
+            lines[lines.length - 1] = text[start .. $ ];
+        } else {
+            bool crlf = (pos > 0) && (text[ pos - 1 ] is '\r');
+            lines[lines.length - 1] = text[ start .. pos - (crlf ? 1 : 0)];
+            start = pos + 1;
+            String[] newLines = new String[lines.length+1];
+            System.arraycopy(lines, 0, newLines, 0, lines.length);
+            lines = newLines;
+        }
+    } while (pos !is text.length);
+    return lines;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CLayoutData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CLayoutData;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+
+class CLayoutData {
+
+    int defaultWidth = -1, defaultHeight = -1;
+    int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+Point computeSize (Control control, int wHint, int hHint, bool flushCache_) {
+    if (flushCache_) flushCache();
+    if (wHint is SWT.DEFAULT && hHint is SWT.DEFAULT) {
+        if (defaultWidth is -1 || defaultHeight is -1) {
+            Point size = control.computeSize (wHint, hHint, flushCache_);
+            defaultWidth = size.x;
+            defaultHeight = size.y;
+        }
+        return new Point(defaultWidth, defaultHeight);
+    }
+    if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
+        Point size = control.computeSize (wHint, hHint, flushCache_);
+        currentWhint = wHint;
+        currentHhint = hHint;
+        currentWidth = size.x;
+        currentHeight = size.y;
+    }
+    return new Point(currentWidth, currentHeight);
+}
+void flushCache () {
+    defaultWidth = defaultHeight = -1;
+    currentWidth = currentHeight = -1;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,4081 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolder;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.CTabFolder2Listener;
+import org.eclipse.swt.custom.CTabFolderListener;
+import org.eclipse.swt.custom.CTabFolderLayout;
+import org.eclipse.swt.custom.CTabFolderEvent;
+
+import java.lang.all;
+import tango.util.Convert;
+static import tango.text.convert.Utf;
+
+/**
+ *
+ * Instances of this class implement the notebook user interface
+ * metaphor.  It allows the user to select a notebook page from
+ * set of pages.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>CTabItem</code>.
+ * <code>Control</code> children are created and then set into a
+ * tab item using <code>CTabItem#setControl</code>.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>CLOSE, TOP, BOTTOM, FLAT, BORDER, SINGLE, MULTI</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * <dd>"CTabFolder2"</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles TOP and BOTTOM
+ * may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ctabfolder">CTabFolder, CTabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class CTabFolder : Composite {
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the form.
+     *
+     * The default value is 0.
+     */
+    public int marginWidth = 0;
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the form.
+     *
+     * The default value is 0.
+     */
+    public int marginHeight = 0;
+
+    /**
+     * A multiple of the tab height that specifies the minimum width to which a tab
+     * will be compressed before scrolling arrows are used to navigate the tabs.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should not be capitalized.
+     *
+     * @deprecated This field is no longer used.  See setMinimumCharacters(int)
+     */
+    public int MIN_TAB_WIDTH = 4;
+
+    /**
+     * Color of innermost line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated drop shadow border is no longer drawn in 3.0
+     */
+    public static RGB borderInsideRGB;
+    /**
+     * Color of middle line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated drop shadow border is no longer drawn in 3.0
+     */
+    public static RGB borderMiddleRGB;
+    /**
+     * Color of outermost line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated drop shadow border is no longer drawn in 3.0
+     */
+    public static RGB borderOutsideRGB;
+
+    /* sizing, positioning */
+    int xClient, yClient;
+    bool onBottom = false;
+    bool single = false;
+    bool simple = true;
+    int fixedTabHeight = SWT.DEFAULT;
+    int tabHeight;
+    int minChars = 20;
+
+    /* item management */
+    CTabItem items[];
+    int firstIndex = -1; // index of the left most visible tab.
+    int selectedIndex = -1;
+    int[] priority;
+    bool mru = false;
+    Listener listener;
+
+    /* External Listener management */
+    CTabFolder2Listener[] folderListeners;
+    // support for deprecated listener mechanism
+    CTabFolderListener[] tabListeners;
+
+    /* Selected item appearance */
+    Image selectionBgImage;
+    Color[] selectionGradientColors;
+    int[] selectionGradientPercents;
+    bool selectionGradientVertical;
+    Color selectionForeground;
+    Color selectionBackground;  //selection fade end
+    Color selectionFadeStart;
+
+    Color selectionHighlightGradientBegin = null;  //null is no highlight
+    //Although we are given new colours all the time to show different states (active, etc),
+    //some of which may have a highlight and some not, we'd like to retain the highlight colours
+    //as a cache so that we can reuse them if we're again told to show the highlight.
+    //We are relying on the fact that only one tab state usually gets a highlight, so only
+    //a single cache is required. If that happens to not be true, cache simply becomes less effective,
+    //but we don't leak colours.
+    Color[] selectionHighlightGradientColorsCache = null;  //null is a legal value, check on access
+
+    /* Unselected item appearance */
+    Image bgImage;
+    Color[] gradientColors;
+    int[] gradientPercents;
+    bool gradientVertical;
+    bool showUnselectedImage = true;
+
+    static Color borderColor;
+
+    // close, min/max and chevron buttons
+    bool showClose = false;
+    bool showUnselectedClose = true;
+
+    Rectangle chevronRect;
+    int chevronImageState = NORMAL;
+    bool showChevron = false;
+    Menu showMenu;
+
+    bool showMin = false;
+    Rectangle minRect;
+    bool minimized = false;
+    int minImageState = NORMAL;
+
+    bool showMax = false;
+    Rectangle maxRect;
+    bool maximized = false;
+    int maxImageState = NORMAL;
+
+    Control topRight;
+    Rectangle topRightRect;
+    int topRightAlignment = SWT.RIGHT;
+
+    // borders and shapes
+    int borderLeft = 0;
+    int borderRight = 0;
+    int borderTop = 0;
+    int borderBottom = 0;
+
+    int highlight_margin = 0;
+    int highlight_header = 0;
+
+    int[] curve;
+    int[] topCurveHighlightStart;
+    int[] topCurveHighlightEnd;
+    int curveWidth = 0;
+    int curveIndent = 0;
+
+    // when disposing CTabFolder, don't try to layout the items or
+    // change the selection as each child is destroyed.
+    bool inDispose = false;
+
+    // keep track of size changes in order to redraw only affected area
+    // on Resize
+    Point oldSize;
+    Font oldFont;
+
+    // internal constants
+    static const int DEFAULT_WIDTH = 64;
+    static const int DEFAULT_HEIGHT = 64;
+    static const int BUTTON_SIZE = 18;
+
+    static const int[] TOP_LEFT_CORNER = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0];
+
+    //TOP_LEFT_CORNER_HILITE is laid out in reverse (ie. top to bottom)
+    //so can fade in same direction as right swoop curve
+    static const int[] TOP_LEFT_CORNER_HILITE = [5,2, 4,2, 3,3, 2,4, 2,5, 1,6];
+
+    static const int[] TOP_RIGHT_CORNER = [-6,0, -5,1, -4,1, -1,4, -1,5, 0,6];
+    static const int[] BOTTOM_LEFT_CORNER = [0,-6, 1,-5, 1,-4, 4,-1, 5,-1, 6,0];
+    static const int[] BOTTOM_RIGHT_CORNER = [-6,0, -5,-1, -4,-1, -1,-4, -1,-5, 0,-6];
+
+    static const int[] SIMPLE_TOP_LEFT_CORNER = [0,2, 1,1, 2,0];
+    static const int[] SIMPLE_TOP_RIGHT_CORNER = [-2,0, -1,1, 0,2];
+    static const int[] SIMPLE_BOTTOM_LEFT_CORNER = [0,-2, 1,-1, 2,0];
+    static const int[] SIMPLE_BOTTOM_RIGHT_CORNER = [-2,0, -1,-1, 0,-2];
+    static const int[] SIMPLE_UNSELECTED_INNER_CORNER = [0,0];
+
+    static const int[] TOP_LEFT_CORNER_BORDERLESS = [0,6, 1,5, 1,4, 4,1, 5,1, 6,0];
+    static const int[] TOP_RIGHT_CORNER_BORDERLESS = [-7,0, -6,1, -5,1, -2,4, -2,5, -1,6];
+    static const int[] BOTTOM_LEFT_CORNER_BORDERLESS = [0,-6, 1,-6, 1,-5, 2,-4, 4,-2, 5,-1, 6,-1, 6,0];
+    static const int[] BOTTOM_RIGHT_CORNER_BORDERLESS = [-7,0, -7,-1, -6,-1, -5,-2, -3,-4, -2,-5, -2,-6, -1,-6];
+
+    static const int[] SIMPLE_TOP_LEFT_CORNER_BORDERLESS = [0,2, 1,1, 2,0];
+    static const int[] SIMPLE_TOP_RIGHT_CORNER_BORDERLESS= [-3,0, -2,1, -1,2];
+    static const int[] SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS = [0,-3, 1,-2, 2,-1, 3,0];
+    static const int[] SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS = [-4,0, -3,-1, -2,-2, -1,-3];
+
+    static const int SELECTION_FOREGROUND = SWT.COLOR_LIST_FOREGROUND;
+    static const int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND;
+    static const int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+    static const int FOREGROUND = SWT.COLOR_WIDGET_FOREGROUND;
+    static const int BACKGROUND = SWT.COLOR_WIDGET_BACKGROUND;
+    static const int BUTTON_BORDER = SWT.COLOR_WIDGET_DARK_SHADOW;
+    static const int BUTTON_FILL = SWT.COLOR_LIST_BACKGROUND;
+
+    static const int NONE = 0;
+    static const int NORMAL = 1;
+    static const int HOT = 2;
+    static const int SELECTED = 3;
+    static const RGB CLOSE_FILL;
+
+    static const int CHEVRON_CHILD_ID = 0;
+    static const int MINIMIZE_CHILD_ID = 1;
+    static const int MAXIMIZE_CHILD_ID = 2;
+    static const int EXTRA_CHILD_ID_COUNT = 3;
+
+static this(){
+    borderInsideRGB  = new RGB (132, 130, 132);
+    borderMiddleRGB  = new RGB (143, 141, 138);
+    borderOutsideRGB = new RGB (171, 168, 165);
+    CLOSE_FILL = new RGB(252, 160, 160);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#TOP
+ * @see SWT#BOTTOM
+ * @see SWT#FLAT
+ * @see SWT#BORDER
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    chevronRect = new Rectangle(0, 0, 0, 0);
+    minRect = new Rectangle(0, 0, 0, 0);
+    maxRect = new Rectangle(0, 0, 0, 0);
+    topRightRect = new Rectangle(0, 0, 0, 0);
+    super(parent, checkStyle (parent, style));
+    super.setLayout(new CTabFolderLayout());
+    int style2 = super.getStyle();
+    oldFont = getFont();
+    onBottom = (style2 & SWT.BOTTOM) !is 0;
+    showClose = (style2 & SWT.CLOSE) !is 0;
+//  showMin = (style2 & SWT.MIN) !is 0; - conflicts with SWT.TOP
+//  showMax = (style2 & SWT.MAX) !is 0; - conflicts with SWT.BOTTOM
+    single = (style2 & SWT.SINGLE) !is 0;
+    borderLeft = borderRight = (style & SWT.BORDER) !is 0 ? 1 : 0;
+    borderTop = onBottom ? borderLeft : 0;
+    borderBottom = onBottom ? 0 : borderLeft;
+    highlight_header = (style & SWT.FLAT) !is 0 ? 1 : 3;
+    highlight_margin = (style & SWT.FLAT) !is 0 ? 0 : 2;
+    //set up default colors
+    Display display = getDisplay();
+    selectionForeground = display.getSystemColor(SELECTION_FOREGROUND);
+    selectionBackground = display.getSystemColor(SELECTION_BACKGROUND);
+    borderColor = display.getSystemColor(BORDER1_COLOR);
+    updateTabHeight(false);
+
+    initAccessible();
+
+    // Add all listeners
+    listener = new class() Listener {
+        public void handleEvent(Event event) {
+            switch (event.type) {
+                case SWT.Dispose:          onDispose(event); break;
+                case SWT.DragDetect:       onDragDetect(event); break;
+                case SWT.FocusIn:          onFocus(event);  break;
+                case SWT.FocusOut:         onFocus(event);  break;
+                case SWT.KeyDown:          onKeyDown(event); break;
+                case SWT.MouseDoubleClick: onMouseDoubleClick(event); break;
+                case SWT.MouseDown:        onMouse(event);  break;
+                case SWT.MouseEnter:       onMouse(event);  break;
+                case SWT.MouseExit:        onMouse(event);  break;
+                case SWT.MouseMove:        onMouse(event); break;
+                case SWT.MouseUp:          onMouse(event); break;
+                case SWT.Paint:            onPaint(event);  break;
+                case SWT.Resize:           onResize();  break;
+                case SWT.Traverse:         onTraverse(event); break;
+                default:
+            }
+        }
+    };
+
+    int[] folderEvents = [
+        SWT.Dispose,
+        SWT.DragDetect,
+        SWT.FocusIn,
+        SWT.FocusOut,
+        SWT.KeyDown,
+        SWT.MouseDoubleClick,
+        SWT.MouseDown,
+        SWT.MouseEnter,
+        SWT.MouseExit,
+        SWT.MouseMove,
+        SWT.MouseUp,
+        SWT.Paint,
+        SWT.Resize,
+        SWT.Traverse,
+    ];
+    for (int i = 0; i < folderEvents.length; i++) {
+        addListener(folderEvents[i], listener);
+    }
+}
+static int checkStyle (Composite parent, int style) {
+    int mask = SWT.CLOSE | SWT.TOP | SWT.BOTTOM | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.SINGLE | SWT.MULTI;
+    style = style & mask;
+    // TOP and BOTTOM are mutually exclusive.
+    // TOP is the default
+    if ((style & SWT.TOP) !is 0) style = style & ~SWT.BOTTOM;
+    // SINGLE and MULTI are mutually exclusive.
+    // MULTI is the default
+    if ((style & SWT.MULTI) !is 0) style = style & ~SWT.SINGLE;
+    // reduce the flash by not redrawing the entire area on a Resize event
+    style |= SWT.NO_REDRAW_RESIZE;
+    //TEMPORARY CODE
+    /*
+     * The default background on carbon and some GTK themes is not a solid color
+     * but a texture.  To show the correct default background, we must allow
+     * the operating system to draw it and therefore, we can not use the
+     * NO_BACKGROUND style.  The NO_BACKGROUND style is not required on platforms
+     * that use double buffering which is true in both of these cases.
+     */
+    String platform = SWT.getPlatform();
+    if ("carbon"==platform || "gtk"==platform) return style; //$NON-NLS-1$ //$NON-NLS-2$
+
+    //TEMPORARY CODE
+    /*
+     * In Right To Left orientation on Windows, all GC calls that use a brush are drawing
+     * offset by one pixel.  This results in some parts of the CTabFolder not drawing correctly.
+     * To alleviate some of the appearance problems, allow the OS to draw the background.
+     * This does not draw correctly but the result is less obviously wrong.
+     */
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) return style;
+    if ((parent.getStyle() & SWT.MIRRORED) !is 0 && (style & SWT.LEFT_TO_RIGHT) is 0) return style;
+
+    return style | SWT.NO_BACKGROUND;
+}
+static void fillRegion(GC gc, Region region) {
+    // NOTE: region passed in to this function will be modified
+    Region clipping = new Region();
+    gc.getClipping(clipping);
+    region.intersect(clipping);
+    gc.setClipping(region);
+    gc.fillRectangle(region.getBounds());
+    gc.setClipping(clipping);
+    clipping.dispose();
+}
+/**
+ *
+ * Adds the listener to the collection of listeners who will
+ * be notified when a tab item is closed, minimized, maximized,
+ * restored, or to show the list of items that are not
+ * currently visible.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @see CTabFolder2Listener
+ * @see #removeCTabFolder2Listener(CTabFolder2Listener)
+ *
+ * @since 3.0
+ */
+public void addCTabFolder2Listener(CTabFolder2Listener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    // add to array
+    CTabFolder2Listener[] newListeners = new CTabFolder2Listener[folderListeners.length + 1];
+    SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, 0, newListeners, 0, folderListeners.length);
+    folderListeners = newListeners;
+    folderListeners[folderListeners.length - 1] = listener;
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when a tab item is closed.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @see CTabFolderListener
+ * @see #removeCTabFolderListener(CTabFolderListener)
+ *
+ * @deprecated use addCTabFolder2Listener(CTabFolder2Listener)
+ */
+public void addCTabFolderListener(CTabFolderListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    // add to array
+    CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length + 1];
+    SimpleType!(CTabFolderListener).arraycopy(tabListeners, 0, newTabListeners, 0, tabListeners.length);
+    tabListeners = newTabListeners;
+    tabListeners[tabListeners.length - 1] = listener;
+    // display close button to be backwards compatible
+    if (!showClose) {
+        showClose = true;
+        updateItems();
+        redraw();
+    }
+}
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the selected tab.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    TypedListener typedListener = new TypedListener(listener);
+    addListener(SWT.Selection, typedListener);
+    addListener(SWT.DefaultSelection, typedListener);
+}
+void antialias (int[] shape, RGB lineRGB, RGB innerRGB, RGB outerRGB, GC gc){
+    // Don't perform anti-aliasing on Mac and WPF because the platform
+    // already does it.  The simple style also does not require anti-aliasing.
+    if (simple || "carbon".equals(SWT.getPlatform()) || "wpf".equals(SWT.getPlatform())) return; //$NON-NLS-1$
+    // Don't perform anti-aliasing on low resolution displays
+    if (getDisplay().getDepth() < 15) return;
+    if (outerRGB !is null) {
+        int index = 0;
+        bool left = true;
+        int oldY = onBottom ? 0 : getSize().y;
+        int[] outer = new int[shape.length];
+        for (int i = 0; i < shape.length/2; i++) {
+            if (left && (index + 3 < shape.length)) {
+                left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+                oldY = shape[index+1];
+            }
+            outer[index] = shape[index] + (left ? -1 : +1);
+            index++;
+            outer[index] = shape[index];
+            index++;
+        }
+        RGB from = lineRGB;
+        RGB to = outerRGB;
+        int red = from.red + 2*(to.red - from.red)/3;
+        int green = from.green + 2*(to.green - from.green)/3;
+        int blue = from.blue + 2*(to.blue - from.blue)/3;
+        Color color = new Color(getDisplay(), red, green, blue);
+        gc.setForeground(color);
+        gc.drawPolyline(outer);
+        color.dispose();
+    }
+    if (innerRGB !is null) {
+        int[] inner = new int[shape.length];
+        int index = 0;
+        bool left = true;
+        int oldY = onBottom ? 0 : getSize().y;
+        for (int i = 0; i < shape.length/2; i++) {
+            if (left && (index + 3 < shape.length)) {
+                left = onBottom ? oldY <= shape[index+3] : oldY >= shape[index+3];
+                oldY = shape[index+1];
+            }
+            inner[index] = shape[index] + (left ? +1 : -1);
+            index++;
+            inner[index] = shape[index];
+            index++;
+        }
+        RGB from = lineRGB;
+        RGB to = innerRGB;
+        int red = from.red + 2*(to.red - from.red)/3;
+        int green = from.green + 2*(to.green - from.green)/3;
+        int blue = from.blue + 2*(to.blue - from.blue)/3;
+        Color color = new Color(getDisplay(), red, green, blue);
+        gc.setForeground(color);
+        gc.drawPolyline(inner);
+        color.dispose();
+    }
+}
+public override Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget();
+    int trimX = x - marginWidth - highlight_margin - borderLeft;
+    int trimWidth = width + borderLeft + borderRight + 2*marginWidth + 2*highlight_margin;
+    if (minimized) {
+        int trimY = onBottom ? y - borderTop : y - highlight_header - tabHeight - borderTop;
+        int trimHeight = borderTop + borderBottom + tabHeight + highlight_header;
+        return new Rectangle (trimX, trimY, trimWidth, trimHeight);
+    } else {
+        int trimY = onBottom ? y - marginHeight - highlight_margin - borderTop: y - marginHeight - highlight_header - tabHeight - borderTop;
+        int trimHeight = height + borderTop + borderBottom + 2*marginHeight + tabHeight + highlight_header + highlight_margin;
+        return new Rectangle (trimX, trimY, trimWidth, trimHeight);
+    }
+}
+void createItem (CTabItem item, int index) {
+    if (0 > index || index > getItemCount ())SWT.error (SWT.ERROR_INVALID_RANGE);
+    item.parent = this;
+    CTabItem[] newItems = new CTabItem [items.length + 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    newItems[index] = item;
+    System.arraycopy(items, index, newItems, index + 1, items.length - index);
+    items = newItems;
+    if (selectedIndex >= index) selectedIndex ++;
+    int[] newPriority = new int[priority.length + 1];
+    int next = 0,  priorityIndex = priority.length;
+    for (int i = 0; i < priority.length; i++) {
+        if (!mru && priority[i] is index) {
+            priorityIndex = next++;
+        }
+        newPriority[next++] = priority[i] >= index ? priority[i] + 1 : priority[i];
+    }
+    newPriority[priorityIndex] = index;
+    priority = newPriority;
+
+    if (items.length is 1) {
+        if (!updateTabHeight(false)) updateItems();
+        redraw();
+    } else {
+        updateItems();
+        redrawTabs();
+    }
+}
+void destroyItem (CTabItem item) {
+    if (inDispose) return;
+    int index = indexOf(item);
+    if (index is -1) return;
+
+    if (items.length is 1) {
+        items = new CTabItem[0];
+        priority = new int[0];
+        firstIndex = -1;
+        selectedIndex = -1;
+
+        Control control = item.getControl();
+        if (control !is null && !control.isDisposed()) {
+            control.setVisible(false);
+        }
+        setToolTipText(null);
+        setButtonBounds();
+        redraw();
+        return;
+    }
+
+    CTabItem[] newItems = new CTabItem [items.length - 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
+    items = newItems;
+
+    int[] newPriority = new int[priority.length - 1];
+    int next = 0;
+    for (int i = 0; i < priority.length; i++) {
+        if (priority [i] is index) continue;
+        newPriority[next++] = priority[i] > index ? priority[i] - 1 : priority [i];
+    }
+    priority = newPriority;
+
+    // move the selection if this item is selected
+    if (selectedIndex is index) {
+        Control control = item.getControl();
+        selectedIndex = -1;
+        int nextSelection = mru ? priority[0] : Math.max(0, index - 1);
+        setSelection(nextSelection, true);
+        if (control !is null && !control.isDisposed()) {
+            control.setVisible(false);
+        }
+    } else if (selectedIndex > index) {
+        selectedIndex --;
+    }
+
+    updateItems();
+    redrawTabs();
+}
+void drawBackground(GC gc, int[] shape, bool selected) {
+    Color defaultBackground = selected ? selectionBackground : getBackground();
+    Image image = selected ? selectionBgImage : bgImage;
+    Color[] colors = selected ? selectionGradientColors : gradientColors;
+    int[] percents = selected ? selectionGradientPercents : gradientPercents;
+    bool vertical = selected ? selectionGradientVertical : gradientVertical;
+    Point size = getSize();
+    int width = size.x;
+    int height = tabHeight + highlight_header;
+    int x = 0;
+    if (borderLeft > 0) {
+        x += 1; width -= 2;
+    }
+    int y = onBottom ? size.y - borderBottom - height : borderTop;
+    drawBackground(gc, shape, x, y, width, height, defaultBackground, image, colors, percents, vertical);
+}
+void drawBackground(GC gc, int[] shape, int x, int y, int width, int height, Color defaultBackground, Image image, Color[] colors, int[] percents, bool vertical) {
+    Region clipping = new Region();
+    gc.getClipping(clipping);
+    Region region = new Region();
+    region.add(shape);
+    region.intersect(clipping);
+    gc.setClipping(region);
+
+    if (image !is null) {
+        // draw the background image in shape
+        gc.setBackground(defaultBackground);
+        gc.fillRectangle(x, y, width, height);
+        Rectangle imageRect = image.getBounds();
+        gc.drawImage(image, imageRect.x, imageRect.y, imageRect.width, imageRect.height, x, y, width, height);
+    } else if (colors !is null) {
+        // draw gradient
+        if (colors.length is 1) {
+            Color background = colors[0] !is null ? colors[0] : defaultBackground;
+            gc.setBackground(background);
+            gc.fillRectangle(x, y, width, height);
+        } else {
+            if (vertical) {
+                if (onBottom) {
+                    int pos = 0;
+                    if (percents[percents.length - 1] < 100) {
+                        pos = percents[percents.length - 1] * height / 100;
+                        gc.setBackground(defaultBackground);
+                        gc.fillRectangle(x, y, width, pos);
+                    }
+                    Color lastColor = colors[colors.length-1];
+                    if (lastColor is null) lastColor = defaultBackground;
+                    for (int i = percents.length-1; i >= 0; i--) {
+                        gc.setForeground(lastColor);
+                        lastColor = colors[i];
+                        if (lastColor is null) lastColor = defaultBackground;
+                        gc.setBackground(lastColor);
+                        int gradientHeight = percents[i] * height / 100;
+                        gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
+                        pos += gradientHeight;
+                    }
+                } else {
+                    Color lastColor = colors[0];
+                    if (lastColor is null) lastColor = defaultBackground;
+                    int pos = 0;
+                    for (int i = 0; i < percents.length; i++) {
+                        gc.setForeground(lastColor);
+                        lastColor = colors[i + 1];
+                        if (lastColor is null) lastColor = defaultBackground;
+                        gc.setBackground(lastColor);
+                        int gradientHeight = percents[i] * height / 100;
+                        gc.fillGradientRectangle(x, y+pos, width, gradientHeight, true);
+                        pos += gradientHeight;
+                    }
+                    if (pos < height) {
+                        gc.setBackground(defaultBackground);
+                        gc.fillRectangle(x, pos, width, height-pos+1);
+                    }
+                }
+            } else { //horizontal gradient
+                y = 0;
+                height = getSize().y;
+                Color lastColor = colors[0];
+                if (lastColor is null) lastColor = defaultBackground;
+                int pos = 0;
+                for (int i = 0; i < percents.length; ++i) {
+                    gc.setForeground(lastColor);
+                    lastColor = colors[i + 1];
+                    if (lastColor is null) lastColor = defaultBackground;
+                    gc.setBackground(lastColor);
+                    int gradientWidth = (percents[i] * width / 100) - pos;
+                    gc.fillGradientRectangle(x+pos, y, gradientWidth, height, false);
+                    pos += gradientWidth;
+                }
+                if (pos < width) {
+                    gc.setBackground(defaultBackground);
+                    gc.fillRectangle(x+pos, y, width-pos, height);
+                }
+            }
+        }
+    } else {
+        // draw a solid background using default background in shape
+        if ((getStyle() & SWT.NO_BACKGROUND) !is 0 || defaultBackground!=getBackground()) {
+            gc.setBackground(defaultBackground);
+            gc.fillRectangle(x, y, width, height);
+        }
+    }
+    gc.setClipping(clipping);
+    clipping.dispose();
+    region.dispose();
+}
+void drawBody(Event event) {
+    GC gc = event.gc;
+    Point size = getSize();
+
+    // fill in body
+    if (!minimized){
+        int width = size.x  - borderLeft - borderRight - 2*highlight_margin;
+        int height = size.y - borderTop - borderBottom - tabHeight - highlight_header - highlight_margin;
+        // Draw highlight margin
+        if (highlight_margin > 0) {
+            int[] shape = null;
+            if (onBottom) {
+                int x1 = borderLeft;
+                int y1 = borderTop;
+                int x2 = size.x - borderRight;
+                int y2 = size.y - borderBottom - tabHeight - highlight_header;
+                shape = [x1,y1, x2,y1, x2,y2, x2-highlight_margin,y2,
+                                   x2-highlight_margin, y1+highlight_margin, x1+highlight_margin,y1+highlight_margin,
+                                   x1+highlight_margin,y2, x1,y2];
+            } else {
+                int x1 = borderLeft;
+                int y1 = borderTop + tabHeight + highlight_header;
+                int x2 = size.x - borderRight;
+                int y2 = size.y - borderBottom;
+                shape = [x1,y1, x1+highlight_margin,y1, x1+highlight_margin,y2-highlight_margin,
+                                   x2-highlight_margin,y2-highlight_margin, x2-highlight_margin,y1,
+                                   x2,y1, x2,y2, x1,y2];
+            }
+            // If horizontal gradient, show gradient across the whole area
+            if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) {
+                drawBackground(gc, shape, true);
+            } else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) {
+                drawBackground(gc, shape, false);
+            } else {
+                gc.setBackground(selectedIndex is -1 ? getBackground() : selectionBackground);
+                gc.fillPolygon(shape);
+            }
+        }
+        //Draw client area
+        if ((getStyle() & SWT.NO_BACKGROUND) !is 0) {
+            gc.setBackground(getBackground());
+            gc.fillRectangle(xClient - marginWidth, yClient - marginHeight, width, height);
+        }
+    } else {
+        if ((getStyle() & SWT.NO_BACKGROUND) !is 0) {
+            int height = borderTop + tabHeight + highlight_header + borderBottom;
+            if (size.y > height) {
+                gc.setBackground(getParent().getBackground());
+                gc.fillRectangle(0, height, size.x, size.y - height);
+            }
+        }
+    }
+
+    //draw 1 pixel border around outside
+    if (borderLeft > 0) {
+        gc.setForeground(borderColor);
+        int x1 = borderLeft - 1;
+        int x2 = size.x - borderRight;
+        int y1 = onBottom ? borderTop - 1 : borderTop + tabHeight;
+        int y2 = onBottom ? size.y - tabHeight - borderBottom - 1 : size.y - borderBottom;
+        gc.drawLine(x1, y1, x1, y2); // left
+        gc.drawLine(x2, y1, x2, y2); // right
+        if (onBottom) {
+            gc.drawLine(x1, y1, x2, y1); // top
+        } else {
+            gc.drawLine(x1, y2, x2, y2); // bottom
+        }
+    }
+}
+
+void drawChevron(GC gc) {
+    if (chevronRect.width is 0 || chevronRect.height is 0) return;
+    // draw chevron (10x7)
+    Display display = getDisplay();
+    Point dpi = display.getDPI();
+    int fontHeight = 72 * 10 / dpi.y;
+    FontData fd = getFont().getFontData()[0];
+    fd.setHeight(fontHeight);
+    Font f = new Font(display, fd);
+    int fHeight = f.getFontData()[0].getHeight() * dpi.y / 72;
+    int indent = Math.max(2, (chevronRect.height - fHeight - 4) /2);
+    int x = chevronRect.x + 2;
+    int y = chevronRect.y + indent;
+    int count;
+    if (single) {
+        count = selectedIndex is -1 ? items.length : items.length - 1;
+    } else {
+        int showCount = 0;
+        while (showCount < priority.length && items[priority[showCount]].showing) {
+            showCount++;
+        }
+        count = items.length - showCount;
+    }
+    String chevronString = count > 99 ? "99+" : to!(String)(count); //$NON-NLS-1$
+    switch (chevronImageState) {
+        case NORMAL: {
+            Color chevronBorder = single ? getSelectionForeground() : getForeground();
+            gc.setForeground(chevronBorder);
+            gc.setFont(f);
+            gc.drawLine(x,y,     x+2,y+2);
+            gc.drawLine(x+2,y+2, x,y+4);
+            gc.drawLine(x+1,y,   x+3,y+2);
+            gc.drawLine(x+3,y+2, x+1,y+4);
+            gc.drawLine(x+4,y,   x+6,y+2);
+            gc.drawLine(x+6,y+2, x+5,y+4);
+            gc.drawLine(x+5,y,   x+7,y+2);
+            gc.drawLine(x+7,y+2, x+4,y+4);
+            gc.drawString(chevronString, x+7, y+3, true);
+            break;
+        }
+        case HOT: {
+            gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+            gc.setBackground(display.getSystemColor(BUTTON_FILL));
+            gc.setFont(f);
+            gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
+            gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
+            gc.drawLine(x,y,     x+2,y+2);
+            gc.drawLine(x+2,y+2, x,y+4);
+            gc.drawLine(x+1,y,   x+3,y+2);
+            gc.drawLine(x+3,y+2, x+1,y+4);
+            gc.drawLine(x+4,y,   x+6,y+2);
+            gc.drawLine(x+6,y+2, x+5,y+4);
+            gc.drawLine(x+5,y,   x+7,y+2);
+            gc.drawLine(x+7,y+2, x+4,y+4);
+            gc.drawString(chevronString, x+7, y+3, true);
+            break;
+        }
+        case SELECTED: {
+            gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+            gc.setBackground(display.getSystemColor(BUTTON_FILL));
+            gc.setFont(f);
+            gc.fillRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, 6, 6);
+            gc.drawRoundRectangle(chevronRect.x, chevronRect.y, chevronRect.width - 1, chevronRect.height - 1, 6, 6);
+            gc.drawLine(x+1,y+1, x+3,y+3);
+            gc.drawLine(x+3,y+3, x+1,y+5);
+            gc.drawLine(x+2,y+1, x+4,y+3);
+            gc.drawLine(x+4,y+3, x+2,y+5);
+            gc.drawLine(x+5,y+1, x+7,y+3);
+            gc.drawLine(x+7,y+3, x+6,y+5);
+            gc.drawLine(x+6,y+1, x+8,y+3);
+            gc.drawLine(x+8,y+3, x+5,y+5);
+            gc.drawString(chevronString, x+8, y+4, true);
+            break;
+        }
+        default:
+    }
+    f.dispose();
+}
+void drawMaximize(GC gc) {
+    if (maxRect.width is 0 || maxRect.height is 0) return;
+    Display display = getDisplay();
+    // 5x4 or 7x9
+    int x = maxRect.x + (CTabFolder.BUTTON_SIZE - 10)/2;
+    int y = maxRect.y + 3;
+
+    gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+    gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+    switch (maxImageState) {
+        case NORMAL: {
+            if (!maximized) {
+                gc.fillRectangle(x, y, 9, 9);
+                gc.drawRectangle(x, y, 9, 9);
+                gc.drawLine(x+1, y+2, x+8, y+2);
+            } else {
+                gc.fillRectangle(x, y+3, 5, 4);
+                gc.fillRectangle(x+2, y, 5, 4);
+                gc.drawRectangle(x, y+3, 5, 4);
+                gc.drawRectangle(x+2, y, 5, 4);
+                gc.drawLine(x+3, y+1, x+6, y+1);
+                gc.drawLine(x+1, y+4, x+4, y+4);
+            }
+            break;
+        }
+        case HOT: {
+            gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
+            gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
+            if (!maximized) {
+                gc.fillRectangle(x, y, 9, 9);
+                gc.drawRectangle(x, y, 9, 9);
+                gc.drawLine(x+1, y+2, x+8, y+2);
+            } else {
+                gc.fillRectangle(x, y+3, 5, 4);
+                gc.fillRectangle(x+2, y, 5, 4);
+                gc.drawRectangle(x, y+3, 5, 4);
+                gc.drawRectangle(x+2, y, 5, 4);
+                gc.drawLine(x+3, y+1, x+6, y+1);
+                gc.drawLine(x+1, y+4, x+4, y+4);
+            }
+            break;
+        }
+        case SELECTED: {
+            gc.fillRoundRectangle(maxRect.x, maxRect.y, maxRect.width, maxRect.height, 6, 6);
+            gc.drawRoundRectangle(maxRect.x, maxRect.y, maxRect.width - 1, maxRect.height - 1, 6, 6);
+            if (!maximized) {
+                gc.fillRectangle(x+1, y+1, 9, 9);
+                gc.drawRectangle(x+1, y+1, 9, 9);
+                gc.drawLine(x+2, y+3, x+9, y+3);
+            } else {
+                gc.fillRectangle(x+1, y+4, 5, 4);
+                gc.fillRectangle(x+3, y+1, 5, 4);
+                gc.drawRectangle(x+1, y+4, 5, 4);
+                gc.drawRectangle(x+3, y+1, 5, 4);
+                gc.drawLine(x+4, y+2, x+7, y+2);
+                gc.drawLine(x+2, y+5, x+5, y+5);
+            }
+            break;
+        }
+        default:
+    }
+}
+void drawMinimize(GC gc) {
+    if (minRect.width is 0 || minRect.height is 0) return;
+    Display display = getDisplay();
+    // 5x4 or 9x3
+    int x = minRect.x + (BUTTON_SIZE - 10)/2;
+    int y = minRect.y + 3;
+
+    gc.setForeground(display.getSystemColor(BUTTON_BORDER));
+    gc.setBackground(display.getSystemColor(BUTTON_FILL));
+
+    switch (minImageState) {
+        case NORMAL: {
+            if (!minimized) {
+                gc.fillRectangle(x, y, 9, 3);
+                gc.drawRectangle(x, y, 9, 3);
+            } else {
+                gc.fillRectangle(x, y+3, 5, 4);
+                gc.fillRectangle(x+2, y, 5, 4);
+                gc.drawRectangle(x, y+3, 5, 4);
+                gc.drawRectangle(x+2, y, 5, 4);
+                gc.drawLine(x+3, y+1, x+6, y+1);
+                gc.drawLine(x+1, y+4, x+4, y+4);
+            }
+            break;
+        }
+        case HOT: {
+            gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
+            gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
+            if (!minimized) {
+                gc.fillRectangle(x, y, 9, 3);
+                gc.drawRectangle(x, y, 9, 3);
+            } else {
+                gc.fillRectangle(x, y+3, 5, 4);
+                gc.fillRectangle(x+2, y, 5, 4);
+                gc.drawRectangle(x, y+3, 5, 4);
+                gc.drawRectangle(x+2, y, 5, 4);
+                gc.drawLine(x+3, y+1, x+6, y+1);
+                gc.drawLine(x+1, y+4, x+4, y+4);
+            }
+            break;
+        }
+        case SELECTED: {
+            gc.fillRoundRectangle(minRect.x, minRect.y, minRect.width, minRect.height, 6, 6);
+            gc.drawRoundRectangle(minRect.x, minRect.y, minRect.width - 1, minRect.height - 1, 6, 6);
+            if (!minimized) {
+                gc.fillRectangle(x+1, y+1, 9, 3);
+                gc.drawRectangle(x+1, y+1, 9, 3);
+            } else {
+                gc.fillRectangle(x+1, y+4, 5, 4);
+                gc.fillRectangle(x+3, y+1, 5, 4);
+                gc.drawRectangle(x+1, y+4, 5, 4);
+                gc.drawRectangle(x+3, y+1, 5, 4);
+                gc.drawLine(x+4, y+2, x+7, y+2);
+                gc.drawLine(x+2, y+5, x+5, y+5);
+            }
+            break;
+        }
+        default:
+    }
+}
+void drawTabArea(Event event) {
+    GC gc = event.gc;
+    Point size = getSize();
+    int[] shape = null;
+
+    if (tabHeight is 0) {
+        int style = getStyle();
+        if ((style & SWT.FLAT) !is 0 && (style & SWT.BORDER) is 0) return;
+        int x1 = borderLeft - 1;
+        int x2 = size.x - borderRight;
+        int y1 = onBottom ? size.y - borderBottom - highlight_header - 1 : borderTop + highlight_header;
+        int y2 = onBottom ? size.y - borderBottom : borderTop;
+        if (borderLeft > 0 && onBottom) y2 -= 1;
+
+        shape = [x1, y1, x1,y2, x2,y2, x2,y1];
+
+        // If horizontal gradient, show gradient across the whole area
+        if (selectedIndex !is -1 && selectionGradientColors !is null && selectionGradientColors.length > 1 && !selectionGradientVertical) {
+            drawBackground(gc, shape, true);
+        } else if (selectedIndex is -1 && gradientColors !is null && gradientColors.length > 1 && !gradientVertical) {
+            drawBackground(gc, shape, false);
+        } else {
+            gc.setBackground(selectedIndex is -1 ? getBackground() : selectionBackground);
+            gc.fillPolygon(shape);
+        }
+
+        //draw 1 pixel border
+        if (borderLeft > 0) {
+            gc.setForeground(borderColor);
+            gc.drawPolyline(shape);
+        }
+        return;
+    }
+
+    int x = Math.max(0, borderLeft - 1);
+    int y = onBottom ? size.y - borderBottom - tabHeight : borderTop;
+    int width = size.x - borderLeft - borderRight + 1;
+    int height = tabHeight - 1;
+
+    // Draw Tab Header
+    if (onBottom) {
+        int[] left, right;
+        if ((getStyle() & SWT.BORDER) !is 0) {
+            left = simple ? SIMPLE_BOTTOM_LEFT_CORNER : BOTTOM_LEFT_CORNER;
+            right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER : BOTTOM_RIGHT_CORNER;
+        } else {
+            left = simple ? SIMPLE_BOTTOM_LEFT_CORNER_BORDERLESS : BOTTOM_LEFT_CORNER_BORDERLESS;
+            right = simple ? SIMPLE_BOTTOM_RIGHT_CORNER_BORDERLESS : BOTTOM_RIGHT_CORNER_BORDERLESS;
+        }
+        shape = new int[left.length + right.length + 4];
+        int index = 0;
+        shape[index++] = x;
+        shape[index++] = y-highlight_header;
+        for (int i = 0; i < left.length/2; i++) {
+            shape[index++] = x+left[2*i];
+            shape[index++] = y+height+left[2*i+1];
+            if (borderLeft is 0) shape[index-1] += 1;
+        }
+        for (int i = 0; i < right.length/2; i++) {
+            shape[index++] = x+width+right[2*i];
+            shape[index++] = y+height+right[2*i+1];
+            if (borderLeft is 0) shape[index-1] += 1;
+        }
+        shape[index++] = x+width;
+        shape[index++] = y-highlight_header;
+    } else {
+        int[] left, right;
+        if ((getStyle() & SWT.BORDER) !is 0) {
+            left = simple ? SIMPLE_TOP_LEFT_CORNER : TOP_LEFT_CORNER;
+            right = simple ? SIMPLE_TOP_RIGHT_CORNER : TOP_RIGHT_CORNER;
+        } else {
+            left = simple ? SIMPLE_TOP_LEFT_CORNER_BORDERLESS : TOP_LEFT_CORNER_BORDERLESS;
+            right = simple ? SIMPLE_TOP_RIGHT_CORNER_BORDERLESS : TOP_RIGHT_CORNER_BORDERLESS;
+        }
+        shape = new int[left.length + right.length + 4];
+        int index = 0;
+        shape[index++] = x;
+        shape[index++] = y+height+highlight_header + 1;
+        for (int i = 0; i < left.length/2; i++) {
+            shape[index++] = x+left[2*i];
+            shape[index++] = y+left[2*i+1];
+        }
+        for (int i = 0; i < right.length/2; i++) {
+            shape[index++] = x+width+right[2*i];
+            shape[index++] = y+right[2*i+1];
+        }
+        shape[index++] = x+width;
+        shape[index++] = y+height+highlight_header + 1;
+    }
+    // Fill in background
+    bool bkSelected = single && selectedIndex !is -1;
+    drawBackground(gc, shape, bkSelected);
+    // Fill in parent background for non-rectangular shape
+    Region r = new Region();
+    r.add(new Rectangle(x, y, width + 1, height + 1));
+    r.subtract(shape);
+    gc.setBackground(getParent().getBackground());
+    fillRegion(gc, r);
+    r.dispose();
+
+    // Draw the unselected tabs.
+    if (!single) {
+        for (int i=0; i < items.length; i++) {
+            if (i !is selectedIndex && event.getBounds().intersects(items[i].getBounds())) {
+                items[i].onPaint(gc, false);
+            }
+        }
+    }
+
+    // Draw selected tab
+    if (selectedIndex !is -1) {
+        CTabItem item = items[selectedIndex];
+        item.onPaint(gc, true);
+    } else {
+        // if no selected tab - draw line across bottom of all tabs
+        int x1 = borderLeft;
+        int y1 = (onBottom) ? size.y - borderBottom - tabHeight - 1 : borderTop + tabHeight;
+        int x2 = size.x - borderRight;
+        gc.setForeground(borderColor);
+        gc.drawLine(x1, y1, x2, y1);
+    }
+
+    // Draw Buttons
+    drawChevron(gc);
+    drawMinimize(gc);
+    drawMaximize(gc);
+
+    // Draw border line
+    if (borderLeft > 0) {
+        RGB outside = getParent().getBackground().getRGB();
+        antialias(shape, borderColor.getRGB(), null, outside, gc);
+        gc.setForeground(borderColor);
+        gc.drawPolyline(shape);
+    }
+}
+/**
+ * Returns <code>true</code> if the receiver's border is visible.
+ *
+ * @return the receiver's border visibility state
+ *
+ * @exception SWTException <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.0
+ */
+public bool getBorderVisible() {
+    checkWidget();
+    return borderLeft is 1;
+}
+public override Rectangle getClientArea() {
+    checkWidget();
+    if (minimized) return new Rectangle(xClient, yClient, 0, 0);
+    Point size = getSize();
+    int width = size.x  - borderLeft - borderRight - 2*marginWidth - 2*highlight_margin;
+    int height = size.y - borderTop - borderBottom - 2*marginHeight - highlight_margin - highlight_header;
+    height -= tabHeight;
+    return new Rectangle(xClient, yClient, width, height);
+}
+/**
+ * Return the tab that is located at the specified index.
+ *
+ * @param index the index of the tab item
+ * @return the item at the specified index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ */
+public CTabItem getItem (int index) {
+    //checkWidget();
+    if (index  < 0 || index >= items.length)
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+/**
+ * Gets the item at a point in the widget.
+ *
+ * @param pt the point in coordinates relative to the CTabFolder
+ * @return the item at a point or null
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public CTabItem getItem (Point pt) {
+    //checkWidget();
+    if (items.length is 0) return null;
+    Point size = getSize();
+    if (size.x <= borderLeft + borderRight) return null;
+    if (showChevron && chevronRect.contains(pt)) return null;
+    for (int i = 0; i < priority.length; i++) {
+        CTabItem item = items[priority[i]];
+        Rectangle rect = item.getBounds();
+        if (rect.contains(pt)) return item;
+    }
+    return null;
+}
+/**
+ * Return the number of tabs in the folder.
+ *
+ * @return the number of tabs in the folder
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public int getItemCount(){
+    //checkWidget();
+    return items.length;
+}
+/**
+ * Return the tab items.
+ *
+ * @return the tab items
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public CTabItem [] getItems() {
+    //checkWidget();
+    CTabItem[] tabItems = new CTabItem [items.length];
+    System.arraycopy(items, 0, tabItems, 0, items.length);
+    return tabItems;
+}
+/*
+ * Return the lowercase of the first non-'&' character following
+ * an '&' character in the given string. If there are no '&'
+ * characters in the given string, return '\0'.
+ */
+dchar _findMnemonic (String string) {
+    if (string is null) return '\0';
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while (index < length_ && string[index] !is '&') index++;
+        if (++index >= length_) return '\0';
+        if (string[index] !is '&') return CharacterFirstToLower(string[index..$]);
+        index++;
+    } while (index < length_);
+    return '\0';
+}
+String stripMnemonic (String string) {
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while ((index < length_) && (string[index] !is '&')) index++;
+        if (++index >= length_) return string;
+        if (string[index] !is '&') {
+            return string.substring(0, index-1) ~ string.substring(index, length_);
+        }
+        index++;
+    } while (index < length_);
+    return string;
+}
+/**
+ * Returns <code>true</code> if the receiver is minimized.
+ *
+ * @return the receiver's minimized state
+ *
+ * @exception SWTException <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.0
+ */
+public bool getMinimized() {
+    checkWidget();
+    return minimized;
+}
+/**
+ * Returns <code>true</code> if the minimize button
+ * is visible.
+ *
+ * @return the visibility of the minimized button
+ *
+ * @exception SWTException <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.0
+ */
+public bool getMinimizeVisible() {
+    checkWidget();
+    return showMin;
+}
+/**
+ * Returns the number of characters that will
+ * appear in a fully compressed tab.
+ *
+ * @return number of characters that will appear in a fully compressed tab
+ *
+ * @since 3.0
+ */
+public int getMinimumCharacters() {
+    checkWidget();
+    return minChars;
+}
+/**
+ * Returns <code>true</code> if the receiver is maximized.
+ * <p>
+ *
+ * @return the receiver's maximized state
+ *
+ * @exception SWTException <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.0
+ */
+public bool getMaximized() {
+    checkWidget();
+    return maximized;
+}
+/**
+ * Returns <code>true</code> if the maximize button
+ * is visible.
+ *
+ * @return the visibility of the maximized button
+ *
+ * @exception SWTException <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.0
+ */
+public bool getMaximizeVisible() {
+    checkWidget();
+    return showMax;
+}
+/**
+ * Returns <code>true</code> if the receiver displays most
+ * recently used tabs and <code>false</code> otherwise.
+ * <p>
+ * When there is not enough horizontal space to show all the tabs,
+ * by default, tabs are shown sequentially from left to right in
+ * order of their index.  When the MRU visibility is turned on,
+ * the tabs that are visible will be the tabs most recently selected.
+ * Tabs will still maintain their left to right order based on index
+ * but only the most recently selected tabs are visible.
+ * <p>
+ * For example, consider a CTabFolder that contains "Tab 1", "Tab 2",
+ * "Tab 3" and "Tab 4" (in order by index).  The user selects
+ * "Tab 1" and then "Tab 3".  If the CTabFolder is now
+ * compressed so that only two tabs are visible, by default,
+ * "Tab 2" and "Tab 3" will be shown ("Tab 3" since it is currently
+ * selected and "Tab 2" because it is the previous item in index order).
+ * If MRU visibility is enabled, the two visible tabs will be "Tab 1"
+ * and "Tab 3" (in that order from left to right).</p>
+ *
+ * @return the receiver's header's visibility state
+ *
+ * @exception SWTException <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.1
+ */
+public bool getMRUVisible() {
+    checkWidget();
+    return mru;
+}
+int getRightItemEdge (){
+    int x = getSize().x - borderRight - 3;
+    if (showMin) x -= BUTTON_SIZE;
+    if (showMax) x -= BUTTON_SIZE;
+    if (showChevron) x -= 3*BUTTON_SIZE/2;
+    if (topRight !is null && topRightAlignment !is SWT.FILL) {
+        Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+        x -= rightSize.x + 3;
+    }
+    return Math.max(0, x);
+}
+/**
+ * Return the selected tab item, or null if there is no selection.
+ *
+ * @return the selected tab item, or null if none has been selected
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public CTabItem getSelection() {
+    //checkWidget();
+    if (selectedIndex is -1) return null;
+    return items[selectedIndex];
+}
+/**
+ * Returns the receiver's selection background color.
+ *
+ * @return the selection background color of the receiver
+ *
+ * @exception SWTException <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.0
+ */
+public Color getSelectionBackground() {
+    checkWidget();
+    return selectionBackground;
+}
+/**
+ * Returns the receiver's selection foreground color.
+ *
+ * @return the selection foreground color of the receiver
+ *
+ * @exception SWTException <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.0
+ */
+public Color getSelectionForeground() {
+    checkWidget();
+    return selectionForeground;
+}
+/**
+ * Return the index of the selected tab item, or -1 if there
+ * is no selection.
+ *
+ * @return the index of the selected tab item or -1
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public int getSelectionIndex() {
+    //checkWidget();
+    return selectedIndex;
+}
+/**
+ * Returns <code>true</code> if the CTabFolder is rendered
+ * with a simple, traditional shape.
+ *
+ * @return <code>true</code> if the CTabFolder is rendered with a simple shape
+ *
+ * @since 3.0
+ */
+public bool getSimple() {
+    checkWidget();
+    return simple;
+}
+/**
+ * Returns <code>true</code> if the CTabFolder only displays the selected tab
+ * and <code>false</code> if the CTabFolder displays multiple tabs.
+ *
+ * @return <code>true</code> if the CTabFolder only displays the selected tab and <code>false</code> if the CTabFolder displays multiple tabs
+ *
+ * @since 3.0
+ */
+public bool getSingle() {
+    checkWidget();
+    return single;
+}
+
+public override int getStyle() {
+    int style = super.getStyle();
+    style &= ~(SWT.TOP | SWT.BOTTOM);
+    style |= onBottom ? SWT.BOTTOM : SWT.TOP;
+    style &= ~(SWT.SINGLE | SWT.MULTI);
+    style |= single ? SWT.SINGLE : SWT.MULTI;
+    if (borderLeft !is 0) style |= SWT.BORDER;
+    style &= ~SWT.CLOSE;
+    if (showClose) style |= SWT.CLOSE;
+    return style;
+}
+/**
+ * Returns the height of the tab
+ *
+ * @return the height of the tab
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public int getTabHeight(){
+    checkWidget();
+    if (fixedTabHeight !is SWT.DEFAULT) return fixedTabHeight;
+    return tabHeight - 1; // -1 for line drawn across top of tab
+}
+/**
+ * Returns the position of the tab.  Possible values are SWT.TOP or SWT.BOTTOM.
+ *
+ * @return the position of the tab
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public int getTabPosition(){
+    checkWidget();
+    return onBottom ? SWT.BOTTOM : SWT.TOP;
+}
+/**
+ * Returns the control in the top right corner of the tab folder.
+ * Typically this is a close button or a composite with a menu and close button.
+ *
+ * @return the control in the top right corner of the tab folder or null
+ *
+ * @exception  SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ *
+ * @since 2.1
+ */
+public Control getTopRight() {
+    checkWidget();
+    return topRight;
+}
+/**
+ * Returns <code>true</code> if the close button appears
+ * when the user hovers over an unselected tabs.
+ *
+ * @return <code>true</code> if the close button appears on unselected tabs
+ *
+ * @since 3.0
+ */
+public bool getUnselectedCloseVisible() {
+    checkWidget();
+    return showUnselectedClose;
+}
+/**
+ * Returns <code>true</code> if an image appears
+ * in unselected tabs.
+ *
+ * @return <code>true</code> if an image appears in unselected tabs
+ *
+ * @since 3.0
+ */
+public bool getUnselectedImageVisible() {
+    checkWidget();
+    return showUnselectedImage;
+}
+/**
+ * Return the index of the specified tab or -1 if the tab is not
+ * in the receiver.
+ *
+ * @param item the tab item for which the index is required
+ *
+ * @return the index of the specified tab item or -1
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ */
+public int indexOf(CTabItem item) {
+    checkWidget();
+    if (item is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    for (int i = 0; i < items.length; i++) {
+        if (items[i] is item) return i;
+    }
+    return -1;
+}
+void initAccessible() {
+    Accessible accessible = getAccessible();
+    accessible.addAccessibleListener(new class() AccessibleAdapter {
+        public void getName(AccessibleEvent e) {
+            String name = null;
+            int childID = e.childID;
+            if (childID >= 0 && childID < items.length) {
+                name = stripMnemonic(items[childID].getText());
+            } else if (childID is items.length + CHEVRON_CHILD_ID) {
+                name = SWT.getMessage("SWT_ShowList"); //$NON-NLS-1$
+            } else if (childID is items.length + MINIMIZE_CHILD_ID) {
+                name = minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$
+            } else if (childID is items.length + MAXIMIZE_CHILD_ID) {
+                name = maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+            e.result = name;
+        }
+
+        public void getHelp(AccessibleEvent e) {
+            String help = null;
+            int childID = e.childID;
+            if (childID is ACC.CHILDID_SELF) {
+                help = getToolTipText();
+            } else if (childID >= 0 && childID < items.length) {
+                help = items[childID].getToolTipText();
+            }
+            e.result = help;
+        }
+
+        public void getKeyboardShortcut(AccessibleEvent e) {
+            String shortcut = null;
+            int childID = e.childID;
+            if (childID >= 0 && childID < items.length) {
+                String text = items[childID].getText();
+                if (text !is null) {
+                    dchar mnemonic = _findMnemonic(text);
+                    if (mnemonic !is '\0') {
+                        shortcut = "Alt+"~tango.text.convert.Utf.toString([mnemonic]); //$NON-NLS-1$
+                    }
+                }
+            }
+            e.result = shortcut;
+        }
+    });
+
+    accessible.addAccessibleControlListener(new class() AccessibleControlAdapter {
+        public void getChildAtPoint(AccessibleControlEvent e) {
+            Point testPoint = toControl(e.x, e.y);
+            int childID = ACC.CHILDID_NONE;
+            for (int i = 0; i < items.length; i++) {
+                if (items[i].getBounds().contains(testPoint)) {
+                    childID = i;
+                    break;
+                }
+            }
+            if (childID is ACC.CHILDID_NONE) {
+                if (showChevron && chevronRect.contains(testPoint)) {
+                    childID = items.length + CHEVRON_CHILD_ID;
+                } else if (showMin && minRect.contains(testPoint)) {
+                    childID = items.length + MINIMIZE_CHILD_ID;
+                } else if (showMax && maxRect.contains(testPoint)) {
+                    childID = items.length + MAXIMIZE_CHILD_ID;
+                } else {
+                    Rectangle location = getBounds();
+                    location.height = location.height - getClientArea().height;
+                    if (location.contains(testPoint)) {
+                        childID = ACC.CHILDID_SELF;
+                    }
+                }
+            }
+            e.childID = childID;
+        }
+
+        public void getLocation(AccessibleControlEvent e) {
+            Rectangle location = null;
+            Point pt = null;
+            int childID = e.childID;
+            if (childID is ACC.CHILDID_SELF) {
+                location = getBounds();
+                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 && pt !is null) {
+                e.x = pt.x;
+                e.y = pt.y;
+                e.width = location.width;
+                e.height = location.height;
+            }
+        }
+
+        public void getChildCount(AccessibleControlEvent e) {
+            e.detail = items.length + EXTRA_CHILD_ID_COUNT;
+        }
+
+        public void getDefaultAction(AccessibleControlEvent e) {
+            String action = null;
+            int childID = e.childID;
+            if (childID >= 0 && childID < items.length) {
+                action = SWT.getMessage ("SWT_Switch"); //$NON-NLS-1$
+            }
+            if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) {
+                action = SWT.getMessage ("SWT_Press"); //$NON-NLS-1$
+            }
+            e.result = action;
+        }
+
+        public void getFocus(AccessibleControlEvent e) {
+            int childID = ACC.CHILDID_NONE;
+            if (isFocusControl()) {
+                if (selectedIndex is -1) {
+                    childID = ACC.CHILDID_SELF;
+                } else {
+                    childID = selectedIndex;
+                }
+            }
+            e.childID = childID;
+        }
+
+        public void getRole(AccessibleControlEvent e) {
+            int role = 0;
+            int childID = e.childID;
+            if (childID is ACC.CHILDID_SELF) {
+                role = ACC.ROLE_TABFOLDER;
+            } else if (childID >= 0 && childID < items.length) {
+                role = ACC.ROLE_TABITEM;
+            } else if (childID >= items.length && childID < items.length + EXTRA_CHILD_ID_COUNT) {
+                role = ACC.ROLE_PUSHBUTTON;
+            }
+            e.detail = role;
+        }
+
+        public void getSelection(AccessibleControlEvent e) {
+            e.childID = (selectedIndex is -1) ? ACC.CHILDID_NONE : selectedIndex;
+        }
+
+        public void getState(AccessibleControlEvent e) {
+            int state = 0;
+            int childID = e.childID;
+            if (childID is ACC.CHILDID_SELF) {
+                state = ACC.STATE_NORMAL;
+            } else if (childID >= 0 && childID < items.length) {
+                state = ACC.STATE_SELECTABLE;
+                if (isFocusControl()) {
+                    state |= ACC.STATE_FOCUSABLE;
+                }
+                if (selectedIndex is childID) {
+                    state |= ACC.STATE_SELECTED;
+                    if (isFocusControl()) {
+                        state |= ACC.STATE_FOCUSED;
+                    }
+                }
+            } else if (childID is items.length + CHEVRON_CHILD_ID) {
+                state = showChevron ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
+            } else if (childID is items.length + MINIMIZE_CHILD_ID) {
+                state = showMin ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
+            } else if (childID is items.length + MAXIMIZE_CHILD_ID) {
+                state = showMax ? ACC.STATE_NORMAL : ACC.STATE_INVISIBLE;
+            }
+            e.detail = state;
+        }
+
+        public void getChildren(AccessibleControlEvent e) {
+            int childIdCount = items.length + EXTRA_CHILD_ID_COUNT;
+            Object[] children = new Object[childIdCount];
+            for (int i = 0; i < childIdCount; i++) {
+                children[i] = new Integer(i);
+            }
+            e.children = children;
+        }
+    });
+
+    addListener(SWT.Selection, new class(accessible) Listener {
+        Accessible acc;
+        this( Accessible a ){
+            this.acc = a;
+        }
+        public void handleEvent(Event event) {
+            if (isFocusControl()) {
+                if (selectedIndex is -1) {
+                    acc.setFocus(ACC.CHILDID_SELF);
+                } else {
+                    acc.setFocus(selectedIndex);
+                }
+            }
+        }
+    });
+
+    addListener(SWT.FocusIn, new class(accessible) Listener {
+        Accessible acc;
+        this( Accessible a ){ this.acc = a; }
+        public void handleEvent(Event event) {
+            if (selectedIndex is -1) {
+                acc.setFocus(ACC.CHILDID_SELF);
+            } else {
+                acc.setFocus(selectedIndex);
+            }
+        }
+    });
+}
+
+void onKeyDown (Event event) {
+    switch (event.keyCode) {
+        case SWT.ARROW_LEFT:
+        case SWT.ARROW_RIGHT:
+            int count = items.length;
+            if (count is 0) return;
+            if (selectedIndex  is -1) return;
+            int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) !is 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+            int offset =  event.keyCode is leadKey ? -1 : 1;
+            int index;
+            if (!mru) {
+                index = selectedIndex + offset;
+            } else {
+                int[] visible = new int[items.length];
+                int idx = 0;
+                int current = -1;
+                for (int i = 0; i < items.length; i++) {
+                    if (items[i].showing) {
+                        if (i is selectedIndex) current = idx;
+                        visible [idx++] = i;
+                    }
+                }
+                if (current + offset >= 0 && current + offset < idx){
+                    index = visible [current + offset];
+                } else {
+                    if (showChevron) {
+                        CTabFolderEvent e = new CTabFolderEvent(this);
+                        e.widget = this;
+                        e.time = event.time;
+                        e.x = chevronRect.x;
+                        e.y = chevronRect.y;
+                        e.width = chevronRect.width;
+                        e.height = chevronRect.height;
+                        e.doit = true;
+                        for (int i = 0; i < folderListeners.length; i++) {
+                            folderListeners[i].showList(e);
+                        }
+                        if (e.doit && !isDisposed()) {
+                            showList(chevronRect);
+                        }
+                    }
+                    return;
+                }
+            }
+            if (index < 0 || index >= count) return;
+            setSelection (index, true);
+            forceFocus();
+        default:
+    }
+}
+void onDispose(Event event) {
+    removeListener(SWT.Dispose, listener);
+    notifyListeners(SWT.Dispose, event);
+    event.type = SWT.None;
+    /*
+     * Usually when an item is disposed, destroyItem will change the size of the items array,
+     * reset the bounds of all the tabs and manage the widget associated with the tab.
+     * Since the whole folder is being disposed, this is not necessary.  For speed
+     * the inDispose flag is used to skip over this part of the item dispose.
+     */
+    inDispose = true;
+
+    if (showMenu !is null && !showMenu.isDisposed()) {
+        showMenu.dispose();
+        showMenu = null;
+    }
+    int length = items.length;
+    for (int i = 0; i < length; i++) {
+        if (items[i] !is null) {
+            items[i].dispose();
+        }
+    }
+
+    selectionGradientColors = null;
+    selectionGradientPercents = null;
+    selectionBgImage = null;
+
+    selectionBackground = null;
+    selectionForeground = null;
+    disposeSelectionHighlightGradientColors();
+}
+void onDragDetect(Event event) {
+    bool consume = false;
+    if (chevronRect.contains(event.x, event.y) ||
+        minRect.contains(event.x, event.y) ||
+        maxRect.contains(event.x, event.y)){
+        consume = true;
+    } else {
+        for (int i = 0; i < items.length; i++) {
+            if (items[i].closeRect.contains(event.x, event.y)) {
+                    consume = true;
+                    break;
+            }
+        }
+    }
+    if (consume) {
+        event.type = SWT.None;
+    }
+}
+void onFocus(Event event) {
+    checkWidget();
+    if (selectedIndex >= 0) {
+        redraw();
+    } else {
+        setSelection(0, true);
+    }
+}
+bool onMnemonic (Event event) {
+    auto key = event.character;
+    for (int i = 0; i < items.length; i++) {
+        if (items[i] !is null) {
+            auto mnemonic = _findMnemonic (items[i].getText ());
+            if (mnemonic !is '\0') {
+                if ( CharacterToLower(key) is mnemonic) {
+                    setSelection(i, true);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+void onMouseDoubleClick(Event event) {
+    if (event.button !is 1 ||
+        (event.stateMask & SWT.BUTTON2) !is 0 ||
+        (event.stateMask & SWT.BUTTON3) !is 0) return;
+    Event e = new Event();
+    e.item = getItem(new Point(event.x, event.y));
+    if (e.item !is null) {
+        notifyListeners(SWT.DefaultSelection, e);
+    }
+}
+void onMouse(Event event) {
+    int x = event.x, y = event.y;
+    switch (event.type) {
+        case SWT.MouseEnter: {
+            setToolTipText(null);
+            break;
+        }
+        case SWT.MouseExit: {
+            if (minImageState !is NORMAL) {
+                minImageState = NORMAL;
+                redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+            }
+            if (maxImageState !is NORMAL) {
+                maxImageState = NORMAL;
+                redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+            }
+            if (chevronImageState !is NORMAL) {
+                chevronImageState = NORMAL;
+                redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+            }
+            for (int i=0; i<items.length; i++) {
+                CTabItem item = items[i];
+                if (i !is selectedIndex && item.closeImageState !is NONE) {
+                    item.closeImageState = NONE;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                }
+                if (i is selectedIndex && item.closeImageState !is NORMAL) {
+                    item.closeImageState = NORMAL;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                }
+            }
+            break;
+        }
+        case SWT.MouseDown: {
+            if (minRect.contains(x, y)) {
+                if (event.button !is 1) return;
+                minImageState = SELECTED;
+                redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+                update();
+                return;
+            }
+            if (maxRect.contains(x, y)) {
+                if (event.button !is 1) return;
+                maxImageState = SELECTED;
+                redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+                update();
+                return;
+            }
+            if (chevronRect.contains(x, y)) {
+                if (event.button !is 1) return;
+                if (chevronImageState !is HOT) {
+                    chevronImageState = HOT;
+                } else {
+                    chevronImageState = SELECTED;
+                }
+                redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+                update();
+                return;
+            }
+            CTabItem item = null;
+            if (single) {
+                if (selectedIndex !is -1) {
+                    Rectangle bounds = items[selectedIndex].getBounds();
+                    if (bounds.contains(x, y)){
+                        item = items[selectedIndex];
+                    }
+                }
+            } else {
+                for (int i=0; i<items.length; i++) {
+                    Rectangle bounds = items[i].getBounds();
+                    if (bounds.contains(x, y)){
+                        item = items[i];
+                    }
+                }
+            }
+            if (item !is null) {
+                if (item.closeRect.contains(x,y)){
+                    if (event.button !is 1) return;
+                    item.closeImageState = SELECTED;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                    update();
+                    return;
+                }
+                int index = indexOf(item);
+                if (item.showing){
+                    setSelection(index, true);
+                }
+                return;
+            }
+            break;
+        }
+        case SWT.MouseMove: {
+            _setToolTipText(event.x, event.y);
+            bool close = false, minimize = false, maximize = false, chevron = false;
+            if (minRect.contains(x, y)) {
+                minimize = true;
+                if (minImageState !is SELECTED && minImageState !is HOT) {
+                    minImageState = HOT;
+                    redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+                }
+            }
+            if (maxRect.contains(x, y)) {
+                maximize = true;
+                if (maxImageState !is SELECTED && maxImageState !is HOT) {
+                    maxImageState = HOT;
+                    redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+                }
+            }
+            if (chevronRect.contains(x, y)) {
+                chevron = true;
+                if (chevronImageState !is SELECTED && chevronImageState !is HOT) {
+                    chevronImageState = HOT;
+                    redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+                }
+            }
+            if (minImageState !is NORMAL && !minimize) {
+                minImageState = NORMAL;
+                redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+            }
+            if (maxImageState !is NORMAL && !maximize) {
+                maxImageState = NORMAL;
+                redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+            }
+            if (chevronImageState !is NORMAL && !chevron) {
+                chevronImageState = NORMAL;
+                redraw(chevronRect.x, chevronRect.y, chevronRect.width, chevronRect.height, false);
+            }
+            for (int i=0; i<items.length; i++) {
+                CTabItem item = items[i];
+                close = false;
+                if (item.getBounds().contains(x, y)) {
+                    close = true;
+                    if (item.closeRect.contains(x, y)) {
+                        if (item.closeImageState !is SELECTED && item.closeImageState !is HOT) {
+                            item.closeImageState = HOT;
+                            redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                        }
+                    } else {
+                        if (item.closeImageState !is NORMAL) {
+                            item.closeImageState = NORMAL;
+                            redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                        }
+                    }
+                }
+                if (i !is selectedIndex && item.closeImageState !is NONE && !close) {
+                    item.closeImageState = NONE;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                }
+                if (i is selectedIndex && item.closeImageState !is NORMAL && !close) {
+                    item.closeImageState = NORMAL;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                }
+            }
+            break;
+        }
+        case SWT.MouseUp: {
+            if (event.button !is 1) return;
+            if (chevronRect.contains(x, y)) {
+                bool selected = chevronImageState is SELECTED;
+                if (!selected) return;
+                CTabFolderEvent e = new CTabFolderEvent(this);
+                e.widget = this;
+                e.time = event.time;
+                e.x = chevronRect.x;
+                e.y = chevronRect.y;
+                e.width = chevronRect.width;
+                e.height = chevronRect.height;
+                e.doit = true;
+                for (int i = 0; i < folderListeners.length; i++) {
+                    folderListeners[i].showList(e);
+                }
+                if (e.doit && !isDisposed()) {
+                    showList(chevronRect);
+                }
+                return;
+            }
+            if (minRect.contains(x, y)) {
+                bool selected = minImageState is SELECTED;
+                minImageState = HOT;
+                redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+                if (!selected) return;
+                CTabFolderEvent e = new CTabFolderEvent(this);
+                e.widget = this;
+                e.time = event.time;
+                for (int i = 0; i < folderListeners.length; i++) {
+                    if (minimized) {
+                        folderListeners[i].restore(e);
+                    } else {
+                        folderListeners[i].minimize(e);
+                    }
+                }
+                return;
+            }
+            if (maxRect.contains(x, y)) {
+                bool selected = maxImageState is SELECTED;
+                maxImageState = HOT;
+                redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+                if (!selected) return;
+                CTabFolderEvent e = new CTabFolderEvent(this);
+                e.widget = this;
+                e.time = event.time;
+                for (int i = 0; i < folderListeners.length; i++) {
+                    if (maximized) {
+                        folderListeners[i].restore(e);
+                    } else {
+                        folderListeners[i].maximize(e);
+                    }
+                }
+                return;
+            }
+            CTabItem item = null;
+            if (single) {
+                if (selectedIndex !is -1) {
+                    Rectangle bounds = items[selectedIndex].getBounds();
+                    if (bounds.contains(x, y)){
+                        item = items[selectedIndex];
+                    }
+                }
+            } else {
+                for (int i=0; i<items.length; i++) {
+                    Rectangle bounds = items[i].getBounds();
+                    if (bounds.contains(x, y)){
+                        item = items[i];
+                    }
+                }
+            }
+            if (item !is null) {
+                if (item.closeRect.contains(x,y)) {
+                    bool selected = item.closeImageState is SELECTED;
+                    item.closeImageState = HOT;
+                    redraw(item.closeRect.x, item.closeRect.y, item.closeRect.width, item.closeRect.height, false);
+                    if (!selected) return;
+                    CTabFolderEvent e = new CTabFolderEvent(this);
+                    e.widget = this;
+                    e.time = event.time;
+                    e.item = item;
+                    e.doit = true;
+                    for (int j = 0; j < folderListeners.length; j++) {
+                        CTabFolder2Listener listener = folderListeners[j];
+                        listener.close(e);
+                    }
+                    for (int j = 0; j < tabListeners.length; j++) {
+                        CTabFolderListener listener = tabListeners[j];
+                        listener.itemClosed(e);
+                    }
+                    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);
+                        CTabItem nextItem = getItem(pt);
+                        if (nextItem !is null) {
+                            if (nextItem.closeRect.contains(pt)) {
+                                if (nextItem.closeImageState !is SELECTED && nextItem.closeImageState !is HOT) {
+                                    nextItem.closeImageState = HOT;
+                                    redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
+                                }
+                            } else {
+                                if (nextItem.closeImageState !is NORMAL) {
+                                    nextItem.closeImageState = NORMAL;
+                                    redraw(nextItem.closeRect.x, nextItem.closeRect.y, nextItem.closeRect.width, nextItem.closeRect.height, false);
+                                }
+                            }
+                        }
+                    }
+                    return;
+                }
+            }
+        default:
+        }
+    }
+}
+bool onPageTraversal(Event event) {
+    int count = items.length;
+    if (count is 0) return false;
+    int index = selectedIndex;
+    if (index  is -1) {
+        index = 0;
+    } else {
+        int offset = (event.detail is SWT.TRAVERSE_PAGE_NEXT) ? 1 : -1;
+        if (!mru) {
+            index = (selectedIndex + offset + count) % count;
+        } else {
+            int[] visible = new int[items.length];
+            int idx = 0;
+            int current = -1;
+            for (int i = 0; i < items.length; i++) {
+                if (items[i].showing) {
+                    if (i is selectedIndex) current = idx;
+                    visible [idx++] = i;
+                }
+            }
+            if (current + offset >= 0 && current + offset < idx){
+                index = visible [current + offset];
+            } else {
+                if (showChevron) {
+                    CTabFolderEvent e = new CTabFolderEvent(this);
+                    e.widget = this;
+                    e.time = event.time;
+                    e.x = chevronRect.x;
+                    e.y = chevronRect.y;
+                    e.width = chevronRect.width;
+                    e.height = chevronRect.height;
+                    e.doit = true;
+                    for (int i = 0; i < folderListeners.length; i++) {
+                        folderListeners[i].showList(e);
+                    }
+                    if (e.doit && !isDisposed()) {
+                        showList(chevronRect);
+                    }
+                }
+                return true;
+            }
+        }
+    }
+    setSelection (index, true);
+    return true;
+}
+void onPaint(Event event) {
+    if (inDispose) return;
+    Font font = getFont();
+    if (oldFont is null || oldFont!=font) {
+        // handle case where  default font changes
+        oldFont = font;
+        if (!updateTabHeight(false)) {
+            updateItems();
+            redraw();
+            return;
+        }
+    }
+
+    GC gc = event.gc;
+    Font gcFont = gc.getFont();
+    Color gcBackground = gc.getBackground();
+    Color gcForeground = gc.getForeground();
+
+// Useful for debugging paint problems
+//{
+//Point size = getSize();
+//gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
+//gc.fillRectangle(-10, -10, size.x + 20, size.y+20);
+//}
+
+    drawBody(event);
+
+    gc.setFont(gcFont);
+    gc.setForeground(gcForeground);
+    gc.setBackground(gcBackground);
+
+    drawTabArea(event);
+
+    gc.setFont(gcFont);
+    gc.setForeground(gcForeground);
+    gc.setBackground(gcBackground);
+}
+
+void onResize() {
+    if (updateItems()) redrawTabs();
+
+    Point size = getSize();
+    if (oldSize is null) {
+        redraw();
+    } else {
+        if (onBottom && size.y !is oldSize.y) {
+            redraw();
+        } else {
+            int x1 = Math.min(size.x, oldSize.x);
+            if (size.x !is oldSize.x) x1 -= borderRight + highlight_margin + 2;
+            if (!simple) x1 -= 5; // rounded top right corner
+            int y1 = Math.min(size.y, oldSize.y);
+            if (size.y !is oldSize.y) y1 -= borderBottom + highlight_margin;
+            int x2 = Math.max(size.x, oldSize.x);
+            int y2 = Math.max(size.y, oldSize.y);
+            redraw(0, y1, x2, y2 - y1, false);
+            redraw(x1, 0, x2 - x1, y2, false);
+        }
+    }
+    oldSize = size;
+}
+void onTraverse (Event event) {
+    switch (event.detail) {
+        case SWT.TRAVERSE_ESCAPE:
+        case SWT.TRAVERSE_RETURN:
+        case SWT.TRAVERSE_TAB_NEXT:
+        case SWT.TRAVERSE_TAB_PREVIOUS:
+            Control focusControl = getDisplay().getFocusControl();
+            if (focusControl is this) event.doit = true;
+            break;
+        case SWT.TRAVERSE_MNEMONIC:
+            event.doit = onMnemonic(event);
+            if (event.doit) event.detail = SWT.TRAVERSE_NONE;
+            break;
+        case SWT.TRAVERSE_PAGE_NEXT:
+        case SWT.TRAVERSE_PAGE_PREVIOUS:
+            event.doit = onPageTraversal(event);
+            event.detail = SWT.TRAVERSE_NONE;
+            break;
+        default:
+    }
+}
+void redrawTabs() {
+    Point size = getSize();
+    if (onBottom) {
+        redraw(0, size.y - borderBottom - tabHeight - highlight_header - 1, size.x, borderBottom + tabHeight + highlight_header + 1, false);
+    } else {
+        redraw(0, 0, size.x, borderTop + tabHeight + highlight_header + 1, false);
+    }
+}
+/**
+ * Removes the listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @see #addCTabFolder2Listener(CTabFolder2Listener)
+ *
+ * @since 3.0
+ */
+public void removeCTabFolder2Listener(CTabFolder2Listener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (folderListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < folderListeners.length; i++) {
+        if (listener is folderListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (folderListeners.length is 1) {
+        folderListeners = new CTabFolder2Listener[0];
+        return;
+    }
+    CTabFolder2Listener[] newTabListeners = new CTabFolder2Listener[folderListeners.length - 1];
+    SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, 0, newTabListeners, 0, index);
+    SimpleType!(CTabFolder2Listener).arraycopy(folderListeners, index + 1, newTabListeners, index, folderListeners.length - index - 1);
+    folderListeners = newTabListeners;
+}
+/**
+ * Removes the listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ *
+ * @deprecated see removeCTabFolderCloseListener(CTabFolderListener)
+ */
+public void removeCTabFolderListener(CTabFolderListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (tabListeners.length is 0) return;
+    int index = -1;
+    for (int i = 0; i < tabListeners.length; i++) {
+        if (listener is tabListeners[i]){
+            index = i;
+            break;
+        }
+    }
+    if (index is -1) return;
+    if (tabListeners.length is 1) {
+        tabListeners = new CTabFolderListener[0];
+        return;
+    }
+    CTabFolderListener[] newTabListeners = new CTabFolderListener[tabListeners.length - 1];
+    SimpleType!(CTabFolderListener).arraycopy(tabListeners, 0, newTabListeners, 0, index);
+    SimpleType!(CTabFolderListener).arraycopy(tabListeners, index + 1, newTabListeners, index, tabListeners.length - index - 1);
+    tabListeners = newTabListeners;
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    removeListener(SWT.Selection, listener);
+    removeListener(SWT.DefaultSelection, listener);
+}
+public override void setBackground (Color color) {
+    super.setBackground(color);
+    redraw();
+}
+/**
+ * Specify a gradient of colours to be drawn in the background of the unselected tabs.
+ * For example to draw a gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ *  cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                     new int[] {25, 50, 100});
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance left to right.  The value <code>null</code> clears the
+ *               background gradient. The value <code>null</code> can be used inside the array of
+ *               Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ *                 of the widget at which the color should change.  The size of the percents array must be one
+ *                 less than the size of the colors array.
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ *
+ * @since 3.0
+ */
+void setBackground(Color[] colors, int[] percents) {
+    setBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colours to be drawn in the background of the unselected tab.
+ * For example to draw a vertical gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ *  cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                        new int[] {25, 50, 100}, true);
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance left to right.  The value <code>null</code> clears the
+ *               background gradient. The value <code>null</code> can be used inside the array of
+ *               Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ *                 of the widget at which the color should change.  The size of the percents array must be one
+ *                 less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient.  True is vertical and false is horizontal.
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ *
+ * @since 3.0
+ */
+void setBackground(Color[] colors, int[] percents, bool vertical) {
+    checkWidget();
+    if (colors !is null) {
+        if (percents is null || percents.length !is colors.length - 1) {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        for (int i = 0; i < percents.length; i++) {
+            if (percents[i] < 0 || percents[i] > 100) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            if (i > 0 && percents[i] < percents[i-1]) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+        }
+        if (getDisplay().getDepth() < 15) {
+            // Don't use gradients on low color displays
+            colors = [colors[colors.length - 1]];
+            percents = null;
+        }
+    }
+
+    // Are these settings the same as before?
+    if (bgImage is null) {
+        if ((gradientColors !is null) && (colors !is null) &&
+            (gradientColors.length is colors.length)) {
+            bool same = false;
+            for (int i = 0; i < gradientColors.length; i++) {
+                if (gradientColors[i] is null) {
+                    same = colors[i] is null;
+                } else {
+                    same = cast(bool)(gradientColors[i]==colors[i]);
+                }
+                if (!same) break;
+            }
+            if (same) {
+                for (int i = 0; i < gradientPercents.length; i++) {
+                    same = gradientPercents[i] is percents[i];
+                    if (!same) break;
+                }
+            }
+            if (same && this.gradientVertical is vertical) return;
+        }
+    } else {
+        bgImage = null;
+    }
+    // Store the new settings
+    if (colors is null) {
+        gradientColors = null;
+        gradientPercents = null;
+        gradientVertical = false;
+        setBackground(cast(Color)null);
+    } else {
+        gradientColors = new Color[colors.length];
+        for (int i = 0; i < colors.length; ++i) {
+            gradientColors[i] = colors[i];
+        }
+        gradientPercents = new int[percents.length];
+        for (int i = 0; i < percents.length; ++i) {
+            gradientPercents[i] = percents[i];
+        }
+        gradientVertical = vertical;
+        setBackground(gradientColors[gradientColors.length-1]);
+    }
+
+    // Refresh with the new settings
+    redraw();
+}
+
+/**
+ * Set the image to be drawn in the background of the unselected tab.  Image
+ * is stretched or compressed to cover entire unselected tab area.
+ *
+ * @param image the image to be drawn in the background
+ *
+ * @exception SWTException <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.0
+ */
+void setBackground(Image image) {
+    checkWidget();
+    if (image is bgImage) return;
+    if (image !is null) {
+        gradientColors = null;
+        gradientPercents = null;
+    }
+    bgImage = image;
+    redraw();
+}
+/**
+ * Toggle the visibility of the border
+ *
+ * @param show true if the border should be displayed
+ *
+ * @exception SWTException <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 setBorderVisible(bool show) {
+    checkWidget();
+    if ((borderLeft is 1) is show) return;
+    borderLeft = borderRight = show ? 1 : 0;
+    borderTop = onBottom ? borderLeft : 0;
+    borderBottom = onBottom ? 0 : borderLeft;
+    Rectangle rectBefore = getClientArea();
+    updateItems();
+    Rectangle rectAfter = getClientArea();
+    if (rectBefore!=rectAfter) {
+        notifyListeners(SWT.Resize, new Event());
+    }
+    redraw();
+}
+void setButtonBounds() {
+    Point size = getSize();
+    int oldX, oldY, oldWidth, oldHeight;
+    // max button
+    oldX = maxRect.x;
+    oldY = maxRect.y;
+    oldWidth = maxRect.width;
+    oldHeight = maxRect.height;
+    maxRect.x = maxRect.y = maxRect.width = maxRect.height = 0;
+    if (showMax) {
+        maxRect.x = size.x - borderRight - BUTTON_SIZE - 3;
+        if (borderRight > 0) maxRect.x += 1;
+        maxRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+        maxRect.width = BUTTON_SIZE;
+        maxRect.height = BUTTON_SIZE;
+    }
+    if (oldX !is maxRect.x || oldWidth !is maxRect.width ||
+        oldY !is maxRect.y || oldHeight !is maxRect.height) {
+        int left = Math.min(oldX, maxRect.x);
+        int right = Math.max(oldX + oldWidth, maxRect.x + maxRect.width);
+        int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+        redraw(left, top, right - left, tabHeight, false);
+    }
+
+    // min button
+    oldX = minRect.x;
+    oldY = minRect.y;
+    oldWidth = minRect.width;
+    oldHeight = minRect.height;
+    minRect.x = minRect.y = minRect.width = minRect.height = 0;
+    if (showMin) {
+        minRect.x = size.x - borderRight - maxRect.width - BUTTON_SIZE - 3;
+        if (borderRight > 0) minRect.x += 1;
+        minRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+        minRect.width = BUTTON_SIZE;
+        minRect.height = BUTTON_SIZE;
+    }
+    if (oldX !is minRect.x || oldWidth !is minRect.width ||
+        oldY !is minRect.y || oldHeight !is minRect.height) {
+        int left = Math.min(oldX, minRect.x);
+        int right = Math.max(oldX + oldWidth, minRect.x + minRect.width);
+        int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+        redraw(left, top, right - left, tabHeight, false);
+    }
+
+    // top right control
+    oldX = topRightRect.x;
+    oldY = topRightRect.y;
+    oldWidth = topRightRect.width;
+    oldHeight = topRightRect.height;
+    topRightRect.x = topRightRect.y = topRightRect.width = topRightRect.height = 0;
+    if (topRight !is null) {
+        switch (topRightAlignment) {
+            case SWT.FILL: {
+                int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width;
+                if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2;
+                if (single) {
+                    if (items.length is 0 || selectedIndex is -1) {
+                        topRightRect.x = borderLeft + 3;
+                        topRightRect.width = rightEdge - topRightRect.x;
+                    } else {
+                        // fill size is 0 if item compressed
+                        CTabItem item = items[selectedIndex];
+                        if (item.x + item.width + 7 + 3*BUTTON_SIZE/2 >= rightEdge) break;
+                        topRightRect.x = item.x + item.width + 7 + 3*BUTTON_SIZE/2;
+                        topRightRect.width = rightEdge - topRightRect.x;
+                    }
+                } else {
+                    // fill size is 0 if chevron showing
+                    if (showChevron) break;
+                    if (items.length is 0) {
+                        topRightRect.x = borderLeft + 3;
+                    } else {
+                        CTabItem item = items[items.length - 1];
+                        topRightRect.x = item.x + item.width;
+                        if (!simple && items.length - 1 is selectedIndex) topRightRect.x += curveWidth - curveIndent;
+                    }
+                    topRightRect.width = Math.max(0, rightEdge - topRightRect.x);
+                }
+                topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+                topRightRect.height = tabHeight - 1;
+                break;
+            }
+            case SWT.RIGHT: {
+                Point topRightSize = topRight.computeSize(SWT.DEFAULT, tabHeight, false);
+                int rightEdge = size.x - borderRight - 3 - maxRect.width - minRect.width;
+                if (!simple && borderRight > 0 && !showMax && !showMin) rightEdge -= 2;
+                topRightRect.x = rightEdge - topRightSize.x;
+                topRightRect.width = topRightSize.x;
+                topRightRect.y = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+                topRightRect.height = tabHeight - 1;
+            }
+            default:
+        }
+        topRight.setBounds(topRightRect);
+    }
+    if (oldX !is topRightRect.x || oldWidth !is topRightRect.width ||
+        oldY !is topRightRect.y || oldHeight !is topRightRect.height) {
+        int left = Math.min(oldX, topRightRect.x);
+        int right = Math.max(oldX + oldWidth, topRightRect.x + topRightRect.width);
+        int top = onBottom ? size.y - borderBottom - tabHeight : borderTop + 1;
+        redraw(left, top, right - left, tabHeight, false);
+    }
+
+    // chevron button
+    oldX = chevronRect.x;
+    oldY = chevronRect.y;
+    oldWidth = chevronRect.width;
+    oldHeight = chevronRect.height;
+    chevronRect.x = chevronRect.y = chevronRect.height = chevronRect.width = 0;
+    if (single) {
+        if (selectedIndex is -1 || items.length > 1) {
+            chevronRect.width = 3*BUTTON_SIZE/2;
+            chevronRect.height = BUTTON_SIZE;
+            chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2;
+            if (selectedIndex is -1) {
+                chevronRect.x = size.x - borderRight - 3 - minRect.width - maxRect.width - topRightRect.width - chevronRect.width;
+            } else {
+                CTabItem item = items[selectedIndex];
+                int w = size.x - borderRight - 3 - minRect.width - maxRect.width - chevronRect.width;
+                if (topRightRect.width > 0) w -= topRightRect.width + 3;
+                chevronRect.x = Math.min(item.x + item.width + 3, w);
+            }
+            if (borderRight > 0) chevronRect.x += 1;
+        }
+    } else {
+        if (showChevron) {
+            chevronRect.width = 3*BUTTON_SIZE/2;
+            chevronRect.height = BUTTON_SIZE;
+            int i = 0, lastIndex = -1;
+            while (i < priority.length && items[priority[i]].showing) {
+                lastIndex = Math.max(lastIndex, priority[i++]);
+            }
+            if (lastIndex is -1) lastIndex = firstIndex;
+            CTabItem lastItem = items[lastIndex];
+            int w = lastItem.x + lastItem.width + 3;
+            if (!simple && lastIndex is selectedIndex) w += curveWidth - 2*curveIndent;
+            chevronRect.x = Math.min(w, getRightItemEdge());
+            chevronRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - chevronRect.height)/2 : borderTop + (tabHeight - chevronRect.height)/2;
+        }
+    }
+    if (oldX !is chevronRect.x || oldWidth !is chevronRect.width ||
+        oldY !is chevronRect.y || oldHeight !is chevronRect.height) {
+        int left = Math.min(oldX, chevronRect.x);
+        int right = Math.max(oldX + oldWidth, chevronRect.x + chevronRect.width);
+        int top = onBottom ? size.y - borderBottom - tabHeight: borderTop + 1;
+        redraw(left, top, right - left, tabHeight, false);
+    }
+}
+public override void setFont(Font font) {
+    checkWidget();
+    if (font !is null && font==getFont()) return;
+    super.setFont(font);
+    oldFont = getFont();
+    if (!updateTabHeight(false)) {
+        updateItems();
+        redraw();
+    }
+}
+public override void setForeground (Color color) {
+    super.setForeground(color);
+    redraw();
+}
+/**
+ * Display an insert marker before or after the specified tab item.
+ *
+ * A value of null will clear the mark.
+ *
+ * @param item the item with which the mark is associated or null
+ *
+ * @param after true if the mark should be displayed after the specified item
+ *
+ * @exception SWTException <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 setInsertMark(CTabItem item, bool after) {
+    checkWidget();
+}
+/**
+ * Display an insert marker before or after the specified tab item.
+ *
+ * A value of -1 will clear the mark.
+ *
+ * @param index the index of the item with which the mark is associated or null
+ *
+ * @param after true if the mark should be displayed after the specified item
+ *
+ * @exception IllegalArgumentException<ul>
+ * </ul>
+ *
+ * @exception SWTException <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 setInsertMark(int index, bool after) {
+    checkWidget();
+    if (index < -1 || index >= getItemCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+}
+bool setItemLocation() {
+    bool changed = false;
+    if (items.length is 0) return false;
+    Point size = getSize();
+    int y = onBottom ? Math.max(borderBottom, size.y - borderBottom - tabHeight) : borderTop;
+    if (single) {
+        int defaultX = getDisplay().getBounds().width + 10; // off screen
+        for (int i = 0; i < items.length; i++) {
+            CTabItem item = items[i];
+            if (i is selectedIndex) {
+                firstIndex = selectedIndex;
+                int oldX = item.x, oldY = item.y;
+                item.x = borderLeft;
+                item.y = y;
+                item.showing = true;
+                if (showClose || item.showClose) {
+                    item.closeRect.x = borderLeft + CTabItem.LEFT_MARGIN;
+                    item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+                }
+                if (item.x !is oldX || item.y !is oldY) changed = true;
+            } else {
+                item.x = defaultX;
+                item.showing = false;
+            }
+        }
+    } else {
+        int rightItemEdge = getRightItemEdge();
+        int maxWidth = rightItemEdge - borderLeft;
+        int width = 0;
+        for (int i = 0; i < priority.length; i++) {
+            CTabItem item = items[priority[i]];
+            width += item.width;
+            item.showing = i is 0 ? true : item.width > 0 && width <= maxWidth;
+            if (!simple && priority[i] is selectedIndex) width += curveWidth - 2*curveIndent;
+        }
+        int x = 0;
+        int defaultX = getDisplay().getBounds().width + 10; // off screen
+        firstIndex = items.length - 1;
+        for (int i = 0; i < items.length; i++) {
+            CTabItem item = items[i];
+            if (!item.showing) {
+                if (item.x !is defaultX) changed = true;
+                item.x = defaultX;
+            } else {
+                firstIndex = Math.min(firstIndex, i);
+                if (item.x !is x || item.y !is y) changed = true;
+                item.x = x;
+                item.y = y;
+                if (i is selectedIndex) {
+                    int edge = Math.min(item.x + item.width, rightItemEdge);
+                    item.closeRect.x = edge - CTabItem.RIGHT_MARGIN - BUTTON_SIZE;
+                } else {
+                    item.closeRect.x = item.x + item.width - CTabItem.RIGHT_MARGIN - BUTTON_SIZE;
+                }
+                item.closeRect.y = onBottom ? size.y - borderBottom - tabHeight + (tabHeight - BUTTON_SIZE)/2: borderTop + (tabHeight - BUTTON_SIZE)/2;
+                x = x + item.width;
+                if (!simple && i is selectedIndex) x += curveWidth - 2*curveIndent;
+            }
+        }
+    }
+    return changed;
+}
+bool setItemSize() {
+    bool changed = false;
+    if (isDisposed()) return changed;
+    Point size = getSize();
+    if (size.x <= 0 || size.y <= 0) return changed;
+    xClient = borderLeft + marginWidth + highlight_margin;
+    if (onBottom) {
+        yClient = borderTop + highlight_margin + marginHeight;
+    } else {
+        yClient = borderTop + tabHeight + highlight_header + marginHeight;
+    }
+    showChevron = false;
+    if (single) {
+        showChevron = true;
+        if (selectedIndex !is -1) {
+            CTabItem tab = items[selectedIndex];
+            GC gc = new GC(this);
+            int width = tab.preferredWidth(gc, true, false);
+            gc.dispose();
+            width = Math.min(width, getRightItemEdge() - borderLeft);
+            if (tab.height !is tabHeight || tab.width !is width) {
+                changed = true;
+                tab.shortenedText = null;
+                tab.shortenedTextWidth = 0;
+                tab.height = tabHeight;
+                tab.width = width;
+                tab.closeRect.width = tab.closeRect.height = 0;
+                if (showClose || tab.showClose) {
+                    tab.closeRect.width = BUTTON_SIZE;
+                    tab.closeRect.height = BUTTON_SIZE;
+                }
+            }
+        }
+        return changed;
+    }
+
+    if (items.length is 0) return changed;
+
+    int[] widths;
+    GC gc = new GC(this);
+    int tabAreaWidth = size.x - borderLeft - borderRight - 3;
+    if (showMin) tabAreaWidth -= BUTTON_SIZE;
+    if (showMax) tabAreaWidth -= BUTTON_SIZE;
+    if (topRightAlignment is SWT.RIGHT && topRight !is null) {
+        Point rightSize = topRight.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
+        tabAreaWidth -= rightSize.x + 3;
+    }
+    if (!simple) tabAreaWidth -= curveWidth - 2*curveIndent;
+    tabAreaWidth = Math.max(0, tabAreaWidth);
+
+    // First, try the minimum tab size at full compression.
+    int minWidth = 0;
+    int[] minWidths = new int[items.length];
+    for (int i = 0; i < priority.length; i++) {
+        int index = priority[i];
+        minWidths[index] = items[index].preferredWidth(gc, index is selectedIndex, true);
+        minWidth += minWidths[index];
+        if (minWidth > tabAreaWidth) break;
+    }
+    if (minWidth > tabAreaWidth) {
+        // full compression required and a chevron
+        showChevron = items.length > 1;
+        if (showChevron) tabAreaWidth -= 3*BUTTON_SIZE/2;
+        widths = minWidths;
+        int index = selectedIndex !is -1 ? selectedIndex : 0;
+        if (tabAreaWidth < widths[index]) {
+            widths[index] = Math.max(0, tabAreaWidth);
+        }
+    } else {
+        int maxWidth = 0;
+        int[] maxWidths = new int[items.length];
+        for (int i = 0; i < items.length; i++) {
+            maxWidths[i] = items[i].preferredWidth(gc, i is selectedIndex, false);
+            maxWidth += maxWidths[i];
+        }
+        if (maxWidth <= tabAreaWidth) {
+            // no compression required
+            widths = maxWidths;
+        } else {
+            // determine compression for each item
+            int extra = (tabAreaWidth - minWidth) / items.length;
+            while (true) {
+                int large = 0, totalWidth = 0;
+                for (int i = 0 ; i < items.length; i++) {
+                    if (maxWidths[i] > minWidths[i] + extra) {
+                        totalWidth += minWidths[i] + extra;
+                        large++;
+                    } else {
+                        totalWidth += maxWidths[i];
+                    }
+                }
+                if (totalWidth >= tabAreaWidth) {
+                    extra--;
+                    break;
+                }
+                if (large is 0 || tabAreaWidth - totalWidth < large) break;
+                extra++;
+            }
+            widths = new int[items.length];
+            for (int i = 0; i < items.length; i++) {
+                widths[i] = Math.min(maxWidths[i], minWidths[i] + extra);
+            }
+        }
+    }
+    gc.dispose();
+
+    for (int i = 0; i < items.length; i++) {
+        CTabItem tab = items[i];
+        int width = widths[i];
+        if (tab.height !is tabHeight || tab.width !is width) {
+            changed = true;
+            tab.shortenedText = null;
+            tab.shortenedTextWidth = 0;
+            tab.height = tabHeight;
+            tab.width = width;
+            tab.closeRect.width = tab.closeRect.height = 0;
+            if (showClose || tab.showClose) {
+                if (i is selectedIndex || showUnselectedClose) {
+                    tab.closeRect.width = BUTTON_SIZE;
+                    tab.closeRect.height = BUTTON_SIZE;
+                }
+            }
+        }
+    }
+    return changed;
+}
+/**
+ * Marks the receiver's maximize button as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException <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.0
+ */
+public void setMaximizeVisible(bool visible) {
+    checkWidget();
+    if (showMax is visible) return;
+    // display maximize button
+    showMax = visible;
+    updateItems();
+    redraw();
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    checkWidget();
+    return;
+}
+/**
+ * Sets the maximized state of the receiver.
+ *
+ * @param maximize the new maximized state
+ *
+ * @exception SWTException <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.0
+ */
+public void setMaximized(bool maximize) {
+    checkWidget ();
+    if (this.maximized is maximize) return;
+    if (maximize && this.minimized) setMinimized(false);
+    this.maximized = maximize;
+    redraw(maxRect.x, maxRect.y, maxRect.width, maxRect.height, false);
+}
+/**
+ * Marks the receiver's minimize button as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException <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.0
+ */
+public void setMinimizeVisible(bool visible) {
+    checkWidget();
+    if (showMin is visible) return;
+    // display minimize button
+    showMin = visible;
+    updateItems();
+    redraw();
+}
+/**
+ * Sets the minimized state of the receiver.
+ *
+ * @param minimize the new minimized state
+ *
+ * @exception SWTException <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.0
+ */
+public void setMinimized(bool minimize) {
+    checkWidget ();
+    if (this.minimized is minimize) return;
+    if (minimize && this.maximized) setMaximized(false);
+    this.minimized = minimize;
+    redraw(minRect.x, minRect.y, minRect.width, minRect.height, false);
+}
+
+/**
+ * Sets the minimum number of characters that will
+ * be displayed in a fully compressed tab.
+ *
+ * @param count the minimum number of characters that will be displayed in a fully compressed tab
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_RANGE - if the count is less than zero</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setMinimumCharacters(int count) {
+    checkWidget ();
+    if (count < 0) SWT.error(SWT.ERROR_INVALID_RANGE);
+    if (minChars is count) return;
+    minChars = count;
+    if (updateItems()) redrawTabs();
+}
+
+/**
+ * When there is not enough horizontal space to show all the tabs,
+ * by default, tabs are shown sequentially from left to right in
+ * order of their index.  When the MRU visibility is turned on,
+ * the tabs that are visible will be the tabs most recently selected.
+ * Tabs will still maintain their left to right order based on index
+ * but only the most recently selected tabs are visible.
+ * <p>
+ * For example, consider a CTabFolder that contains "Tab 1", "Tab 2",
+ * "Tab 3" and "Tab 4" (in order by index).  The user selects
+ * "Tab 1" and then "Tab 3".  If the CTabFolder is now
+ * compressed so that only two tabs are visible, by default,
+ * "Tab 2" and "Tab 3" will be shown ("Tab 3" since it is currently
+ * selected and "Tab 2" because it is the previous item in index order).
+ * If MRU visibility is enabled, the two visible tabs will be "Tab 1"
+ * and "Tab 3" (in that order from left to right).</p>
+ *
+ * @param show the new visibility state
+ *
+ * @exception SWTException <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.1
+ */
+public void setMRUVisible(bool show) {
+    checkWidget();
+    if (mru is show) return;
+    mru = show;
+    if (!mru) {
+        int idx = firstIndex;
+        int next = 0;
+        for (int i = firstIndex; i < items.length; i++) {
+            priority[next++] = i;
+        }
+        for (int i = 0; i < idx; i++) {
+            priority[next++] = i;
+        }
+        if (updateItems()) redrawTabs();
+    }
+}
+/**
+ * Set the selection to the tab at the specified item.
+ *
+ * @param item the tab item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *    <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ * </ul>
+ */
+public void setSelection(CTabItem item) {
+    checkWidget();
+    if (item is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    int index = indexOf(item);
+    setSelection(index);
+}
+/**
+ * Set the selection to the tab at the specified index.
+ *
+ * @param index the index of the tab item to be selected
+ *
+ * @exception SWTException <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 setSelection(int index) {
+    checkWidget();
+    if (index < 0 || index >= items.length) return;
+    CTabItem selection = items[index];
+    if (selectedIndex is index) {
+        showItem(selection);
+        return;
+    }
+
+    int oldIndex = selectedIndex;
+    selectedIndex = index;
+    if (oldIndex !is -1) {
+        items[oldIndex].closeImageState = NONE;
+    }
+    selection.closeImageState = NORMAL;
+    selection.showing = false;
+
+    Control newControl = selection.control;
+    Control oldControl = null;
+    if (oldIndex !is -1) {
+        oldControl = items[oldIndex].control;
+    }
+
+    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);
+    redraw();
+}
+void setSelection(int index, bool notify) {
+    int oldSelectedIndex = selectedIndex;
+    setSelection(index);
+    if (notify && selectedIndex !is oldSelectedIndex && selectedIndex !is -1) {
+        Event event = new Event();
+        event.item = getItem(selectedIndex);
+        notifyListeners(SWT.Selection, event);
+    }
+}
+/**
+ * Sets the receiver's selection background color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setSelectionBackground (Color color) {
+    checkWidget();
+    setSelectionHighlightGradientColor(null);
+    if (selectionBackground is color) return;
+    if (color is null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
+    selectionBackground = color;
+    if (selectedIndex > -1) redraw();
+}
+/**
+ * Specify a gradient of colours to be draw in the background of the selected tab.
+ * For example to draw a gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ *  cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                     new int[] {25, 50, 100});
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance left to right.  The value <code>null</code> clears the
+ *               background gradient. The value <code>null</code> can be used inside the array of
+ *               Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ *                 of the widget at which the color should change.  The size of the percents array must be one
+ *                 less than the size of the colors array.
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public void setSelectionBackground(Color[] colors, int[] percents) {
+    setSelectionBackground(colors, percents, false);
+}
+/**
+ * Specify a gradient of colours to be draw in the background of the selected tab.
+ * For example to draw a vertical gradient that varies from dark blue to blue and then to
+ * white, use the following call to setBackground:
+ * <pre>
+ *  cfolder.setBackground(new Color[]{display.getSystemColor(SWT.COLOR_DARK_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_BLUE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE),
+ *                                 display.getSystemColor(SWT.COLOR_WHITE)},
+ *                        new int[] {25, 50, 100}, true);
+ * </pre>
+ *
+ * @param colors an array of Color that specifies the colors to appear in the gradient
+ *               in order of appearance left to right.  The value <code>null</code> clears the
+ *               background gradient. The value <code>null</code> can be used inside the array of
+ *               Color to specify the background color.
+ * @param percents an array of integers between 0 and 100 specifying the percent of the width
+ *                 of the widget at which the color should change.  The size of the percents array must be one
+ *                 less than the size of the colors array.
+ *
+ * @param vertical indicate the direction of the gradient.  True is vertical and false is horizontal.
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ *
+ * @since 3.0
+ */
+public void setSelectionBackground(Color[] colors, int[] percents, bool vertical) {
+    checkWidget();
+    int colorsLength;
+    Color highlightBeginColor = null;  //null is no highlight
+
+    if (colors !is null) {
+        //The colors array can optionally have an extra entry which describes the highlight top color
+        //Thus its either one or two larger than the percents array
+        if (percents is null ||
+                ! ((percents.length is colors.length - 1) || (percents.length is colors.length - 2))){
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        for (int i = 0; i < percents.length; i++) {
+            if (percents[i] < 0 || percents[i] > 100) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            if (i > 0 && percents[i] < percents[i-1]) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+        }
+        //If the colors is exactly two more than percents then last is highlight
+        //Keep track of *real* colorsLength (minus the highlight)
+        if(percents.length is colors.length - 2) {
+            highlightBeginColor = colors[colors.length - 1];
+            colorsLength = colors.length - 1;
+        } else {
+            colorsLength = colors.length;
+        }
+        if (getDisplay().getDepth() < 15) {
+            // Don't use gradients on low color displays
+            colors = [colors[colorsLength - 1]];
+            colorsLength = colors.length;
+            percents = null;
+        }
+    } else {
+        colorsLength = 0;
+    }
+
+    // Are these settings the same as before?
+    if (selectionBgImage is null) {
+        if ((selectionGradientColors !is null) && (colors !is null) &&
+            (selectionGradientColors.length is colorsLength)) {
+            bool same = false;
+            for (int i = 0; i < selectionGradientColors.length; i++) {
+                if (selectionGradientColors[i] is null) {
+                    same = colors[i] is null;
+                } else {
+                    same = cast(bool)(selectionGradientColors[i]==colors[i]);
+                }
+                if (!same) break;
+            }
+            if (same) {
+                for (int i = 0; i < selectionGradientPercents.length; i++) {
+                    same = selectionGradientPercents[i] is percents[i];
+                    if (!same) break;
+                }
+            }
+            if (same && this.selectionGradientVertical is vertical) return;
+        }
+    } else {
+        selectionBgImage = null;
+    }
+    // Store the new settings
+    if (colors is null) {
+        selectionGradientColors = null;
+        selectionGradientPercents = null;
+        selectionGradientVertical = false;
+        setSelectionBackground(cast(Color)null);
+        setSelectionHighlightGradientColor(null);
+    } else {
+        selectionGradientColors = new Color[colorsLength];
+        for (int i = 0; i < colorsLength; ++i) {
+            selectionGradientColors[i] = colors[i];
+        }
+        selectionGradientPercents = new int[percents.length];
+        for (int i = 0; i < percents.length; ++i) {
+            selectionGradientPercents[i] = percents[i];
+        }
+        selectionGradientVertical = vertical;
+        setSelectionBackground(selectionGradientColors[selectionGradientColors.length-1]);
+        setSelectionHighlightGradientColor(highlightBeginColor);
+    }
+
+    // Refresh with the new settings
+    if (selectedIndex > -1) redraw();
+}
+
+/*
+ * Set the color for the highlight start for selected tabs.
+ * Update the cache of highlight gradient colors if required.
+ */
+
+void setSelectionHighlightGradientColor(Color start) {
+    //Set to null to match all the early return cases.
+    //For early returns, don't realloc the cache, we may get a cache hit next time we're given the highlight
+    selectionHighlightGradientBegin = null;
+
+    if(start is null)
+        return;
+
+    //don't bother on low colour
+    if (getDisplay().getDepth() < 15)
+        return;
+
+    //don't bother if we don't have a background gradient
+    if(selectionGradientColors.length < 2)
+        return;
+
+    //OK we know its a valid gradient now
+    selectionHighlightGradientBegin = start;
+
+    if(! isSelectionHighlightColorsCacheHit(start))
+        createSelectionHighlightGradientColors(start);  //if no cache hit then compute new ones
+}
+
+/*
+ * Return true if given start color, the cache of highlight colors we have
+ * would match the highlight colors we'd compute.
+ */
+bool isSelectionHighlightColorsCacheHit(Color start) {
+
+    if(selectionHighlightGradientColorsCache is null)
+        return false;
+
+    //this case should never happen but check to be safe before accessing array indexes
+    if(selectionHighlightGradientColorsCache.length < 2)
+        return false;
+
+    Color highlightBegin = selectionHighlightGradientColorsCache[0];
+    Color highlightEnd = selectionHighlightGradientColorsCache[selectionHighlightGradientColorsCache.length - 1];
+
+    if( highlightBegin!=start)
+        return false;
+
+    //Compare number of colours we have vs. we'd compute
+    if(selectionHighlightGradientColorsCache.length !is tabHeight)
+        return false;
+
+    //Compare existing highlight end to what it would be (selectionBackground)
+    if( highlightEnd!=selectionBackground)
+        return false;
+
+    return true;
+}
+
+/**
+ * Set the image to be drawn in the background of the selected tab.  Image
+ * is stretched or compressed to cover entire selection tab area.
+ *
+ * @param image the image to be drawn in the background
+ *
+ * @exception SWTException <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 setSelectionBackground(Image image) {
+    checkWidget();
+    setSelectionHighlightGradientColor(null);
+    if (image is selectionBgImage) return;
+    if (image !is null) {
+        selectionGradientColors = null;
+        selectionGradientPercents = null;
+        disposeSelectionHighlightGradientColors();
+    }
+    selectionBgImage = image;
+    if (selectedIndex > -1) redraw();
+}
+/**
+ * Set the foreground color of the selected tab.
+ *
+ * @param color the color of the text displayed in the selected tab
+ *
+ * @exception SWTException <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 setSelectionForeground (Color color) {
+    checkWidget();
+    if (selectionForeground is color) return;
+    if (color is null) color = getDisplay().getSystemColor(SELECTION_FOREGROUND);
+    selectionForeground = color;
+    if (selectedIndex > -1) redraw();
+}
+
+/*
+ * Allocate colors for the highlight line.
+ * Colours will be a gradual blend ranging from to.
+ * Blend length will be tab height.
+ * Recompute this if tab height changes.
+ * Could remain null if there'd be no gradient (start=end or low colour display)
+ */
+void createSelectionHighlightGradientColors(Color start) {
+    disposeSelectionHighlightGradientColors(); //dispose if existing
+
+    if(start is null)  //shouldn't happen but just to be safe
+        return;
+
+    //alloc colours for entire height to ensure it matches wherever we stop drawing
+    int fadeGradientSize = tabHeight;
+
+    RGB from = start.getRGB();
+    RGB to = selectionBackground.getRGB();
+
+    selectionHighlightGradientColorsCache = new Color[fadeGradientSize];
+    int denom = fadeGradientSize - 1;
+
+    for (int i = 0; i < fadeGradientSize; i++) {
+        int propFrom = denom - i;
+        int propTo = i;
+        int red = (to.red * propTo + from.red * propFrom) / denom;
+        int green = (to.green * propTo  + from.green * propFrom) / denom;
+        int blue = (to.blue * propTo  + from.blue * propFrom) / denom;
+        selectionHighlightGradientColorsCache[i] = new Color(getDisplay(), red, green, blue);
+    }
+}
+
+void disposeSelectionHighlightGradientColors() {
+    if(selectionHighlightGradientColorsCache is null)
+        return;
+    for (int i = 0; i < selectionHighlightGradientColorsCache.length; i++) {
+        selectionHighlightGradientColorsCache[i].dispose();
+    }
+    selectionHighlightGradientColorsCache = null;
+}
+
+/*
+ * Return the gradient start color for selected tabs, which is the start of the tab fade
+ * (end is selectionBackground).
+ */
+Color getSelectionBackgroundGradientBegin() {
+    if (selectionGradientColors is null)
+        return getSelectionBackground();
+    if (selectionGradientColors.length is 0)
+        return getSelectionBackground();
+    return selectionGradientColors[0];
+}
+
+/**
+ * Sets the shape that the CTabFolder will use to render itself.
+ *
+ * @param simple <code>true</code> if the CTabFolder should render itself in a simple, traditional style
+ *
+ * @exception SWTException <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.0
+ */
+public void setSimple(bool simple) {
+    checkWidget();
+    if (this.simple !is simple) {
+        this.simple = simple;
+        Rectangle rectBefore = getClientArea();
+        updateItems();
+        Rectangle rectAfter = getClientArea();
+        if (rectBefore!=rectAfter) {
+            notifyListeners(SWT.Resize, new Event());
+        }
+        redraw();
+    }
+}
+/**
+ * Sets the number of tabs that the CTabFolder should display
+ *
+ * @param single <code>true</code> if only the selected tab should be displayed otherwise, multiple tabs will be shown.
+ *
+ * @exception SWTException <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.0
+ */
+public void setSingle(bool single) {
+    checkWidget();
+    if (this.single !is single) {
+        this.single = single;
+        if (!single) {
+            for (int i = 0; i < items.length; i++) {
+                if (i !is selectedIndex && items[i].closeImageState is NORMAL) {
+                    items[i].closeImageState = NONE;
+                }
+            }
+        }
+        Rectangle rectBefore = getClientArea();
+        updateItems();
+        Rectangle rectAfter = getClientArea();
+        if (rectBefore!=rectAfter) {
+            notifyListeners(SWT.Resize, new Event());
+        }
+        redraw();
+    }
+}
+/**
+ * Specify a fixed height for the tab items.  If no height is specified,
+ * the default height is the height of the text or the image, whichever
+ * is greater. Specifying a height of -1 will revert to the default height.
+ *
+ * @param height the pixel value of the height or -1
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if called with a height of less than 0</li>
+ * </ul>
+ */
+public void setTabHeight(int height) {
+    checkWidget();
+    if (height < -1) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    fixedTabHeight = height;
+    updateTabHeight(false);
+}
+/**
+ * Specify whether the tabs should appear along the top of the folder
+ * or along the bottom of the folder.
+ *
+ * @param position <code>SWT.TOP</code> for tabs along the top or <code>SWT.BOTTOM</code> for tabs along the bottom
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the position value is not either SWT.TOP or SWT.BOTTOM</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setTabPosition(int position) {
+    checkWidget();
+    if (position !is SWT.TOP && position !is SWT.BOTTOM) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (onBottom !is (position is SWT.BOTTOM)) {
+        onBottom = position is SWT.BOTTOM;
+        borderTop = onBottom ? borderLeft : 0;
+        borderBottom = onBottom ? 0 : borderRight;
+        updateTabHeight(true);
+        Rectangle rectBefore = getClientArea();
+        updateItems();
+        Rectangle rectAfter = getClientArea();
+        if (rectBefore!=rectAfter) {
+            notifyListeners(SWT.Resize, new Event());
+        }
+        redraw();
+    }
+}
+/**
+ * Set the control that appears in the top right corner of the tab folder.
+ * Typically this is a close button or a composite with a Menu and close button.
+ * The topRight control is optional.  Setting the top right control to null will
+ * remove it from the tab folder.
+ *
+ * @param control the control to be displayed in the top right corner or null
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this CTabFolder</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setTopRight(Control control) {
+    setTopRight(control, SWT.RIGHT);
+}
+/**
+ * Set the control that appears in the top right corner of the tab folder.
+ * Typically this is a close button or a composite with a Menu and close button.
+ * The topRight control is optional.  Setting the top right control to null
+ * will remove it from the tab folder.
+ * <p>
+ * The alignment parameter sets the layout of the control in the tab area.
+ * <code>SWT.RIGHT</code> will cause the control to be positioned on the far
+ * right of the folder and it will have its default size.  <code>SWT.FILL</code>
+ * will size the control to fill all the available space to the right of the
+ * last tab.  If there is no available space, the control will not be visible.
+ * </p>
+ *
+ * @param control the control to be displayed in the top right corner or null
+ * @param alignment <code>SWT.RIGHT</code> or <code>SWT.FILL</code>
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this CTabFolder</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void setTopRight(Control control, int alignment) {
+    checkWidget();
+    if (alignment !is SWT.RIGHT && alignment !is SWT.FILL) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (control !is null && control.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    topRight = control;
+    topRightAlignment = alignment;
+    if (updateItems()) redraw();
+}
+/**
+ * Specify whether the close button appears
+ * when the user hovers over an unselected tabs.
+ *
+ * @param visible <code>true</code> makes the close button appear
+ *
+ * @exception SWTException <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.0
+ */
+public void setUnselectedCloseVisible(bool visible) {
+    checkWidget();
+    if (showUnselectedClose is visible) return;
+    // display close button when mouse hovers
+    showUnselectedClose = visible;
+    updateItems();
+    redraw();
+}
+/**
+ * Specify whether the image appears on unselected tabs.
+ *
+ * @param visible <code>true</code> makes the image appear
+ *
+ * @exception SWTException <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.0
+ */
+public void setUnselectedImageVisible(bool visible) {
+    checkWidget();
+    if (showUnselectedImage is visible) return;
+    // display image on unselected items
+    showUnselectedImage = visible;
+    updateItems();
+    redraw();
+}
+/**
+ * Shows the item.  If the item is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @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 SWTException <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 CTabFolder#showSelection()
+ *
+ * @since 2.0
+ */
+public void showItem (CTabItem item) {
+    checkWidget();
+    if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int index = indexOf(item);
+    if (index is -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int idx = -1;
+    for (int i = 0; i < priority.length; i++) {
+        if (priority[i] is index) {
+            idx = i;
+            break;
+        }
+    }
+    if (mru) {
+        // move to front of mru order
+        int[] newPriority = new int[priority.length];
+        System.arraycopy(priority, 0, newPriority, 1, idx);
+        System.arraycopy(priority, idx+1, newPriority, idx+1, priority.length - idx - 1);
+        newPriority[0] = index;
+        priority = newPriority;
+    }
+    if (item.isShowing()) return;
+    updateItems(index);
+    redrawTabs();
+}
+void showList (Rectangle rect) {
+    if (items.length is 0 || !showChevron) return;
+    if (showMenu is null || showMenu.isDisposed()) {
+        showMenu = new Menu(this);
+    } else {
+        MenuItem[] items = showMenu.getItems();
+        for (int i = 0; i < items.length; i++) {
+            items[i].dispose();
+        }
+    }
+    static const String id = "CTabFolder_showList_Index"; //$NON-NLS-1$
+    for (int i = 0; i < items.length; i++) {
+        CTabItem tab = items[i];
+        if (tab.showing) continue;
+        MenuItem item = new MenuItem(showMenu, SWT.NONE);
+        item.setText(tab.getText());
+        item.setImage(tab.getImage());
+        item.setData(id, tab);
+        item.addSelectionListener(new class() SelectionAdapter {
+            public void widgetSelected(SelectionEvent e) {
+                MenuItem menuItem = cast(MenuItem)e.widget;
+                int index = indexOf(cast(CTabItem)menuItem.getData(id));
+                this.outer.setSelection(index, true);
+            }
+        });
+    }
+    int x = rect.x;
+    int y = rect.y + rect.height;
+    Point location = getDisplay().map(this, null, x, y);
+    showMenu.setLocation(location.x, location.y);
+    showMenu.setVisible(true);
+}
+/**
+ * Shows the selection.  If the selection is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException <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 CTabFolder#showItem(CTabItem)
+ *
+ * @since 2.0
+ */
+public void showSelection () {
+    checkWidget ();
+    if (selectedIndex !is -1) {
+        showItem(getSelection());
+    }
+}
+
+void _setToolTipText (int x, int y) {
+    String oldTip = getToolTipText();
+    String newTip = _getToolTip(x, y);
+    if (newTip is null || newTip!=oldTip) {
+        setToolTipText(newTip);
+    }
+}
+
+bool updateItems() {
+    return updateItems(selectedIndex);
+}
+
+bool updateItems(int showIndex) {
+    if (!single && !mru && showIndex !is -1) {
+        // make sure selected item will be showing
+        int firstIndex = showIndex;
+        if (priority[0] < showIndex) {
+            int maxWidth = getRightItemEdge() - borderLeft;
+            if (!simple) maxWidth -= curveWidth - 2*curveIndent;
+            int width = 0;
+            int[] widths = new int[items.length];
+            GC gc = new GC(this);
+            for (int i = priority[0]; i <= showIndex; i++) {
+                widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true);
+                width += widths[i];
+                if (width > maxWidth) break;
+            }
+            if (width > maxWidth) {
+                width = 0;
+                for (int i = showIndex; i >= 0; i--) {
+                    if (widths[i] is 0) widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true);
+                    width += widths[i];
+                    if (width > maxWidth) break;
+                    firstIndex = i;
+                }
+            } else {
+                firstIndex = priority[0];
+                for (int i = showIndex + 1; i < items.length; i++) {
+                    widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true);
+                    width += widths[i];
+                    if (width >= maxWidth) break;
+                }
+                if (width < maxWidth) {
+                    for (int i = priority[0] - 1; i >= 0; i--) {
+                        if (widths[i] is 0) widths[i] = items[i].preferredWidth(gc, i is selectedIndex, true);
+                        width += widths[i];
+                        if (width > maxWidth) break;
+                        firstIndex = i;
+                    }
+                }
+            }
+            gc.dispose();
+        }
+        if (firstIndex !is priority[0]) {
+            int index = 0;
+            for (int i = firstIndex; i < items.length; i++) {
+                priority[index++] = i;
+            }
+            for (int i = 0; i < firstIndex; i++) {
+                priority[index++] = i;
+            }
+        }
+    }
+
+    bool oldShowChevron = showChevron;
+    bool changed = setItemSize();
+    changed |= setItemLocation();
+    setButtonBounds();
+    changed |= showChevron !is oldShowChevron;
+    if (changed && getToolTipText() !is null) {
+        Point pt = getDisplay().getCursorLocation();
+        pt = toControl(pt);
+        _setToolTipText(pt.x, pt.y);
+    }
+    return changed;
+}
+bool updateTabHeight(bool force){
+    int style = getStyle();
+    if (fixedTabHeight is 0 && (style & SWT.FLAT) !is 0 && (style & SWT.BORDER) is 0) highlight_header = 0;
+    int oldHeight = tabHeight;
+    if (fixedTabHeight !is SWT.DEFAULT) {
+        tabHeight = fixedTabHeight is 0 ? 0 : fixedTabHeight + 1; // +1 for line drawn across top of tab
+    } else {
+        int tempHeight = 0;
+        GC gc = new GC(this);
+        if (items.length is 0) {
+            tempHeight = gc.textExtent("Default", CTabItem.FLAGS).y + CTabItem.TOP_MARGIN + CTabItem.BOTTOM_MARGIN; //$NON-NLS-1$
+        } else {
+            for (int i=0; i < items.length; i++) {
+                tempHeight = Math.max(tempHeight, items[i].preferredHeight(gc));
+            }
+        }
+        gc.dispose();
+        tabHeight =  tempHeight;
+    }
+    if (!force && tabHeight is oldHeight) return false;
+
+    oldSize = null;
+    if (onBottom) {
+        int d = tabHeight - 12;
+        curve = [0,13+d, 0,12+d, 2,12+d, 3,11+d, 5,11+d, 6,10+d, 7,10+d, 9,8+d, 10,8+d,
+                          11,7+d, 11+d,7,
+                          12+d,6, 13+d,6, 15+d,4, 16+d,4, 17+d,3, 19+d,3, 20+d,2, 22+d,2, 23+d,1];
+        curveWidth = 26+d;
+        curveIndent = curveWidth/3;
+    } else {
+        int d = tabHeight - 12;
+        curve = [0,0, 0,1, 2,1, 3,2, 5,2, 6,3, 7,3, 9,5, 10,5,
+                          11,6, 11+d,6+d,
+                          12+d,7+d, 13+d,7+d, 15+d,9+d, 16+d,9+d, 17+d,10+d, 19+d,10+d, 20+d,11+d, 22+d,11+d, 23+d,12+d];
+        curveWidth = 26+d;
+        curveIndent = curveWidth/3;
+
+        //this could be static but since values depend on curve, better to keep in one place
+        topCurveHighlightStart = [
+                0, 2,  1, 2,  2, 2,
+                3, 3,  4, 3,  5, 3,
+                6, 4,  7, 4,
+                8, 5,
+                9, 6, 10, 6];
+
+        //also, by adding in 'd' here we save some math cost when drawing the curve
+        topCurveHighlightEnd = [
+                10+d, 6+d,
+                11+d, 7+d,
+                12+d, 8+d,  13+d, 8+d,
+                14+d, 9+d,
+                15+d, 10+d,  16+d, 10+d,
+                17+d, 11+d,  18+d, 11+d,  19+d, 11+d,
+                20+d, 12+d,  21+d, 12+d,  22+d,  12+d ];
+    }
+    notifyListeners(SWT.Resize, new Event());
+    return true;
+}
+String _getToolTip(int x, int y) {
+    if (showMin && minRect.contains(x, y)) return minimized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Minimize"); //$NON-NLS-1$ //$NON-NLS-2$
+    if (showMax && maxRect.contains(x, y)) return maximized ? SWT.getMessage("SWT_Restore") : SWT.getMessage("SWT_Maximize"); //$NON-NLS-1$ //$NON-NLS-2$
+    if (showChevron && chevronRect.contains(x, y)) return SWT.getMessage("SWT_ShowList"); //$NON-NLS-1$
+    CTabItem item = getItem(new Point (x, y));
+    if (item is null) return null;
+    if (!item.showing) return null;
+    if ((showClose || item.showClose) && item.closeRect.contains(x, y)) {
+        return SWT.getMessage("SWT_Close"); //$NON-NLS-1$
+    }
+    return item.getToolTipText();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Adapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolder2Adapter;
+import org.eclipse.swt.custom.CTabFolder2Listener;
+import org.eclipse.swt.custom.CTabFolderEvent;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>CTabFolder2Listener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>CTabFolderEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see CTabFolder2Listener
+ * @see CTabFolderEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class CTabFolder2Adapter : CTabFolder2Listener {
+
+/**
+ * Sent when the user clicks on the close button of an item in the CTabFolder.  The item being closed is specified
+ * in the event.item field. Setting the event.doit field to false will stop  the CTabItem from closing.
+ * When the CTabItem is closed, it is disposed.  The contents of the CTabItem (see CTabItem#setControl) will be
+ * made not visible when the CTabItem is closed.
+ * <p>
+ * The default behaviour is to close the CTabItem.
+ * </p>
+ *
+ * @param event an event indicating the item being closed
+ */
+public void close(CTabFolderEvent event){}
+
+/**
+ * Sent when the user clicks on the minimize button of a CTabFolder.
+ * <p>
+ * The default behaviour is to do nothing.
+ * </p>
+ *
+ * @param event an event containing information about the minimize
+ */
+public void minimize(CTabFolderEvent event){}
+
+/**
+ * Sent when the user clicks on the maximize button of a CTabFolder.
+ * <p>
+ * The default behaviour is to do nothing.
+ * </p>
+ *
+ * @param event an event containing information about the maximize
+ */
+public void maximize(CTabFolderEvent event){}
+
+/**
+ * Sent when the user clicks on the restore button of a CTabFolder.
+ * <p>
+ * The default behaviour is to do nothing.
+ * </p>
+ *
+ * @param event an event containing information about the restore
+ */
+public void restore(CTabFolderEvent event){}
+
+/**
+ * Sent when the user clicks on the chevron button of a CTabFolder.
+ * <p>
+ * The default behaviour is to show a list of items that are not currently
+ * visible and to change the selection based on the item selected from the list.
+ * </p>
+ *
+ * @param event an event containing information about the show list
+ */
+public void showList(CTabFolderEvent event){}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolder2Listener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolder2Listener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.CTabFolderEvent;
+
+import tango.core.Traits;
+import tango.core.Tuple;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated by the CTabFolder
+ * control.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a CTabFolder using the
+ * <code>addCTabFolder2Listener</code> method and removed using
+ * the <code>removeCTabFolder2Listener</code> method. When
+ * events occurs in a CTabFolder the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see CTabFolder2Adapter
+ * @see CTabFolderEvent
+ *
+ * @since 3.0
+ */
+public interface CTabFolder2Listener : SWTEventListener {
+    public enum {
+        MINIMIZE,
+        MAXIMIZE,
+        SHOWLIST,
+        RESTORE,
+        CLOSE
+    }
+
+/**
+ * Sent when the user clicks on the close button of an item in the CTabFolder.
+ * The item being closed is specified in the event.item field.
+ * Setting the event.doit field to false will stop the CTabItem from closing.
+ * When the CTabItem is closed, it is disposed.  The contents of the
+ * CTabItem (see CTabItem.setControl) will be made not visible when
+ * the CTabItem is closed.
+ *
+ * @param event an event indicating the item being closed
+ */
+public void close(CTabFolderEvent event);
+
+/**
+ * Sent when the user clicks on the minimize button of a CTabFolder.
+ * The state of the CTabFolder does not change automatically - it
+ * is up to the application to change the state of the CTabFolder
+ * in response to this event using CTabFolder.setMinimized(true).
+ *
+ * @param event an event containing information about the minimize
+ *
+ * @see CTabFolder#getMinimized()
+ * @see CTabFolder#setMinimized(bool)
+ * @see CTabFolder#setMinimizeVisible(bool)
+ */
+public void minimize(CTabFolderEvent event);
+
+/**
+ * Sent when the user clicks on the maximize button of a CTabFolder.
+ * The state of the CTabFolder does not change automatically - it
+ * is up to the application to change the state of the CTabFolder
+ * in response to this event using CTabFolder.setMaximized(true).
+ *
+ * @param event an event containing information about the maximize
+ *
+ * @see CTabFolder#getMaximized()
+ * @see CTabFolder#setMaximized(bool)
+ * @see CTabFolder#setMaximizeVisible(bool)
+ */
+public void maximize(CTabFolderEvent event);
+
+/**
+ * Sent when the user clicks on the restore button of a CTabFolder.
+ * This event is sent either to restore the CTabFolder from the
+ * minimized state or from the maximized state.  To determine
+ * which restore is requested, use CTabFolder.getMinimized() or
+ * CTabFolder.getMaximized() to determine the current state.
+ * The state of the CTabFolder does not change automatically - it
+ * is up to the application to change the state of the CTabFolder
+ * in response to this event using CTabFolder.setMaximized(false)
+ * or CTabFolder.setMinimized(false).
+ *
+ * @param event an event containing information about the restore
+ *
+ * @see CTabFolder#getMinimized()
+ * @see CTabFolder#getMaximized()
+ * @see CTabFolder#setMinimized(bool)
+ * @see CTabFolder#setMinimizeVisible(bool)
+ * @see CTabFolder#setMaximized(bool)
+ * @see CTabFolder#setMaximizeVisible(bool)
+ */
+public void restore(CTabFolderEvent event);
+
+/**
+ * Sent when the user clicks on the chevron button of the CTabFolder.
+ * A chevron appears in the CTabFolder when there are more tabs
+ * than can be displayed at the current widget size.  To select a
+ * tab that is not currently visible, the user clicks on the
+ * chevron and selects a tab item from a list.  By default, the
+ * CTabFolder provides a list of all the items that are not currently
+ * visible, however, the application can provide its own list by setting
+ * the event.doit field to <code>false</code> and displaying a selection list.
+ *
+ * @param event an event containing information about the show list
+ *
+ * @see CTabFolder#setSelection(CTabItem)
+ */
+public void showList(CTabFolderEvent event);
+}
+
+
+
+/// Helper class for the dgListener template function
+private class _DgCTabFolder2ListenerT(Dg,T...) : CTabFolder2Listener {
+
+    alias ParameterTupleOf!(Dg) DgArgs;
+    static assert( is(DgArgs == Tuple!(CTabFolderEvent,T)),
+                "Delegate args not correct: "~DgArgs.stringof~" vs. (Event,"~T.stringof~")" );
+
+    Dg dg;
+    T  t;
+    int type;
+
+    private this( int type, Dg dg, T t ){
+        this.type = type;
+        this.dg = dg;
+        static if( T.length > 0 ){
+            this.t = t;
+        }
+    }
+
+    void itemClosed( CTabFolderEvent e ){
+        dg(e,t);
+    }
+    public void close(CTabFolderEvent e){
+        if( type is CTabFolder2Listener.CLOSE ){
+            dg(e,t);
+        }
+    }
+    public void minimize(CTabFolderEvent e){
+        if( type is CTabFolder2Listener.MINIMIZE ){
+            dg(e,t);
+        }
+    }
+    public void maximize(CTabFolderEvent e){
+        if( type is CTabFolder2Listener.MAXIMIZE ){
+            dg(e,t);
+        }
+    }
+    public void restore(CTabFolderEvent e){
+        if( type is CTabFolder2Listener.RESTORE ){
+            dg(e,t);
+        }
+    }
+    public void showList(CTabFolderEvent e){
+        if( type is CTabFolder2Listener.SHOWLIST ){
+            dg(e,t);
+        }
+    }
+}
+
+/++
+ + dgListener creates a class implementing the Listener interface and delegating the call to
+ + handleEvent to the users delegate. This template function will store also additional parameters.
+ +
+ + Examle of usage:
+ + ---
+ + void handleTextEvent ( Event e, int inset ) {
+ +     // ...
+ + }
+ + text.addListener (SWT.FocusOut, dgListener( &handleTextEvent, inset ));
+ + ---
+ +/
+CTabFolder2Listener dgCTabFolder2Listener( Dg, T... )( int type, Dg dg, T args ){
+    return new _DgCTabFolder2ListenerT!( Dg, T )( type, dg, args );
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolderAdapter;
+import org.eclipse.swt.custom.CTabFolderEvent;
+import org.eclipse.swt.custom.CTabFolderListener;
+
+
+/**
+ * This adapter class provides a default implementation for the
+ * method described by the <code>CTabFolderListener</code> interface.
+ * 
+ * @see CTabFolderListener
+ * @see CTabFolderEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class CTabFolderAdapter : CTabFolderListener {
+    public void itemClosed(CTabFolderEvent event){}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolderEvent;
+
+import java.lang.all;
+
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.widgets.Widget;
+
+import tango.util.Convert;
+
+/**
+ * This event is sent when an event is generated in the CTabFolder.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 
+ */
+public class CTabFolderEvent : TypedEvent {
+    /**
+     * The tab item for the operation.
+     */
+    public Widget item;
+
+    /**
+     * A flag indicating whether the operation should be allowed.
+     * Setting this field to <code>false</code> will cancel the operation.
+     * Applies to the close and showList events.
+     */
+    public bool doit;
+
+    /**
+     * The widget-relative, x coordinate of the chevron button
+     * at the time of the event.  Applies to the showList event.
+     *
+     * @since 3.0
+     */
+    public int x;
+    /**
+     * The widget-relative, y coordinate of the chevron button
+     * at the time of the event.  Applies to the showList event.
+     *
+     * @since 3.0
+     */
+    public int y;
+    /**
+     * The width of the chevron button at the time of the event.
+     * Applies to the showList event.
+     *
+     * @since 3.0
+     */
+    public int width;
+    /**
+     * The height of the chevron button at the time of the event.
+     * Applies to the showList event.
+     *
+     * @since 3.0
+     */
+    public int height;
+
+    static final long serialVersionUID = 3760566386225066807L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param w the widget that fired the event
+ */
+this(Widget w) {
+    super(w);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    String string = super.toString ();
+    return string[0.. $ - 1] // remove trailing '}'
+        ~ " item=" ~ to!(String)(item)
+        ~ " doit=" ~ to!(String)(doit)
+        ~ " x=" ~ to!(String)(x)
+        ~ " y=" ~ to!(String)(y)
+        ~ " width=" ~ to!(String)(width)
+        ~ " height=" ~ to!(String)(height)
+        ~ "}";
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolderLayout;
+
+import java.lang.all;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+
+/**
+ * This class provides the layout for CTabFolder
+ *
+ * @see CTabFolder
+ */
+class CTabFolderLayout : Layout {
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    CTabFolder folder = cast(CTabFolder)composite;
+    CTabItem[] items = folder.items;
+    // preferred width of tab area to show all tabs
+    int tabW = 0;
+    GC gc = new GC(folder);
+    for (int i = 0; i < items.length; i++) {
+        if (folder.single) {
+            tabW = Math.max(tabW, items[i].preferredWidth(gc, true, false));
+        } else {
+            tabW += items[i].preferredWidth(gc, i is folder.selectedIndex, false);
+        }
+    }
+    gc.dispose();
+    tabW += 3;
+    if (folder.showMax) tabW += CTabFolder.BUTTON_SIZE;
+    if (folder.showMin) tabW += CTabFolder.BUTTON_SIZE;
+    if (folder.single) tabW += 3*CTabFolder.BUTTON_SIZE/2; //chevron
+    if (folder.topRight !is null) {
+        Point pt = folder.topRight.computeSize(SWT.DEFAULT, folder.tabHeight, flushCache);
+        tabW += 3 + pt.x;
+    }
+    if (!folder.single && !folder.simple) tabW += folder.curveWidth - 2*folder.curveIndent;
+
+    int controlW = 0;
+    int controlH = 0;
+    // preferred size of controls in tab items
+    for (int i = 0; i < items.length; i++) {
+        Control control = items[i].getControl();
+        if (control !is null && !control.isDisposed()){
+            Point size = control.computeSize (wHint, hHint, flushCache);
+            controlW = Math.max (controlW, size.x);
+            controlH = Math.max (controlH, size.y);
+        }
+    }
+
+    int minWidth = Math.max(tabW, controlW);
+    int minHeight = (folder.minimized) ? 0 : controlH;
+    if (minWidth is 0) minWidth = CTabFolder.DEFAULT_WIDTH;
+    if (minHeight is 0) minHeight = CTabFolder.DEFAULT_HEIGHT;
+
+    if (wHint !is SWT.DEFAULT) minWidth  = wHint;
+    if (hHint !is SWT.DEFAULT) minHeight = hHint;
+
+    return new Point (minWidth, minHeight);
+}
+protected override bool flushCache(Control control) {
+    return true;
+}
+protected override void layout(Composite composite, bool flushCache) {
+    CTabFolder folder = cast(CTabFolder)composite;
+    // resize content
+    if (folder.selectedIndex !is -1) {
+        Control control = folder.items[folder.selectedIndex].getControl();
+        if (control !is null && !control.isDisposed()) {
+            control.setBounds(folder.getClientArea());
+        }
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabFolderListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabFolderListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.CTabFolderEvent;
+
+import tango.core.Traits;
+import tango.core.Tuple;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with events generated in the CTabFolder.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a CTabFolder using the
+ * <code>addCTabFolderListener</code> method and removed using
+ * the <code>removeCTabFolderListener</code> method. When a
+ * tab item is closed, the itemClosed method will be invoked.
+ * </p>
+ *
+ * @see CTabFolderEvent
+ */
+public interface CTabFolderListener : SWTEventListener {
+
+/**
+ * Sent when the user clicks on the close button of an item in the CTabFolder.  The item being closed is specified
+ * in the event.item field. Setting the event.doit field to false will stop the CTabItem from closing.
+ * When the CTabItem is closed, it is disposed.  The contents of the CTabItem (see CTabItem.setControl) will be
+ * made not visible when the CTabItem is closed.
+ *
+ * @param event an event indicating the item being closed
+ *
+ * @see CTabItem#setControl
+ */
+public void itemClosed(CTabFolderEvent event);
+}
+
+
+
+/// Helper class for the dgListener template function
+private class _DgCTabFolderListenerT(Dg,T...) : CTabFolderListener {
+
+    alias ParameterTupleOf!(Dg) DgArgs;
+    static assert( is(DgArgs == Tuple!(CTabFolderEvent,T)),
+                "Delegate args not correct" );
+
+    Dg dg;
+    T  t;
+
+    private this( Dg dg, T t ){
+        this.dg = dg;
+        static if( T.length > 0 ){
+            this.t = t;
+        }
+    }
+
+    void itemClosed( CTabFolderEvent e ){
+        dg(e,t);
+    }
+}
+
+/++
+ + dgListener creates a class implementing the Listener interface and delegating the call to
+ + handleEvent to the users delegate. This template function will store also additional parameters.
+ +
+ + Examle of usage:
+ + ---
+ + void handleTextEvent (Event e, int inset ) {
+ +     // ...
+ + }
+ + text.addListener (SWT.FocusOut, dgListener( &handleTextEvent, inset ));
+ + ---
+ +/
+CTabFolderListener dgCTabFolderListener( Dg, T... )( Dg dg, T args ){
+    return new _DgCTabFolderListenerT!( Dg, T )( dg, args );
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/CTabItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1073 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.CTabItem;
+
+import java.lang.all;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.custom.CTabFolder;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represent a page in a notebook widget.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SWT.CLOSE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ctabfolder">CTabFolder, CTabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class CTabItem : Item {
+    CTabFolder parent;
+    int x,y,width,height = 0;
+    Control control; // the tab page
+
+    String toolTipText;
+    String shortenedText;
+    int shortenedTextWidth;
+
+    // Appearance
+    Font font;
+    Image disabledImage;
+
+    Rectangle closeRect;
+    int closeImageState = CTabFolder.NONE;
+    bool showClose = false;
+    bool showing = false;
+
+    // internal constants
+    static final int TOP_MARGIN = 2;
+    static final int BOTTOM_MARGIN = 2;
+    static final int LEFT_MARGIN = 4;
+    static final int RIGHT_MARGIN = 4;
+    static final int INTERNAL_SPACING = 4;
+    static final int FLAGS = SWT.DRAW_TRANSPARENT | SWT.DRAW_MNEMONIC;
+    static final String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026"
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CTabFolder</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a CTabFolder which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this (CTabFolder parent, int style) {
+    this(parent, style, parent.getItemCount());
+}
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CTabFolder</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a CTabFolder 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this (CTabFolder parent, int style, int index) {
+    closeRect = new Rectangle(0, 0, 0, 0);
+    super (parent, style);
+    showClose = (style & SWT.CLOSE) !is 0;
+    parent.createItem (this, index);
+}
+
+/*
+ * Return whether to use ellipses or just truncate labels
+ */
+bool useEllipses() {
+    return parent.simple;
+}
+
+String shortenText(GC gc, String text, int width) {
+    return useEllipses()
+        ? shortenText(gc, text, width, ELLIPSIS)
+        : shortenText(gc, text, width, ""); //$NON-NLS-1$
+}
+
+String shortenText(GC gc, String text, int width, String ellipses) {
+    if (gc.textExtent(text, FLAGS).x <= width) return text;
+    int ellipseWidth = gc.textExtent(ellipses, FLAGS).x;
+    int length = text.length;
+    TextLayout layout = new TextLayout(getDisplay());
+    layout.setText(text);
+    int end = layout.getPreviousOffset(length, SWT.MOVEMENT_CLUSTER);
+    while (end > 0) {
+        text = text[ 0 .. end ];
+        int l = gc.textExtent(text, FLAGS).x;
+        if (l + ellipseWidth <= width) {
+            break;
+        }
+        end = layout.getPreviousOffset(end, SWT.MOVEMENT_CLUSTER);
+    }
+    layout.dispose();
+    return end is 0 ? text.substring(0, 1) : text ~ ellipses;
+}
+
+public override void dispose() {
+    if (isDisposed ()) return;
+    //if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    parent.destroyItem(this);
+    super.dispose();
+    parent = null;
+    control = null;
+    toolTipText = null;
+    shortenedText = null;
+    font = null;
+}
+void drawClose(GC gc) {
+    if (closeRect.width is 0 || closeRect.height is 0) return;
+    Display display = getDisplay();
+
+    // draw X 9x9
+    int indent = Math.max(1, (CTabFolder.BUTTON_SIZE-9)/2);
+    int x = closeRect.x + indent;
+    int y = closeRect.y + indent;
+    y += parent.onBottom ? -1 : 1;
+
+    Color closeBorder = display.getSystemColor(CTabFolder.BUTTON_BORDER);
+    switch (closeImageState) {
+        case CTabFolder.NORMAL: {
+            int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
+                                     x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
+                                     x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
+                                     x,y+7, x+2,y+5, x+2,y+4, x,y+2];
+            gc.setBackground(display.getSystemColor(CTabFolder.BUTTON_FILL));
+            gc.fillPolygon(shape);
+            gc.setForeground(closeBorder);
+            gc.drawPolygon(shape);
+            break;
+        }
+        case CTabFolder.HOT: {
+            int[] shape = [x,y, x+2,y, x+4,y+2, x+5,y+2, x+7,y, x+9,y,
+                                     x+9,y+2, x+7,y+4, x+7,y+5, x+9,y+7, x+9,y+9,
+                                     x+7,y+9, x+5,y+7, x+4,y+7, x+2,y+9, x,y+9,
+                                     x,y+7, x+2,y+5, x+2,y+4, x,y+2];
+            Color fill = new Color(display, CTabFolder.CLOSE_FILL);
+            gc.setBackground(fill);
+            gc.fillPolygon(shape);
+            fill.dispose();
+            gc.setForeground(closeBorder);
+            gc.drawPolygon(shape);
+            break;
+        }
+        case CTabFolder.SELECTED: {
+            int[] shape = [x+1,y+1, x+3,y+1, x+5,y+3, x+6,y+3, x+8,y+1, x+10,y+1,
+                                     x+10,y+3, x+8,y+5, x+8,y+6, x+10,y+8, x+10,y+10,
+                                     x+8,y+10, x+6,y+8, x+5,y+8, x+3,y+10, x+1,y+10,
+                                     x+1,y+8, x+3,y+6, x+3,y+5, x+1,y+3];
+            Color fill = new Color(display, CTabFolder.CLOSE_FILL);
+            gc.setBackground(fill);
+            gc.fillPolygon(shape);
+            fill.dispose();
+            gc.setForeground(closeBorder);
+            gc.drawPolygon(shape);
+            break;
+        }
+        case CTabFolder.NONE: {
+            int[] shape = [x,y, x+10,y, x+10,y+10, x,y+10];
+            if (parent.gradientColors !is null && !parent.gradientVertical) {
+                parent.drawBackground(gc, shape, false);
+            } else {
+                Color defaultBackground = parent.getBackground();
+                Image image = parent.bgImage;
+                Color[] colors = parent.gradientColors;
+                int[] percents = parent.gradientPercents;
+                bool vertical = parent.gradientVertical;
+                parent.drawBackground(gc, shape, x, y, 10, 10, defaultBackground, image, colors, percents, vertical);
+            }
+            break;
+        }
+        default:
+    }
+}
+void drawSelected(GC gc ) {
+    Point size = parent.getSize();
+    int rightEdge = Math.min (x + width, parent.getRightItemEdge());
+
+    //   Draw selection border across all tabs
+    int xx = parent.borderLeft;
+    int yy = parent.onBottom ? size.y - parent.borderBottom - parent.tabHeight - parent.highlight_header : parent.borderTop + parent.tabHeight + 1;
+    int ww = size.x - parent.borderLeft - parent.borderRight;
+    int hh = parent.highlight_header - 1;
+    int[] shape = [xx,yy, xx+ww,yy, xx+ww,yy+hh, xx,yy+hh];
+    if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) {
+        parent.drawBackground(gc, shape, true);
+    } else {
+        gc.setBackground(parent.selectionBackground);
+        gc.fillRectangle(xx, yy, ww, hh);
+    }
+
+    if (parent.single) {
+        if (!showing) return;
+    } else {
+        // if selected tab scrolled out of view or partially out of view
+        // just draw bottom line
+        if (!showing){
+            int x1 = Math.max(0, parent.borderLeft - 1);
+            int y1 = (parent.onBottom) ? y - 1 : y + height;
+            int x2 = size.x - parent.borderRight;
+            gc.setForeground(CTabFolder.borderColor);
+            gc.drawLine(x1, y1, x2, y1);
+            return;
+        }
+
+        // draw selected tab background and outline
+        shape = null;
+        if (this.parent.onBottom) {
+            int[] left = parent.simple ? CTabFolder.SIMPLE_BOTTOM_LEFT_CORNER : CTabFolder.BOTTOM_LEFT_CORNER;
+            int[] right = parent.simple ? CTabFolder.SIMPLE_BOTTOM_RIGHT_CORNER : parent.curve;
+            if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) {
+                left = [x, y+height];
+            }
+            shape = new int[left.length+right.length+8];
+            int index = 0;
+            shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
+            shape[index++] = y - 1;
+            shape[index++] = x;
+            shape[index++] = y - 1;
+            for (int i = 0; i < left.length/2; i++) {
+                shape[index++] = x + left[2*i];
+                shape[index++] = y + height + left[2*i+1] - 1;
+            }
+            for (int i = 0; i < right.length/2; i++) {
+                shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i];
+                shape[index++] = parent.simple ? y + height + right[2*i+1] - 1 : y + right[2*i+1] - 2;
+            }
+            shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
+            shape[index++] = y - 1;
+            shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
+            shape[index++] = y - 1;
+        } else {
+            int[] left = parent.simple ? CTabFolder.SIMPLE_TOP_LEFT_CORNER : CTabFolder.TOP_LEFT_CORNER;
+            int[] right = parent.simple ? CTabFolder.SIMPLE_TOP_RIGHT_CORNER : parent.curve;
+            if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) {
+                left = [x, y];
+            }
+            shape = new int[left.length+right.length+8];
+            int index = 0;
+            shape[index++] = x; // first point repeated here because below we reuse shape to draw outline
+            shape[index++] = y + height + 1;
+            shape[index++] = x;
+            shape[index++] = y + height + 1;
+            for (int i = 0; i < left.length/2; i++) {
+                shape[index++] = x + left[2*i];
+                shape[index++] = y + left[2*i+1];
+            }
+            for (int i = 0; i < right.length/2; i++) {
+                shape[index++] = parent.simple ? rightEdge - 1 + right[2*i] : rightEdge - parent.curveIndent + right[2*i];
+                shape[index++] = y + right[2*i+1];
+            }
+            shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
+            shape[index++] = y + height + 1;
+            shape[index++] = parent.simple ? rightEdge - 1 : rightEdge + parent.curveWidth - parent.curveIndent;
+            shape[index++] = y + height + 1;
+        }
+
+        Rectangle clipping = gc.getClipping();
+        Rectangle bounds = getBounds();
+        bounds.height += 1;
+        if (parent.onBottom) bounds.y -= 1;
+        bool tabInPaint = clipping.intersects(bounds);
+
+        if (tabInPaint) {
+            // fill in tab background
+            if (parent.selectionGradientColors !is null && !parent.selectionGradientVertical) {
+                parent.drawBackground(gc, shape, true);
+            } else {
+                Color defaultBackground = parent.selectionBackground;
+                Image image = parent.selectionBgImage;
+                Color[] colors = parent.selectionGradientColors;
+                int[] percents = parent.selectionGradientPercents;
+                bool vertical = parent.selectionGradientVertical;
+                xx = x;
+                yy = parent.onBottom ? y -1 : y + 1;
+                ww = width;
+                hh = height;
+                if (!parent.single && !parent.simple) ww += parent.curveWidth - parent.curveIndent;
+                parent.drawBackground(gc, shape, xx, yy, ww, hh, defaultBackground, image, colors, percents, vertical);
+            }
+        }
+
+        //Highlight MUST be drawn before the outline so that outline can cover it in the right spots (start of swoop)
+        //otherwise the curve looks jagged
+        drawHighlight(gc, rightEdge);
+
+        // draw outline
+        shape[0] = Math.max(0, parent.borderLeft - 1);
+        if (parent.borderLeft is 0 && parent.indexOf(this) is parent.firstIndex) {
+            shape[1] = parent.onBottom ? y + height - 1 : y;
+            shape[5] = shape[3] = shape[1];
+        }
+        shape[shape.length - 2] = size.x - parent.borderRight + 1;
+        for (int i = 0; i < shape.length/2; i++) {
+            if (shape[2*i + 1] is y + height + 1) shape[2*i + 1] -= 1;
+        }
+        RGB inside = parent.selectionBackground.getRGB();
+        if (parent.selectionBgImage !is null ||
+            (parent.selectionGradientColors !is null && parent.selectionGradientColors.length > 1)) {
+            inside = null;
+        }
+        RGB outside = parent.getBackground().getRGB();
+        if (parent.bgImage !is null ||
+            (parent.gradientColors !is null && parent.gradientColors.length > 1)) {
+            outside = null;
+        }
+        parent.antialias(shape, CTabFolder.borderColor.getRGB(), inside, outside, gc);
+        gc.setForeground(CTabFolder.borderColor);
+        gc.drawPolyline(shape);
+
+        if (!tabInPaint) return;
+    }
+
+    // draw Image
+    int xDraw = x + LEFT_MARGIN;
+    if (parent.single && (parent.showClose || showClose)) xDraw += CTabFolder.BUTTON_SIZE;
+    Image image = getImage();
+    if (image !is null) {
+        Rectangle imageBounds = image.getBounds();
+        // only draw image if it won't overlap with close button
+        int maxImageWidth = rightEdge - xDraw - RIGHT_MARGIN;
+        if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+        if (imageBounds.width < maxImageWidth) {
+            int imageX = xDraw;
+            int imageY = y + (height - imageBounds.height) / 2;
+            imageY += parent.onBottom ? -1 : 1;
+            gc.drawImage(image, imageX, imageY);
+            xDraw += imageBounds.width + INTERNAL_SPACING;
+        }
+    }
+
+    // draw Text
+    int textWidth = rightEdge - xDraw - RIGHT_MARGIN;
+    if (!parent.single && closeRect.width > 0) textWidth -= closeRect.width + INTERNAL_SPACING;
+    if (textWidth > 0) {
+        Font gcFont = gc.getFont();
+        gc.setFont(font is null ? parent.getFont() : font);
+
+        if (shortenedText is null || shortenedTextWidth !is textWidth) {
+            shortenedText = shortenText(gc, getText(), textWidth);
+            shortenedTextWidth = textWidth;
+        }
+        Point extent = gc.textExtent(shortenedText, FLAGS);
+        int textY = y + (height - extent.y) / 2;
+        textY += parent.onBottom ? -1 : 1;
+
+        gc.setForeground(parent.selectionForeground);
+        gc.drawText(shortenedText, xDraw, textY, FLAGS);
+        gc.setFont(gcFont);
+
+        // draw a Focus rectangle
+        if (parent.isFocusControl()) {
+            Display display = getDisplay();
+            if (parent.simple || parent.single) {
+                gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+                gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+                gc.drawFocus(xDraw-1, textY-1, extent.x+2, extent.y+2);
+            } else {
+                gc.setForeground(display.getSystemColor(CTabFolder.BUTTON_BORDER));
+                gc.drawLine(xDraw, textY+extent.y+1, xDraw+extent.x+1, textY+extent.y+1);
+            }
+        }
+    }
+    if (parent.showClose || showClose) drawClose(gc);
+}
+
+/*
+ * Draw a highlight effect along the left, top, and right edges of the tab.
+ * Only for curved tabs, on top.
+ * Do not draw if insufficient colors.
+ */
+void drawHighlight(GC gc, int rightEdge) {
+    //only draw for curvy tabs and only draw for top tabs
+    if(parent.simple || this.parent.onBottom)
+        return;
+
+    if(parent.selectionHighlightGradientBegin is null)
+        return;
+
+    Color[] gradients = parent.selectionHighlightGradientColorsCache;
+    if(gradients is null)
+        return;
+    int gradientsSize = gradients.length;
+    if(gradientsSize is 0)
+        return;     //shouldn't happen but just to be tidy
+
+    gc.setForeground(gradients[0]);
+
+    //draw top horizontal line
+    gc.drawLine(
+            CTabFolder.TOP_LEFT_CORNER_HILITE[0] + x + 1, //rely on fact that first pair is top/right of curve
+            1 + y,
+            rightEdge - parent.curveIndent,
+            1 + y);
+
+    int[] leftHighlightCurve = CTabFolder.TOP_LEFT_CORNER_HILITE;
+
+    int d = parent.tabHeight - parent.topCurveHighlightEnd.length /2;
+
+    int lastX = 0;
+    int lastY = 0;
+    int lastColorIndex = 0;
+
+    //draw upper left curve highlight
+    for (int i = 0; i < leftHighlightCurve.length /2; i++) {
+        int rawX = leftHighlightCurve[i * 2];
+        int rawY = leftHighlightCurve[i * 2 + 1];
+        lastX = rawX + x;
+        lastY = rawY + y;
+        lastColorIndex = rawY - 1;
+        gc.setForeground(gradients[lastColorIndex]);
+        gc.drawPoint(lastX, lastY);
+    }
+    //draw left vertical line highlight
+    for(int i = lastColorIndex; i < gradientsSize; i++) {
+        gc.setForeground(gradients[i]);
+        gc.drawPoint(lastX, 1 + lastY++);
+    }
+
+    int rightEdgeOffset = rightEdge - parent.curveIndent;
+
+    //draw right swoop highlight up to diagonal portion
+    for (int i = 0; i < parent.topCurveHighlightStart.length /2; i++) {
+        int rawX = parent.topCurveHighlightStart[i * 2];
+        int rawY = parent.topCurveHighlightStart[i * 2 + 1];
+        lastX = rawX + rightEdgeOffset;
+        lastY = rawY + y;
+        lastColorIndex = rawY - 1;
+        if(lastColorIndex >= gradientsSize)
+            break;  //can happen if tabs are unusually short and cut off the curve
+        gc.setForeground(gradients[lastColorIndex]);
+        gc.drawPoint(lastX, lastY);
+    }
+    //draw right diagonal line highlight
+    for(int i = lastColorIndex; i < lastColorIndex + d; i++) {
+        if(i >= gradientsSize)
+            break;  //can happen if tabs are unusually short and cut off the curve
+        gc.setForeground(gradients[i]);
+        gc.drawPoint(1 + lastX++, 1 + lastY++);
+    }
+
+    //draw right swoop highlight from diagonal portion to end
+    for (int i = 0; i < parent.topCurveHighlightEnd.length /2; i++) {
+        int rawX = parent.topCurveHighlightEnd[i * 2]; //d is already encoded in this value
+        int rawY = parent.topCurveHighlightEnd[i * 2 + 1]; //d already encoded
+        lastX = rawX + rightEdgeOffset;
+        lastY = rawY + y;
+        lastColorIndex = rawY - 1;
+        if(lastColorIndex >= gradientsSize)
+            break;  //can happen if tabs are unusually short and cut off the curve
+        gc.setForeground(gradients[lastColorIndex]);
+        gc.drawPoint(lastX, lastY);
+    }
+}
+
+/*
+ * Draw the unselected border for the receiver on the right.
+ *
+ * @param gc
+ */
+void drawRightUnselectedBorder(GC gc) {
+
+    int[] shape = null;
+    int startX = x + width - 1;
+
+    if (this.parent.onBottom) {
+        int[] right = parent.simple
+            ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
+            : CTabFolder.BOTTOM_RIGHT_CORNER;
+
+        shape = new int[right.length + 2];
+        int index = 0;
+
+        for (int i = 0; i < right.length / 2; i++) {
+            shape[index++] = startX + right[2 * i];
+            shape[index++] = y + height + right[2 * i + 1] - 1;
+        }
+        shape[index++] = startX;
+        shape[index++] = y - 1;
+    } else {
+        int[] right = parent.simple
+            ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
+            : CTabFolder.TOP_RIGHT_CORNER;
+
+        shape = new int[right.length + 2];
+        int index = 0;
+
+        for (int i = 0; i < right.length / 2; i++) {
+            shape[index++] = startX + right[2 * i];
+            shape[index++] = y + right[2 * i + 1];
+        }
+
+        shape[index++] = startX;
+        shape[index++] = y + height;
+
+    }
+
+    drawBorder(gc, shape);
+
+}
+
+/*
+ * Draw the border of the tab
+ *
+ * @param gc
+ * @param shape
+ */
+void drawBorder(GC gc, int[] shape) {
+
+    gc.setForeground(CTabFolder.borderColor);
+    gc.drawPolyline(shape);
+}
+
+/*
+ * Draw the unselected border for the receiver on the left.
+ *
+ * @param gc
+ */
+void drawLeftUnselectedBorder(GC gc) {
+
+    int[] shape = null;
+    if (this.parent.onBottom) {
+        int[] left = parent.simple
+            ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
+            : CTabFolder.BOTTOM_LEFT_CORNER;
+
+        shape = new int[left.length + 2];
+        int index = 0;
+        shape[index++] = x;
+        shape[index++] = y - 1;
+        for (int i = 0; i < left.length / 2; i++) {
+            shape[index++] = x + left[2 * i];
+            shape[index++] = y + height + left[2 * i + 1] - 1;
+        }
+    } else {
+        int[] left = parent.simple
+            ? CTabFolder.SIMPLE_UNSELECTED_INNER_CORNER
+            : CTabFolder.TOP_LEFT_CORNER;
+
+        shape = new int[left.length + 2];
+        int index = 0;
+        shape[index++] = x;
+        shape[index++] = y + height;
+        for (int i = 0; i < left.length / 2; i++) {
+            shape[index++] = x + left[2 * i];
+            shape[index++] = y + left[2 * i + 1];
+        }
+
+    }
+
+    drawBorder(gc, shape);
+}
+
+void drawUnselected(GC gc) {
+    // Do not draw partial items
+    if (!showing) return;
+
+    Rectangle clipping = gc.getClipping();
+    Rectangle bounds = getBounds();
+    if (!clipping.intersects(bounds)) return;
+
+    // draw border
+    int index = parent.indexOf(this);
+
+    if (index > 0 && index < parent.selectedIndex)
+        drawLeftUnselectedBorder(gc);
+    // If it is the last one then draw a line
+    if (index > parent.selectedIndex)
+        drawRightUnselectedBorder(gc);
+
+    // draw Image
+    int xDraw = x + LEFT_MARGIN;
+    Image image = getImage();
+    if (image !is null && parent.showUnselectedImage) {
+        Rectangle imageBounds = image.getBounds();
+        // only draw image if it won't overlap with close button
+        int maxImageWidth = x + width - xDraw - RIGHT_MARGIN;
+        if (parent.showUnselectedClose && (parent.showClose || showClose)) {
+            maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+        }
+        if (imageBounds.width < maxImageWidth) {
+            int imageX = xDraw;
+            int imageHeight = imageBounds.height;
+            int imageY = y + (height - imageHeight) / 2;
+            imageY += parent.onBottom ? -1 : 1;
+            int imageWidth = imageBounds.width * imageHeight / imageBounds.height;
+            gc.drawImage(image,
+                         imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height,
+                         imageX, imageY, imageWidth, imageHeight);
+            xDraw += imageWidth + INTERNAL_SPACING;
+        }
+    }
+    // draw Text
+    int textWidth = x + width - xDraw - RIGHT_MARGIN;
+    if (parent.showUnselectedClose && (parent.showClose || showClose)) {
+        textWidth -= closeRect.width + INTERNAL_SPACING;
+    }
+    if (textWidth > 0) {
+        Font gcFont = gc.getFont();
+        gc.setFont(font is null ? parent.getFont() : font);
+        if (shortenedText is null || shortenedTextWidth !is textWidth) {
+            shortenedText = shortenText(gc, getText(), textWidth);
+            shortenedTextWidth = textWidth;
+        }
+        Point extent = gc.textExtent(shortenedText, FLAGS);
+        int textY = y + (height - extent.y) / 2;
+        textY += parent.onBottom ? -1 : 1;
+        gc.setForeground(parent.getForeground());
+        gc.drawText(shortenedText, xDraw, textY, FLAGS);
+        gc.setFont(gcFont);
+    }
+    // draw close
+    if (parent.showUnselectedClose && (parent.showClose || showClose)) drawClose(gc);
+}
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding column rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    //checkWidget();
+    int w = width;
+    if (!parent.simple && !parent.single && parent.indexOf(this) is parent.selectedIndex) w += parent.curveWidth - parent.curveIndent;
+    return new Rectangle(x, y, w, height);
+}
+/**
+* Gets the control that is displayed in the content area of the tab item.
+*
+* @return the control
+*
+* @exception SWTException <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 Control getControl () {
+    checkWidget();
+    return control;
+}
+/**
+ * Get the image displayed in the tab if the tab is disabled.
+ *
+ * @return the disabled image or null
+ *
+ * @exception SWTException <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>
+ *
+ * @deprecated the disabled image is not used
+ */
+public Image getDisabledImage(){
+    checkWidget();
+    return disabledImage;
+}
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.0
+ */
+public Font getFont() {
+    checkWidget();
+    if (font !is null) return font;
+    return parent.getFont();
+}
+/**
+ * Returns the receiver's parent, which must be a <code>CTabFolder</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 CTabFolder getParent () {
+    //checkWidget();
+    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 (SWT.CLOSE)
+ * that was used to create the receiver.
+ *
+ * @return <code>true</code> if the close button should be shown
+ *
+ * @exception SWTException <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.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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 String getToolTipText () {
+    checkWidget();
+    if (toolTipText is null && shortenedText !is null) {
+        String text = getText();
+        if (shortenedText!=text) return text;
+    }
+    return toolTipText;
+}
+/**
+* Returns <code>true</code> if the item will be rendered in the visible area of the CTabFolder. Returns false otherwise.
+*
+*  @return <code>true</code> if the item will be rendered in the visible area of the CTabFolder. Returns false otherwise.
+*
+*  @exception SWTException <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.0
+*/
+public bool isShowing () {
+    checkWidget();
+    return showing;
+}
+void onPaint(GC gc, bool isSelected) {
+    if (width is 0 || height is 0) return;
+    if (isSelected) {
+        drawSelected(gc);
+    } else {
+        drawUnselected(gc);
+    }
+}
+int preferredHeight(GC gc) {
+    Image image = getImage();
+    int h = (image is null) ? 0 : image.getBounds().height;
+    String text = getText();
+    if (font is null) {
+        h = Math.max(h, gc.textExtent(text, FLAGS).y);
+    } else {
+        Font gcFont = gc.getFont();
+        gc.setFont(font);
+        h = Math.max(h, gc.textExtent(text, FLAGS).y);
+        gc.setFont(gcFont);
+    }
+    return h + TOP_MARGIN + BOTTOM_MARGIN;
+}
+int preferredWidth(GC gc, bool isSelected, bool minimum) {
+    // NOTE: preferred width does not include the "dead space" caused
+    // by the curve.
+    if (isDisposed()) return 0;
+    int w = 0;
+    Image image = getImage();
+    if (image !is null && (isSelected || parent.showUnselectedImage)) {
+        w += image.getBounds().width;
+    }
+    String text = null;
+    if (minimum) {
+        int minChars = parent.minChars;
+        text = minChars is 0 ? null : getText();
+        if (text !is null && text.length > minChars) {
+            if (useEllipses()) {
+                int end = minChars < ELLIPSIS.length + 1 ? minChars : minChars - ELLIPSIS.length;
+                text = text[ 0 .. end ];
+                if (minChars > ELLIPSIS.length + 1) text ~= ELLIPSIS;
+            } else {
+                int end = minChars;
+                text = text[ 0 .. end ];
+            }
+        }
+    } else {
+        text = getText();
+    }
+    if (text !is null) {
+        if (w > 0) w += INTERNAL_SPACING;
+        if (font is null) {
+            w += gc.textExtent(text, FLAGS).x;
+        } else {
+            Font gcFont = gc.getFont();
+            gc.setFont(font);
+            w += gc.textExtent(text, FLAGS).x;
+            gc.setFont(gcFont);
+        }
+    }
+    if (parent.showClose || showClose) {
+        if (isSelected || parent.showUnselectedClose) {
+            if (w > 0) w += INTERNAL_SPACING;
+            w += CTabFolder.BUTTON_SIZE;
+        }
+    }
+    return w + LEFT_MARGIN + RIGHT_MARGIN;
+}
+/**
+ * Sets the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item.
+ *
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setControl (Control control) {
+    checkWidget();
+    if (control !is null) {
+        if (control.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.getParent() !is parent) SWT.error (SWT.ERROR_INVALID_PARENT);
+    }
+    if (this.control !is null && !this.control.isDisposed()) {
+        this.control.setVisible(false);
+    }
+    this.control = control;
+    if (this.control !is null) {
+        int index = parent.indexOf (this);
+        if (index is parent.getSelectionIndex ()){
+            this.control.setBounds(parent.getClientArea ());
+            this.control.setVisible(true);
+        } else {
+            this.control.setVisible(false);
+        }
+    }
+}
+/**
+ * Sets the image that is displayed if the tab item is disabled.
+ * Null will clear the image.
+ *
+ * @param image the image to be displayed when the item is disabled or null
+ *
+ * @exception SWTException <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>
+ *
+ * @deprecated This image is not used
+ */
+public void setDisabledImage (Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.disabledImage = image;
+}
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setFont (Font font){
+    checkWidget();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (font is null && this.font is null) return;
+    if (font !is null && font==this.font) return;
+    this.font = font;
+    if (!parent.updateTabHeight(false)) {
+        parent.updateItems();
+        parent.redrawTabs();
+    }
+}
+public override void setImage (Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    Image oldImage = getImage();
+    if (image is null && oldImage is null) return;
+    if (image !is null && image==oldImage) return;
+    super.setImage(image);
+    if (!parent.updateTabHeight(false)) {
+        // If image is the same size as before,
+        // redraw only the image
+        if (oldImage !is null && image !is null) {
+            Rectangle oldBounds = oldImage.getBounds();
+            Rectangle bounds = image.getBounds();
+            if (bounds.width is oldBounds.width && bounds.height is oldBounds.height) {
+                if (showing) {
+                    bool selected = parent.indexOf(this) is parent.selectedIndex;
+                    if (selected || parent.showUnselectedImage) {
+                        int imageX = x + LEFT_MARGIN, maxImageWidth;
+                        if (selected) {
+                            if (parent.single && (parent.showClose || showClose)) imageX += CTabFolder.BUTTON_SIZE;
+                            int rightEdge = Math.min (x + width, parent.getRightItemEdge());
+                            maxImageWidth = rightEdge - imageX - RIGHT_MARGIN;
+                            if (!parent.single && closeRect.width > 0) maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+                        } else {
+                            maxImageWidth = x + width - imageX - RIGHT_MARGIN;
+                            if (parent.showUnselectedClose && (parent.showClose || showClose)) {
+                                maxImageWidth -= closeRect.width + INTERNAL_SPACING;
+                            }
+                        }
+                        if (bounds.width < maxImageWidth) {
+                            int imageY = y + (height - bounds.height) / 2 + (parent.onBottom ? -1 : 1);
+                            parent.redraw(imageX, imageY, bounds.width, bounds.height, false);
+                        }
+                    }
+                }
+                return;
+            }
+        }
+        parent.updateItems();
+        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 SWT.CLOSE style, changing this value has
+ * no effect.
+ *
+ * @param close the new state of the close button
+ *
+ * @exception SWTException <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();
+    // SWT extension: allow null for zero length string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (string.equals (getText())) return;
+    super.setText(string);
+    shortenedText = null;
+    shortenedTextWidth = 0;
+    if (!parent.updateTabHeight(false)) {
+        parent.updateItems();
+        parent.redrawTabs();
+    }
+}
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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 setToolTipText (String string) {
+    checkWidget();
+    toolTipText = string;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ControlEditor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ControlEditor;
+
+import java.lang.all;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ScrollBar;
+
+/**
+*
+* A ControlEditor is a manager for a Control that appears above a composite and tracks with the
+* moving and resizing of that composite.  It can be used to display one control above
+* another control.  This could be used when editing a control that does not have editing
+* capabilities by using a text editor or for launching a dialog by placing a button
+* above a control.
+*
+* <p> Here is an example of using a ControlEditor:
+*
+* <code><pre>
+* Canvas canvas = new Canvas(shell, SWT.BORDER);
+* canvas.setBounds(10, 10, 300, 300);
+* Color color = new Color(null, 255, 0, 0);
+* canvas.setBackground(color);
+* ControlEditor editor = new ControlEditor (canvas);
+* // The editor will be a button in the bottom right corner of the canvas.
+* // When selected, it will launch a Color dialog that will change the background
+* // of the canvas.
+* Button button = new Button(canvas, SWT.PUSH);
+* button.setText("Select Color...");
+* button.addSelectionListener (new SelectionAdapter() {
+*   public void widgetSelected(SelectionEvent e) {
+*       ColorDialog dialog = new ColorDialog(shell);
+*       dialog.open();
+*       RGB rgb = dialog.getRGB();
+*       if (rgb !is null) {
+*           if (color !is null) color.dispose();
+*           color = new Color(null, rgb);
+*           canvas.setBackground(color);
+*       }
+*
+*   }
+* });
+*
+* editor.horizontalAlignment = SWT.RIGHT;
+* editor.verticalAlignment = SWT.BOTTOM;
+* editor.grabHorizontal = false;
+* editor.grabVertical = false;
+* Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+* editor.minimumWidth = size.x;
+* editor.minimumHeight = size.y;
+* editor.setEditor (button);
+* </pre></code>
+*
+* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+*/
+public class ControlEditor {
+
+    /**
+    * Specifies how the editor should be aligned relative to the control.  Allowed values
+    * are SWT.LEFT, SWT.RIGHT and SWT.CENTER.  The default value is SWT.CENTER.
+    */
+    public int horizontalAlignment = SWT.CENTER;
+
+    /**
+    * Specifies whether the editor should be sized to use the entire width of the control.
+    * True means resize the editor to the same width as the cell.  False means do not adjust
+    * the width of the editor.  The default value is false.
+    */
+    public bool grabHorizontal = false;
+
+    /**
+    * Specifies the minimum width the editor can have.  This is used in association with
+    * a true value of grabHorizontal.  If the cell becomes smaller than the minimumWidth, the
+    * editor will not made smaller than the minimum width value.  The default value is 0.
+    */
+    public int minimumWidth = 0;
+
+    /**
+    * Specifies how the editor should be aligned relative to the control.  Allowed values
+    * are SWT.TOP, SWT.BOTTOM and SWT.CENTER.  The default value is SWT.CENTER.
+    */
+    public int verticalAlignment = SWT.CENTER;
+
+    /**
+    * Specifies whether the editor should be sized to use the entire height of the control.
+    * True means resize the editor to the same height as the underlying control.  False means do not adjust
+    * the height of the editor. The default value is false.
+    */
+    public bool grabVertical = false;
+
+    /**
+    * Specifies the minimum height the editor can have.  This is used in association with
+    * a true value of grabVertical.  If the control becomes smaller than the minimumHeight, the
+    * editor will not made smaller than the minimum height value.  The default value is 0.
+    */
+    public int minimumHeight = 0;
+
+    Composite parent;
+    Control editor;
+    private bool hadFocus;
+    private Listener controlListener;
+    private Listener scrollbarListener;
+
+    private final static int [] EVENTS = [SWT.KeyDown, SWT.KeyUp, SWT.MouseDown, SWT.MouseUp, SWT.Resize];
+/**
+* Creates a ControlEditor for the specified Composite.
+*
+* @param parent the Composite above which this editor will be displayed
+*
+*/
+public this (Composite parent) {
+    this.parent = parent;
+
+    controlListener = new class() Listener {
+        public void handleEvent(Event e) {
+            layout ();
+        }
+    };
+    for (int i=0; i<EVENTS.length; i++) {
+        parent.addListener (EVENTS [i], controlListener);
+    }
+
+    scrollbarListener = new class() Listener {
+        public void handleEvent(Event e) {
+            scroll (e);
+        }
+    };
+    ScrollBar hBar = parent.getHorizontalBar ();
+    if (hBar !is null) hBar.addListener (SWT.Selection, scrollbarListener);
+    ScrollBar vBar = parent.getVerticalBar ();
+    if (vBar !is null) vBar.addListener (SWT.Selection, scrollbarListener);
+}
+Rectangle computeBounds () {
+    Rectangle clientArea = parent.getClientArea();
+    Rectangle editorRect = new Rectangle(clientArea.x, clientArea.y, minimumWidth, minimumHeight);
+
+    if (grabHorizontal)
+        editorRect.width = Math.max(clientArea.width, minimumWidth);
+
+    if (grabVertical)
+        editorRect.height = Math.max(clientArea.height, minimumHeight);
+
+    switch (horizontalAlignment) {
+        case SWT.RIGHT:
+            editorRect.x += clientArea.width - editorRect.width;
+            break;
+        case SWT.LEFT:
+            // do nothing - clientArea.x is the right answer
+            break;
+        default:
+            // default is CENTER
+            editorRect.x += (clientArea.width - editorRect.width)/2;
+    }
+
+    switch (verticalAlignment) {
+        case SWT.BOTTOM:
+            editorRect.y += clientArea.height - editorRect.height;
+            break;
+        case SWT.TOP:
+            // do nothing - clientArea.y is the right answer
+            break;
+        default :
+            // default is CENTER
+            editorRect.y += (clientArea.height - editorRect.height)/2;
+    }
+
+
+    return editorRect;
+
+}
+/**
+ * Removes all associations between the Editor and the underlying composite.  The
+ * composite and the editor Control are <b>not</b> disposed.
+ */
+public void dispose () {
+    if (parent !is null && !parent.isDisposed()) {
+        for (int i=0; i<EVENTS.length; i++) {
+            parent.removeListener (EVENTS [i], controlListener);
+        }
+        ScrollBar hBar = parent.getHorizontalBar ();
+        if (hBar !is null) hBar.removeListener (SWT.Selection, scrollbarListener);
+        ScrollBar vBar = parent.getVerticalBar ();
+        if (vBar !is null) vBar.removeListener (SWT.Selection, scrollbarListener);
+    }
+
+    parent = null;
+    editor = null;
+    hadFocus = false;
+    controlListener = null;
+    scrollbarListener = null;
+}
+/**
+* Returns the Control that is displayed above the composite being edited.
+*
+* @return the Control that is displayed above the composite being edited
+*/
+public Control getEditor () {
+    return editor;
+}
+/**
+ * Lays out the control within the underlying composite.  This
+ * method should be called after changing one or more fields to
+ * force the Editor to resize.
+ *
+ * @since 2.1
+ */
+public void layout () {
+    if (editor is null || editor.isDisposed()) return;
+    if (editor.getVisible ()) {
+        hadFocus = editor.isFocusControl();
+    } // this doesn't work because
+      // resizing the column takes the focus away
+      // before we get here
+    editor.setBounds (computeBounds ());
+    if (hadFocus) {
+        if (editor is null || editor.isDisposed()) return;
+        editor.setFocus ();
+    }
+}
+void scroll (Event e) {
+    if (editor is null || editor.isDisposed()) return;
+    layout();
+}
+/**
+* Specify the Control that is to be displayed.
+*
+* <p>Note: The Control provided as the editor <b>must</b> be created with its parent
+* being the Composite specified in the ControlEditor constructor.
+*
+* @param editor the Control that is displayed above the composite being edited
+*/
+public void setEditor (Control editor) {
+
+    if (editor is null) {
+        // this is the case where the caller is setting the editor to be blank
+        // set all the values accordingly
+        this.editor = null;
+        return;
+    }
+
+    this.editor = editor;
+    layout();
+    if (this.editor is null || this.editor.isDisposed()) return;
+    editor.setVisible(true);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/DefaultContent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,923 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.DefaultContent;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.custom.StyledTextContent;
+import org.eclipse.swt.custom.TextChangeListener;
+import org.eclipse.swt.custom.StyledTextEvent;
+import org.eclipse.swt.custom.StyledTextListener;
+import org.eclipse.swt.custom.StyledText;
+import java.lang.all;
+
+static import tango.io.model.IFile;
+static import tango.text.Text;
+
+alias tango.text.Text.Text!(char) StringBuffer;
+
+class DefaultContent : StyledTextContent {
+    private final static String LineDelimiter = tango.io.model.IFile.FileConst.NewlineString;
+
+    StyledTextListener[] textListeners; // stores text listeners for event sending
+    char[] textStore; // stores the actual text
+    int gapStart = -1;  // the character position start of the gap
+    int gapEnd = -1;    // the character position after the end of the gap
+    int gapLine = -1;   // the line on which the gap exists, the gap will always be associated with one line
+    int highWatermark = 300;
+    int lowWatermark = 50;
+
+    int[][] lines; // array of character positions and lengths representing the lines of text
+    int lineCount_ = 0;  // the number of lines of text
+    int expandExp = 1;  // the expansion exponent, used to increase the lines array exponentially
+    int replaceExpandExp = 1;   // the expansion exponent, used to increase the lines array exponentially
+
+/**
+ * Creates a new DefaultContent and initializes it.  A <code>StyledTextContent</> will always have
+ * at least one empty line.
+ */
+this() {
+    lines = new int[][]( 50, 2 );
+    setText("");
+}
+/**
+ * Adds a line to the end of the line indexes array.  Increases the size of the array if necessary.
+ * <code>lineCount</code> is updated to reflect the new entry.
+ * <p>
+ *
+ * @param start the start of the line
+ * @param length the length of the line
+ */
+void addLineIndex(int start, int length) {
+    int size = lines.length;
+    if (lineCount_ is size) {
+        // expand the lines by powers of 2
+        int[][] newLines = new int[][]( size+Compatibility.pow2(expandExp), 2 );
+        System.arraycopy(lines, 0, newLines, 0, size);
+        lines = newLines;
+        expandExp++;
+    }
+    int[] range = [start, length];
+    lines[lineCount_] = range;
+    lineCount_++;
+}
+/**
+ * Adds a line index to the end of <code>linesArray</code>.  Increases the
+ * size of the array if necessary and returns a new array.
+ * <p>
+ *
+ * @param start the start of the line
+ * @param length the length of the line
+ * @param linesArray the array to which to add the line index
+ * @param count the position at which to add the line
+ * @return a new array of line indexes
+ */
+int[][] addLineIndex(int start, int length, int[][] linesArray, int count) {
+    int size = linesArray.length;
+    int[][] newLines = linesArray;
+    if (count is size) {
+        newLines = new int[][]( size+Compatibility.pow2(replaceExpandExp), 2 );
+        replaceExpandExp++;
+        System.arraycopy(linesArray, 0, newLines, 0, size);
+    }
+    int[] range = [start, length];
+    newLines[count] = range;
+    return newLines;
+}
+/**
+ * Adds a <code>TextChangeListener</code> listening for
+ * <code>TextChangingEvent</code> and <code>TextChangedEvent</code>. A
+ * <code>TextChangingEvent</code> is sent before changes to the text occur.
+ * A <code>TextChangedEvent</code> is sent after changes to the text
+ * occurred.
+ * <p>
+ *
+ * @param listener the listener
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addTextChangeListener(TextChangeListener listener) {
+    if (listener is null) error(SWT.ERROR_NULL_ARGUMENT);
+    StyledTextListener typedListener = new StyledTextListener(listener);
+    textListeners ~= typedListener;
+}
+/**
+ * Adjusts the gap to accommodate a text change that is occurring.
+ * <p>
+ *
+ * @param position the position at which a change is occurring
+ * @param sizeHint the size of the change
+ * @param line the line where the gap will go
+ */
+void adjustGap(int position, int sizeHint, int line) {
+    if (position is gapStart) {
+        // text is being inserted at the gap position
+        int size = (gapEnd - gapStart) - sizeHint;
+        if (lowWatermark <= size && size <= highWatermark)
+            return;
+    } else if ((position + sizeHint is gapStart) && (sizeHint < 0)) {
+        // text is being deleted at the gap position
+        int size = (gapEnd - gapStart) - sizeHint;
+        if (lowWatermark <= size && size <= highWatermark)
+            return;
+    }
+    moveAndResizeGap(position, sizeHint, line);
+}
+/**
+ * Calculates the indexes of each line in the text store.  Assumes no gap exists.
+ * Optimized to do less checking.
+ */
+void indexLines(){
+    int start = 0;
+    lineCount_ = 0;
+    int textLength = textStore.length;
+    int i;
+    for (i = start; i < textLength; i++) {
+        char ch = textStore[i];
+        if (ch is SWT.CR) {
+            // see if the next character is a LF
+            if (i + 1 < textLength) {
+                ch = textStore[i+1];
+                if (ch is SWT.LF) {
+                    i++;
+                }
+            }
+            addLineIndex(start, i - start + 1);
+            start = i + 1;
+        } else if (ch is SWT.LF) {
+            addLineIndex(start, i - start + 1);
+            start = i + 1;
+        }
+    }
+    addLineIndex(start, i - start);
+}
+/**
+ * Returns whether or not the given character is a line delimiter.  Both CR and LF
+ * are valid line delimiters.
+ * <p>
+ *
+ * @param ch the character to test
+ * @return true if ch is a delimiter, false otherwise
+ */
+bool isDelimiter(char ch) {
+    if (ch is SWT.CR) return true;
+    if (ch is SWT.LF) return true;
+    return false;
+}
+/**
+ * Determine whether or not the replace operation is valid.  DefaultContent will not allow
+ * the /r/n line delimiter to be split or partially deleted.
+ * <p>
+ *
+ * @param start start offset of text to replace
+ * @param replaceLength start offset of text to replace
+ * @param newText start offset of text to replace
+ * @return a bool specifying whether or not the replace operation is valid
+ */
+protected bool isValidReplace(int start, int replaceLength, String newText){
+    if (replaceLength is 0) {
+        // inserting text, see if the \r\n line delimiter is being split
+        if (start is 0) return true;
+        if (start is getCharCount()) return true;
+        char before = getTextRange(start - 1, 1)[0];
+        if (before is '\r') {
+            char after = getTextRange(start, 1)[0];
+            if (after is '\n') return false;
+        }
+    } else {
+        // deleting text, see if part of a \r\n line delimiter is being deleted
+        char startChar = getTextRange(start, 1)[0];
+        if (startChar is '\n') {
+            // see if char before delete position is \r
+            if (start !is 0) {
+                char before = getTextRange(start - 1, 1)[0];
+                if (before is '\r') return false;
+            }
+        }
+        char endChar = getTextRange(start + replaceLength - 1, 1)[0];
+        if (endChar is '\r') {
+            // see if char after delete position is \n
+            if (start + replaceLength !is getCharCount()) {
+                char after = getTextRange(start + replaceLength, 1)[0];
+                if (after is '\n') return false;
+            }
+        }
+    }
+    return true;
+}
+/**
+ * Calculates the indexes of each line of text in the given range.
+ * <p>
+ *
+ * @param offset the logical start offset of the text lineate
+ * @param length the length of the text to lineate, includes gap
+ * @param numLines the number of lines to initially allocate for the line index array,
+ *  passed in for efficiency (the exact number of lines may be known)
+ * @return a line indexes array where each line is identified by a start offset and
+ *  a length
+ */
+int[][] indexLines(int offset, int length, int numLines){
+    int[][] indexedLines = new int[][]( numLines, 2 );
+    int start = 0;
+    int lineCount_ = 0;
+    int i;
+    replaceExpandExp = 1;
+    for (i = start; i < length; i++) {
+        int location = i + offset;
+        if ((location >= gapStart) && (location < gapEnd)) {
+            // ignore the gap
+        } else {
+            char ch = textStore[location];
+            if (ch is SWT.CR) {
+                // see if the next character is a LF
+                if (location+1 < textStore.length) {
+                    ch = textStore[location+1];
+                    if (ch is SWT.LF) {
+                        i++;
+                    }
+                }
+                indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount_);
+                lineCount_++;
+                start = i + 1;
+            } else if (ch is SWT.LF) {
+                indexedLines = addLineIndex(start, i - start + 1, indexedLines, lineCount_);
+                lineCount_++;
+                start = i + 1;
+            }
+        }
+    }
+    int[][] newLines = new int[][]( lineCount_+1, 2 );
+    System.arraycopy(indexedLines, 0, newLines, 0, lineCount_);
+    int[] range = [start, i - start];
+    newLines[lineCount_] = range;
+    return newLines;
+}
+/**
+ * Inserts text.
+ * <p>
+ *
+ * @param position the position at which to insert the text
+ * @param text the text to insert
+ */
+void insert(int position, String text) {
+    if (text.length is 0) return;
+
+    int startLine = getLineAtOffset(position);
+    int change = text.length;
+    bool endInsert = position is getCharCount();
+    adjustGap(position, change, startLine);
+
+    // during an insert the gap will be adjusted to start at
+    // position and it will be associated with startline, the
+    // inserted text will be placed in the gap
+    int startLineOffset = getOffsetAtLine(startLine);
+    // at this point, startLineLength will include the start line
+    // and all of the newly inserted text
+    int startLineLength = getPhysicalLine(startLine).length;
+
+    if (change > 0) {
+        // shrink gap
+        gapStart += (change);
+        for (int i = 0; i < text.length; i++) {
+            textStore[position + i]= text[i];
+        }
+    }
+
+    // figure out the number of new lines that have been inserted
+    int [][] newLines = indexLines(startLineOffset, startLineLength, 10);
+    // only insert an empty line if it is the last line in the text
+    int numNewLines = newLines.length - 1;
+    if (newLines[numNewLines][1] is 0) {
+        // last inserted line is a new line
+        if (endInsert) {
+            // insert happening at end of the text, leave numNewLines as
+            // is since the last new line will not be concatenated with another
+            // line
+            numNewLines += 1;
+        } else {
+            numNewLines -= 1;
+        }
+    }
+
+    // make room for the new lines
+    expandLinesBy(numNewLines);
+    // shift down the lines after the replace line
+    for (int i = lineCount_ - 1; i > startLine; i--) {
+        lines[i + numNewLines]=lines[i];
+    }
+    // insert the new lines
+    for (int i = 0; i < numNewLines; i++) {
+        newLines[i][0] += startLineOffset;
+        lines[startLine + i]=newLines[i];
+    }
+    // update the last inserted line
+    if (numNewLines < newLines.length) {
+        newLines[numNewLines][0] += startLineOffset;
+        lines[startLine + numNewLines] = newLines[numNewLines];
+    }
+
+    lineCount_ += numNewLines;
+    gapLine = getLineAtPhysicalOffset(gapStart);
+}
+/**
+ * Moves the gap and adjusts its size in anticipation of a text change.
+ * The gap is resized to actual size + the specified size and moved to the given
+ * position.
+ * <p>
+ *
+ * @param position the position at which a change is occurring
+ * @param size the size of the change
+ * @param newGapLine the line where the gap should be put
+ */
+void moveAndResizeGap(int position, int size, int newGapLine) {
+    char[] content = null;
+    int oldSize = gapEnd - gapStart;
+    int newSize;
+    if (size > 0) {
+        newSize = highWatermark + size;
+    } else {
+        newSize = lowWatermark - size;
+    }
+    // remove the old gap from the lines information
+    if (gapExists()) {
+        // adjust the line length
+        lines[gapLine][1] = lines[gapLine][1] - oldSize;
+        // adjust the offsets of the lines after the gapLine
+        for (int i = gapLine + 1; i < lineCount_; i++) {
+            lines[i][0] = lines[i][0] - oldSize;
+        }
+    }
+
+    if (newSize < 0) {
+        if (oldSize > 0) {
+            // removing the gap
+            content = new char[textStore.length - oldSize];
+            System.arraycopy(textStore, 0, content, 0, gapStart);
+            System.arraycopy(textStore, gapEnd, content, gapStart, content.length - gapStart);
+            textStore = content;
+        }
+        gapStart = gapEnd = position;
+        return;
+    }
+    content = new char[textStore.length + (newSize - oldSize)];
+    int newGapStart = position;
+    int newGapEnd = newGapStart + newSize;
+    if (oldSize is 0) {
+        System.arraycopy(textStore, 0, content, 0, newGapStart);
+        System.arraycopy(textStore, newGapStart, content, newGapEnd, content.length - newGapEnd);
+    } else if (newGapStart < gapStart) {
+        int delta = gapStart - newGapStart;
+        System.arraycopy(textStore, 0, content, 0, newGapStart);
+        System.arraycopy(textStore, newGapStart, content, newGapEnd, delta);
+        System.arraycopy(textStore, gapEnd, content, newGapEnd + delta, textStore.length - gapEnd);
+    } else {
+        int delta = newGapStart - gapStart;
+        System.arraycopy(textStore, 0, content, 0, gapStart);
+        System.arraycopy(textStore, gapEnd, content, gapStart, delta);
+        System.arraycopy(textStore, gapEnd + delta, content, newGapEnd, content.length - newGapEnd);
+    }
+    textStore = content;
+    gapStart = newGapStart;
+    gapEnd = newGapEnd;
+
+    // add the new gap to the lines information
+    if (gapExists()) {
+        gapLine = newGapLine;
+        // adjust the line length
+        int gapLength = gapEnd - gapStart;
+        lines[gapLine][1] = lines[gapLine][1] + (gapLength);
+        // adjust the offsets of the lines after the gapLine
+        for (int i = gapLine + 1; i < lineCount_; i++) {
+            lines[i][0] = lines[i][0] + gapLength;
+        }
+    }
+}
+/**
+ * Returns the number of lines that are in the specified text.
+ * <p>
+ *
+ * @param startOffset the start of the text to lineate
+ * @param length the length of the text to lineate
+ * @return number of lines
+ */
+int lineCount(int startOffset, int length){
+    if (length is 0) {
+        return 0;
+    }
+    int lineCount_ = 0;
+    int count = 0;
+    int i = startOffset;
+    if (i >= gapStart) {
+        i += gapEnd - gapStart;
+    }
+    while (count < length) {
+        if ((i >= gapStart) && (i < gapEnd)) {
+            // ignore the gap
+        } else {
+            char ch = textStore[i];
+            if (ch is SWT.CR) {
+                // see if the next character is a LF
+                if (i + 1 < textStore.length) {
+                    ch = textStore[i+1];
+                    if (ch is SWT.LF) {
+                        i++;
+                        count++;
+                    }
+                }
+                lineCount_++;
+            } else if (ch is SWT.LF) {
+                lineCount_++;
+            }
+            count++;
+        }
+        i++;
+    }
+    return lineCount_;
+}
+/**
+ * Returns the number of lines that are in the specified text.
+ * <p>
+ *
+ * @param text the text to lineate
+ * @return number of lines in the text
+ */
+int lineCount(String text){
+    int lineCount_ = 0;
+    int length = text.length;
+    for (int i = 0; i < length; i++) {
+        char ch = text[i];
+        if (ch is SWT.CR) {
+            if (i + 1 < length && text[i + 1] is SWT.LF) {
+                i++;
+            }
+            lineCount_++;
+        } else if (ch is SWT.LF) {
+            lineCount_++;
+        }
+    }
+    return lineCount_;
+}
+/**
+ * @return the logical length of the text store
+ */
+public int getCharCount() {
+    int length = gapEnd - gapStart;
+    return (textStore.length - length);
+}
+/**
+ * Returns the line at <code>index</code> without delimiters.
+ * <p>
+ *
+ * @param index the index of the line to return
+ * @return the logical line text (i.e., without the gap)
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_INVALID_ARGUMENT when index is out of range</li>
+ * </ul>
+ */
+public String getLine(int index) {
+    if ((index >= lineCount_) || (index < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+    int start = lines[index][0];
+    int length_ = lines[index][1];
+    int end = start + length_ - 1;
+    if (!gapExists() || (end < gapStart) || (start >= gapEnd)) {
+        // line is before or after the gap
+        while ((length_ - 1 >= 0) && isDelimiter(textStore[start+length_-1])) {
+            length_--;
+        }
+        return textStore[ start .. start + length_].dup;
+    } else {
+        // gap is in the specified range, strip out the gap
+        StringBuffer buf = new StringBuffer();
+        int gapLength = gapEnd - gapStart;
+        buf.append(textStore[ start .. gapStart ] );
+        buf.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]);
+        length_ = buf.length;
+        while ((length_ - 1 >=0) && isDelimiter(buf.slice[length_ - 1])) {
+            length_--;
+        }
+        return buf.toString()[ 0 .. length_ ].dup;
+    }
+}
+/**
+ * Returns the line delimiter that should be used by the StyledText
+ * widget when inserting new lines.  This delimiter may be different than the
+ * delimiter that is used by the <code>StyledTextContent</code> interface.
+ * <p>
+ *
+ * @return the platform line delimiter as specified in the line.separator
+ *  system property.
+ */
+public String getLineDelimiter() {
+    return LineDelimiter;
+}
+/**
+ * Returns the line at the given index with delimiters.
+ * <p>
+ * @param index the index of the line to return
+ * @return the logical line text (i.e., without the gap) with delimiters
+ */
+String getFullLine(int index) {
+    int start = lines[index][0];
+    int length_ = lines[index][1];
+    int end = start + length_ - 1;
+    if (!gapExists() || (end < gapStart) || (start >= gapEnd)) {
+        // line is before or after the gap
+        return textStore[ start .. start + length_ ].dup;
+    } else {
+        // gap is in the specified range, strip out the gap
+        StringBuffer buffer = new StringBuffer();
+        int gapLength = gapEnd - gapStart;
+        buffer.append(textStore[ start .. gapStart ]);
+        buffer.append(textStore[ gapEnd .. gapEnd + length_ - gapLength - (gapStart - start) ]);
+        return buffer.toString().dup;
+    }
+}
+/**
+ * Returns the physical line at the given index (i.e., with delimiters and the gap).
+ * <p>
+ *
+ * @param index the line index
+ * @return the physical line
+ */
+String getPhysicalLine(int index) {
+    int start = lines[index][0];
+    int length_ = lines[index][1];
+    return getPhysicalText(start, length_);
+}
+/**
+ * @return the number of lines in the text store
+ */
+public int getLineCount(){
+    return lineCount_;
+}
+/**
+ * Returns the line at the given offset.
+ * <p>
+ *
+ * @param charPosition logical character offset (i.e., does not include gap)
+ * @return the line index
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT when charPosition is out of range</li>
+ * </ul>
+ */
+public int getLineAtOffset(int charPosition){
+    if ((charPosition > getCharCount()) || (charPosition < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+    int position;
+    if (charPosition < gapStart) {
+        // position is before the gap
+        position = charPosition;
+    } else {
+        // position includes the gap
+        position = charPosition + (gapEnd - gapStart);
+    }
+
+    // if last line and the line is not empty you can ask for
+    // a position that doesn't exist (the one to the right of the
+    // last character) - for inserting
+    if (lineCount_ > 0) {
+        int lastLine = lineCount_ - 1;
+        if (position is lines[lastLine][0] + lines[lastLine][1])
+            return lastLine;
+    }
+
+    int high = lineCount_;
+    int low = -1;
+    int index = lineCount_;
+    while (high - low > 1) {
+        index = (high + low) / 2;
+        int lineStart = lines[index][0];
+        int lineEnd = lineStart + lines[index][1] - 1;
+        if (position <= lineStart) {
+            high = index;
+        } else if (position <= lineEnd) {
+            high = index;
+            break;
+        } else {
+            low = index;
+        }
+    }
+    return high;
+}
+/**
+ * Returns the line index at the given physical offset.
+ * <p>
+ *
+ * @param position physical character offset (i.e., includes gap)
+ * @return the line index
+ */
+int getLineAtPhysicalOffset(int position){
+    int high = lineCount_;
+    int low = -1;
+    int index = lineCount_;
+    while (high - low > 1) {
+        index = (high + low) / 2;
+        int lineStart = lines[index][0];
+        int lineEnd = lineStart + lines[index][1] - 1;
+        if (position <= lineStart) {
+            high = index;
+        } else if (position <= lineEnd) {
+            high = index;
+            break;
+        } else {
+            low = index;
+        }
+    }
+    return high;
+}
+/**
+ * Returns the logical offset of the given line.
+ * <p>
+ *
+ * @param lineIndex index of line
+ * @return the logical starting offset of the line.  When there are not any lines,
+ *  getOffsetAtLine(0) is a valid call that should answer 0.
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_INVALID_ARGUMENT when lineIndex is out of range</li>
+ * </ul>
+ */
+public int getOffsetAtLine(int lineIndex) {
+    if (lineIndex is 0) return 0;
+    if ((lineIndex >= lineCount_) || (lineIndex < 0)) error(SWT.ERROR_INVALID_ARGUMENT);
+    int start = lines[lineIndex][0];
+    if (start > gapEnd) {
+        return start - (gapEnd - gapStart);
+    } else {
+        return start;
+    }
+}
+/**
+ * Increases the line indexes array to accommodate more lines.
+ * <p>
+ *
+ * @param numLines the number to increase the array by
+ */
+void expandLinesBy(int numLines) {
+    int size = lines.length;
+    if (size - lineCount_ >= numLines) {
+        return;
+    }
+    int[][] newLines = new int[][]( size+Math.max(10, numLines), 2 );
+    System.arraycopy(lines, 0, newLines, 0, size);
+    lines = newLines;
+}
+/**
+ * Reports an SWT error.
+ * <p>
+ *
+ * @param code the error code
+ */
+void error (int code) {
+    SWT.error(code);
+}
+/**
+ * Returns whether or not a gap exists in the text store.
+ * <p>
+ *
+ * @return true if gap exists, false otherwise
+ */
+bool gapExists() {
+    return gapStart !is gapEnd;
+}
+/**
+ * Returns a string representing the continuous content of
+ * the text store.
+ * <p>
+ *
+ * @param start the physical start offset of the text to return
+ * @param length the physical length of the text to return
+ * @return the text
+ */
+String getPhysicalText(int start, int length_) {
+    return textStore[ start .. start + length_ ].dup;
+}
+/**
+ * Returns a string representing the logical content of
+ * the text store (i.e., gap stripped out).
+ * <p>
+ *
+ * @param start the logical start offset of the text to return
+ * @param length the logical length of the text to return
+ * @return the text
+ */
+public String getTextRange(int start, int length_) {
+    if (textStore is null)
+        return "";
+    if (length_ is 0)
+        return "";
+    int end= start + length_;
+    if (!gapExists() || (end < gapStart))
+        return textStore[ start .. start + length_].dup;
+    if (gapStart < start) {
+        int gapLength= gapEnd - gapStart;
+        return textStore[ start + gapLength .. start + gapLength + length_ ].dup;
+    }
+    StringBuffer buf = new StringBuffer();
+    buf.append(textStore[ start .. start + gapStart - start ] );
+    buf.append(textStore[ gapEnd .. gapEnd + end - gapStart ] );
+    return buf.toString().dup;
+}
+/**
+ * Removes the specified <code>TextChangeListener</code>.
+ * <p>
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeTextChangeListener(TextChangeListener listener){
+    if (listener is null) error(SWT.ERROR_NULL_ARGUMENT);
+    for (int i = 0; i < textListeners.length; i++) {
+        TypedListener typedListener = cast(TypedListener) textListeners[i];
+        if (typedListener.getEventListener () is listener) {
+            textListeners = textListeners[ 0 .. i ] ~ textListeners[ i+1 .. $ ];
+            break;
+        }
+    }
+}
+/**
+ * Replaces the text with <code>newText</code> starting at position <code>start</code>
+ * for a length of <code>replaceLength</code>.  Notifies the appropriate listeners.
+ * <p>
+ *
+ * When sending the TextChangingEvent, <code>newLineCount</code> is the number of
+ * lines that are going to be inserted and <code>replaceLineCount</code> is
+ * the number of lines that are going to be deleted, based on the change
+ * that occurs visually.  For example:
+ * <ul>
+ * <li>(replaceText,newText) is> (replaceLineCount,newLineCount)
+ * <li>("","\n") is> (0,1)
+ * <li>("\n\n","a") is> (2,0)
+ * </ul>
+ * </p>
+ *
+ * @param start start offset of text to replace
+ * @param replaceLength start offset of text to replace
+ * @param newText start offset of text to replace
+ *
+ * @exception SWTException <ul>
+ *   <li>ERROR_INVALID_ARGUMENT when the text change results in a multi byte
+ *      line delimiter being split or partially deleted.  Splitting a line
+ *      delimiter by inserting text between the CR and LF characters of the
+ *      \r\n delimiter or deleting part of this line delimiter is not supported</li>
+ * </ul>
+ */
+public void replaceTextRange(int start, int replaceLength, String newText){
+    // check for invalid replace operations
+    if (!isValidReplace(start, replaceLength, newText)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    // inform listeners
+    StyledTextEvent event = new StyledTextEvent(this);
+    event.type = StyledText.TextChanging;
+    event.start = start;
+    event.replaceLineCount = lineCount(start, replaceLength);
+    event.text = newText;
+    event.newLineCount = lineCount(newText);
+    event.replaceCharCount = replaceLength;
+    event.newCharCount = newText.length;
+    sendTextEvent(event);
+
+    // first delete the text to be replaced
+    delete_(start, replaceLength, event.replaceLineCount + 1);
+    // then insert the new text
+    insert(start, newText);
+    // inform listeners
+    event = new StyledTextEvent(this);
+    event.type = StyledText.TextChanged;
+    sendTextEvent(event);
+}
+/**
+ * Sends the text listeners the TextChanged event.
+ */
+void sendTextEvent(StyledTextEvent event) {
+    for (int i = 0; i < textListeners.length; i++) {
+        (cast(StyledTextListener)textListeners[i]).handleEvent(event);
+    }
+}
+/**
+ * Sets the content to text and removes the gap since there are no sensible predictions
+ * about where the next change will occur.
+ * <p>
+ *
+ * @param text the text
+ */
+public void setText (String text){
+    textStore = text.dup;
+    gapStart = -1;
+    gapEnd = -1;
+    expandExp = 1;
+    indexLines();
+    StyledTextEvent event = new StyledTextEvent(this);
+    event.type = StyledText.TextSet;
+    event.text = "";
+    sendTextEvent(event);
+}
+/**
+ * Deletes text.
+ * <p>
+ * @param position the position at which the text to delete starts
+ * @param length the length of the text to delete
+ * @param numLines the number of lines that are being deleted
+ */
+void delete_(int position, int length_, int numLines) {
+    if (length_ is 0) return;
+
+    int startLine = getLineAtOffset(position);
+    int startLineOffset = getOffsetAtLine(startLine);
+    int endLine = getLineAtOffset(position + length_);
+
+    String endText = "";
+    bool splittingDelimiter = false;
+    if (position + length_ < getCharCount()) {
+        endText = getTextRange(position + length_ - 1, 2);
+        if ((endText[0] is SWT.CR) && (endText[1] is SWT.LF)) {
+            splittingDelimiter = true;
+        }
+    }
+
+    adjustGap(position + length_, -length_, startLine);
+    int [][] oldLines = indexLines(position, length_ + (gapEnd - gapStart), numLines);
+
+    // enlarge the gap - the gap can be enlarged either to the
+    // right or left
+    if (position + length_ is gapStart) {
+        gapStart -= length_;
+    } else {
+        gapEnd += length_;
+    }
+
+    // figure out the length of the new concatenated line, do so by
+    // finding the first line delimiter after position
+    int j = position;
+    bool eol = false;
+    while (j < textStore.length && !eol) {
+        if (j < gapStart || j >= gapEnd) {
+            char ch = textStore[j];
+            if (isDelimiter(ch)) {
+                if (j + 1 < textStore.length) {
+                    if (ch is SWT.CR && (textStore[j+1] is SWT.LF)) {
+                        j++;
+                    }
+                }
+                eol = true;
+            }
+        }
+        j++;
+    }
+    // update the line where the deletion started
+    lines[startLine][1] = (position - startLineOffset) + (j - position);
+    // figure out the number of lines that have been deleted
+    int numOldLines = oldLines.length - 1;
+    if (splittingDelimiter) numOldLines -= 1;
+    // shift up the lines after the last deleted line, no need to update
+    // the offset or length of the lines
+    for (int i = endLine + 1; i < lineCount_; i++) {
+        lines[i - numOldLines] = lines[i];
+    }
+    lineCount_ -= numOldLines;
+    gapLine = getLineAtPhysicalOffset(gapStart);
+}
+
+/++
+ + SWT extension
+ +/
+int utf8AdjustOffset( int offset ){
+    if (textStore is null)
+        return offset;
+    if (offset is 0)
+        return offset;
+    if( offset >= textStore.length ){
+        return offset;
+    }
+    if (!gapExists() || (offset < gapStart)){
+        while( textStore[offset] & 0xC0 is 0x80 ){
+            offset--;
+        }
+        return offset;
+    }
+    int gapLength= gapEnd - gapStart;
+    if( offset+gapLength >= textStore.length ){
+        return offset;
+    }
+    while( textStore[offset+gapLength] & 0xC0 is 0x80 ){
+        offset--;
+    }
+    return offset;
+}
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ExtendedModifyEvent;
+
+import java.lang.all;
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent after a text change occurs.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class ExtendedModifyEvent : TypedEvent {
+    /** start offset of the new text */
+    public int start;
+    /** length of the new text */
+    public int length;
+    /** replaced text or empty string if no text was replaced */
+    public String replacedText;
+
+    static final long serialVersionUID = 3258696507027830832L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+    super(cast(Object)e);
+    start = e.start;
+    length = e.end - e.start;
+    replacedText = e.text;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ExtendedModifyListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ExtendedModifyListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.ExtendedModifyEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when text
+ * is modified.
+ *
+ * @see ExtendedModifyEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public interface ExtendedModifyListener : SWTEventListener {
+
+/**
+ * This method is called after a text change occurs.
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.start the start offset of the new text (input)</li>
+ * <li>event.length the length of the new text (input)</li>
+ * <li>event.replacedText the replaced text (input)</li>
+ * </ul>
+ *
+ * @param event the given event
+ * @see ExtendedModifyEvent
+ */
+public void modifyText(ExtendedModifyEvent event);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.LineBackgroundEvent;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent when a line is about to be drawn.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class LineBackgroundEvent : TypedEvent {
+
+    /**
+     * line start offset
+     */
+    public int lineOffset;
+
+    /**
+     * line text
+     */
+    public String lineText;
+
+    /**
+     * line background color
+     */
+    public Color lineBackground;
+
+    static final long serialVersionUID = 3978711687853324342L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+    super(cast(Object)e);
+    lineOffset = e.detail;
+    lineText = e.text;
+    lineBackground = e.lineBackground;
+}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineBackgroundListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.LineBackgroundListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.LineBackgroundEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that can provide the background color for a line that
+ * is to be drawn.
+ *
+ * @see LineBackgroundEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public interface LineBackgroundListener : SWTEventListener {
+
+/**
+ * This method is called when a line is about to be drawn in order to get its
+ * background color.
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineOffset line start offset (input)</li>
+ * <li>event.lineText line text (input)</li>
+ * <li>event.lineBackground line background color (output)</li>
+ * </ul>
+ *
+ * @param event the given event
+ * @see LineBackgroundEvent
+ */
+public void lineGetBackground(LineBackgroundEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.LineStyleEvent;
+
+import java.lang.all;
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.Bullet;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent when a line is about to be drawn.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class LineStyleEvent : TypedEvent {
+
+    /**
+     * line start offset (input)
+     */
+    public int lineOffset;
+
+    /**
+     * line text (input)
+     */
+    public String lineText;
+
+    /**
+     * line ranges (output)
+     *
+     * @since 3.2
+     */
+    public int[] ranges;
+
+    /**
+     * line styles (output)
+     *
+     * Note: Because a StyleRange includes the start and length, the
+     * same instance cannot occur multiple times in the array of styles.
+     * If the same style attributes, such as font and color, occur in
+     * multiple StyleRanges, <code>ranges</code> can be used to share
+     * styles and reduce memory usage.
+     */
+    public StyleRange[] styles;
+
+    /**
+     * line alignment (input, output)
+     *
+     * @since 3.2
+     */
+    public int alignment;
+
+    /**
+     * line indent (input, output)
+     *
+     * @since 3.2
+     */
+    public int indent;
+
+    /**
+     * line justification (input, output)
+     *
+     * @since 3.2
+     */
+    public bool justify;
+
+    /**
+     * line bullet (output)
+     * @since 3.2
+     */
+    public Bullet bullet;
+
+    /**
+     * line bullet index (output)
+     * @since 3.2
+     */
+    public int bulletIndex;
+
+    static final long serialVersionUID = 3906081274027192884L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+    super(cast(Object)e);
+    styles = e.styles;
+    ranges = e.ranges;
+    lineOffset = e.detail;
+    lineText = e.text;
+    alignment = e.alignment;
+    justify = e.justify;
+    indent = e.indent;
+    bullet = e.bullet;
+    bulletIndex = e.bulletIndex;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/LineStyleListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.LineStyleListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.LineStyleEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that can provide the style information for a line that
+ * is to be drawn.
+ *
+ * @see LineStyleEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public interface LineStyleListener : SWTEventListener {
+
+/**
+ * This method is called when a line is about to be drawn in order to get the
+ * line's style information.
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineOffset line start offset (input)</li>
+ * <li>event.lineText line text (input)</li>
+ * <li>event.styles array of StyleRanges, need to be in order (output)</li>
+ * </ul>
+ *
+ * @param event the given event
+ * @see LineStyleEvent
+ */
+public void lineGetStyle(LineStyleEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.MovementEvent;
+
+import java.lang.all;
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent when a new offset is required based on the current
+ * offset and a movement type.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class MovementEvent : TypedEvent {
+
+    /**
+     * line start offset (input)
+     */
+    public int lineOffset;
+
+    /**
+     * line text (input)
+     */
+    public String lineText;
+
+    /**
+     * the current offset (input)
+     */
+    public int offset;
+
+    /**
+     * the new offset  (input, output)
+     */
+    public int newOffset;
+
+    /**
+     * the movement type (input)
+     *
+     * @see org.eclipse.swt.SWT#MOVEMENT_WORD
+     * @see org.eclipse.swt.SWT#MOVEMENT_WORD_END
+     * @see org.eclipse.swt.SWT#MOVEMENT_WORD_START
+     * @see org.eclipse.swt.SWT#MOVEMENT_CHAR
+     * @see org.eclipse.swt.SWT#MOVEMENT_CLUSTER
+     */
+    public int movement;
+
+    static final long serialVersionUID = 3978765487853324342L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+    super(cast(Object)e);
+    lineOffset = e.detail;
+    lineText = e.text;
+    movement = e.count;
+    offset = e.start;
+    newOffset = e.end;
+}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/MovementListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.MovementListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.MovementEvent;
+
+/**
+ * This listener is invoked when a new offset is required based on the current
+ * offset and a movement type.
+ *
+ * @see org.eclipse.swt.SWT#MOVEMENT_WORD
+ * @see org.eclipse.swt.SWT#MOVEMENT_WORD_END
+ * @see org.eclipse.swt.SWT#MOVEMENT_WORD_START
+ * @see org.eclipse.swt.SWT#MOVEMENT_CHAR
+ * @see org.eclipse.swt.SWT#MOVEMENT_CLUSTER
+ *
+ * @since 3.3
+ */
+public interface MovementListener : SWTEventListener {
+/**
+ * This method is called when a new offset is required based on the current
+ * offset and a movement type.
+ *
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineOffset line start offset (input)</li>
+ * <li>event.lineText line text (input)</li>
+ * <li>event.movement the movement type (input)</li>
+ * <li>event.offset the current offset (input)</li>
+ * <li>event.newOffset the new offset (input, output)</li>
+ * </ul>
+ *
+ * @param event the event
+ *
+ * @see MovementEvent
+ * @see StyledText#addWordMovementListener(MovementListener)
+ */
+public void getNextOffset (MovementEvent event);
+/**
+ * This method is called when a new offset is required based on the current
+ * offset and a movement type.
+ *
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.lineOffset line start offset (input)</li>
+ * <li>event.lineText line text (input)</li>
+ * <li>event.movement the movement type (input)</li>
+ * <li>event.offset the current offset (input)</li>
+ * <li>event.newOffset the new offset (input, output)</li>
+ * </ul>
+ *
+ * @param event the event
+ *
+ * @see MovementEvent
+ * @see StyledText#addWordMovementListener(MovementListener)
+ */
+public void getPreviousOffset (MovementEvent event);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.PaintObjectEvent;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.Bullet;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent when an object needs to be drawn.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public class PaintObjectEvent : TypedEvent {
+
+    /**
+     * the GC
+     */
+    public GC gc;
+
+    /**
+     * the x location
+     */
+    public int x;
+
+    /**
+     * the y location
+     */
+    public int y;
+
+    /**
+     * the line ascent
+     */
+    public int ascent;
+
+    /**
+     * the line descent
+     */
+    public int descent;
+
+    /**
+     * the StyleRange
+     */
+    public StyleRange style;
+
+    /**
+     * the Bullet
+     */
+    public Bullet bullet;
+
+    /**
+     * the bullet index
+     */
+    public int bulletIndex;
+
+    static final long serialVersionUID = 3906081274027192855L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given event.
+ *
+ * @param e the event containing the information
+ */
+public this(StyledTextEvent e) {
+    super(cast(Object)e);
+    gc = e.gc;
+    x = e.x;
+    y = e.y;
+    ascent = e.ascent;
+    descent = e.descent;
+    style = e.style;
+    bullet = e.bullet;
+    bulletIndex = e.bulletIndex;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PaintObjectListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.PaintObjectListener;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.PaintObjectEvent;
+
+/**
+ * This listener is invoked when an object needs to be drawn.
+ *
+ * @since 3.2
+ */
+public interface PaintObjectListener : SWTEventListener {
+/**
+ * This method is called when an object needs to be drawn.
+ *
+ * <p>
+ * The following event fields are used:<ul>
+ * <li>event.x the x location (input)</li>
+ * <li>event.y the y location (input)</li>
+ * <li>event.ascent the line ascent (input)</li>
+ * <li>event.descent the line descent (input)</li>
+ * <li>event.gc the gc (input)</li>
+ * <li>event.style the style (input)</li>
+ * </ul>
+ *
+ * @param event the event
+ *
+ * @see PaintObjectEvent
+ * @see StyledText#addPaintObjectListener(PaintObjectListener)
+ */
+public void paintObject(PaintObjectEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/PopupList.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.PopupList;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+* A PopupList is a list of selectable items that appears in its own shell positioned above
+* its parent shell.  It is used for selecting items when editing a Table cell (similar to the
+* list that appears when you open a Combo box).
+*
+* The list will be positioned so that it does not run off the screen and the largest number of items
+* are visible.  It may appear above the current cursor location or below it depending how close you
+* are to the edge of the screen.
+*
+* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+*/
+public class PopupList {
+    Shell  shell;
+    List   list;
+    int    minimumWidth;
+/**
+* Creates a PopupList above the specified shell.
+*
+* @param parent a Shell control which will be the parent of the new instance (cannot be null)
+*/
+public this(Shell parent) {
+    this (parent, 0);
+}
+/**
+* Creates a PopupList above the specified shell.
+*
+* @param parent a widget which will be the parent of the new instance (cannot be null)
+* @param style the style of widget to construct
+*
+* @since 3.0
+*/
+public this(Shell parent, int style) {
+    shell = new Shell(parent, checkStyle(style));
+
+    list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);
+
+    // close dialog if user selects outside of the shell
+    shell.addListener(SWT.Deactivate, new class() Listener {
+        public void handleEvent(Event e){
+            shell.setVisible (false);
+        }
+    });
+
+    // resize shell when list resizes
+    shell.addControlListener(new class() ControlListener {
+        public void controlMoved(ControlEvent e){}
+        public void controlResized(ControlEvent e){
+            Rectangle shellSize = shell.getClientArea();
+            list.setSize(shellSize.width, shellSize.height);
+        }
+    });
+
+    // return list selection on Mouse Up or Carriage Return
+    list.addMouseListener(new class() MouseListener {
+        public void mouseDoubleClick(MouseEvent e){}
+        public void mouseDown(MouseEvent e){}
+        public void mouseUp(MouseEvent e){
+            shell.setVisible (false);
+        }
+    });
+    list.addKeyListener(new class() KeyListener {
+        public void keyReleased(KeyEvent e){}
+        public void keyPressed(KeyEvent e){
+            if (e.character is '\r'){
+                shell.setVisible (false);
+            }
+        }
+    });
+
+}
+private static int checkStyle (int style) {
+    int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    return style & mask;
+}
+/**
+* Gets the widget font.
+* <p>
+* @return the widget font
+*
+* @exception SWTException <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 Font getFont () {
+    return list.getFont();
+}
+/**
+* Gets the items.
+* <p>
+* This operation will fail if the items cannot
+* be queried from the OS.
+*
+* @return the items in the widget
+*
+* @exception SWTException <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 String[] getItems () {
+    return list.getItems();
+}
+/**
+* Gets the minimum width of the list.
+*
+* @return the minimum width of the list
+*/
+public int getMinimumWidth () {
+    return minimumWidth;
+}
+/**
+* Launches the Popup List, waits for an item to be selected and then closes the PopupList.
+*
+* @param rect the initial size and location of the PopupList; the dialog will be
+*        positioned so that it does not run off the screen and the largest number of items are visible
+*
+* @return the text of the selected item or null if no item is selected
+*/
+public String open (Rectangle rect) {
+
+    Point listSize = list.computeSize (rect.width, SWT.DEFAULT, false);
+    Rectangle screenSize = shell.getDisplay().getBounds();
+
+    // Position the dialog so that it does not run off the screen and the largest number of items are visible
+    int spaceBelow = screenSize.height - (rect.y + rect.height) - 30;
+    int spaceAbove = rect.y - 30;
+
+    int y = 0;
+    if (spaceAbove > spaceBelow && listSize.y > spaceBelow) {
+        // place popup list above table cell
+        if (listSize.y > spaceAbove){
+            listSize.y = spaceAbove;
+        } else {
+            listSize.y += 2;
+        }
+        y = rect.y - listSize.y;
+
+    } else {
+        // place popup list below table cell
+        if (listSize.y > spaceBelow){
+            listSize.y = spaceBelow;
+        } else {
+            listSize.y += 2;
+        }
+        y = rect.y + rect.height;
+    }
+
+    // Make dialog as wide as the cell
+    listSize.x = rect.width;
+    // dialog width should not be less than minimumWidth
+    if (listSize.x < minimumWidth)
+        listSize.x = minimumWidth;
+
+    // Align right side of dialog with right side of cell
+    int x = rect.x + rect.width - listSize.x;
+
+    shell.setBounds(x, y, listSize.x, listSize.y);
+
+    shell.open();
+    list.setFocus();
+
+    Display display = shell.getDisplay();
+    while (!shell.isDisposed () && shell.isVisible ()) {
+        if (!display.readAndDispatch()) display.sleep();
+    }
+
+    String result = null;
+    if (!shell.isDisposed ()) {
+        String [] strings = list.getSelection ();
+        shell.dispose();
+        if (strings.length !is 0) result = strings [0];
+    }
+    return result;
+}
+/**
+* Selects an item with text that starts with specified String.
+* <p>
+* If the item is not currently selected, it is selected.
+* If the item at an index is selected, it remains selected.
+* If the string is not matched, it is ignored.
+*
+* @param string the text of the item
+*
+* @exception SWTException <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 select(String string) {
+    String[] items = list.getItems();
+
+    // find the first entry in the list that starts with the
+    // specified string
+    if (string !is null){
+        for (int i = 0; i < items.length; i++) {
+            if ( tango.text.Util.locatePattern( items[i], string) is 0 ){
+                int index = list.indexOf(items[i]);
+                list.select(index);
+                break;
+            }
+        }
+    }
+}
+/**
+* Sets the widget font.
+* <p>
+* When new font is null, the font reverts
+* to the default system font for the widget.
+*
+* @param font the new font (or null)
+*
+* @exception SWTException <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 setFont (Font font) {
+    list.setFont(font);
+}
+/**
+* Sets all items.
+* <p>
+* The previous selection is cleared.
+* The previous items are deleted.
+* The new items are added.
+* The top index is set to 0.
+*
+* @param strings the array of items
+*
+* This operation will fail when an item is null
+* or could not be added in the OS.
+*
+* @exception IllegalArgumentException <ul>
+*    <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li>
+* </ul>
+* @exception SWTException <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 setItems (String[] strings) {
+    list.setItems(strings);
+}
+/**
+* Sets the minimum width of the list.
+*
+* @param width the minimum width of the list
+*/
+public void setMinimumWidth (int width) {
+    if (width < 0)
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    minimumWidth = width;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ST.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ST;
+
+
+/**
+ * This class provides access to the public constants provided by <code>StyledText</code>.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class ST {
+
+    /*
+     *  Navigation Key Actions. Key bindings for the actions are set
+     *  by the StyledText widget.
+     */
+    public static const int LINE_UP = 16777217;             // binding = SWT.ARROW_UP
+    public static const int LINE_DOWN = 16777218;       // binding = SWT.ARROW_DOWN
+    public static const int LINE_START = 16777223;      // binding = SWT.HOME
+    public static const int LINE_END = 16777224;        // binding = SWT.END
+    public static const int COLUMN_PREVIOUS = 16777219;     // binding = SWT.ARROW_LEFT
+    public static const int COLUMN_NEXT = 16777220;         // binding = SWT.ARROW_RIGHT
+    public static const int PAGE_UP = 16777221;             // binding = SWT.PAGE_UP
+    public static const int PAGE_DOWN = 16777222;       // binding = SWT.PAGE_DOWN
+    public static const int WORD_PREVIOUS = 17039363;   // binding = SWT.MOD1 + SWT.ARROW_LEFT
+    public static const int WORD_NEXT = 17039364;       // binding = SWT.MOD1 + SWT.ARROW_RIGHT
+    public static const int TEXT_START = 17039367;      // binding = SWT.MOD1 + SWT.HOME
+    public static const int TEXT_END = 17039368;        // binding = SWT.MOD1 + SWT.END
+    public static const int WINDOW_START = 17039365;    // binding = SWT.MOD1 + SWT.PAGE_UP
+    public static const int WINDOW_END = 17039366;      // binding = SWT.MOD1 + SWT.PAGE_DOWN
+
+    /*
+     * Selection Key Actions
+     */
+    public static const int SELECT_ALL = 262209;                // binding = SWT.MOD1 + 'A'
+    public static const int SELECT_LINE_UP = 16908289;          // binding = SWT.MOD2 + SWT.ARROW_UP
+    public static const int SELECT_LINE_DOWN = 16908290;        // binding = SWT.MOD2 + SWT.ARROW_DOWN
+    public static const int SELECT_LINE_START = 16908295;       // binding = SWT.MOD2 + SWT.HOME
+    public static const int SELECT_LINE_END = 16908296;             // binding = SWT.MOD2 + SWT.END
+    public static const int SELECT_COLUMN_PREVIOUS = 16908291;  // binding = SWT.MOD2 + SWT.ARROW_LEFT
+    public static const int SELECT_COLUMN_NEXT = 16908292;      // binding = SWT.MOD2 + SWT.ARROW_RIGHT
+    public static const int SELECT_PAGE_UP = 16908293;          // binding = SWT.MOD2 + SWT.PAGE_UP
+    public static const int SELECT_PAGE_DOWN = 16908294;        // binding = SWT.MOD2 + SWT.PAGE_DOWN
+    public static const int SELECT_WORD_PREVIOUS = 17170435;        // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_LEFT
+    public static const int SELECT_WORD_NEXT = 17170436;        // binding = SWT.MOD1 + SWT.MOD2 + SWT.ARROW_RIGHT
+    public static const int SELECT_TEXT_START = 17170439;       // binding = SWT.MOD1 + SWT.MOD2 + SWT.HOME
+    public static const int SELECT_TEXT_END = 17170440;             // binding = SWT.MOD1 + SWT.MOD2 + SWT.END
+    public static const int SELECT_WINDOW_START = 17170437;         // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_UP
+    public static const int SELECT_WINDOW_END = 17170438;       // binding = SWT.MOD1 + SWT.MOD2 + SWT.PAGE_DOWN
+
+    /*
+     *  Modification Key Actions
+     */
+    public static const int CUT = 131199;           // binding = SWT.MOD2 + SWT.DEL
+    public static const int COPY = 17039369;        // binding = SWT.MOD1 + SWT.INSERT;
+    public static const int PASTE = 16908297;       // binding = SWT.MOD2 + SWT.INSERT ;
+    public static const int DELETE_PREVIOUS = '\b';     // binding = SWT.BS;
+    public static const int DELETE_NEXT = 0x7F;         // binding = SWT.DEL;
+    public static const int DELETE_WORD_PREVIOUS = 262152;  // binding = SWT.BS | SWT.MOD1;
+    public static const int DELETE_WORD_NEXT = 262271;  // binding = SWT.DEL | SWT.MOD1;
+
+    /*
+     * Miscellaneous Key Actions
+     */
+    public static const int TOGGLE_OVERWRITE = 16777225; // binding = SWT.INSERT;
+
+    /**
+     *  Bullet style dot.
+     *
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_DOT = 1 << 0;
+
+    /**
+     *  Bullet style number.
+     *
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_NUMBER = 1 << 1;
+
+    /**
+     *  Bullet style lower case letter.
+     *
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_LETTER_LOWER = 1 << 2;
+
+    /**
+     *  Bullet style upper case letter.
+     *
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_LETTER_UPPER = 1 << 3;
+
+    /**
+     *  Bullet style text.
+     *
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_TEXT = 1 << 4;
+
+    /**
+     *  Bullet style custom draw.
+     *
+     *  @see StyledText#addPaintObjectListener(PaintObjectListener)
+     *  @see StyledText#removePaintObjectListener(PaintObjectListener)
+     *  @see Bullet
+     *
+     *  @since 3.2
+     */
+    public static const int BULLET_CUSTOM = 1 << 5;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashForm.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.SashForm;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.custom.SashFormLayout;
+import org.eclipse.swt.custom.SashFormData;
+import java.lang.all;
+
+/**
+ * The SashForm is a composite control that lays out its children in a
+ * row or column arrangement (as specified by the orientation) and places
+ * a Sash between each child. One child may be maximized to occupy the
+ * entire size of the SashForm.  The relative sizes of the children may
+ * be specified using weights.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL, SMOOTH</dd>
+ * </dl>
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#sashform">SashForm snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class SashForm : Composite {
+
+    /**
+    * The width of all sashes in the form.
+    */
+    public int SASH_WIDTH = 3;
+
+    int sashStyle;
+    Sash[] sashes;
+    // Remember background and foreground
+    // colors to determine whether to set
+    // sashes to the default color (null) or
+    // a specific color
+    Color background = null;
+    Color foreground = null;
+    Control[] controls;
+    Control maxControl = null;
+    Listener sashListener;
+    static const int DRAG_MINIMUM = 20;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle(style));
+    super.setLayout(new SashFormLayout());
+    sashStyle = ((style & SWT.VERTICAL) !is 0) ? SWT.HORIZONTAL : SWT.VERTICAL;
+    if ((style & SWT.BORDER) !is 0) sashStyle |= SWT.BORDER;
+    if ((style & SWT.SMOOTH) !is 0) sashStyle |= SWT.SMOOTH;
+    sashListener = new class() Listener {
+        public void handleEvent(Event e) {
+            onDragSash(e);
+        }
+    };
+}
+static int checkStyle (int style) {
+    int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    return style & mask;
+}
+/**
+ * Returns SWT.HORIZONTAL if the controls in the SashForm are laid out side by side
+ * or SWT.VERTICAL   if the controls in the SashForm are laid out top to bottom.
+ *
+ * @return SWT.HORIZONTAL or SWT.VERTICAL
+ */
+public int getOrientation() {
+    //checkWidget();
+    return (sashStyle & SWT.VERTICAL) !is 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
+}
+/**
+ * Returns the width of the sashes when the controls in the SashForm are 
+ * laid out.
+ * 
+ * @return the width of the sashes
+ * 
+ * @exception SWTException <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 SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
+    if ((sashStyle & SWT.SMOOTH) !is 0) style |= SWT.SMOOTH;
+    return style;
+}
+/**
+ * Answer the control that currently is maximized in the SashForm.
+ * This value may be null.
+ *
+ * @return the control that currently is maximized or null
+ */
+public Control getMaximizedControl(){
+    //checkWidget();
+    return this.maxControl;
+}
+/**
+ * Answer the relative weight of each child in the SashForm.  The weight represents the
+ * percent of the total width (if SashForm has Horizontal orientation) or
+ * total height (if SashForm has Vertical orientation) each control occupies.
+ * The weights are returned in order of the creation of the widgets (weight[0]
+ * corresponds to the weight of the first child created).
+ *
+ * @return the relative weight of each child
+ *
+ * @exception SWTException <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 int[] getWeights() {
+    checkWidget();
+    Control[] cArray = getControls(false);
+    int[] ratios = new int[cArray.length];
+    for (int i = 0; i < cArray.length; i++) {
+        Object data = cArray[i].getLayoutData();
+        if ( auto sfd = cast(SashFormData)data ) {
+            ratios[i] = cast(int)(sfd.weight * 1000 >> 16);
+        } else {
+            ratios[i] = 200;
+        }
+    }
+    return ratios;
+}
+Control[] getControls(bool onlyVisible) {
+    Control[] children = getChildren();
+    Control[] result = new Control[0];
+    for (int i = 0; i < children.length; i++) {
+        if ( null !is cast(Sash)children[i]) continue;
+        if (onlyVisible && !children[i].getVisible()) continue;
+
+        Control[] newResult = new Control[result.length + 1];
+        System.arraycopy(result, 0, newResult, 0, result.length);
+        newResult[result.length] = children[i];
+        result = newResult;
+    }
+    return result;
+}
+void onDragSash(Event event) {
+    Sash sash = cast(Sash)event.widget;
+    int sashIndex = -1;
+    for (int i= 0; i < sashes.length; i++) {
+        if (sashes[i] is sash) {
+            sashIndex = i;
+            break;
+        }
+    }
+    if (sashIndex is -1) return;
+
+    Control c1 = controls[sashIndex];
+    Control c2 = controls[sashIndex + 1];
+    Rectangle b1 = c1.getBounds();
+    Rectangle b2 = c2.getBounds();
+
+    Rectangle sashBounds = sash.getBounds();
+    Rectangle area = getClientArea();
+    bool correction = false;
+    if (getOrientation() is SWT.HORIZONTAL) {
+        correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
+        int totalWidth = b2.x + b2.width - b1.x;
+        int shift = event.x - sashBounds.x;
+        b1.width += shift;
+        b2.x += shift;
+        b2.width -= shift;
+        if (b1.width < DRAG_MINIMUM) {
+            b1.width = DRAG_MINIMUM;
+            b2.x = b1.x + b1.width + sashBounds.width;
+            b2.width = totalWidth - b2.x;
+            event.x = b1.x + b1.width;
+            event.doit = false;
+        }
+        if (b2.width < DRAG_MINIMUM) {
+            b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
+            b2.x = b1.x + b1.width + sashBounds.width;
+            b2.width = DRAG_MINIMUM;
+            event.x = b1.x + b1.width;
+            event.doit = false;
+        }
+        Object data1 = c1.getLayoutData();
+        if (data1 is null || !( null !is cast(SashFormData)data1 )) {
+            data1 = new SashFormData();
+            c1.setLayoutData(data1);
+        }
+        Object data2 = c2.getLayoutData();
+        if (data2 is null || !( null !is cast(SashFormData)data2 )) {
+            data2 = new SashFormData();
+            c2.setLayoutData(data2);
+        }
+        (cast(SashFormData)data1).weight = ((cast(long)b1.width << 16) + area.width - 1) / area.width;
+        (cast(SashFormData)data2).weight = ((cast(long)b2.width << 16) + area.width - 1) / area.width;
+    } else {
+        correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
+        int totalHeight = b2.y + b2.height - b1.y;
+        int shift = event.y - sashBounds.y;
+        b1.height += shift;
+        b2.y += shift;
+        b2.height -= shift;
+        if (b1.height < DRAG_MINIMUM) {
+            b1.height = DRAG_MINIMUM;
+            b2.y = b1.y + b1.height + sashBounds.height;
+            b2.height = totalHeight - b2.y;
+            event.y = b1.y + b1.height;
+            event.doit = false;
+        }
+        if (b2.height < DRAG_MINIMUM) {
+            b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
+            b2.y = b1.y + b1.height + sashBounds.height;
+            b2.height = DRAG_MINIMUM;
+            event.y = b1.y + b1.height;
+            event.doit = false;
+        }
+        Object data1 = c1.getLayoutData();
+        if (data1 is null || !( null !is cast(SashFormData)data1 )) {
+            data1 = new SashFormData();
+            c1.setLayoutData(data1);
+        }
+        Object data2 = c2.getLayoutData();
+        if (data2 is null || !(null !is cast(SashFormData)data2 )) {
+            data2 = new SashFormData();
+            c2.setLayoutData(data2);
+        }
+        (cast(SashFormData)data1).weight = ((cast(long)b1.height << 16) + area.height - 1) / area.height;
+        (cast(SashFormData)data2).weight = ((cast(long)b2.height << 16) + area.height - 1) / area.height;
+    }
+    if (correction || (event.doit && event.detail !is SWT.DRAG)) {
+        c1.setBounds(b1);
+        sash.setBounds(event.x, event.y, event.width, event.height);
+        c2.setBounds(b2);
+    }
+}
+/**
+ * If orientation is SWT.HORIZONTAL, lay the controls in the SashForm
+ * out side by side.  If orientation is SWT.VERTICAL, lay the
+ * controls in the SashForm out top to bottom.
+ *
+ * @param orientation SWT.HORIZONTAL or SWT.VERTICAL
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the value of orientation is not SWT.HORIZONTAL or SWT.VERTICAL
+ * </ul>
+ */
+public void setOrientation(int orientation) {
+    checkWidget();
+    if (getOrientation() is orientation) return;
+    if (orientation !is SWT.HORIZONTAL && orientation !is SWT.VERTICAL) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    sashStyle &= ~(SWT.HORIZONTAL | SWT.VERTICAL);
+    sashStyle |= orientation is SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
+    for (int i = 0; i < sashes.length; i++) {
+        sashes[i].dispose();
+        sashes[i] = new Sash(this, sashStyle);
+        sashes[i].setBackground(background);
+        sashes[i].setForeground(foreground);
+        sashes[i].addListener(SWT.Selection, sashListener);
+    }
+    layout(false);
+}
+public override void setBackground (Color color) {
+    super.setBackground(color);
+    background = color;
+    for (int i = 0; i < sashes.length; i++) {
+        sashes[i].setBackground(background);
+    }
+}
+public override void setForeground (Color color) {
+    super.setForeground(color);
+    foreground = color;
+    for (int i = 0; i < sashes.length; i++) {
+        sashes[i].setForeground(foreground);
+    }
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    checkWidget();
+    return;
+}
+/**
+ * Specify the control that should take up the entire client area of the SashForm.
+ * If one control has been maximized, and this method is called with a different control,
+ * the previous control will be minimized and the new control will be maximized.
+ * If the value of control is null, the SashForm will minimize all controls and return to
+ * the default layout where all controls are laid out separated by sashes.
+ *
+ * @param control the control to be maximized or null
+ *
+ * @exception SWTException <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 setMaximizedControl(Control control){
+    checkWidget();
+    if (control is null) {
+        if (maxControl !is null) {
+            this.maxControl = null;
+            layout(false);
+            for (int i= 0; i < sashes.length; i++){
+                sashes[i].setVisible(true);
+            }
+        }
+        return;
+    }
+
+    for (int i= 0; i < sashes.length; i++){
+        sashes[i].setVisible(false);
+    }
+    maxControl = control;
+    layout(false);
+}
+
+/**
+ * Specify the width of the sashes when the controls in the SashForm are 
+ * laid out.
+ * 
+ * @param width the width of the sashes
+ * 
+ * @exception SWTException <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.
+ * The weights must be positive values and there must be an entry for each
+ * non-sash child of the SashForm.
+ *
+ * @param weights the relative weight of each child
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - if the weights value is null or of incorrect length (must match the number of children)</li>
+ * </ul>
+ */
+public void setWeights(int[] weights) {
+    checkWidget();
+    Control[] cArray = getControls(false);
+    if (weights is null || weights.length !is cArray.length) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    int total = 0;
+    for (int i = 0; i < weights.length; i++) {
+        if (weights[i] < 0) {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        total += weights[i];
+    }
+    if (total is 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    for (int i = 0; i < cArray.length; i++) {
+        Object data = cArray[i].getLayoutData();
+        if (data is null || !( null !is cast(SashFormData)data )) {
+            data = new SashFormData();
+            cArray[i].setLayoutData(data);
+        }
+        (cast(SashFormData)data).weight = ((cast(long)weights[i] << 16) + total - 1) / total;
+    }
+
+    layout(false);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashFormData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.SashFormData;
+
+import java.lang.all;
+
+static import tango.text.Util;
+import tango.util.Convert;
+
+class SashFormData {
+
+    long weight;
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = tango.text.Util.locatePrior( string ,'.' );
+    if (index is string.length ) return string;
+    return string[ index + 1 .. $ ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString () {
+    return getName()~" {weight="~to!(String)(weight)~"}"; //$NON-NLS-2$
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/SashFormLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.SashFormLayout;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.SashFormData;
+import java.lang.all;
+
+/**
+ * This class provides the layout for SashForm
+ *
+ * @see SashForm
+ */
+class SashFormLayout : Layout {
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    SashForm sashForm = cast(SashForm)composite;
+    Control[] cArray = sashForm.getControls(true);
+    int width = 0;
+    int height = 0;
+    if (cArray.length is 0) {
+        if (wHint !is SWT.DEFAULT) width = wHint;
+        if (hHint !is SWT.DEFAULT) height = hHint;
+        return new Point(width, height);
+    }
+    // determine control sizes
+    bool vertical = sashForm.getOrientation() is SWT.VERTICAL;
+    int maxIndex = 0;
+    int maxValue = 0;
+    for (int i = 0; i < cArray.length; i++) {
+        if (vertical) {
+            Point size = cArray[i].computeSize(wHint, SWT.DEFAULT, flushCache);
+            if (size.y > maxValue) {
+                maxIndex = i;
+                maxValue = size.y;
+            }
+            width = Math.max(width, size.x);
+        } else {
+            Point size = cArray[i].computeSize(SWT.DEFAULT, hHint, flushCache);
+            if (size.x > maxValue) {
+                maxIndex = i;
+                maxValue = size.x;
+            }
+            height = Math.max(height, size.y);
+        }
+    }
+    // get the ratios
+    long[] ratios = new long[cArray.length];
+    long total = 0;
+    for (int i = 0; i < cArray.length; i++) {
+        Object data = cArray[i].getLayoutData();
+        if ( auto sfd = cast(SashFormData)data) {
+            ratios[i] = sfd.weight;
+        } else {
+            data = new SashFormData();
+            cArray[i].setLayoutData(data);
+            (cast(SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
+
+        }
+        total += ratios[i];
+    }
+    if (ratios[maxIndex] > 0) {
+        int sashwidth = sashForm.sashes.length > 0 ? sashForm.SASH_WIDTH + sashForm.sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
+        if (vertical) {
+            height += cast(int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
+        } else {
+            width += cast(int)(total * maxValue / ratios[maxIndex]) + (cArray.length - 1) * sashwidth;
+        }
+    }
+    width += sashForm.getBorderWidth()*2;
+    height += sashForm.getBorderWidth()*2;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    return new Point(width, height);
+}
+
+protected override bool flushCache(Control control) {
+    return true;
+}
+
+protected override void layout(Composite composite, bool flushCache) {
+    SashForm sashForm = cast(SashForm)composite;
+    Rectangle area = sashForm.getClientArea();
+    if (area.width <= 1 || area.height <= 1) return;
+
+    Control[] newControls = sashForm.getControls(true);
+    if (sashForm.controls.length is 0 && newControls.length is 0) return;
+    sashForm.controls = newControls;
+
+    Control[] controls = sashForm.controls;
+
+    if (sashForm.maxControl !is null && !sashForm.maxControl.isDisposed()) {
+        for (int i= 0; i < controls.length; i++){
+            if (controls[i] !is sashForm.maxControl) {
+                controls[i].setBounds(-200, -200, 0, 0);
+            } else {
+                controls[i].setBounds(area);
+            }
+        }
+        return;
+    }
+
+    // keep just the right number of sashes
+    if (sashForm.sashes.length < controls.length - 1) {
+        Sash[] newSashes = new Sash[controls.length - 1];
+        System.arraycopy(sashForm.sashes, 0, newSashes, 0, sashForm.sashes.length);
+        for (int i = sashForm.sashes.length; i < newSashes.length; i++) {
+            newSashes[i] = new Sash(sashForm, sashForm.sashStyle);
+            newSashes[i].setBackground(sashForm.background);
+            newSashes[i].setForeground(sashForm.foreground);
+            newSashes[i].addListener(SWT.Selection, sashForm.sashListener);
+        }
+        sashForm.sashes = newSashes;
+    }
+    if (sashForm.sashes.length > controls.length - 1) {
+        if (controls.length is 0) {
+            for (int i = 0; i < sashForm.sashes.length; i++) {
+                sashForm.sashes[i].dispose();
+            }
+            sashForm.sashes = new Sash[0];
+        } else {
+            Sash[] newSashes = new Sash[controls.length - 1];
+            System.arraycopy(sashForm.sashes, 0, newSashes, 0, newSashes.length);
+            for (int i = controls.length - 1; i < sashForm.sashes.length; i++) {
+                sashForm.sashes[i].dispose();
+            }
+            sashForm.sashes = newSashes;
+        }
+    }
+    if (controls.length is 0) return;
+    Sash[] sashes = sashForm.sashes;
+    // get the ratios
+    long[] ratios = new long[controls.length];
+    long total = 0;
+    for (int i = 0; i < controls.length; i++) {
+        Object data = controls[i].getLayoutData();
+        if ( auto sfd = cast(SashFormData)data ) {
+            ratios[i] = sfd.weight;
+        } else {
+            data = new SashFormData();
+            controls[i].setLayoutData(data);
+            (cast(SashFormData)data).weight = ratios[i] = ((200 << 16) + 999) / 1000;
+
+        }
+        total += ratios[i];
+    }
+
+    int sashwidth = sashes.length > 0 ? sashForm.SASH_WIDTH + sashes [0].getBorderWidth() * 2 : sashForm.SASH_WIDTH;
+    if (sashForm.getOrientation() is SWT.HORIZONTAL) {
+        int width = cast(int)(ratios[0] * (area.width - sashes.length * sashwidth) / total);
+        int x = area.x;
+        controls[0].setBounds(x, area.y, width, area.height);
+        x += width;
+        for (int i = 1; i < controls.length - 1; i++) {
+            sashes[i - 1].setBounds(x, area.y, sashwidth, area.height);
+            x += sashwidth;
+            width = cast(int)(ratios[i] * (area.width - sashes.length * sashwidth) / total);
+            controls[i].setBounds(x, area.y, width, area.height);
+            x += width;
+        }
+        if (controls.length > 1) {
+            sashes[sashes.length - 1].setBounds(x, area.y, sashwidth, area.height);
+            x += sashwidth;
+            width = area.width - x;
+            controls[controls.length - 1].setBounds(x, area.y, width, area.height);
+        }
+    } else {
+        int height = cast(int)(ratios[0] * (area.height - sashes.length * sashwidth) / total);
+        int y = area.y;
+        controls[0].setBounds(area.x, y, area.width, height);
+        y += height;
+        for (int i = 1; i < controls.length - 1; i++) {
+            sashes[i - 1].setBounds(area.x, y, area.width, sashwidth);
+            y += sashwidth;
+            height = cast(int)(ratios[i] * (area.height - sashes.length * sashwidth) / total);
+            controls[i].setBounds(area.x, y, area.width, height);
+            y += height;
+        }
+        if (controls.length > 1) {
+            sashes[sashes.length - 1].setBounds(area.x, y, area.width, sashwidth);
+            y += sashwidth;
+            height = area.height - y;
+            controls[controls.length - 1].setBounds(area.x, y, area.width, height);
+        }
+
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ScrolledComposite.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,709 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ScrolledComposite;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.custom.ScrolledCompositeLayout;
+
+/**
+ * A ScrolledComposite provides scrollbars and will scroll its content when the user
+ * uses the scrollbars.
+ *
+ *
+ * <p>There are two ways to use the ScrolledComposite:
+ *
+ * <p>
+ * 1) Set the size of the control that is being scrolled and the ScrolledComposite
+ * will show scrollbars when the contained control can not be fully seen.
+ *
+ * 2) The second way imitates the way a browser would work.  Set the minimum size of
+ * the control and the ScrolledComposite will show scroll bars if the visible area is
+ * less than the minimum size of the control and it will expand the size of the control
+ * if the visible area is greater than the minimum size.  This requires invoking
+ * both setMinWidth(), setMinHeight() and setExpandHorizontal(), setExpandVertical().
+ *
+ * <code><pre>
+ * public static void main (String [] args) {
+ *      Display display = new Display ();
+ *      Color red = display.getSystemColor(SWT.COLOR_RED);
+ *      Color blue = display.getSystemColor(SWT.COLOR_BLUE);
+ *      Shell shell = new Shell (display);
+ *      shell.setLayout(new FillLayout());
+ *
+ *      // set the size of the scrolled content - method 1
+ *      final ScrolledComposite sc1 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ *      final Composite c1 = new Composite(sc1, SWT.NONE);
+ *      sc1.setContent(c1);
+ *      c1.setBackground(red);
+ *      GridLayout layout = new GridLayout();
+ *      layout.numColumns = 4;
+ *      c1.setLayout(layout);
+ *      Button b1 = new Button (c1, SWT.PUSH);
+ *      b1.setText("first button");
+ *      c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *
+ *      // set the minimum width and height of the scrolled content - method 2
+ *      final ScrolledComposite sc2 = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ *      sc2.setExpandHorizontal(true);
+ *      sc2.setExpandVertical(true);
+ *      final Composite c2 = new Composite(sc2, SWT.NONE);
+ *      sc2.setContent(c2);
+ *      c2.setBackground(blue);
+ *      layout = new GridLayout();
+ *      layout.numColumns = 4;
+ *      c2.setLayout(layout);
+ *      Button b2 = new Button (c2, SWT.PUSH);
+ *      b2.setText("first button");
+ *      sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *
+ *      Button add = new Button (shell, SWT.PUSH);
+ *      add.setText("add children");
+ *      final int[] index = new int[]{0};
+ *      add.addListener(SWT.Selection, new Listener() {
+ *          public void handleEvent(Event e) {
+ *              index[0]++;
+ *              Button button = new Button(c1, SWT.PUSH);
+ *              button.setText("button "+index[0]);
+ *              // reset size of content so children can be seen - method 1
+ *              c1.setSize(c1.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *              c1.layout();
+ *
+ *              button = new Button(c2, SWT.PUSH);
+ *              button.setText("button "+index[0]);
+ *              // reset the minimum width and height so children can be seen - method 2
+ *              sc2.setMinSize(c2.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ *              c2.layout();
+ *          }
+ *      });
+ *
+ *      shell.open ();
+ *      while (!shell.isDisposed ()) {
+ *          if (!display.readAndDispatch ()) display.sleep ();
+ *      }
+ *      display.dispose ();
+ * }
+ * </pre></code>
+ *
+ * <dl>
+ * <dt><b>Styles:</b><dd>H_SCROLL, V_SCROLL
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#scrolledcomposite">ScrolledComposite snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class ScrolledComposite : Composite {
+
+    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
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#H_SCROLL
+ * @see SWT#V_SCROLL
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle(style));
+    super.setLayout(new ScrolledCompositeLayout());
+    ScrollBar hBar = getHorizontalBar ();
+    if (hBar !is null) {
+        hBar.setVisible(false);
+        hBar.addListener (SWT.Selection, new class() Listener  {
+            public void handleEvent (Event e) {
+                hScroll();
+            }
+        });
+    }
+
+    ScrollBar vBar = getVerticalBar ();
+    if (vBar !is null) {
+        vBar.setVisible(false);
+        vBar.addListener (SWT.Selection, new class() Listener {
+            public void handleEvent (Event e) {
+                vScroll();
+            }
+        });
+    }
+
+    contentListener = new class() Listener {
+        public void handleEvent(Event e) {
+            if (e.type !is SWT.Resize) return;
+            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(SWT.FocusIn, filter);
+        }
+    });
+}
+
+static int checkStyle (int style) {
+    int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    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
+ * visible when some part of the composite needs to be scrolled to be seen.
+ * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
+ * horizontal and vertical directions.
+ *
+ * @return the Always Show Scrollbars flag value
+ */
+public bool getAlwaysShowScrollBars() {
+    //checkWidget();
+    return alwaysShowScroll;
+}
+
+/**
+ * Returns <code>true</code> if the content control
+ * will be expanded to fill available horizontal space.
+ *
+ * @return the receiver's horizontal expansion state
+ *
+ * @exception SWTException <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.2
+ */
+public bool getExpandHorizontal() {
+    checkWidget();
+    return expandHorizontal;
+}
+
+/**
+ * Returns <code>true</code> if the content control
+ * will be expanded to fill available vertical space.
+ *
+ * @return the receiver's vertical expansion state
+ *
+ * @exception SWTException <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.2
+ */
+public bool getExpandVertical() {
+    checkWidget();
+    return expandVertical;
+}
+
+/**
+ * Returns the minimum width of the content control.
+ *
+ * @return the minimum width
+ *
+ * @exception SWTException <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.2
+ */
+public int getMinWidth() {
+    checkWidget();
+    return minWidth;
+}
+
+/**
+ * Returns the minimum height of the content control.
+ *
+ * @return the minimum height
+ *
+ * @exception SWTException <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.2
+ */
+public int getMinHeight() {
+    checkWidget();
+    return minHeight;
+}
+
+/**
+ * Get the content that is being scrolled.
+ *
+ * @return the control displayed in the content area
+ */
+public Control getContent() {
+    //checkWidget();
+    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>.
+ *
+ * @return a bool indicating whether focused child controls are automatically scrolled into the viewport
+ *
+ * @exception SWTException <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 ();
+    ScrollBar hBar = getHorizontalBar ();
+    int hSelection = hBar.getSelection ();
+    content.setLocation (-hSelection, location.y);
+}
+bool needHScroll(Rectangle contentRect, bool vVisible) {
+    ScrollBar hBar = getHorizontalBar();
+    if (hBar is null) return false;
+
+    Rectangle hostRect = getBounds();
+    int border = getBorderWidth();
+    hostRect.width -= 2*border;
+    ScrollBar vBar = getVerticalBar();
+    if (vVisible && vBar !is null) hostRect.width -= vBar.getSize().x;
+
+    if (!expandHorizontal && contentRect.width > hostRect.width) return true;
+    if (expandHorizontal && minWidth > hostRect.width) return true;
+    return false;
+}
+
+bool needVScroll(Rectangle contentRect, bool hVisible) {
+    ScrollBar vBar = getVerticalBar();
+    if (vBar is null) return false;
+
+    Rectangle hostRect = getBounds();
+    int border = getBorderWidth();
+    hostRect.height -= 2*border;
+    ScrollBar hBar = getHorizontalBar();
+    if (hVisible && hBar !is null) hostRect.height -= hBar.getSize().y;
+
+    if (!expandVertical && contentRect.height > hostRect.height) return true;
+    if (expandVertical && minHeight > hostRect.height) return true;
+    return false;
+}
+
+/**
+ * Return the point in the content that currently appears in the top left
+ * corner of the scrolled composite.
+ *
+ * @return the point in the content that currently appears in the top left
+ * corner of the scrolled composite.  If no content has been set, this returns
+ * (0, 0).
+ *
+ * @exception SWTException <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 2.0
+ */
+public Point getOrigin() {
+    checkWidget();
+    if (content is null) return new Point(0, 0);
+    Point location = content.getLocation();
+    return new Point(-location.x, -location.y);
+}
+/**
+ * Scrolls the content so that the specified point in the content is in the top
+ * left corner.  If no content has been set, nothing will occur.
+ *
+ * Negative values will be ignored.  Values greater than the maximum scroll
+ * distance will result in scrolling to the end of the scrollbar.
+ *
+ * @param origin the point on the content to appear in the top left corner
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_INVALID_ARGUMENT - value of origin is outside of content
+ * </ul>
+ * @since 2.0
+ */
+public void setOrigin(Point origin) {
+    setOrigin(origin.x, origin.y);
+}
+/**
+ * Scrolls the content so that the specified point in the content is in the top
+ * left corner.  If no content has been set, nothing will occur.
+ *
+ * Negative values will be ignored.  Values greater than the maximum scroll
+ * distance will result in scrolling to the end of the scrollbar.
+ *
+ * @param x the x coordinate of the content to appear in the top left corner
+ *
+ * @param y the y coordinate of the content to appear in the top left corner
+ *
+ * @exception SWTException <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 2.0
+ */
+public void setOrigin(int x, int y) {
+    checkWidget();
+    if (content is null) return;
+    ScrollBar hBar = getHorizontalBar ();
+    if (hBar !is null) {
+        hBar.setSelection(x);
+        x = -hBar.getSelection ();
+    } else {
+        x = 0;
+    }
+    ScrollBar vBar = getVerticalBar ();
+    if (vBar !is null) {
+        vBar.setSelection(y);
+        y = -vBar.getSelection ();
+    } else {
+        y = 0;
+    }
+    content.setLocation(x, y);
+}
+/**
+ * Set the Always Show Scrollbars flag.  True if the scrollbars are
+ * always shown even if they are not required.  False if the scrollbars are only
+ * visible when some part of the composite needs to be scrolled to be seen.
+ * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the
+ * horizontal and vertical directions.
+ *
+ * @param show true to show the scrollbars even when not required, false to show scrollbars only when required
+ *
+ * @exception SWTException <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 setAlwaysShowScrollBars(bool show) {
+    checkWidget();
+    if (show is alwaysShowScroll) return;
+    alwaysShowScroll = show;
+    ScrollBar hBar = getHorizontalBar ();
+    if (hBar !is null && alwaysShowScroll) hBar.setVisible(true);
+    ScrollBar vBar = getVerticalBar ();
+    if (vBar !is null && alwaysShowScroll) vBar.setVisible(true);
+    layout(false);
+}
+
+/**
+ * Set the content that will be scrolled.
+ *
+ * @param content the control to be displayed in the content area
+ *
+ * @exception SWTException <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 setContent(Control content) {
+    checkWidget();
+    if (this.content !is null && !this.content.isDisposed()) {
+        this.content.removeListener(SWT.Resize, contentListener);
+        this.content.setBounds(new Rectangle(-200, -200, 0, 0));
+    }
+
+    this.content = content;
+    ScrollBar vBar = getVerticalBar ();
+    ScrollBar hBar = getHorizontalBar ();
+    if (this.content !is null) {
+        if (vBar !is null) {
+            vBar.setMaximum (0);
+            vBar.setThumb (0);
+            vBar.setSelection(0);
+        }
+        if (hBar !is null) {
+            hBar.setMaximum (0);
+            hBar.setThumb (0);
+            hBar.setSelection(0);
+        }
+        content.setLocation(0, 0);
+        layout(false);
+        this.content.addListener(SWT.Resize, contentListener);
+    } else {
+        if (hBar !is null) hBar.setVisible(alwaysShowScroll);
+        if (vBar !is null) vBar.setVisible(alwaysShowScroll);
+    }
+}
+/**
+ * Configure the ScrolledComposite to resize the content object to be as wide as the
+ * ScrolledComposite when the width of the ScrolledComposite is greater than the
+ * minimum width specified in setMinWidth.  If the ScrolledComposite is less than the
+ * minimum width, the content will not be resized and instead the horizontal scroll bar will be
+ * used to view the entire width.
+ * If expand is false, this behaviour is turned off.  By default, this behaviour is turned off.
+ *
+ * @param expand true to expand the content control to fill available horizontal space
+ *
+ * @exception SWTException <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 setExpandHorizontal(bool expand) {
+    checkWidget();
+    if (expand is expandHorizontal) return;
+    expandHorizontal = expand;
+    layout(false);
+}
+/**
+ * Configure the ScrolledComposite to resize the content object to be as tall as the
+ * ScrolledComposite when the height of the ScrolledComposite is greater than the
+ * minimum height specified in setMinHeight.  If the ScrolledComposite is less than the
+ * minimum height, the content will not be resized and instead the vertical scroll bar will be
+ * used to view the entire height.
+ * If expand is false, this behaviour is turned off.  By default, this behaviour is turned off.
+ *
+ * @param expand true to expand the content control to fill available vertical space
+ *
+ * @exception SWTException <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 setExpandVertical(bool expand) {
+    checkWidget();
+    if (expand is expandVertical) return;
+    expandVertical = expand;
+    layout(false);
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    checkWidget();
+    return;
+}
+/**
+ * Specify the minimum height at which the ScrolledComposite will begin scrolling the
+ * content with the vertical scroll bar.  This value is only relevant if
+ * setExpandVertical(true) has been set.
+ *
+ * @param height the minimum height or 0 for default height
+ *
+ * @exception SWTException <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 setMinHeight(int height) {
+    setMinSize(minWidth, height);
+}
+/**
+ * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the
+ * content with the horizontal scroll bar.  This value is only relevant if
+ * setExpandHorizontal(true) and setExpandVertical(true) have been set.
+ *
+ * @param size the minimum size or null for the default size
+ *
+ * @exception SWTException <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 setMinSize(Point size) {
+    if (size is null) {
+        setMinSize(0, 0);
+    } else {
+        setMinSize(size.x, size.y);
+    }
+}
+/**
+ * Specify the minimum width and height at which the ScrolledComposite will begin scrolling the
+ * content with the horizontal scroll bar.  This value is only relevant if
+ * setExpandHorizontal(true) and setExpandVertical(true) have been set.
+ *
+ * @param width the minimum width or 0 for default width
+ * @param height the minimum height or 0 for default height
+ *
+ * @exception SWTException <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 setMinSize(int width, int height) {
+    checkWidget();
+    if (width is minWidth && height is minHeight) return;
+    minWidth = Math.max(0, width);
+    minHeight = Math.max(0, height);
+    layout(false);
+}
+/**
+ * Specify the minimum width at which the ScrolledComposite will begin scrolling the
+ * content with the horizontal scroll bar.  This value is only relevant if
+ * setExpandHorizontal(true) has been set.
+ *
+ * @param width the minimum width or 0 for default width
+ *
+ * @exception SWTException <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 setMinWidth(int width) {
+    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 SWTException <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(SWT.FocusIn, filter);
+    showFocusedControl = show;
+    if (!showFocusedControl) return;
+    display.addFilter(SWT.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 SWTException <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) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (control.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (!contains(control)) SWT.error(SWT.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 ();
+    ScrollBar vBar = getVerticalBar ();
+    int vSelection = vBar.getSelection ();
+    content.setLocation (location.x, -vSelection);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ScrolledCompositeLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ScrolledCompositeLayout;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.custom.ScrolledComposite;
+
+import Math = tango.math.Math;
+
+/**
+ * This class provides the layout for ScrolledComposite
+ *
+ * @see ScrolledComposite
+ */
+class ScrolledCompositeLayout : Layout {
+
+    bool inLayout = false;
+    static final int DEFAULT_WIDTH  = 64;
+    static final int DEFAULT_HEIGHT = 64;
+
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    ScrolledComposite sc = cast(ScrolledComposite)composite;
+    Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    if (sc.content !is null) {
+        Point preferredSize = sc.content.computeSize(wHint, hHint, flushCache);
+        Point currentSize = sc.content.getSize();
+        size.x = sc.getExpandHorizontal() ? preferredSize.x : currentSize.x;
+        size.y = sc.getExpandVertical() ? preferredSize.y : currentSize.y;
+    }
+    size.x = Math.max(size.x, sc.minWidth);
+    size.y = Math.max(size.y, sc.minHeight);
+    if (wHint !is SWT.DEFAULT) size.x = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+    return size;
+}
+
+protected override bool flushCache(Control control) {
+    return true;
+}
+
+protected override void layout(Composite composite, bool flushCache) {
+    if (inLayout) return;
+    ScrolledComposite sc = cast(ScrolledComposite)composite;
+    if (sc.content is null) return;
+    ScrollBar hBar = sc.getHorizontalBar();
+    ScrollBar vBar = sc.getVerticalBar();
+    if (hBar !is null) {
+        if (hBar.getSize().y >= sc.getSize().y) {
+            return;
+        }
+    }
+    if (vBar !is null) {
+        if (vBar.getSize().x >= sc.getSize().x) {
+            return;
+        }
+    }
+    inLayout = true;
+    Rectangle contentRect = sc.content.getBounds();
+    if (!sc.alwaysShowScroll) {
+        bool hVisible = sc.needHScroll(contentRect, false);
+        bool vVisible = sc.needVScroll(contentRect, hVisible);
+        if (!hVisible && vVisible) hVisible = sc.needHScroll(contentRect, vVisible);
+        if (hBar !is null) hBar.setVisible(hVisible);
+        if (vBar !is null) vBar.setVisible(vVisible);
+    }
+    Rectangle hostRect = sc.getClientArea();
+    if (sc.expandHorizontal) {
+        contentRect.width = Math.max(sc.minWidth, hostRect.width);
+    }
+    if (sc.expandVertical) {
+        contentRect.height = Math.max(sc.minHeight, hostRect.height);
+    }
+
+    if (hBar !is null) {
+        hBar.setMaximum (contentRect.width);
+        hBar.setThumb (Math.min (contentRect.width, hostRect.width));
+        int hPage = contentRect.width - hostRect.width;
+        int hSelection = hBar.getSelection ();
+        if (hSelection >= hPage) {
+            if (hPage <= 0) {
+                hSelection = 0;
+                hBar.setSelection(0);
+            }
+            contentRect.x = -hSelection;
+        }
+    }
+
+    if (vBar !is null) {
+        vBar.setMaximum (contentRect.height);
+        vBar.setThumb (Math.min (contentRect.height, hostRect.height));
+        int vPage = contentRect.height - hostRect.height;
+        int vSelection = vBar.getSelection ();
+        if (vSelection >= vPage) {
+            if (vPage <= 0) {
+                vSelection = 0;
+                vBar.setSelection(0);
+            }
+            contentRect.y = -vSelection;
+        }
+    }
+
+    sc.content.setBounds (contentRect);
+    inLayout = false;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StackLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StackLayout;
+
+import java.lang.all;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+
+import tango.util.Convert;
+static import tango.text.Util;
+
+/**
+ * This Layout stacks all the controls one on top of the other and resizes all controls
+ * to have the same size and location.
+ * The control specified in topControl is visible and all other controls are not visible.
+ * Users must set the topControl value to flip between the visible items and then call
+ * layout() on the composite which has the StackLayout.
+ *
+ * <p> Here is an example which places ten buttons in a stack layout and
+ * flips between them:
+ *
+ * <pre><code>
+ *  public static void main(String[] args) {
+ *      Display display = new Display();
+ *      Shell shell = new Shell(display);
+ *      shell.setLayout(new GridLayout());
+ *
+ *      final Composite parent = new Composite(shell, SWT.NONE);
+ *      parent.setLayoutData(new GridData(GridData.FILL_BOTH));
+ *      final StackLayout layout = new StackLayout();
+ *      parent.setLayout(layout);
+ *      final Button[] bArray = new Button[10];
+ *      for (int i = 0; i &lt; 10; i++) {
+ *          bArray[i] = new Button(parent, SWT.PUSH);
+ *          bArray[i].setText("Button "+i);
+ *      }
+ *      layout.topControl = bArray[0];
+ *
+ *      Button b = new Button(shell, SWT.PUSH);
+ *      b.setText("Show Next Button");
+ *      final int[] index = new int[1];
+ *      b.addListener(SWT.Selection, new Listener(){
+ *          public void handleEvent(Event e) {
+ *              index[0] = (index[0] + 1) % 10;
+ *              layout.topControl = bArray[index[0]];
+ *              parent.layout();
+ *          }
+ *      });
+ *
+ *      shell.open();
+ *      while (shell !is null && !shell.isDisposed()) {
+ *          if (!display.readAndDispatch())
+ *              display.sleep();
+ *      }
+ *  }
+ * </code></pre>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#stacklayout">StackLayout snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class StackLayout : Layout {
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the layout.
+     *
+     * The default value is 0.
+     */
+    public int marginWidth = 0;
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the layout.
+     *
+     * The default value is 0.
+     */
+    public int marginHeight = 0;
+
+    /**
+     * topControl the Control that is displayed at the top of the stack.
+     * All other controls that are children of the parent composite will not be visible.
+     */
+    public Control topControl;
+
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    Control children[] = composite.getChildren();
+    int maxWidth = 0;
+    int maxHeight = 0;
+    for (int i = 0; i < children.length; i++) {
+        Point size = children[i].computeSize(wHint, hHint, flushCache);
+        maxWidth = Math.max(size.x, maxWidth);
+        maxHeight = Math.max(size.y, maxHeight);
+    }
+    int width = maxWidth + 2 * marginWidth;
+    int height = maxHeight + 2 * marginHeight;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    return new Point(width, height);
+}
+
+protected override bool flushCache(Control control) {
+    return true;
+}
+
+protected override void layout(Composite composite, bool flushCache) {
+    Control children[] = composite.getChildren();
+    Rectangle rect = composite.getClientArea();
+    rect.x += marginWidth;
+    rect.y += marginHeight;
+    rect.width -= 2 * marginWidth;
+    rect.height -= 2 * marginHeight;
+    for (int i = 0; i < children.length; i++) {
+        children[i].setBounds(rect);
+        children[i].setVisible(children[i] is topControl);
+
+    }
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = tango.text.Util.locatePrior( string ,'.');
+    if (index is string.length ) return string;
+    return string[ index + 1 .. $ ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+public override String toString () {
+    String string = getName ()~" {";
+    if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+    if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+    if (topControl !is null) string ~= "topControl="~to!(String)(topControl)~" ";
+    string = tango.text.Util.trim(string);
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyleRange.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyleRange;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.internal.CloneableCompatibility;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.TextChangedEvent;
+import org.eclipse.swt.custom.TextChangingEvent;
+
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * <code>StyleRange</code> defines a set of styles for a specified
+ * range of text.
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class StyleRange : TextStyle, CloneableCompatibility {
+
+    /**
+     * the start offset of the range, zero-based from the document start
+     */
+    public int start;
+
+    /**
+     * the length of the range
+     */
+    public int length;
+
+    /**
+     * the font style of the range. It may be a combination of
+     * SWT.NORMAL, SWT.ITALIC or SWT.BOLD
+     *
+     * Note: the font style is not used if the <code>font</code> attribute
+     * is set
+     */
+    public int fontStyle = SWT.NORMAL;
+
+/**
+ * Create a new style range with no styles
+ *
+ * @since 3.2
+ */
+public this() {
+}
+/++
+ + SWT extension for clone implementation
+ +/
+protected this( StyleRange other ){
+    super( other );
+    start = other.start;
+    length = other.length;
+    fontStyle = other.fontStyle;
+}
+
+/**
+ * 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);
+}
+
+/**
+ * Create a new style range.
+ *
+ * @param start start offset of the style
+ * @param length length of the style
+ * @param foreground foreground color of the style, null if none
+ * @param background background color of the style, null if none
+ */
+public this(int start, int length, Color foreground, Color background) {
+    super(null, foreground, background);
+    this.start = start;
+    this.length = length;
+}
+
+/**
+ * Create a new style range.
+ *
+ * @param start start offset of the style
+ * @param length length of the style
+ * @param foreground foreground color of the style, null if none
+ * @param background background color of the style, null if none
+ * @param fontStyle font style of the style, may be SWT.NORMAL, SWT.ITALIC or SWT.BOLD
+ */
+public this(int start, int length, Color foreground, Color background, int fontStyle) {
+    this(start, length, foreground, background);
+    this.fontStyle = fontStyle;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals(Object object) {
+    if (object is this) return true;
+    if (auto style = cast(StyleRange) object ) {
+        if (start !is style.start) return false;
+        if (length !is style.length) return false;
+        return similarTo(style);
+    }
+    return false;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash() {
+    return super.toHash() ^ fontStyle;
+}
+bool isVariableHeight() {
+    return font !is null || metrics !is null || rise !is 0;
+}
+/**
+ * Returns whether or not the receiver is unstyled (i.e., does not have any
+ * style attributes specified).
+ *
+ * @return true if the receiver is unstyled, false otherwise.
+ */
+public bool isUnstyled() {
+    if (font !is null) return false;
+    if (rise !is 0) return false;
+    if (metrics !is null) return false;
+    if (foreground !is null) return false;
+    if (background !is null) return false;
+    if (fontStyle !is SWT.NORMAL) return false;
+    if (underline) return false;
+    if (strikeout) return false;
+    if (borderStyle !is SWT.NONE) return false;
+    return true;
+}
+
+/**
+ * Compares the specified object to this StyleRange and answer if the two
+ * are similar. The object must be an instance of StyleRange and have the
+ * same field values for except for start and length.
+ *
+ * @param style the object to compare with this object
+ * @return true if the objects are similar, false otherwise
+ */
+public bool similarTo(StyleRange style) {
+    if (!super.opEquals(style)) return false;
+    if (fontStyle !is style.fontStyle) return false;
+    return true;
+}
+
+/**
+ * Returns a new StyleRange with the same values as this StyleRange.
+ *
+ * @return a shallow copy of this StyleRange
+ */
+public /+override+/ Object clone() {
+    return new StyleRange( this );
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the StyleRange
+ */
+public override String toString() {
+    StringBuffer buffer = new StringBuffer();
+    buffer.append("StyleRange {");
+    buffer.append(start);
+    buffer.append(", ");
+    buffer.append(length);
+    buffer.append(", fontStyle=");
+    switch (fontStyle) {
+        case SWT.BOLD:
+            buffer.append("bold");
+            break;
+        case SWT.ITALIC:
+            buffer.append("italic");
+            break;
+        case SWT.BOLD | SWT.ITALIC:
+            buffer.append("bold-italic");
+            break;
+        default:
+            buffer.append("normal");
+    }
+    String str = super.toString();
+    int index = tango.text.Util.locate( str, '{');
+    if( index is str.length ) index = -1;
+    str = str[ index + 1 .. $ ];
+    if (str.length > 1) buffer.append(", ");
+    buffer.append(str);
+    return buffer.toString();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledText.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,8457 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledText;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.accessibility.AccessibleTextAdapter;
+import org.eclipse.swt.accessibility.AccessibleTextEvent;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.RTFTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GlyphMetrics;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.internal.BidiUtil;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.printing.Printer;
+import org.eclipse.swt.printing.PrinterData;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Caret;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.IME;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.custom.StyledTextContent;
+import org.eclipse.swt.custom.TextChangeListener;
+import org.eclipse.swt.custom.StyledTextRenderer;
+import org.eclipse.swt.custom.StyledTextPrintOptions;
+import org.eclipse.swt.custom.ExtendedModifyListener;
+import org.eclipse.swt.custom.BidiSegmentListener;
+import org.eclipse.swt.custom.LineBackgroundListener;
+import org.eclipse.swt.custom.LineStyleListener;
+import org.eclipse.swt.custom.PaintObjectListener;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.custom.MovementListener;
+import org.eclipse.swt.custom.Bullet;
+import org.eclipse.swt.custom.StyledTextEvent;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.TextChangedEvent;
+import org.eclipse.swt.custom.TextChangingEvent;
+import org.eclipse.swt.custom.DefaultContent;
+import org.eclipse.swt.custom.StyledTextDropTargetEffect;
+import org.eclipse.swt.custom.StyledTextListener;
+import org.eclipse.swt.custom.ST;
+import java.lang.Runnable;
+
+static import tango.text.Text;
+static import tango.text.Util;
+static import tango.io.model.IFile;
+static import tango.text.convert.Utf;
+import tango.util.Convert;
+import java.lang.all;
+
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * A StyledText is an editable user interface object that displays lines
+ * of text.  The following style attributes can be defined for the text:
+ * <ul>
+ * <li>foreground color
+ * <li>background color
+ * <li>font style (bold, italic, bold-italic, regular)
+ * <li>underline
+ * <li>strikeout
+ * </ul>
+ * <p>
+ * In addition to text style attributes, the background color of a line may
+ * be specified.
+ * </p><p>
+ * There are two ways to use this widget when specifying text style information.
+ * You may use the API that is defined for StyledText or you may define your own
+ * LineStyleListener.  If you define your own listener, you will be responsible
+ * for maintaining the text style information for the widget.  IMPORTANT: You may
+ * not define your own listener and use the StyledText API.  The following
+ * StyledText API is not supported if you have defined a LineStyleListener:
+ * <ul>
+ * <li>getStyleRangeAtOffset(int)
+ * <li>getStyleRanges()
+ * <li>replaceStyleRanges(int,int,StyleRange[])
+ * <li>setStyleRange(StyleRange)
+ * <li>setStyleRanges(StyleRange[])
+ * </ul>
+ * </p><p>
+ * There are two ways to use this widget when specifying line background colors.
+ * You may use the API that is defined for StyledText or you may define your own
+ * LineBackgroundListener.  If you define your own listener, you will be responsible
+ * for maintaining the line background color information for the widget.
+ * IMPORTANT: You may not define your own listener and use the StyledText API.
+ * The following StyledText API is not supported if you have defined a
+ * LineBackgroundListener:
+ * <ul>
+ * <li>getLineBackground(int)
+ * <li>setLineBackground(int,int,Color)
+ * </ul>
+ * </p><p>
+ * The content implementation for this widget may also be user-defined.  To do so,
+ * you must implement the StyledTextContent interface and use the StyledText API
+ * setContent(StyledTextContent) to initialize the widget.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b><dd>FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
+ * <dt><b>Events:</b><dd>ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#styledtext">StyledText snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: CustomControlExample, TextEditor</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class StyledText : Canvas {
+    alias Canvas.computeSize computeSize;
+
+    static const char TAB = '\t';
+    static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString;
+    static const int BIDI_CARET_WIDTH = 3;
+    static const int DEFAULT_WIDTH  = 64;
+    static const int DEFAULT_HEIGHT = 64;
+    static const int V_SCROLL_RATE = 50;
+    static const int H_SCROLL_RATE = 10;
+
+    static const int ExtendedModify = 3000;
+    static const int LineGetBackground = 3001;
+    static const int LineGetStyle = 3002;
+    static const int TextChanging = 3003;
+    static const int TextSet = 3004;
+    static const int VerifyKey = 3005;
+    static const int TextChanged = 3006;
+    static const int LineGetSegments = 3007;
+    static const int PaintObject = 3008;
+    static const int WordNext = 3009;
+    static const int WordPrevious = 3010;
+
+    static const int PREVIOUS_OFFSET_TRAILING = 0;
+    static const int OFFSET_LEADING = 1;
+
+    Color selectionBackground;  // selection background color
+    Color selectionForeground;  // selection foreground color
+    StyledTextContent content;          // native content (default or user specified)
+    StyledTextRenderer renderer;
+    Listener listener;
+    TextChangeListener textChangeListener;  // listener for TextChanging, TextChanged and TextSet events from StyledTextContent
+    int verticalScrollOffset = 0;       // pixel based
+    int horizontalScrollOffset = 0;     // pixel based
+    int topIndex = 0;                   // top visible line
+    int topIndexY;
+    int clientAreaHeight = 0;           // the client area height. Needed to calculate content width for new visible lines during Resize callback
+    int clientAreaWidth = 0;            // the client area width. Needed during Resize callback to determine if line wrap needs to be recalculated
+    int tabLength = 4;                  // number of characters in a tab
+    int leftMargin;
+    int topMargin;
+    int rightMargin;
+    int bottomMargin;
+    int columnX;                        // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
+    int caretOffset = 0;
+    int caretAlignment;
+    Point selection;                    // x and y are start and end caret offsets of selection
+    Point clipboardSelection;           // x and y are start and end caret offsets of previous selection
+    int selectionAnchor;                // position of selection anchor. 0 based offset from beginning of text
+    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
+    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
+    Color foreground = null;            //
+    Clipboard clipboard;
+    int clickCount;
+    int autoScrollDirection = SWT.NULL; // the direction of autoscrolling (up, down, right, left)
+    int autoScrollDistance = 0;
+    int lastTextChangeStart;            // cache data of the
+    int lastTextChangeNewLineCount;     // last text changing
+    int lastTextChangeNewCharCount;     // event for use in the
+    int lastTextChangeReplaceLineCount; // text changed handler
+    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
+    Image leftCaretBitmap = null;
+    Image rightCaretBitmap = null;
+    int caretDirection = SWT.NULL;
+    int caretWidth = 0;
+    Caret defaultCaret = null;
+    bool updateCaretDirection = true;
+    bool fixedLineHeight;
+    bool dragDetect_ = true;
+    IME ime;
+
+    int alignment;
+    bool justify;
+    int indent;
+    int lineSpacing;
+
+    const static bool IS_CARBON, IS_GTK, IS_MOTIF;
+    static this(){
+        String platform = SWT.getPlatform();
+        IS_CARBON = ("carbon" == platform);
+        IS_GTK    = ("gtk"    == platform);
+        IS_MOTIF  = ("motif"  == platform);
+    }
+
+    /**
+     * The Printing class : printing of a range of text.
+     * An instance of <code>Printing</code> is returned in the
+     * StyledText#print(Printer) API. The run() method may be
+     * invoked from any thread.
+     */
+    static class Printing : Runnable {
+        const static int LEFT = 0;                      // left aligned header/footer segment
+        const static int CENTER = 1;                    // centered header/footer segment
+        const static int RIGHT = 2;                     // right aligned header/footer segment
+
+        Printer printer;
+        StyledTextRenderer printerRenderer;
+        StyledTextPrintOptions printOptions;
+        Rectangle clientArea;
+        FontData fontData;
+        Font printerFont;
+        Resource[Resource] resources;
+        int tabLength;
+        GC gc;                                          // printer GC
+        int pageWidth;                                  // width of a printer page in pixels
+        int startPage;                                  // first page to print
+        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
+        Point selection = null;                 // selected text
+        bool mirrored;                       // indicates the printing gc should be mirrored
+        int lineSpacing;
+        int printMargin;
+
+    /**
+     * Creates an instance of <code>Printing</code>.
+     * Copies the widget content and rendering data that needs
+     * to be requested from listeners.
+     * </p>
+     * @param parent StyledText widget to print.
+     * @param printer printer device to print on.
+     * @param printOptions print options
+     */
+    this(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) {
+        this.printer = printer;
+        this.printOptions = printOptions;
+        this.mirrored = (styledText.getStyle() & SWT.MIRRORED) !is 0;
+        singleLine = styledText.isSingleLine();
+        startPage = 1;
+        endPage = int.max;
+        PrinterData data = printer.getPrinterData();
+        if (data.scope_ is PrinterData.PAGE_RANGE) {
+            startPage = data.startPage;
+            endPage = data.endPage;
+            if (endPage < startPage) {
+                int temp = endPage;
+                endPage = startPage;
+                startPage = temp;
+            }
+        } else if (data.scope_ is PrinterData.SELECTION) {
+            selection = styledText.getSelectionRange();
+        }
+        printerRenderer = new StyledTextRenderer(printer, null);
+        printerRenderer.setContent(copyContent(styledText.getContent()));
+        cacheLineData(styledText);
+    }
+    /**
+     * Caches all line data that needs to be requested from a listener.
+     * </p>
+     * @param printerContent <code>StyledTextContent</code> to request
+     *  line data for.
+     */
+    void cacheLineData(StyledText styledText) {
+        StyledTextRenderer renderer = styledText.renderer;
+        renderer.copyInto(printerRenderer);
+        fontData = styledText.getFont().getFontData()[0];
+        tabLength = styledText.tabLength;
+        int lineCount = printerRenderer.lineCount;
+        if (styledText.isListening(LineGetBackground) || (styledText.isBidi() && styledText.isListening(LineGetSegments)) || styledText.isListening(LineGetStyle)) {
+            StyledTextContent content = printerRenderer.content;
+            for (int i = 0; i < lineCount; i++) {
+                String line = content.getLine(i);
+                int lineOffset = content.getOffsetAtLine(i);
+                StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
+                if (event !is null && event.lineBackground !is null) {
+                    printerRenderer.setLineBackground(i, 1, event.lineBackground);
+                }
+                if (styledText.isBidi()) {
+                    int[] segments = styledText.getBidiSegments(lineOffset, line);
+                    printerRenderer.setLineSegments(i, 1, segments);
+                }
+                event = styledText.getLineStyleData(lineOffset, line);
+                if (event !is null) {
+                    printerRenderer.setLineIndent(i, 1, event.indent);
+                    printerRenderer.setLineAlignment(i, 1, event.alignment);
+                    printerRenderer.setLineJustify(i, 1, event.justify);
+                    printerRenderer.setLineBullet(i, 1, event.bullet);
+                    StyleRange[] styles = event.styles;
+                    if (styles !is null && styles.length > 0) {
+                        printerRenderer.setStyleRanges(event.ranges, styles);
+                    }
+                }
+            }
+        }
+        Point screenDPI = styledText.getDisplay().getDPI();
+        Point printerDPI = printer.getDPI();
+        resources = null;
+        for (int i = 0; i < lineCount; i++) {
+            Color color = printerRenderer.getLineBackground(i, null);
+            if (color !is null) {
+                if (printOptions.printLineBackground) {
+                    Color printerColor;
+                    if ( auto p = color in resources ) {
+                        printerColor = cast(Color)*p;
+                    }
+                    else {
+                        printerColor = new Color (printer, color.getRGB());
+                        resources[color]=printerColor;
+                    }
+                    printerRenderer.setLineBackground(i, 1, printerColor);
+                } else {
+                    printerRenderer.setLineBackground(i, 1, null);
+                }
+            }
+            int indent = printerRenderer.getLineIndent(i, 0);
+            if (indent !is 0) {
+                printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
+            }
+        }
+        StyleRange[] styles = printerRenderer.styles;
+        for (int i = 0; i < printerRenderer.styleCount; i++) {
+            StyleRange style = styles[i];
+            Font font = style.font;
+            if (style.font !is null) {
+                Font printerFont;
+                if ( auto p = font in resources ) {
+                    printerFont = cast(Font)*p;
+                }
+                else {
+                    printerFont = new Font (printer, font.getFontData());
+                    resources[font]= printerFont;
+                }
+                style.font = printerFont;
+            }
+            Color color = style.foreground;
+            if (color !is null) {
+                if (printOptions.printTextForeground) {
+                    Color printerColor;
+                    if ( auto p = color in resources ) {
+                        printerColor = cast(Color)*p;
+                    }
+                    else {
+                        printerColor = new Color (printer, color.getRGB());
+                        resources[color]=printerColor;
+                    }
+                    style.foreground = printerColor;
+                } else {
+                    style.foreground = null;
+                }
+            }
+            color = style.background;
+            if (color !is null) {
+                if (printOptions.printTextBackground) {
+                    Color printerColor;
+                    if ( auto p = color in resources ) {
+                        printerColor = cast(Color)*p;
+                    }
+                    else {
+                        printerColor = new Color (printer, color.getRGB());
+                        resources[color]=printerColor;
+                    }
+                    style.background = printerColor;
+                } else {
+                    style.background = null;
+                }
+            }
+            if (!printOptions.printTextFontStyle) {
+                style.fontStyle = SWT.NORMAL;
+            }
+            style.rise = style.rise * printerDPI.y / screenDPI.y;
+            GlyphMetrics metrics = style.metrics;
+            if (metrics !is null) {
+                metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
+                metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
+                metrics.width = metrics.width * printerDPI.x / screenDPI.x;
+            }
+        }
+        lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
+        if (printOptions.printLineNumbers) {
+            printMargin = 3 * printerDPI.x / screenDPI.x;
+        }
+    }
+    /**
+     * Copies the text of the specified <code>StyledTextContent</code>.
+     * </p>
+     * @param original the <code>StyledTextContent</code> to copy.
+     */
+    StyledTextContent copyContent(StyledTextContent original) {
+        StyledTextContent printerContent = new DefaultContent();
+        int insertOffset = 0;
+        for (int i = 0; i < original.getLineCount(); i++) {
+            int insertEndOffset;
+            if (i < original.getLineCount() - 1) {
+                insertEndOffset = original.getOffsetAtLine(i + 1);
+            } else {
+                insertEndOffset = original.getCharCount();
+            }
+            printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset));
+            insertOffset = insertEndOffset;
+        }
+        return printerContent;
+    }
+    /**
+     * Disposes of the resources and the <code>PrintRenderer</code>.
+     */
+    void dispose() {
+        if (gc !is null) {
+            gc.dispose();
+            gc = null;
+        }
+        foreach( resource; resources.values ){
+            resource.dispose();
+        }
+        resources = null;
+        if (printerFont !is null) {
+            printerFont.dispose();
+            printerFont = null;
+        }
+        if (printerRenderer !is null) {
+            printerRenderer.dispose();
+            printerRenderer = null;
+        }
+    }
+    void init_() {
+        Rectangle trim = printer.computeTrim(0, 0, 0, 0);
+        Point dpi = printer.getDPI();
+
+        printerFont = new Font( cast(Device)printer, fontData.getName(), fontData.getHeight(), SWT.NORMAL);
+        clientArea = printer.getClientArea();
+        pageWidth = clientArea.width;
+        // one inch margin around text
+        clientArea.x = dpi.x + trim.x;
+        clientArea.y = dpi.y + trim.y;
+        clientArea.width -= (clientArea.x + trim.width);
+        clientArea.height -= (clientArea.y + trim.height);
+
+        int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+        gc = new GC(printer, style);
+        gc.setFont(printerFont);
+        printerRenderer.setFont(printerFont, tabLength);
+        int lineHeight = printerRenderer.getLineHeight();
+        if (printOptions.header !is null) {
+            clientArea.y += lineHeight * 2;
+            clientArea.height -= lineHeight * 2;
+        }
+        if (printOptions.footer !is null) {
+            clientArea.height -= lineHeight * 2;
+        }
+
+        // TODO not wrapped
+        StyledTextContent content = printerRenderer.content;
+        startLine = 0;
+        endLine = singleLine ? 0 : content.getLineCount() - 1;
+        PrinterData data = printer.getPrinterData();
+        if (data.scope_ is PrinterData.PAGE_RANGE) {
+            int pageSize = clientArea.height / lineHeight;//WRONG
+            startLine = (startPage - 1) * pageSize;
+        } else if (data.scope_ is PrinterData.SELECTION) {
+            startLine = content.getLineAtOffset(selection.x);
+            if (selection.y > 0) {
+                endLine = content.getLineAtOffset(selection.x + selection.y - 1);
+            } else {
+                endLine = startLine - 1;
+            }
+        }
+    }
+    /**
+     * Prints the lines in the specified page range.
+     */
+    void print() {
+        Color background = gc.getBackground();
+        Color foreground = gc.getForeground();
+        int paintY = clientArea.y;
+        int paintX = clientArea.x;
+        int width = clientArea.width;
+        int page = startPage;
+        int pageBottom = clientArea.y + clientArea.height;
+        int orientation =  gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
+        TextLayout printLayout = null;
+        if (printOptions.printLineNumbers || printOptions.header !is null || printOptions.footer !is null) {
+            printLayout = new TextLayout(printer);
+            printLayout.setFont(printerFont);
+        }
+        if (printOptions.printLineNumbers) {
+            int numberingWidth = 0;
+            int count = endLine - startLine + 1;
+            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;
+        }
+        for (int i = startLine; i <= endLine && page <= endPage; i++) {
+            if (paintY is clientArea.y) {
+                printer.startPage();
+                printDecoration(page, true, printLayout);
+            }
+            TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing);
+            Color lineBackground = printerRenderer.getLineBackground(i, background);
+            int paragraphBottom = paintY + layout.getBounds().height;
+            if (paragraphBottom <= pageBottom) {
+                //normal case, the whole paragraph fits in the current page
+                printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+                paintY = paragraphBottom;
+            } else {
+                int lineCount = layout.getLineCount();
+                while (paragraphBottom > pageBottom && lineCount > 0) {
+                    lineCount--;
+                    paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing();
+                }
+                if (lineCount is 0) {
+                    //the whole paragraph goes to the next page
+                    printDecoration(page, false, printLayout);
+                    printer.endPage();
+                    page++;
+                    if (page <= endPage) {
+                        printer.startPage();
+                        printDecoration(page, true, printLayout);
+                        paintY = clientArea.y;
+                        printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+                        paintY += layout.getBounds().height;
+                    }
+                } else {
+                    //draw paragraph top in the current page and paragraph bottom in the next
+                    int height = paragraphBottom - paintY;
+                    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++;
+                    if (page <= endPage) {
+                        printer.startPage();
+                        printDecoration(page, true, printLayout);
+                        paintY = clientArea.y - height;
+                        int layoutHeight = layout.getBounds().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;
+                    }
+                }
+            }
+            printerRenderer.disposeTextLayout(layout);
+        }
+        if (page <= endPage && paintY > clientArea.y) {
+            // close partial page
+            printDecoration(page, false, printLayout);
+            printer.endPage();
+        }
+        if (printLayout !is null) printLayout.dispose();
+    }
+    /**
+     * Print header or footer decorations.
+     *
+     * @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
+     * @param header true = print the header, false = print the footer
+     */
+    void printDecoration(int page, bool header, TextLayout layout) {
+        String text = header ? printOptions.header : printOptions.footer;
+        if (text is null) return;
+        int lastSegmentIndex = 0;
+        for (int i = 0; i < 3; i++) {
+            int segmentIndex = text.indexOf( StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
+            String segment;
+            if (segmentIndex is -1 ) {
+                segment = text.substring(lastSegmentIndex);
+                printDecorationSegment(segment, i, page, header, layout);
+                break;
+            } else {
+                segment = text.substring(lastSegmentIndex, segmentIndex);
+                printDecorationSegment(segment, i, page, header, layout);
+                lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length;
+            }
+        }
+    }
+    /**
+     * Print one segment of a header or footer decoration.
+     * Headers and footers have three different segments.
+     * One each for left aligned, centered, and right aligned text.
+     *
+     * @param segment decoration segment to print
+     * @param alignment alignment of the segment. 0=left, 1=center, 2=right
+     * @param page page number to print, if specified in the decoration segment.
+     * @param header true = print the header, false = print the footer
+     */
+    void printDecorationSegment(String segment, int alignment, int page, bool header, TextLayout layout) {
+        int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
+        if (pageIndex !is -1 ) {
+            int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length;
+            StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex));
+            buffer.append (page);
+            buffer.append (segment.substring(pageIndex + pageTagLength));
+            segment = buffer.toString().dup;
+        }
+        if (segment.length > 0) {
+            layout.setText(segment);
+            int segmentWidth = layout.getBounds().width;
+            int segmentHeight = printerRenderer.getLineHeight();
+            int drawX = 0, drawY;
+            if (alignment is LEFT) {
+                drawX = clientArea.x;
+            } else if (alignment is CENTER) {
+                drawX = (pageWidth - segmentWidth) / 2;
+            } else if (alignment is RIGHT) {
+                drawX = clientArea.x + clientArea.width - segmentWidth;
+            }
+            if (header) {
+                drawY = clientArea.y - segmentHeight * 2;
+            } else {
+                drawY = clientArea.y + clientArea.height + segmentHeight;
+            }
+            layout.draw(gc, drawX, drawY);
+        }
+    }
+    void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) {
+        if (background !is null) {
+            Rectangle rect = layout.getBounds();
+            gc.setBackground(background);
+            gc.fillRectangle(x, y, rect.width, rect.height);
+
+//          int lineCount = layout.getLineCount();
+//          for (int i = 0; i < lineCount; i++) {
+//              Rectangle rect = layout.getLineBounds(i);
+//              rect.x += paintX;
+//              rect.y += paintY + layout.getSpacing();
+//              rect.width = width;//layout bounds
+//              gc.fillRectangle(rect);
+//          }
+        }
+        if (printOptions.printLineNumbers) {
+            FontMetrics metrics = layout.getLineMetrics(0);
+            printLayout.setAscent(metrics.getAscent() + metrics.getLeading());
+            printLayout.setDescent(metrics.getDescent());
+            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);
+            printLayout.setDescent(-1);
+        }
+        gc.setForeground(foreground);
+        layout.draw(gc, x, y);
+    }
+    /**
+     * Starts a print job and prints the pages specified in the constructor.
+     */
+    public void run() {
+        String jobName = printOptions.jobName;
+        if (jobName is null) {
+            jobName = "Printing";
+        }
+        if (printer.startJob(jobName)) {
+            init_();
+            print();
+            dispose();
+            printer.endJob();
+        }
+    }
+    }
+    /**
+     * The <code>RTFWriter</code> class is used to write widget content as
+     * rich text. The implementation complies with the RTF specification
+     * version 1.5.
+     * <p>
+     * toString() is guaranteed to return a valid RTF string only after
+     * close() has been called.
+     * </p><p>
+     * Whole and partial lines and line breaks can be written. Lines will be
+     * formatted using the styles queried from the LineStyleListener, if
+     * set, or those set directly in the widget. All styles are applied to
+     * the RTF stream like they are rendered by the widget. In addition, the
+     * widget font name and size is used for the whole text.
+     * </p>
+     */
+    class RTFWriter : TextWriter {
+
+        alias TextWriter.write write;
+
+        static const int DEFAULT_FOREGROUND = 0;
+        static const int DEFAULT_BACKGROUND = 1;
+        Color[] colorTable;
+        Font[] fontTable;
+        bool WriteUnicode;
+
+    /**
+     * Creates a RTF writer that writes content starting at offset "start"
+     * in the document.  <code>start</code> and <code>length</code>can be set to specify partial
+     * lines.
+     *
+     * @param start start offset of content to write, 0 based from
+     *  beginning of document
+     * @param length length of content to write
+     */
+    public this(int start, int length) {
+        super(start, length);
+        colorTable ~= getForeground();
+        colorTable ~= getBackground();
+        fontTable ~= getFont();
+        setUnicode();
+    }
+    /**
+     * Closes the RTF writer. Once closed no more content can be written.
+     * <b>NOTE:</b>  <code>toString()</code> does not return a valid RTF string until
+     * <code>close()</code> has been called.
+     */
+    public override void close() {
+        if (!isClosed()) {
+            writeHeader();
+            write("\n}}\0");
+            super.close();
+        }
+    }
+    /**
+     * Returns the index of the specified color in the RTF color table.
+     *
+     * @param color the color
+     * @param defaultIndex return value if color is null
+     * @return the index of the specified color in the RTF color table
+     *  or "defaultIndex" if "color" is null.
+     */
+    int getColorIndex(Color color, int defaultIndex) {
+        if (color is null) return defaultIndex;
+        int index = -1;
+        foreach( i, col; colorTable ){
+            if( col == color ){
+                index = i;
+                break;
+            }
+        }
+        if (index is -1) {
+            index = colorTable.length;
+            colorTable ~= color;
+        }
+        return index;
+    }
+    /**
+     * Returns the index of the specified color in the RTF color table.
+     *
+     * @param color the color
+     * @param defaultIndex return value if color is null
+     * @return the index of the specified color in the RTF color table
+     *  or "defaultIndex" if "color" is null.
+     */
+    int getFontIndex(Font font) {
+        int index = -1;
+        foreach( i, f; colorTable ){
+            if( f == font ){
+                index = i;
+                break;
+            }
+        }
+        if (index is -1) {
+            index = fontTable.length;
+            fontTable ~= font;
+        }
+        return index;
+    }
+    /**
+     * Determines if Unicode RTF should be written.
+     * Don't write Unicode RTF on Windows 95/98/ME or NT.
+     */
+    void setUnicode() {
+//         const String Win95 = "windows 95";
+//         const String Win98 = "windows 98";
+//         const String WinME = "windows me";
+//         const String WinNT = "windows nt";
+//         String osName = System.getProperty("os.name").toLowerCase();
+//         String osVersion = System.getProperty("os.version");
+//         int majorVersion = 0;
+//
+//         if (osName.startsWith(WinNT) && osVersion !is null) {
+//             int majorIndex = osVersion.indexOf('.');
+//             if (majorIndex !is -1) {
+//                 osVersion = osVersion.substring(0, majorIndex);
+//                 try {
+//                     majorVersion = Integer.parseInt(osVersion);
+//                 } catch (NumberFormatException exception) {
+//                     // ignore exception. version number remains unknown.
+//                     // will write without Unicode
+//                 }
+//             }
+//         }
+//         WriteUnicode =  !osName.startsWith(Win95) &&
+//                         !osName.startsWith(Win98) &&
+//                         !osName.startsWith(WinME) &&
+//                         (!osName.startsWith(WinNT) || majorVersion > 4);
+        WriteUnicode = true; // we are on linux-gtk
+    }
+    /**
+     * Appends the specified segment of "string" to the RTF data.
+     * Copy from <code>start</code> up to, but excluding, <code>end</code>.
+     *
+     * @param string string to copy a segment from. Must not contain
+     *  line breaks. Line breaks should be written using writeLineDelimiter()
+     * @param start start offset of segment. 0 based.
+     * @param end end offset of segment
+     */
+    void write(String string, int start, int end) {
+        start = 0;
+        end = string.length;
+        int incr = 1;
+        for (int index = start; index < end; index+=incr) {
+            dchar ch = firstCodePoint( string[index .. $], incr );
+            if (ch > 0xFF && WriteUnicode) {
+                // write the sub string from the last escaped character
+                // to the current one. Fixes bug 21698.
+                if (index > start) {
+                    write( string[start .. index ] );
+                }
+                write("\\u");
+                write( to!(String)( cast(short)ch ));
+                write(' ');                     // control word delimiter
+                start = index + incr;
+            } else if (ch is '}' || ch is '{' || ch is '\\') {
+                // write the sub string from the last escaped character
+                // to the current one. Fixes bug 21698.
+                if (index > start) {
+                    write(string[start .. index]);
+                }
+                write('\\');
+                write(cast(char)ch); // ok because one of {}\
+                start = index + 1;
+            }
+        }
+        // write from the last escaped character to the end.
+        // Fixes bug 21698.
+        if (start < end) {
+            write(string[ start .. end]);
+        }
+    }
+    /**
+     * Writes the RTF header including font table and color table.
+     */
+    void writeHeader() {
+        StringBuffer header = new StringBuffer();
+        FontData fontData = getFont().getFontData()[0];
+        header.append("{\\rtf1\\ansi");
+        // specify code page, necessary for copy to work in bidi
+        // systems that don't support Unicode RTF.
+        // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase();
+        String cpg = "UTF16";
+        /+
+        if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
+            cpg = cpg.substring(2, cpg.length());
+            header.append("\\ansicpg");
+            header.append(cpg);
+        }
+        +/
+        header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil ");
+        header.append(fontData.getName());
+        header.append(";");
+        for (int i = 1; i < fontTable.length; i++) {
+            header.append("\\f");
+            header.append(i);
+            header.append(" ");
+            FontData fd = (cast(Font)fontTable[i]).getFontData()[0];
+            header.append(fd.getName());
+            header.append(";");
+        }
+        header.append("}}\n{\\colortbl");
+        for (int i = 0; i < colorTable.length; i++) {
+            Color color = cast(Color) colorTable[i];
+            header.append("\\red");
+            header.append(color.getRed());
+            header.append("\\green");
+            header.append(color.getGreen());
+            header.append("\\blue");
+            header.append(color.getBlue());
+            header.append(";");
+        }
+        // some RTF readers ignore the deff0 font tag. Explicitly
+        // set the font for the whole document to work around this.
+        header.append("}\n{\\f0\\fs");
+        // font size is specified in half points
+        header.append(fontData.getHeight() * 2);
+        header.append(" ");
+        write(header.toString(), 0);
+    }
+    /**
+     * Appends the specified line text to the RTF data.  Lines will be formatted
+     * using the styles queried from the LineStyleListener, if set, or those set
+     * directly in the widget.
+     *
+     * @param line line text to write as RTF. Must not contain line breaks
+     *  Line breaks should be written using writeLineDelimiter()
+     * @param lineOffset offset of the line. 0 based from the start of the
+     *  widget document. Any text occurring before the start offset or after the
+     *  end offset specified during object creation is ignored.
+     * @exception SWTException <ul>
+     *   <li>ERROR_IO when the writer is closed.</li>
+     * </ul>
+     */
+    public override void writeLine(String line, int lineOffset) {
+        if (isClosed()) {
+            SWT.error(SWT.ERROR_IO);
+        }
+        int lineIndex = content.getLineAtOffset(lineOffset);
+        int lineAlignment, lineIndent;
+        bool lineJustify;
+        int[] ranges;
+        StyleRange[] styles;
+        StyledTextEvent event = getLineStyleData(lineOffset, line);
+        if (event !is null) {
+            lineAlignment = event.alignment;
+            lineIndent = event.indent;
+            lineJustify = event.justify;
+            ranges = event.ranges;
+            styles = event.styles;
+        } else {
+            lineAlignment = renderer.getLineAlignment(lineIndex, alignment);
+            lineIndent =  renderer.getLineIndent(lineIndex, indent);
+            lineJustify = renderer.getLineJustify(lineIndex, justify);
+            ranges = renderer.getRanges(lineOffset, line.length);
+            styles = renderer.getStyleRanges(lineOffset, line.length, false);
+        }
+        if (styles is null) styles = new StyleRange[0];
+        Color lineBackground = renderer.getLineBackground(lineIndex, null);
+        event = getLineBackgroundData(lineOffset, line);
+        if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground;
+        writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, lineAlignment, lineJustify);
+    }
+    /**
+     * Appends the specified line delimiter to the RTF data.
+     *
+     * @param lineDelimiter line delimiter to write as RTF.
+     * @exception SWTException <ul>
+     *   <li>ERROR_IO when the writer is closed.</li>
+     * </ul>
+     */
+    public override void writeLineDelimiter(String lineDelimiter) {
+        if (isClosed()) {
+            SWT.error(SWT.ERROR_IO);
+        }
+        write(lineDelimiter, 0, lineDelimiter.length);
+        write("\\par ");
+    }
+    /**
+     * Appends the specified line text to the RTF data.
+     * <p>
+     * Use the colors and font styles specified in "styles" and "lineBackground".
+     * Formatting is written to reflect the text rendering by the text widget.
+     * Style background colors take precedence over the line background color.
+     * Background colors are written using the \highlight tag (vs. the \cb tag).
+     * </p>
+     *
+     * @param line line text to write as RTF. Must not contain line breaks
+     *  Line breaks should be written using writeLineDelimiter()
+     * @param lineOffset offset of the line. 0 based from the start of the
+     *  widget document. Any text occurring before the start offset or after the
+     *  end offset specified during object creation is ignored.
+     * @param styles styles to use for formatting. Must not be null.
+     * @param lineBackground line background color to use for formatting.
+     *  May be null.
+     */
+    void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, bool justify) {
+        int lineLength = line.length;
+        int startOffset = getStart();
+        int writeOffset = startOffset - lineOffset;
+        if (writeOffset >= lineLength) return;
+        int lineIndex = Math.max(0, writeOffset);
+
+        write("\\fi");
+        write(indent);
+        switch (alignment) {
+            case SWT.LEFT: write("\\ql"); break;
+            case SWT.CENTER: write("\\qc"); break;
+            case SWT.RIGHT: write("\\qr"); break;
+            default:
+        }
+        if (justify) write("\\qj");
+        write(" ");
+
+        if (lineBackground !is null) {
+            write("{\\highlight");
+            write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
+            write(" ");
+        }
+        int endOffset = startOffset + super.getCharCount();
+        int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
+        for (int i = 0; i < styles.length; i++) {
+            StyleRange style = styles[i];
+            int start, end;
+            if (ranges !is null) {
+                start = ranges[i << 1] - lineOffset;
+                end = start + ranges[(i << 1) + 1];
+            } else {
+                start = style.start - lineOffset;
+                end = start + style.length;
+            }
+            // skip over partial first line
+            if (end < writeOffset) {
+                continue;
+            }
+            // style starts beyond line end or RTF write end
+            if (start >= lineEndOffset) {
+                break;
+            }
+            // write any unstyled text
+            if (lineIndex < start) {
+                // copy to start of style
+                // style starting beyond end of write range or end of line
+                // is guarded against above.
+                write(line, lineIndex, start);
+                lineIndex = start;
+            }
+            // write styled text
+            write("{\\cf");
+            write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
+            int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
+            if (colorIndex !is DEFAULT_BACKGROUND) {
+                write("\\highlight");
+                write(colorIndex);
+            }
+            Font font = style.font;
+            if (font !is null) {
+                int fontIndex = getFontIndex(font);
+                write("\\f");
+                write(fontIndex);
+                FontData fontData = font.getFontData()[0];
+                write("\\fs");
+                write(fontData.getHeight() * 2);
+            } else {
+                if ((style.fontStyle & SWT.BOLD) !is 0) {
+                    write("\\b");
+                }
+                if ((style.fontStyle & SWT.ITALIC) !is 0) {
+                    write("\\i");
+                }
+            }
+            if (style.underline) {
+                write("\\ul");
+            }
+            if (style.strikeout) {
+                write("\\strike");
+            }
+            write(" ");
+            // copy to end of style or end of write range or end of line
+            int copyEnd = Math.min(end, lineEndOffset);
+            // guard against invalid styles and let style processing continue
+            copyEnd = Math.max(copyEnd, lineIndex);
+            write(line, lineIndex, copyEnd);
+            if (font is null) {
+                if ((style.fontStyle & SWT.BOLD) !is 0) {
+                    write("\\b0");
+                }
+                if ((style.fontStyle & SWT.ITALIC) !is 0) {
+                    write("\\i0");
+                }
+            }
+            if (style.underline) {
+                write("\\ul0");
+            }
+            if (style.strikeout) {
+                write("\\strike0");
+            }
+            write("}");
+            lineIndex = copyEnd;
+        }
+        // write unstyled text at the end of the line
+        if (lineIndex < lineEndOffset) {
+            write(line, lineIndex, lineEndOffset);
+        }
+        if (lineBackground !is null) write("}");
+    }
+    }
+    /**
+     * The <code>TextWriter</code> class is used to write widget content to
+     * a string.  Whole and partial lines and line breaks can be written. To write
+     * partial lines, specify the start and length of the desired segment
+     * during object creation.
+     * <p>
+     * </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close()
+     * has been called.
+     * </p>
+     */
+    class TextWriter {
+        private StringBuffer buffer;
+        private int startOffset;    // offset of first character that will be written
+        private int endOffset;      // offset of last character that will be written.
+                                    // 0 based from the beginning of the widget text.
+        private bool isClosed_ = false;
+
+    /**
+     * Creates a writer that writes content starting at offset "start"
+     * in the document.  <code>start</code> and <code>length</code> can be set to specify partial lines.
+     *
+     * @param start start offset of content to write, 0 based from beginning of document
+     * @param length length of content to write
+     */
+    public this(int start, int length) {
+        buffer = new StringBuffer(length);
+        startOffset = start;
+        endOffset = start + length;
+    }
+    /**
+     * Closes the writer. Once closed no more content can be written.
+     * <b>NOTE:</b>  <code>toString()</code> is not guaranteed to return a valid string unless
+     * the writer is closed.
+     */
+    public void close() {
+        if (!isClosed_) {
+            isClosed_ = true;
+        }
+    }
+    /**
+     * Returns the number of characters to write.
+     * @return the integer number of characters to write
+     */
+    public int getCharCount() {
+        return endOffset - startOffset;
+    }
+    /**
+     * Returns the offset where writing starts. 0 based from the start of
+     * the widget text. Used to write partial lines.
+     * @return the integer offset where writing starts
+     */
+    public int getStart() {
+        return startOffset;
+    }
+    /**
+     * Returns whether the writer is closed.
+     * @return a bool specifying whether or not the writer is closed
+     */
+    public bool isClosed() {
+        return isClosed_;
+    }
+    /**
+     * Returns the string.  <code>close()</code> must be called before <code>toString()</code>
+     * is guaranteed to return a valid string.
+     *
+     * @return the string
+     */
+    public override String toString() {
+        return buffer.toString();
+    }
+    /**
+     * Appends the given string to the data.
+     */
+    void write(String string) {
+        buffer.append(string);
+    }
+    /**
+     * Inserts the given string to the data at the specified offset.
+     * <p>
+     * Do nothing if "offset" is < 0 or > getCharCount()
+     * </p>
+     *
+     * @param string text to insert
+     * @param offset offset in the existing data to insert "string" at.
+     */
+    void write(String string, int offset) {
+        if (offset < 0 || offset > buffer.length()) {
+            return;
+        }
+        buffer.select( offset );
+        buffer.prepend( string );
+    }
+    /**
+     * Appends the given int to the data.
+     */
+    void write(int i) {
+        buffer.append(i);
+    }
+    /**
+     * Appends the given character to the data.
+     */
+    void write(char i) {
+        buffer.append(i);
+    }
+    /**
+     * Appends the specified line text to the data.
+     *
+     * @param line line text to write. Must not contain line breaks
+     *  Line breaks should be written using writeLineDelimiter()
+     * @param lineOffset offset of the line. 0 based from the start of the
+     *  widget document. Any text occurring before the start offset or after the
+     *  end offset specified during object creation is ignored.
+     * @exception SWTException <ul>
+     *   <li>ERROR_IO when the writer is closed.</li>
+     * </ul>
+     */
+    public void writeLine(String line, int lineOffset) {
+        if (isClosed_) {
+            SWT.error(SWT.ERROR_IO);
+        }
+        int writeOffset = startOffset - lineOffset;
+        int lineLength = line.length;
+        int lineIndex;
+        if (writeOffset >= lineLength) {
+            return;                         // whole line is outside write range
+        } else if (writeOffset > 0) {
+            lineIndex = writeOffset;        // line starts before write start
+        } else {
+            lineIndex = 0;
+        }
+        int copyEnd = Math.min(lineLength, endOffset - lineOffset);
+        if (lineIndex < copyEnd) {
+            write(line.substring(lineIndex, copyEnd));
+        }
+    }
+    /**
+     * Appends the specified line delimiter to the data.
+     *
+     * @param lineDelimiter line delimiter to write
+     * @exception SWTException <ul>
+     *   <li>ERROR_IO when the writer is closed.</li>
+     * </ul>
+     */
+    public void writeLineDelimiter(String lineDelimiter) {
+        if (isClosed_) {
+            SWT.error(SWT.ERROR_IO);
+        }
+        write(lineDelimiter);
+    }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#FULL_SELECTION
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#SINGLE
+ * @see SWT#WRAP
+ * @see #getStyle
+ */
+public this(Composite parent, int style) {
+    selection = new Point(0, 0);
+    super(parent, checkStyle(style));
+    // set the fg in the OS to ensure that these are the same as StyledText, necessary
+    // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses
+    super.setForeground(getForeground());
+    super.setDragDetect(false);
+    Display display = getDisplay();
+    isMirrored_ = (super.getStyle() & SWT.MIRRORED) !is 0;
+    fixedLineHeight = true;
+    if ((style & SWT.READ_ONLY) !is 0) {
+        setEditable(false);
+    }
+    leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
+    if ((style & SWT.SINGLE) !is 0 && (style & SWT.BORDER) !is 0) {
+        leftMargin = topMargin = rightMargin = bottomMargin = 2;
+    }
+    alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    if (alignment is 0) alignment = SWT.LEFT;
+    clipboard = new Clipboard(display);
+    installDefaultContent();
+    renderer = new StyledTextRenderer(getDisplay(), this);
+    renderer.setContent(content);
+    renderer.setFont(getFont(), tabLength);
+    ime = new IME(this, SWT.NONE);
+    defaultCaret = new Caret(this, SWT.NONE);
+    if ((style & SWT.WRAP) !is 0) {
+        setWordWrap(true);
+    }
+    if (isBidiCaret()) {
+        createCaretBitmaps();
+        Runnable runnable = new class() Runnable {
+            public void run() {
+                int direction = BidiUtil.getKeyboardLanguage() is BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
+                if (direction is caretDirection) return;
+                if (getCaret() !is defaultCaret) return;
+                Point newCaretPos = getPointAtOffset(caretOffset);
+                setCaretLocation(newCaretPos, direction);
+            }
+        };
+        BidiUtil.addLanguageListener(this, runnable);
+    }
+    setCaret(defaultCaret);
+    calculateScrollBars();
+    createKeyBindings();
+    setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+    installListeners();
+    initializeAccessible();
+    setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this));
+}
+/**
+ * Adds an extended modify listener. An ExtendedModify event is sent by the
+ * widget when the widget text has changed.
+ *
+ * @param extendedModifyListener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
+    checkWidget();
+    if (extendedModifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    StyledTextListener typedListener = new StyledTextListener(extendedModifyListener);
+    addListener(ExtendedModify, typedListener);
+}
+/**
+ * Adds a bidirectional segment listener.
+ * <p>
+ * A BidiSegmentEvent is sent
+ * whenever a line of text is measured or rendered. The user can
+ * specify text ranges in the line that should be treated as if they
+ * had a different direction than the surrounding text.
+ * This may be used when adjacent segments of right-to-left text should
+ * not be reordered relative to each other.
+ * E.g., Multiple Java string literals in a right-to-left language
+ * should generally remain in logical order to each other, that is, the
+ * way they are stored.
+ * </p>
+ *
+ * @param listener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ * @see BidiSegmentEvent
+ * @since 2.0
+ */
+public void addBidiSegmentListener(BidiSegmentListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(LineGetSegments, new StyledTextListener(listener));
+}
+/**
+ * Adds a line background listener. A LineGetBackground event is sent by the
+ * widget to determine the background color for a line.
+ *
+ * @param listener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addLineBackgroundListener(LineBackgroundListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (!isListening(LineGetBackground)) {
+        renderer.clearLineBackground(0, content.getLineCount());
+    }
+    addListener(LineGetBackground, new StyledTextListener(listener));
+}
+/**
+ * Adds a line style listener. A LineGetStyle event is sent by the widget to
+ * determine the styles for a line.
+ *
+ * @param listener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addLineStyleListener(LineStyleListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (!isListening(LineGetStyle)) {
+        setStyleRanges(0, 0, null, null, true);
+        renderer.clearLineStyle(0, content.getLineCount());
+    }
+    addListener(LineGetStyle, new StyledTextListener(listener));
+}
+/**
+ * Adds a modify listener. A Modify event is sent by the widget when the widget text
+ * has changed.
+ *
+ * @param modifyListener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addModifyListener(ModifyListener modifyListener) {
+    checkWidget();
+    if (modifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(SWT.Modify, new TypedListener(modifyListener));
+}
+/**
+ * Adds a paint object listener. A paint object event is sent by the widget when an object
+ * needs to be drawn.
+ *
+ * @param listener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ *
+ * @since 3.2
+ *
+ * @see PaintObjectListener
+ * @see PaintObjectEvent
+ */
+public void addPaintObjectListener(PaintObjectListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(PaintObject, new StyledTextListener(listener));
+}
+/**
+ * Adds a selection listener. A Selection event is sent by the widget when the
+ * user changes the selection.
+ * <p>
+ * When <code>widgetSelected</code> is called, the event x and y fields contain
+ * the start and end caret indices of the selection.
+ * <code>widgetDefaultSelected</code> is not called for StyledTexts.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(SWT.Selection, new TypedListener(listener));
+}
+/**
+ * Adds a verify key listener. A VerifyKey event is sent by the widget when a key
+ * is pressed. The widget ignores the key press if the listener sets the doit field
+ * of the event to false.
+ *
+ * @param listener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addVerifyKeyListener(VerifyKeyListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(VerifyKey, new StyledTextListener(listener));
+}
+/**
+ * Adds a verify listener. A Verify event is sent by the widget when the widget text
+ * is about to change. The listener can set the event text and the doit field to
+ * change the text that is set in the widget or to force the widget to ignore the
+ * text change.
+ *
+ * @param verifyListener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addVerifyListener(VerifyListener verifyListener) {
+    checkWidget();
+    if (verifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(SWT.Verify, new TypedListener(verifyListener));
+}
+/**
+ * Adds a word movement listener. A movement event is sent when the boundary
+ * of a word is needed. For example, this occurs during word next and word
+ * previous actions.
+ *
+ * @param movementListener the listener
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ *
+ * @see MovementEvent
+ * @see MovementListener
+ * @see #removeWordMovementListener
+ *
+ * @since 3.3
+ */
+public void addWordMovementListener(MovementListener movementListener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    addListener(WordNext, new StyledTextListener(movementListener));
+    addListener(WordPrevious, new StyledTextListener(movementListener));
+}
+/**
+ * Appends a string to the text at the end of the widget.
+ *
+ * @param string the string to be appended
+ * @see #replaceTextRange(int,int,String)
+ * @exception SWTException <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 append(String string) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+//     if (string is null) {
+//         SWT.error(SWT.ERROR_NULL_ARGUMENT);
+//     }
+    int lastChar = Math.max(getCharCount(), 0);
+    replaceTextRange(lastChar, 0, string);
+}
+/**
+ * Calculates the scroll bars
+ */
+void calculateScrollBars() {
+    ScrollBar horizontalBar = getHorizontalBar();
+    ScrollBar verticalBar = getVerticalBar();
+    setScrollBars(true);
+    if (verticalBar !is null) {
+        verticalBar.setIncrement(getVerticalIncrement());
+    }
+    if (horizontalBar !is null) {
+        horizontalBar.setIncrement(getHorizontalIncrement());
+    }
+}
+/**
+ * Calculates the top index based on the current vertical scroll offset.
+ * The top index is the index of the topmost fully visible line or the
+ * topmost partially visible line if no line is fully visible.
+ * The top index starts at 0.
+ */
+void calculateTopIndex(int delta) {
+    int oldTopIndex = topIndex;
+    int oldTopIndexY = topIndexY;
+    if (isFixedLineHeight()) {
+        int verticalIncrement = getVerticalIncrement();
+        if (verticalIncrement is 0) {
+            return;
+        }
+        topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement);
+        // Set top index to partially visible top line if no line is fully
+        // visible but at least some of the widget client area is visible.
+        // Fixes bug 15088.
+        if (topIndex > 0) {
+            if (clientAreaHeight > 0) {
+                int bottomPixel = getVerticalScrollOffset() + clientAreaHeight;
+                int fullLineTopPixel = topIndex * verticalIncrement;
+                int fullLineVisibleHeight = bottomPixel - fullLineTopPixel;
+                // set top index to partially visible line if no line fully fits in
+                // client area or if space is available but not used (the latter should
+                // never happen because we use claimBottomFreeSpace)
+                if (fullLineVisibleHeight < verticalIncrement) {
+                    topIndex--;
+                }
+            } else if (topIndex >= content.getLineCount()) {
+                topIndex = content.getLineCount() - 1;
+            }
+        }
+    } else {
+        if (delta >= 0) {
+            delta -= topIndexY;
+            int lineIndex = topIndex;
+            int lineCount = content.getLineCount();
+            while (lineIndex < lineCount) {
+                if (delta <= 0) break;
+                delta -= renderer.getLineHeight(lineIndex++);
+            }
+            if (lineIndex < lineCount && -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+                topIndex = lineIndex;
+                topIndexY = -delta;
+            } else {
+                topIndex = lineIndex - 1;
+                topIndexY = -renderer.getLineHeight(topIndex) - delta;
+            }
+        } else {
+            delta -= topIndexY;
+            int lineIndex = topIndex;
+            while (lineIndex > 0) {
+                int lineHeight = renderer.getLineHeight(lineIndex - 1);
+                if (delta + lineHeight > 0) break;
+                delta += lineHeight;
+                lineIndex--;
+            }
+            if (lineIndex is 0 || -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
+                topIndex = lineIndex;
+                topIndexY = - delta;
+            } else {
+                topIndex = lineIndex - 1;
+                topIndexY = - renderer.getLineHeight(topIndex) - delta;
+            }
+        }
+    }
+    if (topIndex !is oldTopIndex || oldTopIndexY !is topIndexY) {
+        renderer.calculateClientArea();
+        setScrollBars(false);
+    }
+}
+/**
+ * Hides the scroll bars if widget is created in single line mode.
+ */
+static int checkStyle(int style) {
+    if ((style & SWT.SINGLE) !is 0) {
+        style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP | SWT.MULTI);
+    } else {
+        style |= SWT.MULTI;
+        if ((style & SWT.WRAP) !is 0) {
+            style &= ~SWT.H_SCROLL;
+        }
+    }
+    style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
+    return style;
+}
+/**
+ * Scrolls down the text to use new space made available by a resize or by
+ * deleted lines.
+ */
+void claimBottomFreeSpace() {
+    int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - clientAreaHeight);
+        if (newVerticalOffset < getVerticalScrollOffset()) {
+            scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true);
+        }
+    } else {
+        int bottomIndex = getPartialBottomIndex();
+        int height = getLinePixel(bottomIndex + 1);
+        if (clientAreaHeight > height) {
+            scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true);
+        }
+    }
+}
+/**
+ * Scrolls text to the right to use new space made available by a resize.
+ */
+void claimRightFreeSpace() {
+    int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin));
+    if (newHorizontalOffset < horizontalScrollOffset) {
+        // item is no longer drawn past the right border of the client area
+        // align the right end of the item with the right border of the
+        // client area (window is scrolled right).
+        scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true);
+    }
+}
+/**
+ * Removes the widget selection.
+ *
+ * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
+ */
+void clearSelection(bool sendEvent) {
+    int selectionStart = selection.x;
+    int selectionEnd = selection.y;
+    resetSelection();
+    // redraw old selection, if any
+    if (selectionEnd - selectionStart > 0) {
+        int length = content.getCharCount();
+        // called internally to remove selection after text is removed
+        // therefore make sure redraw range is valid.
+        int redrawStart = Math.min(selectionStart, length);
+        int redrawEnd = Math.min(selectionEnd, length);
+        if (redrawEnd - redrawStart > 0) {
+            internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+        }
+        if (sendEvent) {
+            sendSelectionEvent();
+        }
+    }
+}
+public override Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget();
+    int lineCount = (getStyle() & SWT.SINGLE) !is 0 ? 1 : content.getLineCount();
+    int width = 0;
+    int height = 0;
+    if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+        Display display = getDisplay();
+        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;
+        }
+        if (isFixedLineHeight()) {
+            height = lineCount * renderer.getLineHeight();
+        }
+    }
+    // Use default values if no text is defined.
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int wTrim = leftMargin + rightMargin + getCaretWidth();
+    int hTrim = topMargin + bottomMargin;
+    Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim);
+    return new Point (rect.width, rect.height);
+}
+/**
+ * Copies the selected text to the <code>DND.CLIPBOARD</code> clipboard.
+ * <p>
+ * The text will be put on the clipboard in plain text format and RTF format.
+ * The <code>DND.CLIPBOARD</code> clipboard is used for data that is
+ * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or
+ * by menu action.
+ * </p>
+ *
+ * @exception SWTException <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 copy() {
+    checkWidget();
+    copy(DND.CLIPBOARD);
+}
+/**
+ * Copies the selected text to the specified clipboard.  The text will be put in the
+ * clipboard in plain text format and RTF format.
+ * <p>
+ * The clipboardType is  one of the clipboard constants defined in class
+ * <code>DND</code>.  The <code>DND.CLIPBOARD</code>  clipboard is
+ * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V)
+ * or by menu action.  The <code>DND.SELECTION_CLIPBOARD</code>
+ * clipboard is used for data that is transferred by selecting text and pasting
+ * with the middle mouse button.
+ * </p>
+ *
+ * @param clipboardType indicates the type of clipboard
+ *
+ * @exception SWTException <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.1
+ */
+public void copy(int clipboardType) {
+    checkWidget();
+    if (clipboardType !is DND.CLIPBOARD && clipboardType !is DND.SELECTION_CLIPBOARD) return;
+    int length = selection.y - selection.x;
+    if (length > 0) {
+        try {
+            setClipboardContent(selection.x, length, clipboardType);
+        } catch (SWTError error) {
+            // Copy to clipboard failed. This happens when another application
+            // is accessing the clipboard while we copy. Ignore the error.
+            // Fixes 1GDQAVN
+            // Rethrow all other errors. Fixes bug 17578.
+            if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) {
+                throw error;
+            }
+        }
+    }
+}
+/**
+ * Returns the alignment of the widget.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <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 #getLineAlignment(int)
+ *
+ * @since 3.2
+ */
+public int getAlignment() {
+    checkWidget();
+    return alignment;
+}
+int getAvailableHeightAbove(int height) {
+    int maxHeight = verticalScrollOffset;
+    if (maxHeight is -1) {
+        int lineIndex = topIndex - 1;
+        maxHeight = -topIndexY;
+        if (topIndexY > 0) {
+            maxHeight += renderer.getLineHeight(lineIndex--);
+        }
+        while (height > maxHeight && lineIndex >= 0) {
+            maxHeight += renderer.getLineHeight(lineIndex--);
+        }
+    }
+    return Math.min(height, maxHeight);
+}
+int getAvailableHeightBellow(int height) {
+    int partialBottomIndex = getPartialBottomIndex();
+    int topY = getLinePixel(partialBottomIndex);
+    int lineHeight = renderer.getLineHeight(partialBottomIndex);
+    int availableHeight = 0;
+    int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+    if (topY + lineHeight > clientAreaHeight) {
+        availableHeight = lineHeight - (clientAreaHeight - topY);
+    }
+    int lineIndex = partialBottomIndex + 1;
+    int lineCount = content.getLineCount();
+    while (height > availableHeight && lineIndex < lineCount) {
+        availableHeight += renderer.getLineHeight(lineIndex++);
+    }
+    return Math.min(height, availableHeight);
+}
+/**
+ * Returns a string that uses only the line delimiter specified by the
+ * StyledTextContent implementation.
+ * <p>
+ * Returns only the first line if the widget has the SWT.SINGLE style.
+ * </p>
+ *
+ * @param text the text that may have line delimiters that don't
+ *  match the model line delimiter. Possible line delimiters
+ *  are CR ('\r'), LF ('\n'), CR/LF ("\r\n")
+ * @return the converted text that only uses the line delimiter
+ *  specified by the model. Returns only the first line if the widget
+ *  has the SWT.SINGLE style.
+ */
+String getModelDelimitedText(String text) {
+    int length = text.length;
+    if (length is 0) {
+        return text;
+    }
+    int crIndex = 0;
+    int lfIndex = 0;
+    int i = 0;
+    StringBuffer convertedText = new StringBuffer(length);
+    String delimiter = getLineDelimiter();
+    while (i < length) {
+        if (crIndex !is -1) {
+            crIndex = text.indexOf (SWT.CR, i);
+        }
+        if (lfIndex !is -1) {
+            lfIndex = text.indexOf (SWT.LF, i);
+        }
+        if (lfIndex is -1 && crIndex is -1) {   // no more line breaks?
+            break;
+        } else if ((crIndex < lfIndex && crIndex !is -1) || lfIndex is -1) {
+            convertedText.append(text.substring(i, crIndex));
+            if (lfIndex is crIndex + 1) {       // CR/LF combination?
+                i = lfIndex + 1;
+            } else {
+                i = crIndex + 1;
+            }
+        } else {                                    // LF occurs before CR!
+            convertedText.append(text.substring(i, lfIndex));
+            i = lfIndex + 1;
+        }
+        if (isSingleLine()) {
+            break;
+        }
+        convertedText.append(delimiter);
+    }
+    // copy remaining text if any and if not in single line mode or no
+    // text copied thus far (because there only is one line)
+    if (i < length && (!isSingleLine() || convertedText.length() is 0)) {
+        convertedText.append(text.substring(i));
+    }
+    return convertedText.toString();
+}
+bool checkDragDetect(Event event) {
+    if (!isListening(SWT.DragDetect)) return false;
+    if (IS_MOTIF) {
+        if (event.button !is 2) return false;
+    } else {
+        if (event.button !is 1) return false;
+    }
+    if (selection.x is selection.y) return false;
+    int offset = getOffsetAtPoint(event.x, event.y, null, true);
+    if (selection.x <= offset && offset < selection.y) {
+        return dragDetect(event);
+    }
+    return false;
+}
+/**
+ * Creates default key bindings.
+ */
+void createKeyBindings() {
+    int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+    int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+
+    // Navigation
+    setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);
+    setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
+    if (IS_CARBON) {
+        setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START);
+        setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END);
+        setKeyBinding(SWT.HOME, ST.TEXT_START);
+        setKeyBinding(SWT.END, ST.TEXT_END);
+        setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START);
+        setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END);
+        setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT);
+        setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS);
+    } else {
+        setKeyBinding(SWT.HOME, ST.LINE_START);
+        setKeyBinding(SWT.END, ST.LINE_END);
+        setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);
+        setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
+        setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT);
+        setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS);
+    }
+    setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
+    setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
+    setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
+    setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
+    setKeyBinding(nextKey, ST.COLUMN_NEXT);
+    setKeyBinding(previousKey, ST.COLUMN_PREVIOUS);
+
+    // Selection
+    setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);
+    setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
+    if (IS_CARBON) {
+        setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START);
+        setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END);
+        setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START);
+        setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END);
+        setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+        setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+        setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT);
+        setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS);
+    } else  {
+        setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
+        setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
+        setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);
+        setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
+        setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
+        setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
+    }
+    setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
+    setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
+    setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
+    setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
+    setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
+    setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
+
+    // Modification
+    // Cut, Copy, Paste
+    setKeyBinding('X' | SWT.MOD1, ST.CUT);
+    setKeyBinding('C' | SWT.MOD1, ST.COPY);
+    setKeyBinding('V' | SWT.MOD1, ST.PASTE);
+    if (IS_CARBON) {
+        setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT);
+        setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS);
+        setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT);
+    } else {
+        // Cut, Copy, Paste Wordstar style
+        setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT);
+        setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY);
+        setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE);
+    }
+    setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS);
+    setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS);
+    setKeyBinding(SWT.DEL, ST.DELETE_NEXT);
+    setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS);
+    setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT);
+
+    // Miscellaneous
+    setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE);
+}
+/**
+ * Create the bitmaps to use for the caret in bidi mode.  This
+ * method only needs to be called upon widget creation and when the
+ * font changes (the caret bitmap height needs to match font height).
+ */
+void createCaretBitmaps() {
+    int caretWidth = BIDI_CARET_WIDTH;
+    Display display = getDisplay();
+    if (leftCaretBitmap !is null) {
+        if (defaultCaret !is null && leftCaretBitmap==/*eq*/defaultCaret.getImage()) {
+            defaultCaret.setImage(null);
+        }
+        leftCaretBitmap.dispose();
+    }
+    int lineHeight = renderer.getLineHeight();
+    leftCaretBitmap = new Image(display, caretWidth, lineHeight);
+    GC gc = new GC (leftCaretBitmap);
+    gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+    gc.fillRectangle(0, 0, caretWidth, lineHeight);
+    gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+    gc.drawLine(0,0,0,lineHeight);
+    gc.drawLine(0,0,caretWidth-1,0);
+    gc.drawLine(0,1,1,1);
+    gc.dispose();
+
+    if (rightCaretBitmap !is null) {
+        if (defaultCaret !is null && rightCaretBitmap==/*eq*/defaultCaret.getImage()) {
+            defaultCaret.setImage(null);
+        }
+        rightCaretBitmap.dispose();
+    }
+    rightCaretBitmap = new Image(display, caretWidth, lineHeight);
+    gc = new GC (rightCaretBitmap);
+    gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+    gc.fillRectangle(0, 0, caretWidth, lineHeight);
+    gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+    gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
+    gc.drawLine(0,0,caretWidth-1,0);
+    gc.drawLine(caretWidth-1,1,1,1);
+    gc.dispose();
+}
+/**
+ * Moves the selected text to the clipboard.  The text will be put in the
+ * clipboard in plain text format and RTF format.
+ *
+ * @exception SWTException <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 cut(){
+    checkWidget();
+    int length = selection.y - selection.x;
+    if (length > 0) {
+        try {
+            setClipboardContent(selection.x, length, DND.CLIPBOARD);
+        } catch (SWTError error) {
+            // Copy to clipboard failed. This happens when another application
+            // is accessing the clipboard while we copy. Ignore the error.
+            // Fixes 1GDQAVN
+            // Rethrow all other errors. Fixes bug 17578.
+            if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) {
+                throw error;
+            }
+            // Abort cut operation if copy to clipboard fails.
+            // Fixes bug 21030.
+            return;
+        }
+        doDelete();
+    }
+}
+/**
+ * A mouse move event has occurred.  See if we should start autoscrolling.  If
+ * the move position is outside of the client area, initiate autoscrolling.
+ * Otherwise, we've moved back into the widget so end autoscrolling.
+ */
+void doAutoScroll(Event event) {
+    if (event.y > clientAreaHeight) {
+        doAutoScroll(SWT.DOWN, event.y - clientAreaHeight);
+    } else if (event.y < 0) {
+        doAutoScroll(SWT.UP, -event.y);
+    } else if (event.x < leftMargin && !wordWrap) {
+        doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
+    } else if (event.x > clientAreaWidth - leftMargin - rightMargin && !wordWrap) {
+        doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - leftMargin - rightMargin));
+    } else {
+        endAutoScroll();
+    }
+}
+/**
+ * Initiates autoscrolling.
+ *
+ * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
+ */
+void doAutoScroll(int direction, int distance) {
+    autoScrollDistance = distance;
+    // If we're already autoscrolling in the given direction do nothing
+    if (autoScrollDirection is direction) {
+        return;
+    }
+
+    Runnable timer = null;
+    final Display disp = getDisplay();
+    // Set a timer that will simulate the user pressing and holding
+    // down a cursor key (i.e., arrowUp, arrowDown).
+    if (direction is SWT.UP) {
+        timer = new class(disp) Runnable {
+            Display display;
+            this( Display d ){ this.display = d; }
+            public void run() {
+                if (autoScrollDirection is SWT.UP) {
+                    doSelectionPageUp(autoScrollDistance);
+                    display.timerExec(V_SCROLL_RATE, this);
+                }
+            }
+        };
+        autoScrollDirection = direction;
+        display.timerExec(V_SCROLL_RATE, timer);
+    } else if (direction is SWT.DOWN) {
+        timer = new class(disp) Runnable {
+            Display display;
+            this( Display d ){ this.display = d; }
+            public void run() {
+                if (autoScrollDirection is SWT.DOWN) {
+                    doSelectionPageDown(autoScrollDistance);
+                    display.timerExec(V_SCROLL_RATE, this);
+                }
+            }
+        };
+        autoScrollDirection = direction;
+        display.timerExec(V_SCROLL_RATE, timer);
+    } else if (direction is ST.COLUMN_NEXT) {
+        timer = new class(disp) Runnable {
+            Display display;
+            this( Display d ){ this.display = d; }
+            public void run() {
+                if (autoScrollDirection is ST.COLUMN_NEXT) {
+                    doVisualNext();
+                    setMouseWordSelectionAnchor();
+                    doMouseSelection();
+                    display.timerExec(H_SCROLL_RATE, this);
+                }
+            }
+        };
+        autoScrollDirection = direction;
+        display.timerExec(H_SCROLL_RATE, timer);
+    } else if (direction is ST.COLUMN_PREVIOUS) {
+        timer = new class(disp) Runnable {
+            Display display;
+            this( Display d ){ this.display = d; }
+            public void run() {
+                if (autoScrollDirection is ST.COLUMN_PREVIOUS) {
+                    doVisualPrevious();
+                    setMouseWordSelectionAnchor();
+                    doMouseSelection();
+                    display.timerExec(H_SCROLL_RATE, this);
+                }
+            }
+        };
+        autoScrollDirection = direction;
+        display.timerExec(H_SCROLL_RATE, timer);
+    }
+}
+/**
+ * Deletes the previous character. Delete the selected text if any.
+ * Move the caret in front of the deleted text.
+ */
+void doBackspace() {
+    Event event = new Event();
+    event.text = "";
+    if (selection.x !is selection.y) {
+        event.start = selection.x;
+        event.end = selection.y;
+        sendKeyEvent(event);
+    } else if (caretOffset > 0) {
+        int lineIndex = content.getLineAtOffset(caretOffset);
+        int lineOffset = content.getOffsetAtLine(lineIndex);
+        if (caretOffset is lineOffset) {
+            // SWT: on line start, delete line break
+            lineOffset = content.getOffsetAtLine(lineIndex - 1);
+            event.start = lineOffset + content.getLine(lineIndex - 1).length;
+            event.end = caretOffset;
+        } else {
+            TextLayout layout = renderer.getTextLayout(lineIndex);
+            int start = layout.getPreviousOffset(caretOffset - lineOffset, SWT.MOVEMENT_CLUSTER);
+            renderer.disposeTextLayout(layout);
+            event.start = start + lineOffset;
+            event.end = caretOffset;
+        }
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Replaces the selection with the character or insert the character at the
+ * current caret position if no selection exists.
+ * <p>
+ * If a carriage return was typed replace it with the line break character
+ * used by the widget on this platform.
+ * </p>
+ *
+ * @param key the character typed by the user
+ */
+void doContent(dchar key) {
+    Event event = new Event();
+    event.start = selection.x;
+    event.end = selection.y;
+    // replace a CR line break with the widget line break
+    // CR does not make sense on Windows since most (all?) applications
+    // don't recognize CR as a line break.
+    if (key is SWT.CR || key is SWT.LF) {
+        if (!isSingleLine()) {
+            event.text = getLineDelimiter();
+        }
+    } else if (selection.x is selection.y && overwrite && key !is TAB) {
+        // no selection and overwrite mode is on and the typed key is not a
+        // tab character (tabs are always inserted without overwriting)?
+        int lineIndex = content.getLineAtOffset(event.end);
+        int lineOffset = content.getOffsetAtLine(lineIndex);
+        String line = content.getLine(lineIndex);
+        // replace character at caret offset if the caret is not at the
+        // end of the line
+        if (event.end < lineOffset + line.length) {
+            event.end+=dcharToString( key ).length;
+        }
+        event.text = dcharToString( key );
+    } else {
+        event.text = dcharToString( key );
+    }
+    if (event.text !is null) {
+        if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) {
+            return;
+        }
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Moves the caret after the last character of the widget content.
+ */
+void doContentEnd() {
+    // place caret at end of first line if receiver is in single
+    // line mode. fixes 4820.
+    if (isSingleLine()) {
+        doLineEnd();
+    } else {
+        int length = content.getCharCount();
+        if (caretOffset < length) {
+            caretOffset = length;
+            showCaret();
+        }
+    }
+}
+/**
+ * Moves the caret in front of the first character of the widget content.
+ */
+void doContentStart() {
+    if (caretOffset > 0) {
+        caretOffset = 0;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret to the start of the selection if a selection exists.
+ * Otherwise, if no selection exists move the cursor according to the
+ * cursor selection rules.
+ *
+ * @see #doSelectionCursorPrevious
+ */
+void doCursorPrevious() {
+    if (selection.y - selection.x > 0) {
+        caretOffset = selection.x;
+        caretAlignment = OFFSET_LEADING;
+        showCaret();
+    } else {
+        doSelectionCursorPrevious();
+    }
+}
+/**
+ * Moves the caret to the end of the selection if a selection exists.
+ * Otherwise, if no selection exists move the cursor according to the
+ * cursor selection rules.
+ *
+ * @see #doSelectionCursorNext
+ */
+void doCursorNext() {
+    if (selection.y - selection.x > 0) {
+        caretOffset = selection.y;
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        showCaret();
+    } else {
+        doSelectionCursorNext();
+    }
+}
+/**
+ * Deletes the next character. Delete the selected text if any.
+ */
+void doDelete() {
+    Event event = new Event();
+    event.text = "";
+    if (selection.x !is selection.y) {
+        event.start = selection.x;
+        event.end = selection.y;
+        sendKeyEvent(event);
+    } else if (caretOffset < content.getCharCount()) {
+        int line = content.getLineAtOffset(caretOffset);
+        int lineOffset = content.getOffsetAtLine(line);
+        int lineLength = content.getLine(line).length;
+        if (caretOffset is lineOffset + lineLength) {
+            event.start = caretOffset;
+            event.end = content.getOffsetAtLine(line + 1);
+        } else {
+            event.start = caretOffset;
+            event.end = getClusterNext(caretOffset, line);
+        }
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Deletes the next word.
+ */
+void doDeleteWordNext() {
+    if (selection.x !is selection.y) {
+        // if a selection exists, treat the as if
+        // only the delete key was pressed
+        doDelete();
+    } else {
+        Event event = new Event();
+        event.text = "";
+        event.start = caretOffset;
+        event.end = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Deletes the previous word.
+ */
+void doDeleteWordPrevious() {
+    if (selection.x !is selection.y) {
+        // if a selection exists, treat as if
+        // only the backspace key was pressed
+        doBackspace();
+    } else {
+        Event event = new Event();
+        event.text = "";
+        event.start = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
+        event.end = caretOffset;
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Moves the caret one line down and to the same character offset relative
+ * to the beginning of the line. Move the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ */
+void doLineDown(bool select) {
+    int caretLine = getCaretLine();
+    int lineCount = content.getLineCount();
+    int y = 0;
+    bool lastLine = false;
+    if (wordWrap) {
+        int lineOffset = content.getOffsetAtLine(caretLine);
+        int offsetInLine = caretOffset - lineOffset;
+        TextLayout layout = renderer.getTextLayout(caretLine);
+        int lineIndex = getVisualLineIndex(layout, offsetInLine);
+        int layoutLineCount = layout.getLineCount();
+        if (lineIndex is layoutLineCount - 1) {
+            lastLine = caretLine is lineCount - 1;
+            caretLine++;
+        } else {
+            y = layout.getLineBounds(lineIndex + 1).y;
+        }
+        renderer.disposeTextLayout(layout);
+    } else {
+        lastLine = caretLine is lineCount - 1;
+        caretLine++;
+    }
+    if (lastLine) {
+        if (select) caretOffset = content.getCharCount();
+    } else {
+        caretOffset = getOffsetAtPoint(columnX, y, caretLine);
+    }
+    int oldColumnX = columnX;
+    int oldHScrollOffset = horizontalScrollOffset;
+    if (select) {
+        setMouseWordSelectionAnchor();
+        // select first and then scroll to reduce flash when key
+        // repeat scrolls lots of lines
+        doSelection(ST.COLUMN_NEXT);
+    }
+    showCaret();
+    int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+    columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the caret to the end of the line.
+ */
+void doLineEnd() {
+    int caretLine = getCaretLine();
+    int lineOffset = content.getOffsetAtLine(caretLine);
+    int lineEndOffset;
+    if (wordWrap) {
+        TextLayout layout = renderer.getTextLayout(caretLine);
+        int offsetInLine = caretOffset - lineOffset;
+        int lineIndex = getVisualLineIndex(layout, offsetInLine);
+        int[] offsets = layout.getLineOffsets();
+        lineEndOffset = lineOffset + offsets[lineIndex + 1];
+        renderer.disposeTextLayout(layout);
+    } else {
+        int lineLength = content.getLine(caretLine).length;
+        lineEndOffset = lineOffset + lineLength;
+    }
+    if (caretOffset < lineEndOffset) {
+        caretOffset = lineEndOffset;
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret to the beginning of the line.
+ */
+void doLineStart() {
+    int caretLine = getCaretLine();
+    int lineOffset = content.getOffsetAtLine(caretLine);
+    if (wordWrap) {
+        TextLayout layout = renderer.getTextLayout(caretLine);
+        int offsetInLine = caretOffset - lineOffset;
+        int lineIndex = getVisualLineIndex(layout, offsetInLine);
+        int[] offsets = layout.getLineOffsets();
+        lineOffset += offsets[lineIndex];
+        renderer.disposeTextLayout(layout);
+    }
+    if (caretOffset > lineOffset) {
+        caretOffset = lineOffset;
+        caretAlignment = OFFSET_LEADING;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret one line up and to the same character offset relative
+ * to the beginning of the line. Move the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ */
+void doLineUp(bool select) {
+    int caretLine = getCaretLine(), y = 0;
+    bool firstLine = false;
+    if (wordWrap) {
+        int lineOffset = content.getOffsetAtLine(caretLine);
+        int offsetInLine = caretOffset - lineOffset;
+        TextLayout layout = renderer.getTextLayout(caretLine);
+        int lineIndex = getVisualLineIndex(layout, offsetInLine);
+        if (lineIndex is 0) {
+            firstLine = caretLine is 0;
+            if (!firstLine) {
+                caretLine--;
+                y = renderer.getLineHeight(caretLine) - 1;
+            }
+        } else {
+            y = layout.getLineBounds(lineIndex - 1).y;
+        }
+        renderer.disposeTextLayout(layout);
+    } else {
+        firstLine = caretLine is 0;
+        caretLine--;
+    }
+    if (firstLine) {
+        if (select) caretOffset = 0;
+    } else {
+        caretOffset = getOffsetAtPoint(columnX, y, caretLine);
+    }
+    int oldColumnX = columnX;
+    int oldHScrollOffset = horizontalScrollOffset;
+    if (select) setMouseWordSelectionAnchor();
+    showCaret();
+    if (select) doSelection(ST.COLUMN_PREVIOUS);
+    int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+    columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the caret to the specified location.
+ *
+ * @param x x location of the new caret position
+ * @param y y location of the new caret position
+ * @param select the location change is a selection operation.
+ *  include the line delimiter in the selection
+ */
+void doMouseLocationChange(int x, int y, bool select) {
+    int line = getLineIndex(y);
+
+    updateCaretDirection = true;
+    // allow caret to be placed below first line only if receiver is
+    // not in single line mode. fixes 4820.
+    if (line < 0 || (isSingleLine() && line > 0)) {
+        return;
+    }
+    int oldCaretAlignment = caretAlignment;
+    int newCaretOffset = getOffsetAtPoint(x, y);
+
+    if (doubleClickEnabled && clickCount > 1) {
+        newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
+    }
+
+    int newCaretLine = content.getLineAtOffset(newCaretOffset);
+
+    // Is the mouse within the left client area border or on
+    // a different line? If not the autoscroll selection
+    // could be incorrectly reset. Fixes 1GKM3XS
+    if (0 <= y && y < clientAreaHeight &&
+        (0 <= x && x < clientAreaWidth || wordWrap ||
+        newCaretLine !is content.getLineAtOffset(caretOffset))) {
+        if (newCaretOffset !is caretOffset || caretAlignment !is oldCaretAlignment) {
+            caretOffset = newCaretOffset;
+            if (select) doMouseSelection();
+            showCaret();
+        }
+    }
+    if (!select) {
+        caretOffset = newCaretOffset;
+        clearSelection(true);
+    }
+}
+/**
+ * Updates the selection based on the caret position
+ */
+void doMouseSelection() {
+    if (caretOffset <= selection.x ||
+        (caretOffset > selection.x &&
+         caretOffset < selection.y && selectionAnchor is selection.x)) {
+        doSelection(ST.COLUMN_PREVIOUS);
+    } else {
+        doSelection(ST.COLUMN_NEXT);
+    }
+}
+/**
+ * Returns the offset of the word at the specified offset.
+ * If the current selection extends from high index to low index
+ * (i.e., right to left, or caret is at left border of selection on
+ * non-bidi platforms) the start offset of the word preceding the
+ * selection is returned. If the current selection extends from
+ * low index to high index the end offset of the word following
+ * the selection is returned.
+ *
+ * @param x mouse x location
+ * @param newCaretOffset caret offset of the mouse cursor location
+ * @param line line index of the mouse cursor location
+ */
+int doMouseWordSelect(int x, int newCaretOffset, int line) {
+    // flip selection anchor based on word selection direction from
+    // base double click. Always do this here (and don't rely on doAutoScroll)
+    // because auto scroll only does not cover all possible mouse selections
+    // (e.g., mouse x < 0 && mouse y > caret line y)
+    if (newCaretOffset < selectionAnchor && selectionAnchor is selection.x) {
+        selectionAnchor = doubleClickSelection.y;
+    } else if (newCaretOffset > selectionAnchor && selectionAnchor is selection.y) {
+        selectionAnchor = doubleClickSelection.x;
+    }
+    if (0 <= x && x < clientAreaWidth) {
+        bool wordSelect = (clickCount & 1) is 0;
+        if (caretOffset is selection.x) {
+            if (wordSelect) {
+                newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START);
+            } else {
+                newCaretOffset = content.getOffsetAtLine(line);
+            }
+        } else {
+            if (wordSelect) {
+                newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END);
+            } else {
+                int lineEnd = content.getCharCount();
+                if (line + 1 < content.getLineCount()) {
+                    lineEnd = content.getOffsetAtLine(line + 1);
+                }
+                newCaretOffset = lineEnd;
+            }
+        }
+    }
+    return newCaretOffset;
+}
+/**
+ * Scrolls one page down so that the last line (truncated or whole)
+ * of the current page becomes the fully visible top line.
+ * <p>
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the end
+ * of the text where a full page scroll is not possible. In this case
+ * the caret is moved after the last character.
+ * </p>
+ *
+ * @param select whether or not to select the page
+ */
+void doPageDown(bool select, int height) {
+    if (isSingleLine()) return;
+    int oldColumnX = columnX;
+    int oldHScrollOffset = horizontalScrollOffset;
+    if (isFixedLineHeight()) {
+        int lineCount = content.getLineCount();
+        int caretLine = getCaretLine();
+        if (caretLine < lineCount - 1) {
+            int lineHeight = renderer.getLineHeight();
+            int lines = (height is -1 ? clientAreaHeight : height) / lineHeight;
+            int scrollLines = Math.min(lineCount - caretLine - 1, lines);
+            // ensure that scrollLines never gets negative and at least one
+            // line is scrolled. fixes bug 5602.
+            scrollLines = Math.max(1, scrollLines);
+            caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines));
+            if (select) {
+                doSelection(ST.COLUMN_NEXT);
+            }
+            // scroll one page down or to the bottom
+            int verticalMaximum = lineCount * getVerticalIncrement();
+            int pageSize = clientAreaHeight;
+            int verticalScrollOffset = getVerticalScrollOffset();
+            int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
+            if (scrollOffset + pageSize > verticalMaximum) {
+                scrollOffset = verticalMaximum - pageSize;
+            }
+            if (scrollOffset > verticalScrollOffset) {
+                scrollVertical(scrollOffset - verticalScrollOffset, true);
+            }
+        }
+    } else {
+        int lineCount = content.getLineCount();
+        int caretLine = getCaretLine();
+        int lineIndex, lineHeight;
+        if (height is -1) {
+            lineIndex = getPartialBottomIndex();
+            int topY = getLinePixel(lineIndex);
+            lineHeight = renderer.getLineHeight(lineIndex);
+            height = topY;
+            if (topY + lineHeight <= clientAreaHeight) {
+                height += lineHeight;
+            } else {
+                if (wordWrap) {
+                    TextLayout layout = renderer.getTextLayout(lineIndex);
+                    int y = clientAreaHeight - topY;
+                    for (int i = 0; i < layout.getLineCount(); i++) {
+                        Rectangle bounds = layout.getLineBounds(i);
+                        if (bounds.contains(bounds.x, y)) {
+                            height += bounds.y;
+                            break;
+                        }
+                    }
+                    renderer.disposeTextLayout(layout);
+                }
+            }
+        } else {
+            lineIndex = getLineIndex(height);
+            int topLineY = getLinePixel(lineIndex);
+            if (wordWrap) {
+                TextLayout layout = renderer.getTextLayout(lineIndex);
+                int y = height - topLineY;
+                for (int i = 0; i < layout.getLineCount(); i++) {
+                    Rectangle bounds = layout.getLineBounds(i);
+                    if (bounds.contains(bounds.x, y)) {
+                        height = topLineY + bounds.y + bounds.height;
+                        break;
+                    }
+                }
+                renderer.disposeTextLayout(layout);
+            } else {
+                height = topLineY + renderer.getLineHeight(lineIndex);
+            }
+        }
+        int caretHeight = height;
+        if (wordWrap) {
+            TextLayout layout = renderer.getTextLayout(caretLine);
+            int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+            lineIndex = getVisualLineIndex(layout, offsetInLine);
+            caretHeight += layout.getLineBounds(lineIndex).y;
+            renderer.disposeTextLayout(layout);
+        }
+        lineIndex = caretLine;
+        lineHeight = renderer.getLineHeight(lineIndex);
+        while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) {
+            caretHeight -= lineHeight;
+            lineHeight = renderer.getLineHeight(++lineIndex);
+        }
+        caretOffset = getOffsetAtPoint(columnX, caretHeight, lineIndex);
+        if (select) doSelection(ST.COLUMN_NEXT);
+        height = getAvailableHeightBellow(height);
+        scrollVertical(height, true);
+        if (height is 0) setCaretLocation();
+    }
+    showCaret();
+    int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+    columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Moves the cursor to the end of the last fully visible line.
+ */
+void doPageEnd() {
+    // go to end of line if in single line mode. fixes 5673
+    if (isSingleLine()) {
+        doLineEnd();
+    } else {
+        int bottomOffset;
+        if (wordWrap) {
+            int lineIndex = getPartialBottomIndex();
+            TextLayout layout = renderer.getTextLayout(lineIndex);
+            int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex);
+            int index = layout.getLineCount() - 1;
+            while (index >= 0) {
+                Rectangle bounds = layout.getLineBounds(index);
+                if (y >= bounds.y + bounds.height) break;
+                index--;
+            }
+            if (index is -1 && lineIndex > 0) {
+                bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length;
+            } else {
+                bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
+            }
+            renderer.disposeTextLayout(layout);
+        } else {
+            int lineIndex = getBottomIndex();
+            bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length;
+        }
+        if (caretOffset < bottomOffset) {
+            caretOffset = bottomOffset;
+            caretAlignment = OFFSET_LEADING;
+            showCaret();
+        }
+    }
+}
+/**
+ * Moves the cursor to the beginning of the first fully visible line.
+ */
+void doPageStart() {
+    int topOffset;
+    if (wordWrap) {
+        int y, lineIndex;
+        if (topIndexY > 0) {
+            lineIndex = topIndex - 1;
+            y = renderer.getLineHeight(lineIndex) - topIndexY;
+        } else {
+            lineIndex = topIndex;
+            y = -topIndexY;
+        }
+        TextLayout layout = renderer.getTextLayout(lineIndex);
+        int index = 0;
+        int lineCount = layout.getLineCount();
+        while (index < lineCount) {
+            Rectangle bounds = layout.getLineBounds(index);
+            if (y <= bounds.y) break;
+            index++;
+        }
+        if (index is lineCount) {
+            topOffset = content.getOffsetAtLine(lineIndex + 1);
+        } else {
+            topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index];
+        }
+        renderer.disposeTextLayout(layout);
+    } else {
+        topOffset = content.getOffsetAtLine(topIndex);
+    }
+    if (caretOffset > topOffset) {
+        caretOffset = topOffset;
+        caretAlignment = OFFSET_LEADING;
+        showCaret();
+    }
+}
+/**
+ * Scrolls one page up so that the first line (truncated or whole)
+ * of the current page becomes the fully visible last line.
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the beginning
+ * of the text where a full page scroll is not possible. In this case the
+ * caret is moved in front of the first character.
+ */
+void doPageUp(bool select, int height) {
+    if (isSingleLine()) return;
+    int oldHScrollOffset = horizontalScrollOffset;
+    int oldColumnX = columnX;
+    if (isFixedLineHeight()) {
+        int caretLine = getCaretLine();
+        if (caretLine > 0) {
+            int lineHeight = renderer.getLineHeight();
+            int lines = (height is -1 ? clientAreaHeight : height) / lineHeight;
+            int scrollLines = Math.max(1, Math.min(caretLine, lines));
+            caretLine -= scrollLines;
+            caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine));
+            if (select) {
+                doSelection(ST.COLUMN_PREVIOUS);
+            }
+            int verticalScrollOffset = getVerticalScrollOffset();
+            int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
+            if (scrollOffset < verticalScrollOffset) {
+                scrollVertical(scrollOffset - verticalScrollOffset, true);
+            }
+        }
+    } else {
+        int caretLine = getCaretLine();
+        int lineHeight, lineIndex;
+        if (height is -1) {
+            if (topIndexY is 0) {
+                height = clientAreaHeight;
+            } else {
+                int y;
+                if (topIndex > 0) {
+                    lineIndex = topIndex - 1;
+                    lineHeight = renderer.getLineHeight(lineIndex);
+                    height = clientAreaHeight - topIndexY;
+                    y = lineHeight - topIndexY;
+                } else {
+                    lineIndex = topIndex;
+                    lineHeight = renderer.getLineHeight(lineIndex);
+                    height = clientAreaHeight - (lineHeight + topIndexY);
+                    y = -topIndexY;
+                }
+                if (wordWrap) {
+                    TextLayout layout = renderer.getTextLayout(lineIndex);
+                    for (int i = 0; i < layout.getLineCount(); i++) {
+                        Rectangle bounds = layout.getLineBounds(i);
+                        if (bounds.contains(bounds.x, y)) {
+                            height += lineHeight - (bounds.y + bounds.height);
+                            break;
+                        }
+                    }
+                    renderer.disposeTextLayout(layout);
+                }
+            }
+        } else {
+            lineIndex = getLineIndex(clientAreaHeight - height);
+            int topLineY = getLinePixel(lineIndex);
+            if (wordWrap) {
+                TextLayout layout = renderer.getTextLayout(lineIndex);
+                int y = topLineY;
+                for (int i = 0; i < layout.getLineCount(); i++) {
+                    Rectangle bounds = layout.getLineBounds(i);
+                    if (bounds.contains(bounds.x, y)) {
+                        height = clientAreaHeight - (topLineY + bounds.y);
+                        break;
+                    }
+                }
+                renderer.disposeTextLayout(layout);
+            } else {
+                height = clientAreaHeight - topLineY;
+            }
+        }
+        int caretHeight = height;
+        if (wordWrap) {
+            TextLayout layout = renderer.getTextLayout(caretLine);
+            int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
+            lineIndex = getVisualLineIndex(layout, offsetInLine);
+            caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y;
+            renderer.disposeTextLayout(layout);
+        }
+        lineIndex = caretLine;
+        lineHeight = renderer.getLineHeight(lineIndex);
+        while (caretHeight - lineHeight >= 0 && lineIndex > 0) {
+            caretHeight -= lineHeight;
+            lineHeight = renderer.getLineHeight(--lineIndex);
+        }
+        lineHeight = renderer.getLineHeight(lineIndex);
+        caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex);
+        if (select) doSelection(ST.COLUMN_PREVIOUS);
+        height = getAvailableHeightAbove(height);
+        scrollVertical(-height, true);
+        if (height is 0) setCaretLocation();
+    }
+    showCaret();
+    int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
+    columnX = oldColumnX + hScrollChange;
+}
+/**
+ * Updates the selection to extend to the current caret position.
+ */
+void doSelection(int direction) {
+    int redrawStart = -1;
+    int redrawEnd = -1;
+    if (selectionAnchor is -1) {
+        selectionAnchor = selection.x;
+    }
+    if (direction is ST.COLUMN_PREVIOUS) {
+        if (caretOffset < selection.x) {
+            // grow selection
+            redrawEnd = selection.x;
+            redrawStart = selection.x = caretOffset;
+            // check if selection has reversed direction
+            if (selection.y !is selectionAnchor) {
+                redrawEnd = selection.y;
+                selection.y = selectionAnchor;
+            }
+        // test whether selection actually changed. Fixes 1G71EO1
+        } else if (selectionAnchor is selection.x && caretOffset < selection.y) {
+            // caret moved towards selection anchor (left side of selection).
+            // shrink selection
+            redrawEnd = selection.y;
+            redrawStart = selection.y = caretOffset;
+        }
+    } else {
+        if (caretOffset > selection.y) {
+            // grow selection
+            redrawStart = selection.y;
+            redrawEnd = selection.y = caretOffset;
+            // check if selection has reversed direction
+            if (selection.x !is selectionAnchor) {
+                redrawStart = selection.x;
+                selection.x = selectionAnchor;
+            }
+        // test whether selection actually changed. Fixes 1G71EO1
+        } else if (selectionAnchor is selection.y && caretOffset > selection.x) {
+            // caret moved towards selection anchor (right side of selection).
+            // shrink selection
+            redrawStart = selection.x;
+            redrawEnd = selection.x = caretOffset;
+        }
+    }
+    if (redrawStart !is -1 && redrawEnd !is -1) {
+        internalRedrawRange(redrawStart, redrawEnd - redrawStart);
+        sendSelectionEvent();
+    }
+}
+/**
+ * Moves the caret to the next character or to the beginning of the
+ * next line if the cursor is at the end of a line.
+ */
+void doSelectionCursorNext() {
+    int caretLine = getCaretLine();
+    int lineOffset = content.getOffsetAtLine(caretLine);
+    int offsetInLine = caretOffset - lineOffset;
+    if (offsetInLine < content.getLine(caretLine).length) {
+        TextLayout layout = renderer.getTextLayout(caretLine);
+        offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+        int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)];
+        renderer.disposeTextLayout(layout);
+        caretOffset = offsetInLine + lineOffset;
+        caretAlignment = offsetInLine is lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
+        showCaret();
+    } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
+        caretLine++;
+        caretOffset = content.getOffsetAtLine(caretLine);
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret to the previous character or to the end of the previous
+ * line if the cursor is at the beginning of a line.
+ */
+void doSelectionCursorPrevious() {
+    int caretLine = getCaretLine();
+    int lineOffset = content.getOffsetAtLine(caretLine);
+    int offsetInLine = caretOffset - lineOffset;
+    caretAlignment = OFFSET_LEADING;
+
+    if (offsetInLine > 0) {
+        caretOffset = getClusterPrevious(caretOffset, caretLine);
+        showCaret();
+    } else if (caretLine > 0) {
+        caretLine--;
+        lineOffset = content.getOffsetAtLine(caretLine);
+        caretOffset = lineOffset + content.getLine(caretLine).length;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret one line down and to the same character offset relative
+ * to the beginning of the line. Moves the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ * Moves the caret to the end of the text if the caret already is on the
+ * last line.
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ */
+void doSelectionLineDown() {
+    int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+    doLineDown(true);
+    columnX = oldColumnX;
+}
+/**
+ * Moves the caret one line up and to the same character offset relative
+ * to the beginning of the line. Moves the caret to the end of the new line
+ * if the new line is shorter than the character offset.
+ * Moves the caret to the beginning of the document if it is already on the
+ * first line.
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ */
+void doSelectionLineUp() {
+    int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+    doLineUp(true);
+    columnX = oldColumnX;
+}
+/**
+ * Scrolls one page down so that the last line (truncated or whole)
+ * of the current page becomes the fully visible top line.
+ * <p>
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the end
+ * of the text where a full page scroll is not possible. In this case
+ * the caret is moved after the last character.
+ * <p></p>
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ * </p>
+ */
+void doSelectionPageDown(int pixels) {
+    int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+    doPageDown(true, pixels);
+    columnX = oldColumnX;
+}
+/**
+ * Scrolls one page up so that the first line (truncated or whole)
+ * of the current page becomes the fully visible last line.
+ * <p>
+ * The caret is scrolled the same number of lines so that its location
+ * relative to the top line remains the same. The exception is the beginning
+ * of the text where a full page scroll is not possible. In this case the
+ * caret is moved in front of the first character.
+ * </p><p>
+ * Adjusts the selection according to the caret change. This can either add
+ * to or subtract from the old selection, depending on the previous selection
+ * direction.
+ * </p>
+ */
+void doSelectionPageUp(int pixels) {
+    int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
+    doPageUp(true, pixels);
+    columnX = oldColumnX;
+}
+/**
+ * Moves the caret to the end of the next word .
+ */
+void doSelectionWordNext() {
+    int newCaretOffset = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
+    // Force symmetrical movement for word next and previous. Fixes 14536
+    caretAlignment = OFFSET_LEADING;
+    // don't change caret position if in single line mode and the cursor
+    // would be on a different line. fixes 5673
+    if (!isSingleLine() ||
+        content.getLineAtOffset(caretOffset) is content.getLineAtOffset(newCaretOffset)) {
+        caretOffset = newCaretOffset;
+        showCaret();
+    }
+}
+/**
+ * Moves the caret to the start of the previous word.
+ */
+void doSelectionWordPrevious() {
+    caretAlignment = OFFSET_LEADING;
+    caretOffset = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
+    int caretLine = content.getLineAtOffset(caretOffset);
+    // word previous always comes from bottom line. when
+    // wrapping lines, stay on bottom line when on line boundary
+    if (wordWrap && caretLine < content.getLineCount() - 1 &&
+        caretOffset is content.getOffsetAtLine(caretLine + 1)) {
+        caretLine++;
+    }
+    showCaret();
+}
+/**
+ * Moves the caret one character to the left.  Do not go to the previous line.
+ * When in a bidi locale and at a R2L character the caret is moved to the
+ * beginning of the R2L segment (visually right) and then one character to the
+ * left (visually left because it's now in a L2R segment).
+ */
+void doVisualPrevious() {
+    caretOffset = getClusterPrevious(caretOffset, getCaretLine());
+    showCaret();
+}
+/**
+ * Moves the caret one character to the right.  Do not go to the next line.
+ * When in a bidi locale and at a R2L character the caret is moved to the
+ * end of the R2L segment (visually left) and then one character to the
+ * right (visually right because it's now in a L2R segment).
+ */
+void doVisualNext() {
+    caretOffset = getClusterNext(caretOffset, getCaretLine());
+    showCaret();
+}
+/**
+ * Moves the caret to the end of the next word.
+ * If a selection exists, move the caret to the end of the selection
+ * and remove the selection.
+ */
+void doWordNext() {
+    if (selection.y - selection.x > 0) {
+        caretOffset = selection.y;
+        showCaret();
+    } else {
+        doSelectionWordNext();
+    }
+}
+/**
+ * Moves the caret to the start of the previous word.
+ * If a selection exists, move the caret to the start of the selection
+ * and remove the selection.
+ */
+void doWordPrevious() {
+    if (selection.y - selection.x > 0) {
+        caretOffset = selection.x;
+        showCaret();
+    } else {
+        doSelectionWordPrevious();
+    }
+}
+/**
+ * Ends the autoscroll process.
+ */
+void endAutoScroll() {
+    autoScrollDirection = SWT.NULL;
+}
+public override Color getBackground() {
+    checkWidget();
+    if (background is null) {
+        return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
+    }
+    return background;
+}
+/**
+ * Returns the baseline, in pixels.
+ *
+ * Note: this API should not be used if a StyleRange attribute causes lines to
+ * have different heights (i.e. different fonts, rise, etc).
+ *
+ * @return baseline the baseline
+ * @exception SWTException <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.0
+ *
+ * @see #getBaseline(int)
+ */
+public int getBaseline() {
+    checkWidget();
+    return renderer.getBaseline();
+}
+/**
+ * Returns the baseline at the given offset, in pixels.
+ *
+ * @param offset the offset
+ *
+ * @return baseline the baseline
+ *
+ * @exception SWTException <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 offset is outside the valid range (< 0 or > getCharCount())</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public int getBaseline(int offset) {
+    checkWidget();
+    if (!(0 <= offset && offset <= content.getCharCount())) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    if (isFixedLineHeight()) {
+        return renderer.getBaseline();
+    }
+    int lineIndex = content.getLineAtOffset(offset);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length));
+    FontMetrics metrics = layout.getLineMetrics(lineInParagraph);
+    renderer.disposeTextLayout(layout);
+    return metrics.getAscent() + metrics.getLeading();
+}
+/**
+ * Gets the BIDI coloring mode.  When true the BIDI text display
+ * algorithm is applied to segments of text that are the same
+ * color.
+ *
+ * @return the current coloring mode
+ * @exception SWTException <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>
+ *
+ * @deprecated use BidiSegmentListener instead.
+ */
+public bool getBidiColoring() {
+    checkWidget();
+    return bidiColoring;
+}
+/**
+ * Returns the index of the last fully visible line.
+ *
+ * @return index of the last fully visible line.
+ */
+int getBottomIndex() {
+    int bottomIndex;
+    if (isFixedLineHeight()) {
+        int lineCount = 1;
+        int lineHeight = renderer.getLineHeight();
+        if (lineHeight !is 0) {
+            // calculate the number of lines that are fully visible
+            int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset();
+            lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight;
+        }
+        bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
+    } else {
+        int clientAreaHeight = this.clientAreaHeight - bottomMargin;
+        bottomIndex = getLineIndex(clientAreaHeight);
+        if (bottomIndex > 0) {
+            int linePixel = getLinePixel(bottomIndex);
+            int lineHeight = renderer.getLineHeight(bottomIndex);
+            if (linePixel + lineHeight > clientAreaHeight) {
+                if (getLinePixel(bottomIndex - 1) >= topMargin) {
+                    bottomIndex--;
+                }
+            }
+        }
+    }
+    return bottomIndex;
+}
+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 - 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.
+ *
+ * @return the caret position relative to the start of the text.
+ * @exception SWTException <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 int getCaretOffset() {
+    checkWidget();
+    return caretOffset;
+}
+/**
+ * Returns the caret width.
+ *
+ * @return the caret width, 0 if caret is null.
+ */
+int getCaretWidth() {
+    Caret caret = getCaret();
+    if (caret is null) return 0;
+    return caret.getSize().x;
+}
+Object getClipboardContent(int clipboardType) {
+    TextTransfer plainTextTransfer = TextTransfer.getInstance();
+    return clipboard.getContents(plainTextTransfer, clipboardType);
+}
+int getClusterNext(int offset, int lineIndex) {
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    offset -= lineOffset;
+    offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
+    offset += lineOffset;
+    renderer.disposeTextLayout(layout);
+    return offset;
+}
+int getClusterPrevious(int offset, int lineIndex) {
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    offset -= lineOffset;
+    offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER);
+    offset += lineOffset;
+    renderer.disposeTextLayout(layout);
+    return offset;
+}
+/**
+ * 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 SWTException <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 StyledTextContent getContent() {
+    checkWidget();
+    return content;
+}
+public override bool getDragDetect () {
+    checkWidget ();
+    return dragDetect_;
+}
+/**
+ * Returns whether the widget implements double click mouse behavior.
+ *
+ * @return true if double clicking a word selects the word, false if double clicks
+ * have the same effect as regular mouse clicks
+ * @exception SWTException <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 getDoubleClickEnabled() {
+    checkWidget();
+    return doubleClickEnabled;
+}
+/**
+ * Returns whether the widget content can be edited.
+ *
+ * @return true if content can be edited, false otherwise
+ * @exception SWTException <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 getEditable() {
+    checkWidget();
+    return editable;
+}
+public override Color getForeground() {
+    checkWidget();
+    if (foreground is null) {
+        return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
+    }
+    return foreground;
+}
+/**
+ * Returns the horizontal scroll increment.
+ *
+ * @return horizontal scroll increment.
+ */
+int getHorizontalIncrement() {
+    return renderer.averageCharWidth;
+}
+/**
+ * Returns the horizontal scroll offset relative to the start of the line.
+ *
+ * @return horizontal scroll offset relative to the start of the line,
+ * measured in character increments starting at 0, if > 0 the content is scrolled
+ * @exception SWTException <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 int getHorizontalIndex() {
+    checkWidget();
+    return horizontalScrollOffset / getHorizontalIncrement();
+}
+/**
+ * Returns the horizontal scroll offset relative to the start of the line.
+ *
+ * @return the horizontal scroll offset relative to the start of the line,
+ * measured in pixel starting at 0, if > 0 the content is scrolled.
+ * @exception SWTException <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 int getHorizontalPixel() {
+    checkWidget();
+    return horizontalScrollOffset;
+}
+/**
+ * Returns the line indentation of the widget.
+ *
+ * @return the line indentation
+ *
+ * @exception SWTException <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 #getLineIndent(int)
+ *
+ * @since 3.2
+ */
+public int getIndent() {
+    checkWidget();
+    return indent;
+}
+/**
+ * Returns whether the widget justifies lines.
+ *
+ * @return whether lines are justified
+ *
+ * @exception SWTException <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 #getLineJustify(int)
+ *
+ * @since 3.2
+ */
+public bool getJustify() {
+    checkWidget();
+    return justify;
+}
+/**
+ * Returns the action assigned to the key.
+ * Returns SWT.NULL if there is no action associated with the key.
+ *
+ * @param key a key code defined in SWT.java or a character.
+ *  Optionally ORd with a state mask.  Preferred state masks are one or more of
+ *  SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+ *  differences.  However, there may be cases where using the specific state masks
+ *  (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+ * @return one of the predefined actions defined in ST.java or SWT.NULL
+ *  if there is no action associated with the key.
+ * @exception SWTException <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 int getKeyBinding(int key) {
+    checkWidget();
+    if( auto p = key in keyActionMap ){
+        return *p;
+    }
+    return SWT.NULL;
+}
+/**
+ * Gets the number of characters.
+ *
+ * @return number of characters in the widget
+ * @exception SWTException <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 int getCharCount() {
+    checkWidget();
+    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 SWTException <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())) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return content.getLine(lineIndex);
+}
+/**
+ * Returns the alignment of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line alignment
+ *
+ * @exception SWTException <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_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @see #getAlignment()
+ *
+ * @since 3.2
+ */
+public int getLineAlignment(int index) {
+    checkWidget();
+    if (index < 0 || index > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return renderer.getLineAlignment(index, alignment);
+}
+/**
+ * Returns the line at the specified offset in the text
+ * where 0 &lt; offset &lt; getCharCount() so that getLineAtOffset(getCharCount())
+ * returns the line of the insert location.
+ *
+ * @param offset offset relative to the start of the content.
+ *  0 <= offset <= getCharCount()
+ * @return line at the specified offset in the text
+ * @exception SWTException <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 offset is outside the valid range (< 0 or > getCharCount())</li>
+ * </ul>
+ */
+public int getLineAtOffset(int offset) {
+    checkWidget();
+    if (offset < 0 || offset > getCharCount()) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return content.getLineAtOffset(offset);
+}
+/**
+ * Returns the background color of the line at the given index.
+ * Returns null if a LineBackgroundListener has been set or if no background
+ * color has been specified for the line. Should not be called if a
+ * LineBackgroundListener has been set since the listener maintains the
+ * line background colors.
+ *
+ * @param index the index of the line
+ * @return the background color of the line at the given index.
+ *
+ * @exception SWTException <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_ARGUMENT when the index is invalid</li>
+ * </ul>
+ */
+public Color getLineBackground(int index) {
+    checkWidget();
+    if (index < 0 || index > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return isListening(LineGetBackground) ? null : renderer.getLineBackground(index, null);
+}
+/**
+ * Returns the bullet of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line bullet
+ *
+ * @exception SWTException <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_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public Bullet getLineBullet(int index) {
+    checkWidget();
+    if (index < 0 || index > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null);
+}
+/**
+ * Returns the line background data for the given line or null if
+ * there is none.
+ *
+ * @param lineOffset offset of the line start relative to the start
+ *  of the content.
+ * @param line line to get line background data for
+ * @return line background data for the given line.
+ */
+StyledTextEvent getLineBackgroundData(int lineOffset, String line) {
+    return sendLineEvent(LineGetBackground, lineOffset, line);
+}
+/**
+ * Gets the number of text lines.
+ *
+ * @return the number of lines in the widget
+ * @exception SWTException <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 int getLineCount() {
+    checkWidget();
+    return content.getLineCount();
+}
+/**
+ * Returns the number of lines that can be completely displayed in the
+ * widget client area.
+ *
+ * @return number of lines that can be completely displayed in the widget
+ *  client area.
+ */
+int getLineCountWhole() {
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        return lineHeight !is 0 ? clientAreaHeight / lineHeight : 1;
+    }
+    return getBottomIndex() - topIndex + 1;
+}
+/**
+ * Returns the line delimiter used for entering new lines by key down
+ * or paste operation.
+ *
+ * @return line delimiter used for entering new lines by key down
+ * or paste operation.
+ * @exception SWTException <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 String getLineDelimiter() {
+    checkWidget();
+    return content.getLineDelimiter();
+}
+/**
+ * Returns the line height.
+ * <p>
+ * Note: this API should not be used if a StyleRange attribute causes lines to
+ * have different heights (i.e. different fonts, rise, etc).
+ * </p>
+ *
+ * @return line height in pixel.
+ * @exception SWTException <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 #getLineHeight(int)
+ */
+public int getLineHeight() {
+    checkWidget();
+    return renderer.getLineHeight();
+}
+/**
+ * Returns the line height at the given offset.
+ *
+ * @param offset the offset
+ *
+ * @return line height in pixels
+ *
+ * @exception SWTException <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 offset is outside the valid range (< 0 or > getCharCount())</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public int getLineHeight(int offset) {
+    checkWidget();
+    if (!(0 <= offset && offset <= content.getCharCount())) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    if (isFixedLineHeight()) {
+        return renderer.getLineHeight();
+    }
+    int lineIndex = content.getLineAtOffset(offset);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length));
+    int height = layout.getLineBounds(lineInParagraph).height;
+    renderer.disposeTextLayout(layout);
+    return height;
+}
+/**
+ * Returns the indentation of the line at the given index.
+ *
+ * @param index the index of the line
+ *
+ * @return the line indentation
+ *
+ * @exception SWTException <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_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @see #getIndent()
+ *
+ * @since 3.2
+ */
+public int getLineIndent(int index) {
+    checkWidget();
+    if (index < 0 || index > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return isListening(LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
+}
+/**
+ * Returns whether the line at the given index is justified.
+ *
+ * @param index the index of the line
+ *
+ * @return whether the line is justified
+ *
+ * @exception SWTException <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_ARGUMENT when the index is invalid</li>
+ * </ul>
+ *
+ * @see #getJustify()
+ *
+ * @since 3.2
+ */
+public bool getLineJustify(int index) {
+    checkWidget();
+    if (index < 0 || index > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify);
+}
+/**
+ * Returns the line spacing of the widget.
+ *
+ * @return the line spacing
+ *
+ * @exception SWTException <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.2
+ */
+public int getLineSpacing() {
+    checkWidget();
+    return lineSpacing;
+}
+/**
+ * Returns the line style data for the given line or null if there is
+ * none.
+ * <p>
+ * If there is a LineStyleListener but it does not set any styles,
+ * the StyledTextEvent.styles field will be initialized to an empty
+ * array.
+ * </p>
+ *
+ * @param lineOffset offset of the line start relative to the start of
+ *  the content.
+ * @param line line to get line styles for
+ * @return line style data for the given line. Styles may start before
+ *  line start and end after line end
+ */
+StyledTextEvent getLineStyleData(int lineOffset, String line) {
+    return sendLineEvent(LineGetStyle, lineOffset, line);
+}
+/**
+ * Returns the top pixel, relative to the client area, of a given line.
+ * Clamps out of ranges index.
+ *
+ * @param lineIndex the line index, the max value is lineCount. If
+ * lineIndex is lineCount it returns the bottom pixel of the last line.
+ * It means this function can be used to retrieve the bottom pixel of any line.
+ *
+ * @return the top pixel of a given line index
+ *
+ * @since 3.2
+ */
+public int getLinePixel(int lineIndex) {
+    checkWidget();
+    int lineCount = content.getLineCount();
+    lineIndex = Math.max(0, Math.min(lineCount, lineIndex));
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin;
+    }
+    if (lineIndex is topIndex) return topIndexY + topMargin;
+    int height = topIndexY;
+    if (lineIndex > topIndex) {
+        for (int i = topIndex; i < lineIndex; i++) {
+            height += renderer.getLineHeight(i);
+        }
+    } else {
+        for (int i = topIndex - 1; i >= lineIndex; i--) {
+            height -= renderer.getLineHeight(i);
+        }
+    }
+    return height + topMargin;
+}
+/**
+ * Returns the line index for a y, relative to the client area.
+ * The line index returned is always in the range 0..lineCount - 1.
+ *
+ * @param y the y-coordinate pixel
+ *
+ * @return the line index for a given y-coordinate pixel
+ *
+ * @since 3.2
+ */
+public int getLineIndex(int y) {
+    checkWidget();
+    y -= topMargin;
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        int lineIndex = (y + getVerticalScrollOffset()) / lineHeight;
+        int lineCount = content.getLineCount();
+        lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex));
+        return lineIndex;
+    }
+    if (y is topIndexY) return topIndex;
+    int line = topIndex;
+    if (y < topIndexY) {
+        while (y < topIndexY && line > 0) {
+            y += renderer.getLineHeight(--line);
+        }
+    } else {
+        int lineCount = content.getLineCount();
+        int lineHeight = renderer.getLineHeight(line);
+        while (y - lineHeight >= topIndexY && line < lineCount - 1) {
+            y -= lineHeight;
+            lineHeight = renderer.getLineHeight(++line);
+        }
+    }
+    return line;
+}
+/**
+ * Returns the x, y location of the upper left corner of the character
+ * bounding box at the specified offset in the text. The point is
+ * relative to the upper left corner of the widget client area.
+ *
+ * @param offset offset relative to the start of the content.
+ *  0 <= offset <= getCharCount()
+ * @return x, y location of the upper left corner of the character
+ *  bounding box at the specified offset in the text.
+ * @exception SWTException <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 offset is outside the valid range (< 0 or > getCharCount())</li>
+ * </ul>
+ */
+public Point getLocationAtOffset(int offset) {
+    checkWidget();
+    if (offset < 0 || offset > getCharCount()) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return getPointAtOffset(offset);
+}
+/**
+ * Returns the character offset of the first character of the given line.
+ *
+ * @param lineIndex index of the line, 0 based relative to the first
+ *  line in the content. 0 <= lineIndex < getLineCount(), except
+ *  lineIndex may always be 0
+ * @return offset offset of the first character of the line, relative to
+ *  the beginning of the document. The first character of the document is
+ *  at offset 0.
+ *  When there are not any lines, getOffsetAtLine(0) is a valid call that
+ *  answers 0.
+ * @exception SWTException <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 2.0
+ */
+public int getOffsetAtLine(int lineIndex) {
+    checkWidget();
+    if (lineIndex < 0 ||
+        (lineIndex > 0 && lineIndex >= content.getLineCount())) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return content.getOffsetAtLine(lineIndex);
+}
+/**
+ * Returns the offset of the character at the given location relative
+ * to the first character in the document.
+ * <p>
+ * The return value reflects the character offset that the caret will
+ * be placed at if a mouse click occurred at the specified location.
+ * If the x coordinate of the location is beyond the center of a character
+ * the returned offset will be behind the character.
+ * </p>
+ *
+ * @param point the origin of character bounding box relative to
+ *  the origin of the widget client area.
+ * @return offset of the character at the given location relative
+ *  to the first character in the document.
+ * @exception SWTException <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_NULL_ARGUMENT when point is null</li>
+ *   <li>ERROR_INVALID_ARGUMENT when there is no character at the specified location</li>
+ * </ul>
+ */
+public int getOffsetAtLocation(Point point) {
+    checkWidget();
+    if (point is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    int[] trailing = new int[1];
+    int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+    if (offset is -1) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    return offset + trailing[0];
+}
+int getOffsetAtPoint(int x, int y) {
+    int lineIndex = getLineIndex(y);
+    y -= getLinePixel(lineIndex);
+    return getOffsetAtPoint(x, y, lineIndex);
+}
+/**
+ * Returns the offset at the specified x location in the specified line.
+ *
+ * @param x x location of the mouse location
+ * @param line  line the mouse location is in
+ * @return the offset at the specified x location in the specified line,
+ *  relative to the beginning of the document
+ */
+int getOffsetAtPoint(int x, int y, int lineIndex) {
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    x += horizontalScrollOffset - leftMargin;
+    int[1] trailing;
+    int offsetInLine = layout.getOffset(x, y, trailing);
+    caretAlignment = OFFSET_LEADING;
+    if (trailing[0] !is 0) {
+        int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
+        int lineStart = layout.getLineOffsets()[lineInParagraph];
+        if (offsetInLine + trailing[0] is lineStart) {
+            offsetInLine += trailing[0];
+            caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        } else {
+            String line = content.getLine(lineIndex);
+            int level;
+            int offset = offsetInLine;
+            while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--;
+            if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) {
+                level = isMirrored() ? 1 : 0;
+            } else {
+                level = layout.getLevel(offset) & 0x1;
+            }
+            offsetInLine += trailing[0];
+            int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
+            if ((level ^ trailingLevel) !is 0) {
+                caretAlignment = PREVIOUS_OFFSET_TRAILING;
+            } else {
+                caretAlignment = OFFSET_LEADING;
+            }
+        }
+    }
+    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.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public int getOrientation () {
+    checkWidget();
+    return isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+}
+/**
+ * Returns the index of the last partially visible line.
+ *
+ * @return index of the last partially visible line.
+ */
+int getPartialBottomIndex() {
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
+        return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1);
+    }
+    return getLineIndex(clientAreaHeight - bottomMargin);
+}
+/**
+ * Returns the index of the first partially visible line.
+ *
+ * @return index of the first partially visible line.
+ */
+int getPartialTopIndex() {
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        return getVerticalScrollOffset() / lineHeight;
+    }
+    return topIndexY <= 0 ? topIndex : topIndex - 1;
+}
+/**
+ * Returns the content in the specified range using the platform line
+ * delimiter to separate lines.
+ *
+ * @param writer the TextWriter to write line text into
+ * @return the content in the specified range using the platform line
+ *  delimiter to separate lines as written by the specified TextWriter.
+ */
+String getPlatformDelimitedText(TextWriter writer) {
+    int end = writer.getStart() + writer.getCharCount();
+    int startLine = content.getLineAtOffset(writer.getStart());
+    int endLine = content.getLineAtOffset(end);
+    String endLineText = content.getLine(endLine);
+    int endLineOffset = content.getOffsetAtLine(endLine);
+
+    for (int i = startLine; i <= endLine; i++) {
+        writer.writeLine(content.getLine(i), content.getOffsetAtLine(i));
+        if (i < endLine) {
+            writer.writeLineDelimiter(PlatformLineDelimiter);
+        }
+    }
+    if (end > endLineOffset + endLineText.length) {
+        writer.writeLineDelimiter(PlatformLineDelimiter);
+    }
+    writer.close();
+    return writer.toString();
+}
+/**
+ * Returns all the ranges of text that have an associated StyleRange.
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * <p>
+ * The ranges array contains start and length pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>.
+ * </p>
+ *
+ * @return the ranges or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException <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.2
+ *
+ * @see #getStyleRanges(bool)
+ */
+public int[] getRanges() {
+    checkWidget();
+    if (!isListening(LineGetStyle)) {
+        int[] ranges = renderer.getRanges(0, content.getCharCount());
+        if (ranges !is null) return ranges;
+    }
+    return new int[0];
+}
+/**
+ * Returns the ranges of text that have an associated StyleRange.
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * <p>
+ * The ranges array contains start and length pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>.
+ * </p>
+ *
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ *
+ * @return the ranges or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException <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 if start or length are outside the widget content</li>
+ * </ul>
+ *
+ * @since 3.2
+ *
+ * @see #getStyleRanges(int, int, bool)
+ */
+public int[] getRanges(int start, int length) {
+    checkWidget();
+    int contentLength = getCharCount();
+    int end = start + length;
+    if (start > end || start < 0 || end > contentLength) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    if (!isListening(LineGetStyle)) {
+        int[] ranges = renderer.getRanges(start, length);
+        if (ranges !is null) return ranges;
+    }
+    return new int[0];
+}
+/**
+ * Returns the selection.
+ * <p>
+ * Text selections are specified in terms of caret positions.  In a text
+ * widget that contains N characters, there are N+1 caret positions,
+ * ranging from 0..N
+ * </p>
+ *
+ * @return start and end of the selection, x is the offset of the first
+ *  selected character, y is the offset after the last selected character.
+ *  The selection values returned are visual (i.e., x will always always be
+ *  <= y).  To determine if a selection is right-to-left (RtoL) vs. left-to-right
+ *  (LtoR), compare the caretOffset to the start and end of the selection
+ *  (e.g., caretOffset is start of selection implies that the selection is RtoL).
+ * @see #getSelectionRange
+ * @exception SWTException <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 Point getSelection() {
+    checkWidget();
+    return new Point(selection.x, selection.y);
+}
+/**
+ * Returns the selection.
+ *
+ * @return start and length of the selection, x is the offset of the
+ *  first selected character, relative to the first character of the
+ *  widget content. y is the length of the selection.
+ *  The selection values returned are visual (i.e., length will always always be
+ *  positive).  To determine if a selection is right-to-left (RtoL) vs. left-to-right
+ *  (LtoR), compare the caretOffset to the start and end of the selection
+ *  (e.g., caretOffset is start of selection implies that the selection is RtoL).
+ * @exception SWTException <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 Point getSelectionRange() {
+    checkWidget();
+    return new Point(selection.x, selection.y - selection.x);
+}
+/**
+ * Returns the receiver's selection background color.
+ *
+ * @return the selection background color
+ *
+ * @exception SWTException <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 2.1
+ */
+public Color getSelectionBackground() {
+    checkWidget();
+    if (selectionBackground is null) {
+        return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+    }
+    return selectionBackground;
+}
+/**
+ * Gets the number of selected characters.
+ *
+ * @return the number of selected characters.
+ * @exception SWTException <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 int getSelectionCount() {
+    checkWidget();
+    return getSelectionRange().y;
+}
+/**
+ * Returns the receiver's selection foreground color.
+ *
+ * @return the selection foreground color
+ *
+ * @exception SWTException <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 2.1
+ */
+public Color getSelectionForeground() {
+    checkWidget();
+    if (selectionForeground is null) {
+        return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+    }
+    return selectionForeground;
+}
+/**
+ * Returns the selected text.
+ *
+ * @return selected text, or an empty String if there is no selection.
+ * @exception SWTException <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 String getSelectionText() {
+    checkWidget();
+    return content.getTextRange(selection.x, selection.y - selection.x);
+}
+public override int getStyle() {
+    int style = super.getStyle();
+    style &= ~(SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT | SWT.MIRRORED);
+    if (isMirrored()) {
+        style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+    } else {
+        style |= SWT.LEFT_TO_RIGHT;
+    }
+    return style;
+}
+
+/**
+ * Returns the text segments that should be treated as if they
+ * had a different direction than the surrounding text.
+ *
+ * @param lineOffset offset of the first character in the line.
+ *  0 based from the beginning of the document.
+ * @param line text of the line to specify bidi segments for
+ * @return text segments that should be treated as if they had a
+ *  different direction than the surrounding text. Only the start
+ *  index of a segment is specified, relative to the start of the
+ *  line. Always starts with 0 and ends with the line length.
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the segment indices returned
+ *      by the listener do not start with 0, are not in ascending order,
+ *      exceed the line length or have duplicates</li>
+ * </ul>
+ */
+int [] getBidiSegments(int lineOffset, String line) {
+    if (!isBidi()) return null;
+    if (!isListening(LineGetSegments)) {
+        return getBidiSegmentsCompatibility(line, lineOffset);
+    }
+    StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line);
+    int lineLength = line.length;
+    int[] segments;
+    if (event is null || event.segments is null || event.segments.length is 0) {
+        segments = [0, lineLength];
+    } else {
+        int segmentCount = event.segments.length;
+
+        // test segment index consistency
+        if (event.segments[0] !is 0) {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        for (int i = 1; i < segmentCount; i++) {
+            if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) {
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+        }
+        // ensure that last segment index is line end offset
+        if (event.segments[segmentCount - 1] !is lineLength) {
+            segments = new int[segmentCount + 1];
+            System.arraycopy(event.segments, 0, segments, 0, segmentCount);
+            segments[segmentCount] = lineLength;
+        } else {
+            segments = event.segments;
+        }
+    }
+    return segments;
+}
+/**
+ * @see #getBidiSegments
+ * Supports deprecated setBidiColoring API. Remove when API is removed.
+ */
+int [] getBidiSegmentsCompatibility(String line, int lineOffset) {
+    int lineLength = line.length;
+    if (!bidiColoring) {
+        return [0, lineLength];
+    }
+    StyleRange [] styles = null;
+    StyledTextEvent event = getLineStyleData(lineOffset, line);
+    if (event !is null) {
+        styles = event.styles;
+    } else {
+        styles = renderer.getStyleRanges(lineOffset, lineLength, true);
+    }
+    if (styles is null || styles.length is 0) {
+        return [0, lineLength];
+    }
+    int k=0, count = 1;
+    while (k < styles.length && styles[k].start is 0 && styles[k].length is lineLength) {
+        k++;
+    }
+    int[] offsets = new int[(styles.length - k) * 2 + 2];
+    for (int i = k; i < styles.length; i++) {
+        StyleRange style = styles[i];
+        int styleLineStart = Math.max(style.start - lineOffset, 0);
+        int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart);
+        styleLineEnd = Math.min (styleLineEnd, line.length );
+        if (i > 0 && count > 1 &&
+            ((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) ||
+             (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) &&
+             style.similarTo(styles[i-1])) {
+            offsets[count-2] = Math.min(offsets[count-2], styleLineStart);
+            offsets[count-1] = Math.max(offsets[count-1], styleLineEnd);
+        } else {
+            if (styleLineStart > offsets[count - 1]) {
+                offsets[count] = styleLineStart;
+                count++;
+            }
+            offsets[count] = styleLineEnd;
+            count++;
+        }
+    }
+    // add offset for last non-colored segment in line, if any
+    if (lineLength > offsets[count-1]) {
+        offsets [count] = lineLength;
+        count++;
+    }
+    if (count is offsets.length) {
+        return offsets;
+    }
+    int [] result = new int [count];
+    System.arraycopy (offsets, 0, result, 0, count);
+    return result;
+}
+/**
+ * Returns the style range at the given offset.
+ * <p>
+ * Returns null if a LineStyleListener has been set or if a style is not set
+ * for the offset.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param offset the offset to return the style for.
+ *  0 <= offset < getCharCount() must be true.
+ * @return a StyleRange with start is offset and length is 1, indicating
+ *  the style at the given offset. null if a LineStyleListener has been set
+ *  or if a style is not set for the given offset.
+ * @exception SWTException <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_ARGUMENT when the offset is invalid</li>
+ * </ul>
+ */
+public StyleRange getStyleRangeAtOffset(int offset) {
+    checkWidget();
+    if (offset < 0 || offset >= getCharCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (!isListening(LineGetStyle)) {
+        StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true);
+        if (ranges !is null) return ranges[0];
+    }
+    return null;
+}
+/**
+ * Returns the styles.
+ * <p>
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * <p></p>
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, <code>getStyleRanges(bool)</code>
+ * can be used to get the styles without the ranges.
+ * </p>
+ *
+ * @return the styles or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException <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 #getStyleRanges(bool)
+ */
+public StyleRange[] getStyleRanges() {
+    checkWidget();
+    return getStyleRanges(0, content.getCharCount(), true);
+}
+/**
+ * Returns the styles.
+ * <p>
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p><p>
+ * Note: When <code>includeRanges</code> is true, the start and length
+ * fields of each StyleRange will be valid, however the StyleRange
+ * objects may need to be cloned. When <code>includeRanges</code> is
+ * false, <code>getRanges(int, int)</code> can be used to get the
+ * associated ranges.
+ * </p>
+ *
+ * @param includeRanges whether the start and length field of the StyleRanges should be set.
+ *
+ * @return the styles or an empty array if a LineStyleListener has been set.
+ *
+ * @exception SWTException <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.2
+ *
+ * @see #getRanges(int, int)
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public StyleRange[] getStyleRanges(bool includeRanges) {
+    checkWidget();
+    return getStyleRanges(0, content.getCharCount(), includeRanges);
+}
+/**
+ * Returns the styles for the given text range.
+ * <p>
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p><p>
+ * Note: Because the StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, <code>getStyleRanges(int, int, bool)</code>
+ * can be used to get the styles without the ranges.
+ * </p>
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ *
+ * @return the styles or an empty array if a LineStyleListener has
+ *  been set.  The returned styles will reflect the given range.  The first
+ *  returned <code>StyleRange</code> will have a starting offset >= start
+ *  and the last returned <code>StyleRange</code> will have an ending
+ *  offset <= start + length - 1
+ *
+ * @exception SWTException <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 start and/or end are outside the widget content</li>
+ * </ul>
+ *
+ * @see #getStyleRanges(int, int, bool)
+ *
+ * @since 3.0
+ */
+public StyleRange[] getStyleRanges(int start, int length) {
+    checkWidget();
+    return getStyleRanges(start, length, true);
+}
+/**
+ * Returns the styles for the given text range.
+ * <p>
+ * Returns an empty array if a LineStyleListener has been set.
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p><p>
+ * Note: When <code>includeRanges</code> is true, the start and length
+ * fields of each StyleRange will be valid, however the StyleRange
+ * objects may need to be cloned. When <code>includeRanges</code> is
+ * false, <code>getRanges(int, int)</code> can be used to get the
+ * associated ranges.
+ * </p>
+ *
+ * @param start the start offset of the style ranges to return
+ * @param length the number of style ranges to return
+ * @param includeRanges whether the start and length field of the StyleRanges should be set.
+ *
+ * @return the styles or an empty array if a LineStyleListener has
+ *  been set.  The returned styles will reflect the given range.  The first
+ *  returned <code>StyleRange</code> will have a starting offset >= start
+ *  and the last returned <code>StyleRange</code> will have an ending
+ *  offset <= start + length - 1
+ *
+ * @exception SWTException <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 start and/or end are outside the widget content</li>
+ * </ul>
+ *
+ * @since 3.2
+ *
+ * @see #getRanges(int, int)
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public StyleRange[] getStyleRanges(int start, int length, bool includeRanges) {
+    checkWidget();
+    int contentLength = getCharCount();
+    int end = start + length;
+    if (start > end || start < 0 || end > contentLength) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    if (!isListening(LineGetStyle)) {
+        StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
+        if (ranges !is null) return ranges;
+    }
+    return new StyleRange[0];
+}
+/**
+ * Returns the tab width measured in characters.
+ *
+ * @return tab width measured in characters
+ * @exception SWTException <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 int getTabs() {
+    checkWidget();
+    return tabLength;
+}
+/**
+ * Returns a copy of the widget content.
+ *
+ * @return copy of the widget content
+ * @exception SWTException <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 String getText() {
+    checkWidget();
+    return content.getTextRange(0, getCharCount());
+}
+/**
+ * Returns the widget content between the two offsets.
+ *
+ * @param start offset of the first character in the returned String
+ * @param end offset of the last character in the returned String
+ * @return widget content starting at start and ending at end
+ * @see #getTextRange(int,int)
+ * @exception SWTException <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 start and/or end are outside the widget content</li>
+ * </ul>
+ */
+public String getText(int start, int end) {
+    checkWidget();
+    int contentLength = getCharCount();
+    if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return content.getTextRange(start, end - start + 1);
+}
+/**
+ * Returns the smallest bounding rectangle that includes the characters between two offsets.
+ *
+ * @param start offset of the first character included in the bounding box
+ * @param end offset of the last character included in the bounding box
+ * @return bounding box of the text between start and end
+ * @exception SWTException <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 start and/or end are outside the widget content</li>
+ * </ul>
+ * @since 3.1
+ */
+public Rectangle getTextBounds(int start, int end) {
+    checkWidget();
+    int contentLength = getCharCount();
+    if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    int lineStart = content.getLineAtOffset(start);
+    int lineEnd = content.getLineAtOffset(end);
+    Rectangle rect;
+    int y = getLinePixel(lineStart);
+    int height = 0;
+    int left = 0x7fffffff, right = 0;
+    for (int i = lineStart; i <= lineEnd; i++) {
+        int lineOffset = content.getOffsetAtLine(i);
+        TextLayout layout = renderer.getTextLayout(i);
+        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 {
+                rect = layout.getBounds();
+            }
+            left = Math.min(left, rect.x);
+            right = Math.max(right, rect.x + rect.width);
+            height += rect.height;
+        } else {
+            height += renderer.getLineHeight();
+        }
+        renderer.disposeTextLayout(layout);
+    }
+    rect = new Rectangle (left, y, right-left, height);
+    rect.x += leftMargin - horizontalScrollOffset;
+    return rect;
+}
+/**
+ * Returns the widget content starting at start for length characters.
+ *
+ * @param start offset of the first character in the returned String
+ * @param length number of characters to return
+ * @return widget content starting at start and extending length characters.
+ * @exception SWTException <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 start and/or length are outside the widget content</li>
+ * </ul>
+ */
+public String getTextRange(int start, int length) {
+    checkWidget();
+    int contentLength = getCharCount();
+    int end = start + length;
+    if (start > end || start < 0 || end > contentLength) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return content.getTextRange(start, length);
+}
+/**
+ * Returns the maximum number of characters that the receiver is capable of holding.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException <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 int getTextLimit() {
+    checkWidget();
+    return textLimit;
+}
+/**
+ * Gets the top index.
+ * <p>
+ * The top index is the index of the fully visible line that is currently
+ * at the top of the widget or the topmost partially visible line if no line is fully visible.
+ * The top index changes when the widget is scrolled. Indexing is zero based.
+ * </p>
+ *
+ * @return the index of the top line
+ * @exception SWTException <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 int getTopIndex() {
+    checkWidget();
+    return topIndex;
+}
+/**
+ * Gets the top pixel.
+ * <p>
+ * The top pixel is the pixel position of the line that is
+ * currently at the top of the widget. The text widget can be scrolled by pixels
+ * by dragging the scroll thumb so that a partial line may be displayed at the top
+ * the widget.  The top pixel changes when the widget is scrolled.  The top pixel
+ * does not include the widget trimming.
+ * </p>
+ *
+ * @return pixel position of the top line
+ * @exception SWTException <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 int getTopPixel() {
+    checkWidget();
+    return getVerticalScrollOffset();
+}
+/**
+ * Returns the vertical scroll increment.
+ *
+ * @return vertical scroll increment.
+ */
+int getVerticalIncrement() {
+    return renderer.getLineHeight();
+}
+int getVerticalScrollOffset() {
+    if (verticalScrollOffset is -1) {
+        renderer.calculate(0, topIndex);
+        int height = 0;
+        for (int i = 0; i < topIndex; i++) {
+            height += renderer.getLineHeight(i);
+        }
+        height -= topIndexY;
+        verticalScrollOffset = height;
+    }
+    return verticalScrollOffset;
+}
+int getVisualLineIndex(TextLayout layout, int offsetInLine) {
+    int lineIndex = layout.getLineIndex(offsetInLine);
+    int[] offsets = layout.getLineOffsets();
+    if (lineIndex !is 0 && offsetInLine is offsets[lineIndex]) {
+        int lineY = layout.getLineBounds(lineIndex).y;
+        int caretY = getCaret().getLocation().y - topMargin - getLinePixel(getCaretLine());
+        if (lineY > caretY) lineIndex--;
+    }
+    return lineIndex;
+}
+int getCaretDirection() {
+    if (!isBidiCaret()) return SWT.DEFAULT;
+    if (ime.getCompositionOffset() !is -1) return SWT.DEFAULT;
+    if (!updateCaretDirection && caretDirection !is SWT.NULL) return caretDirection;
+    updateCaretDirection = false;
+    int caretLine = getCaretLine();
+    int lineOffset = content.getOffsetAtLine(caretLine);
+    String line = content.getLine(caretLine);
+    int offset = caretOffset - lineOffset;
+    int lineLength = line.length;
+    if (lineLength is 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+    if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--;
+    if (offset is lineLength && offset > 0) offset--;
+    while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--;
+    if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) {
+        return isMirrored() ? SWT.RIGHT : SWT.LEFT;
+    }
+    TextLayout layout = renderer.getTextLayout(caretLine);
+    int level = layout.getLevel(offset);
+    renderer.disposeTextLayout(layout);
+    return ((level & 1) !is 0) ? SWT.RIGHT : SWT.LEFT;
+}
+/*
+ * Returns the index of the line the caret is on.
+ */
+int getCaretLine() {
+    return content.getLineAtOffset(caretOffset);
+}
+int getWrapWidth () {
+    if (wordWrap && !isSingleLine()) {
+        int width = clientAreaWidth - leftMargin - rightMargin - getCaretWidth();
+        return width > 0 ? width : 1;
+    }
+    return -1;
+}
+int getWordNext (int offset, int movement) {
+    int newOffset, lineOffset;
+    String lineText;
+    if (offset >= getCharCount()) {
+        newOffset = offset;
+        int lineIndex = content.getLineCount() - 1;
+        lineOffset = content.getOffsetAtLine(lineIndex);
+        lineText = content.getLine(lineIndex);
+    } else {
+        int lineIndex = content.getLineAtOffset(offset);
+        lineOffset = content.getOffsetAtLine(lineIndex);
+        lineText = content.getLine(lineIndex);
+        int lineLength = lineText.length;
+        if (offset is lineOffset + lineLength) {
+            newOffset = content.getOffsetAtLine(lineIndex + 1);
+        } else {
+            TextLayout layout = renderer.getTextLayout(lineIndex);
+            newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement);
+            renderer.disposeTextLayout(layout);
+        }
+    }
+    return sendWordBoundaryEvent(WordNext, movement, offset, newOffset, lineText, lineOffset);
+}
+int getWordPrevious(int offset, int movement) {
+    int newOffset, lineOffset;
+    String lineText;
+    if (offset <= 0) {
+        newOffset = 0;
+        int lineIndex = content.getLineAtOffset(newOffset);
+        lineOffset = content.getOffsetAtLine(lineIndex);
+        lineText = content.getLine(lineIndex);
+    } else {
+        int lineIndex = content.getLineAtOffset(offset);
+        lineOffset = content.getOffsetAtLine(lineIndex);
+        lineText = content.getLine(lineIndex);
+        if (offset is lineOffset) {
+            String nextLineText = content.getLine(lineIndex - 1);
+            int nextLineOffset = content.getOffsetAtLine(lineIndex - 1);
+            newOffset = nextLineOffset + nextLineText.length;
+        } else {
+            TextLayout layout = renderer.getTextLayout(lineIndex);
+            newOffset = lineOffset + layout.getPreviousOffset(offset - lineOffset, movement);
+            renderer.disposeTextLayout(layout);
+        }
+    }
+    return sendWordBoundaryEvent(WordPrevious, movement, offset, newOffset, lineText, lineOffset);
+}
+/**
+ * Returns whether the widget wraps lines.
+ *
+ * @return true if widget wraps lines, false otherwise
+ * @since 2.0
+ */
+public bool getWordWrap() {
+    checkWidget();
+    return wordWrap;
+}
+/**
+ * Returns the location of the given offset.
+ * <p>
+ * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts).
+ * </p>
+ *
+ * @return location of the character at the given offset in the line.
+ */
+Point getPointAtOffset(int offset) {
+    int lineIndex = content.getLineAtOffset(offset);
+    String line = content.getLine(lineIndex);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    int offsetInLine = offset - lineOffset;
+    int lineLength = line.length;
+    if (lineIndex < content.getLineCount() - 1) {
+        int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
+        if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
+            offsetInLine = lineLength;
+        }
+    }
+    Point point;
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    if (lineLength !is 0  && offsetInLine <= lineLength) {
+        if (offsetInLine is lineLength) {
+            // SWT: Instead of go back one byte, go back one codepoint
+            int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+            point = layout.getLocation(offsetInLine_m1, true);
+        } else {
+            switch (caretAlignment) {
+                case OFFSET_LEADING:
+                    point = layout.getLocation(offsetInLine, false);
+                    break;
+                case PREVIOUS_OFFSET_TRAILING:
+                default:
+                    if (offsetInLine is 0) {
+                        point = layout.getLocation(offsetInLine, false);
+                    } else {
+                        // SWT: Instead of go back one byte, go back one codepoint
+                        int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
+                        point = layout.getLocation(offsetInLine_m1, true);
+                    }
+                    break;
+            }
+        }
+    } else {
+        point = new Point(layout.getIndent(), 0);
+    }
+    renderer.disposeTextLayout(layout);
+    point.x += leftMargin - horizontalScrollOffset;
+    point.y += getLinePixel(lineIndex);
+    return point;
+}
+/**
+ * Inserts a string.  The old selection is replaced with the new text.
+ *
+ * @param string the string
+ * @see #replaceTextRange(int,int,String)
+ * @exception SWTException <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 insert(String string) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+//     if (string is null) {
+//         SWT.error(SWT.ERROR_NULL_ARGUMENT);
+//     }
+    Point sel = getSelectionRange();
+    replaceTextRange(sel.x, sel.y, string);
+}
+/**
+ * Creates content change listeners and set the default content model.
+ */
+void installDefaultContent() {
+    textChangeListener = new class() TextChangeListener {
+        public void textChanging(TextChangingEvent event) {
+            handleTextChanging(event);
+        }
+        public void textChanged(TextChangedEvent event) {
+            handleTextChanged(event);
+        }
+        public void textSet(TextChangedEvent event) {
+            handleTextSet(event);
+        }
+    };
+    content = new DefaultContent();
+    content.addTextChangeListener(textChangeListener);
+}
+/**
+ * Adds event listeners
+ */
+void installListeners() {
+    ScrollBar verticalBar = getVerticalBar();
+    ScrollBar horizontalBar = getHorizontalBar();
+
+    listener = new class() Listener {
+        public void handleEvent(Event event) {
+            switch (event.type) {
+                case SWT.Dispose: handleDispose(event); break;
+                case SWT.KeyDown: handleKeyDown(event); break;
+                case SWT.KeyUp: handleKeyUp(event); break;
+                case SWT.MouseDown: handleMouseDown(event); break;
+                case SWT.MouseUp: handleMouseUp(event); break;
+                case SWT.MouseMove: handleMouseMove(event); break;
+                case SWT.Paint: handlePaint(event); break;
+                case SWT.Resize: handleResize(event); break;
+                case SWT.Traverse: handleTraverse(event); break;
+                default:
+            }
+        }
+    };
+    addListener(SWT.Dispose, listener);
+    addListener(SWT.KeyDown, listener);
+    addListener(SWT.KeyUp, listener);
+    addListener(SWT.MouseDown, listener);
+    addListener(SWT.MouseUp, listener);
+    addListener(SWT.MouseMove, listener);
+    addListener(SWT.Paint, listener);
+    addListener(SWT.Resize, listener);
+    addListener(SWT.Traverse, listener);
+    ime.addListener(SWT.ImeComposition, new class() Listener {
+        public void handleEvent(Event event) {
+            switch (event.detail) {
+                case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
+                case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
+                case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
+                default:
+            }
+        }
+    });
+    if (verticalBar !is null) {
+        verticalBar.addListener(SWT.Selection, new class() Listener {
+            public void handleEvent(Event event) {
+                handleVerticalScroll(event);
+            }
+        });
+    }
+    if (horizontalBar !is null) {
+        horizontalBar.addListener(SWT.Selection, new class() Listener {
+            public void handleEvent(Event event) {
+                handleHorizontalScroll(event);
+            }
+        });
+    }
+}
+void internalRedrawRange(int start, int length) {
+    if (length <= 0) return;
+    int end = start + length;
+    int startLine = content.getLineAtOffset(start);
+    int endLine = content.getLineAtOffset(end);
+    int partialBottomIndex = getPartialBottomIndex();
+    int partialTopIndex = getPartialTopIndex();
+    if (startLine > partialBottomIndex || endLine < partialTopIndex) {
+        return;
+    }
+    if (partialTopIndex > startLine) {
+        startLine = partialTopIndex;
+        start = 0;
+    } else {
+        start -= content.getOffsetAtLine(startLine);
+    }
+    if (partialBottomIndex < endLine) {
+        endLine = partialBottomIndex + 1;
+        end = 0;
+    } else {
+        end -= content.getOffsetAtLine(endLine);
+    }
+
+    TextLayout layout = renderer.getTextLayout(startLine);
+    int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine);
+    int[] offsets = layout.getLineOffsets();
+    int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length));
+
+    /* Redraw end of line before start line if wrapped and start offset is first char */
+    if (wordWrap && startIndex > 0 && offsets[startIndex] is start) {
+        Rectangle rect = layout.getLineBounds(startIndex - 1);
+        rect.x = rect.width;
+        rect.width = clientAreaWidth - rightMargin - rect.x;
+        rect.x += lineX;
+        rect.y += startLineY;
+        super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+    }
+
+    if (startLine is endLine) {
+        int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length));
+        if (startIndex is endIndex) {
+            /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
+            Rectangle rect = layout.getBounds(start, end - 1);
+            rect.x += lineX;
+            rect.y += startLineY;
+            super.redraw(rect.x, rect.y, rect.width, rect.height, false);
+            renderer.disposeTextLayout(layout);
+            return;
+        }
+    }
+
+    /* Redraw start line from the start offset to the end of client area */
+    Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
+    if (startRect.height is 0) {
+        Rectangle bounds = layout.getLineBounds(startIndex);
+        startRect.x = bounds.width;
+        startRect.y = bounds.y;
+        startRect.height = bounds.height;
+    }
+    startRect.x += lineX;
+    startRect.y += startLineY;
+    startRect.width = clientAreaWidth - rightMargin - startRect.x;
+    super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false);
+
+    /* Redraw end line from the beginning of the line to the end offset */
+    if (startLine !is endLine) {
+        renderer.disposeTextLayout(layout);
+        layout = renderer.getTextLayout(endLine);
+        offsets = layout.getLineOffsets();
+    }
+    int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length));
+    Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
+    if (endRect.height is 0) {
+        Rectangle bounds = layout.getLineBounds(endIndex);
+        endRect.y = bounds.y;
+        endRect.height = bounds.height;
+    }
+    endRect.x += lineX;
+    endRect.y += getLinePixel(endLine);
+    super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false);
+    renderer.disposeTextLayout(layout);
+
+    /* Redraw all lines in between start and end line */
+    int y = startRect.y + startRect.height;
+    if (endRect.y > y) {
+        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 = ime.getCompositionOffset();
+        caretWidth = 0;
+        caretDirection = SWT.NULL;
+    } else {
+        content.replaceTextRange(start, end - start, text);
+        caretOffset = ime.getCaretOffset();
+        if (ime.getWideCaret()) {
+            start = ime.getCompositionOffset();
+            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.
+ */
+void handleDispose(Event event) {
+    removeListener(SWT.Dispose, listener);
+    notifyListeners(SWT.Dispose, event);
+    event.type = SWT.None;
+
+    clipboard.dispose();
+    if (renderer !is null) {
+        renderer.dispose();
+        renderer = null;
+    }
+    if (content !is null) {
+        content.removeTextChangeListener(textChangeListener);
+        content = null;
+    }
+    if (defaultCaret !is null) {
+        defaultCaret.dispose();
+        defaultCaret = null;
+    }
+    if (leftCaretBitmap !is null) {
+        leftCaretBitmap.dispose();
+        leftCaretBitmap = null;
+    }
+    if (rightCaretBitmap !is null) {
+        rightCaretBitmap.dispose();
+        rightCaretBitmap = null;
+    }
+    if (isBidiCaret()) {
+        BidiUtil.removeLanguageListener(this);
+    }
+    selectionBackground = null;
+    selectionForeground = null;
+    textChangeListener = null;
+    selection = null;
+    doubleClickSelection = null;
+    keyActionMap = null;
+    background = null;
+    foreground = null;
+    clipboard = null;
+}
+/**
+ * Scrolls the widget horizontally.
+ */
+void handleHorizontalScroll(Event event) {
+    int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
+    scrollHorizontal(scrollPixel, false);
+}
+/**
+ * If an action has been registered for the key stroke execute the action.
+ * Otherwise, if a character has been entered treat it as new content.
+ *
+ * @param event keyboard event
+ */
+void handleKey(Event event) {
+    int action;
+    caretAlignment = PREVIOUS_OFFSET_TRAILING;
+    if (event.keyCode !is 0) {
+        // special key pressed (e.g., F1)
+        action = getKeyBinding(event.keyCode | event.stateMask);
+    } else {
+        // character key pressed
+        action = getKeyBinding(event.character | event.stateMask);
+        if (action is SWT.NULL) {
+            // see if we have a control character
+            if ((event.stateMask & SWT.CTRL) !is 0 && (event.character >= 0) && event.character <= 31) {
+                // get the character from the CTRL+char sequence, the control
+                // key subtracts 64 from the value of the key that it modifies
+                int c = event.character + 64;
+                action = getKeyBinding(c | event.stateMask);
+            }
+        }
+    }
+    if (action is SWT.NULL) {
+        bool ignore = false;
+
+        if (IS_CARBON) {
+            // Ignore accelerator key combinations (we do not want to
+            // insert a character in the text in this instance). Do not
+            // ignore COMMAND+ALT combinations since that key sequence
+            // produces characters on the mac.
+            ignore = (event.stateMask ^ SWT.COMMAND) is 0 ||
+                    (event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) is 0;
+        } else if (IS_MOTIF) {
+            // Ignore accelerator key combinations (we do not want to
+            // insert a character in the text in this instance). Do not
+            // ignore ALT combinations since this key sequence
+            // produces characters on motif.
+            ignore = (event.stateMask ^ SWT.CTRL) is 0 ||
+                    (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) is 0;
+        } else {
+            // Ignore accelerator key combinations (we do not want to
+            // insert a character in the text in this instance). Don't
+            // ignore CTRL+ALT combinations since that is the Alt Gr
+            // key on some keyboards.  See bug 20953.
+            ignore = (event.stateMask ^ SWT.ALT) is 0 ||
+                    (event.stateMask ^ SWT.CTRL) is 0 ||
+                    (event.stateMask ^ (SWT.ALT | SWT.SHIFT)) is 0 ||
+                    (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) is 0;
+        }
+        // -ignore anything below SPACE except for line delimiter keys and tab.
+        // -ignore DEL
+        if (!ignore && event.character > 31 && event.character !is SWT.DEL ||
+            event.character is SWT.CR || event.character is SWT.LF ||
+            event.character is TAB) {
+            doContent(event.character);
+            update();
+        }
+    } else {
+        invokeAction(action);
+    }
+}
+/**
+ * If a VerifyKey listener exists, verify that the key that was entered
+ * should be processed.
+ *
+ * @param event keyboard event
+ */
+void handleKeyDown(Event event) {
+    if (clipboardSelection is null) {
+        clipboardSelection = new Point(selection.x, selection.y);
+    }
+
+    Event verifyEvent = new Event();
+    verifyEvent.character = event.character;
+    verifyEvent.keyCode = event.keyCode;
+    verifyEvent.stateMask = event.stateMask;
+    verifyEvent.doit = true;
+    notifyListeners(VerifyKey, verifyEvent);
+    if (verifyEvent.doit) {
+        handleKey(event);
+    }
+}
+/**
+ * Update the Selection Clipboard.
+ *
+ * @param event keyboard event
+ */
+void handleKeyUp(Event event) {
+    if (clipboardSelection !is null) {
+        if (clipboardSelection.x !is selection.x || clipboardSelection.y !is selection.y) {
+            try {
+                if (selection.y - selection.x > 0) {
+                    setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD);
+                }
+            } catch (SWTError error) {
+                // Copy to clipboard failed. This happens when another application
+                // is accessing the clipboard while we copy. Ignore the error.
+                // Fixes 1GDQAVN
+                // Rethrow all other errors. Fixes bug 17578.
+                if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) {
+                    throw error;
+                }
+            }
+        }
+    }
+    clipboardSelection = null;
+}
+/**
+ * Updates the caret location and selection if mouse button 1 has been
+ * pressed.
+ */
+void handleMouseDown(Event event) {
+    //force focus (object support)
+    forceFocus();
+
+    //drag detect
+    if (dragDetect_ && checkDragDetect(event)) return;
+
+    //paste clipboard selection
+    if (event.button is 2) {
+        auto o = cast(ArrayWrapperString)getClipboardContent(DND.SELECTION_CLIPBOARD);
+        String text = o.array;
+        if (text !is null && text.length > 0) {
+            // position cursor
+            doMouseLocationChange(event.x, event.y, false);
+            // insert text
+            Event e = new Event();
+            e.start = selection.x;
+            e.end = selection.y;
+            e.text = getModelDelimitedText(text);
+            sendKeyEvent(e);
+        }
+    }
+
+    //set selection
+    if ((event.button !is 1) || (IS_CARBON && (event.stateMask & SWT.MOD4) !is 0)) {
+        return;
+    }
+    clickCount = event.count;
+    if (clickCount is 1) {
+        bool select = (event.stateMask & SWT.MOD2) !is 0;
+        doMouseLocationChange(event.x, event.y, select);
+    } else {
+        if (doubleClickEnabled) {
+            clearSelection(false);
+            int offset = getOffsetAtPoint(event.x, event.y);
+            int lineIndex = content.getLineAtOffset(offset);
+            int lineOffset = content.getOffsetAtLine(lineIndex);
+            int lineEnd = content.getCharCount();
+            if (lineIndex + 1 < content.getLineCount()) {
+                lineEnd = content.getOffsetAtLine(lineIndex + 1);
+            }
+            int start, end;
+            if ((clickCount & 1) is 0) {
+                start = Math.max(0, getWordPrevious(offset, SWT.MOVEMENT_WORD_START));
+                end = Math.min(content.getCharCount(), getWordNext(start, SWT.MOVEMENT_WORD_END));
+            } else {
+                start = lineOffset;
+                end = lineEnd;
+            }
+            caretOffset = start;
+            resetSelection();
+            caretOffset = end;
+            showCaret();
+            doMouseSelection();
+            doubleClickSelection = new Point(selection.x, selection.y);
+        }
+    }
+}
+/**
+ * Updates the caret location and selection if mouse button 1 is pressed
+ * during the mouse move.
+ */
+void handleMouseMove(Event event) {
+    if (clickCount is 0) return;
+    doMouseLocationChange(event.x, event.y, true);
+    update();
+    doAutoScroll(event);
+}
+/**
+ * Autoscrolling ends when the mouse button is released.
+ */
+void handleMouseUp(Event event) {
+    clickCount = 0;
+    endAutoScroll();
+    if (event.button is 1) {
+        try {
+            if (selection.y - selection.x > 0) {
+                setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD);
+            }
+        } catch (SWTError error) {
+            // Copy to clipboard failed. This happens when another application
+            // is accessing the clipboard while we copy. Ignore the error.
+            // Fixes 1GDQAVN
+            // Rethrow all other errors. Fixes bug 17578.
+            if (error.code !is DND.ERROR_CANNOT_SET_CLIPBOARD) {
+                throw error;
+            }
+        }
+    }
+}
+/**
+ * Renders the invalidated area specified in the paint event.
+ *
+ * @param event paint event
+ */
+void handlePaint(Event event) {
+    if (event.width is 0 || event.height is 0) return;
+    if (clientAreaWidth is 0 || clientAreaHeight is 0) return;
+
+    int startLine = getLineIndex(event.y);
+    int y = getLinePixel(startLine);
+    int endY = event.y + event.height;
+    GC gc = event.gc;
+    Color background = getBackground();
+    Color foreground = getForeground();
+    if (endY > 0) {
+        int lineCount = isSingleLine() ? 1 : content.getLineCount();
+        int x = leftMargin - horizontalScrollOffset;
+        for (int i = startLine; y < endY && i < lineCount; i++) {
+            y += renderer.drawLine(i, x, y, gc, background, foreground);
+        }
+        if (y < endY) {
+            gc.setBackground(background);
+            drawBackground(gc, 0, y, clientAreaWidth, endY - y);
+        }
+    }
+    // fill the margin background
+    gc.setBackground(background);
+    if (topMargin > 0) {
+        drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
+    }
+    if (bottomMargin > 0) {
+        drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
+    }
+    if (leftMargin > 0) {
+        drawBackground(gc, 0, 0, leftMargin, clientAreaHeight);
+    }
+    if (rightMargin > 0) {
+        drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight);
+    }
+}
+/**
+ * Recalculates the scroll bars. Rewraps all lines when in word
+ * wrap mode.
+ *
+ * @param event resize event
+ */
+void handleResize(Event event) {
+    int oldHeight = clientAreaHeight;
+    int oldWidth = clientAreaWidth;
+    Rectangle clientArea = getClientArea();
+    clientAreaHeight = clientArea.height;
+    clientAreaWidth = clientArea.width;
+    /* Redraw the old or new right/bottom margin if needed */
+    if (oldWidth !is clientAreaWidth) {
+        if (rightMargin > 0) {
+            int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin;
+            super.redraw(x, 0, rightMargin, oldHeight, false);
+        }
+    }
+    if (oldHeight !is clientAreaHeight) {
+        if (bottomMargin > 0) {
+            int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin;
+            super.redraw(0, y, oldWidth, bottomMargin, false);
+        }
+    }
+    if (wordWrap) {
+        if (oldWidth !is clientAreaWidth) {
+            renderer.reset(0, content.getLineCount());
+            verticalScrollOffset = -1;
+            renderer.calculateIdle();
+            super.redraw();
+        }
+        if (oldHeight !is clientAreaHeight) {
+            if (oldHeight is 0) topIndexY = 0;
+            setScrollBars(true);
+        }
+        setCaretLocation();
+    } else  {
+        renderer.calculateClientArea();
+        setScrollBars(true);
+        claimRightFreeSpace();
+        // StyledText allows any value for horizontalScrollOffset when clientArea is zero
+        // in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429.
+        if (clientAreaWidth !is 0) {
+            ScrollBar horizontalBar = getHorizontalBar();
+            if (horizontalBar !is null && horizontalBar.getVisible()) {
+                if (horizontalScrollOffset !is horizontalBar.getSelection()) {
+                    horizontalBar.setSelection(horizontalScrollOffset);
+                    horizontalScrollOffset = horizontalBar.getSelection();
+                }
+            }
+        }
+    }
+    claimBottomFreeSpace();
+    //TODO FIX TOP INDEX DURING RESIZE
+//  if (oldHeight !is clientAreaHeight || wordWrap) {
+//      calculateTopIndex(0);
+//  }
+}
+/**
+ * Updates the caret position and selection and the scroll bars to reflect
+ * 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) {
+        topIndex = firstLine;
+        topIndexY = 0;
+        super.redraw();
+    } else {
+        int lastLine = firstLine + lastTextChangeNewLineCount;
+        int firstLineTop = getLinePixel(firstLine);
+        int newLastLineBottom = getLinePixel(lastLine + 1);
+        if (lastLineBottom !is newLastLineBottom) {
+            super.redraw();
+        } else {
+            super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false);
+            redrawLinesBullet(renderer.redrawLines);
+        }
+    }
+    renderer.redrawLines = null;
+    // update selection/caret location after styles have been changed.
+    // otherwise any text measuring could be incorrect
+    //
+    // also, this needs to be done after all scrolling. Otherwise,
+    // selection redraw would be flushed during scroll which is wrong.
+    // in some cases new text would be drawn in scroll source area even
+    // though the intent is to scroll it.
+    updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
+    if (lastTextChangeReplaceLineCount > 0 || wordWrap) {
+        claimBottomFreeSpace();
+    }
+    if (lastTextChangeReplaceCharCount > 0) {
+        claimRightFreeSpace();
+    }
+}
+/**
+ * Updates the screen to reflect a pending content change.
+ *
+ * @param event .start the start offset of the change
+ * @param event .newText text that is going to be inserted or empty String
+ *  if no text will be inserted
+ * @param event .replaceCharCount length of text that is going to be replaced
+ * @param event .newCharCount length of text that is going to be inserted
+ * @param event .replaceLineCount number of lines that are going to be replaced
+ * @param event .newLineCount number of new lines that are going to be inserted
+ */
+void handleTextChanging(TextChangingEvent event) {
+    if (event.replaceCharCount < 0) {
+        event.start += event.replaceCharCount;
+        event.replaceCharCount *= -1;
+    }
+    lastTextChangeStart = event.start;
+    lastTextChangeNewLineCount = event.newLineCount;
+    lastTextChangeNewCharCount = event.newCharCount;
+    lastTextChangeReplaceLineCount = event.replaceLineCount;
+    lastTextChangeReplaceCharCount = event.replaceCharCount;
+    int lineIndex = content.getLineAtOffset(event.start);
+    int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1);
+    int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight();
+    lastLineBottom = destY;
+    if (srcY < 0 && destY < 0) {
+        lastLineBottom += srcY - destY;
+        verticalScrollOffset += destY - srcY;
+        calculateTopIndex(destY - srcY);
+        setScrollBars(true);
+    } else {
+        scrollText(srcY, destY);
+    }
+
+    renderer.textChanging(event);
+
+    // Update the caret offset if it is greater than the length of the content.
+    // This is necessary since style range API may be called between the
+    // handleTextChanging and handleTextChanged events and this API sets the
+    // caretOffset.
+    int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount;
+    if (caretOffset > newEndOfText) caretOffset = newEndOfText;
+}
+/**
+ * Called when the widget content is set programmatically, overwriting
+ * the old content. Resets the caret position, selection and scroll offsets.
+ * Recalculates the content width and scroll bars. Redraws the widget.
+ *
+ * @param event text change event.
+ */
+void handleTextSet(TextChangedEvent event) {
+    reset();
+}
+/**
+ * Called when a traversal key is pressed.
+ * Allow tab next traversal to occur when the widget is in single
+ * line mode or in multi line and non-editable mode .
+ * When in editable multi line mode we want to prevent the tab
+ * traversal and receive the tab key event instead.
+ *
+ * @param event the event
+ */
+void handleTraverse(Event event) {
+    switch (event.detail) {
+        case SWT.TRAVERSE_ESCAPE:
+        case SWT.TRAVERSE_PAGE_NEXT:
+        case SWT.TRAVERSE_PAGE_PREVIOUS:
+            event.doit = true;
+            break;
+        case SWT.TRAVERSE_RETURN:
+        case SWT.TRAVERSE_TAB_NEXT:
+        case SWT.TRAVERSE_TAB_PREVIOUS:
+            if ((getStyle() & SWT.SINGLE) !is 0) {
+                event.doit = true;
+            } else {
+                if (!editable || (event.stateMask & SWT.MODIFIER_MASK) !is 0) {
+                    event.doit = true;
+                }
+            }
+            break;
+        default:
+    }
+}
+/**
+ * Scrolls the widget vertically.
+ */
+void handleVerticalScroll(Event event) {
+    int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
+    scrollVertical(scrollPixel, false);
+}
+/**
+ * Add accessibility support for the widget.
+ */
+void initializeAccessible() {
+    final Accessible accessible = getAccessible();
+    accessible.addAccessibleListener(new class() AccessibleAdapter {
+        public void getName (AccessibleEvent e) {
+            String name = null;
+            Label label = getAssociatedLabel ();
+            if (label !is null) {
+                name = stripMnemonic (label.getText());
+            }
+            e.result = name;
+        }
+        public void getHelp(AccessibleEvent e) {
+            e.result = getToolTipText();
+        }
+        public void getKeyboardShortcut(AccessibleEvent e) {
+            String shortcut = null;
+            Label label = getAssociatedLabel ();
+            if (label !is null) {
+                String text = label.getText ();
+                if (text !is null) {
+                    dchar mnemonic = _findMnemonic (text);
+                    if (mnemonic !is '\0') {
+                        shortcut = "Alt+"~tango.text.convert.Utf.toString( [mnemonic] ); //$NON-NLS-1$
+                    }
+                }
+            }
+            e.result = shortcut;
+        }
+    });
+    accessible.addAccessibleTextListener(new class() AccessibleTextAdapter {
+        public void getCaretOffset(AccessibleTextEvent e) {
+            e.offset = this.outer.getCaretOffset();
+        }
+        public void getSelectionRange(AccessibleTextEvent e) {
+            Point selection = this.outer.getSelectionRange();
+            e.offset = selection.x;
+            e.length = selection.y;
+        }
+    });
+    accessible.addAccessibleControlListener(new class() AccessibleControlAdapter {
+        public void getRole(AccessibleControlEvent e) {
+            e.detail = ACC.ROLE_TEXT;
+        }
+        public void getState(AccessibleControlEvent e) {
+            int state = 0;
+            if (isEnabled()) state |= ACC.STATE_FOCUSABLE;
+            if (isFocusControl()) state |= ACC.STATE_FOCUSED;
+            if (!isVisible()) state |= ACC.STATE_INVISIBLE;
+            if (!getEditable()) state |= ACC.STATE_READONLY;
+            e.detail = state;
+        }
+        public void getValue(AccessibleControlEvent e) {
+            e.result = this.outer.getText();
+        }
+    });
+    addListener(SWT.FocusIn, new class(accessible) Listener {
+        Accessible acc;
+        this( Accessible acc ){ this.acc = acc; }
+        public void handleEvent(Event event) {
+            acc.setFocus(ACC.CHILDID_SELF);
+        }
+    });
+}
+/*
+ * Return the Label immediately preceding the receiver in the z-order,
+ * or null if none.
+ */
+Label getAssociatedLabel () {
+    Control[] siblings = getParent ().getChildren ();
+    for (int i = 0; i < siblings.length; i++) {
+        if (siblings [i] is this) {
+            if (i > 0 && ( null !is cast(Label)siblings [i-1])) {
+                return cast(Label) siblings [i-1];
+            }
+        }
+    }
+    return null;
+}
+String stripMnemonic (String string) {
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while ((index < length_) && (string[index] !is '&')) index++;
+        if (++index >= length_) return string;
+        if (string[index] !is '&') {
+            return string.substring(0, index-1) ~ string.substring(index, length_);
+        }
+        index++;
+    } while (index < length_);
+    return string;
+}
+/*
+ * Return the lowercase of the first non-'&' character following
+ * an '&' character in the given string. If there are no '&'
+ * characters in the given string, return '\0'.
+ */
+dchar _findMnemonic (String string) {
+    if (string is null) return '\0';
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while (index < length_ && string[index] !is '&') index++;
+        if (++index >= length_) return '\0';
+        if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] );
+        index++;
+    } while (index < length_);
+    return '\0';
+}
+/**
+ * Executes the action.
+ *
+ * @param action one of the actions defined in ST.java
+ */
+public void invokeAction(int action) {
+    checkWidget();
+    updateCaretDirection = true;
+    switch (action) {
+        // Navigation
+        case ST.LINE_UP:
+            doLineUp(false);
+            clearSelection(true);
+            break;
+        case ST.LINE_DOWN:
+            doLineDown(false);
+            clearSelection(true);
+            break;
+        case ST.LINE_START:
+            doLineStart();
+            clearSelection(true);
+            break;
+        case ST.LINE_END:
+            doLineEnd();
+            clearSelection(true);
+            break;
+        case ST.COLUMN_PREVIOUS:
+            doCursorPrevious();
+            clearSelection(true);
+            break;
+        case ST.COLUMN_NEXT:
+            doCursorNext();
+            clearSelection(true);
+            break;
+        case ST.PAGE_UP:
+            doPageUp(false, -1);
+            clearSelection(true);
+            break;
+        case ST.PAGE_DOWN:
+            doPageDown(false, -1);
+            clearSelection(true);
+            break;
+        case ST.WORD_PREVIOUS:
+            doWordPrevious();
+            clearSelection(true);
+            break;
+        case ST.WORD_NEXT:
+            doWordNext();
+            clearSelection(true);
+            break;
+        case ST.TEXT_START:
+            doContentStart();
+            clearSelection(true);
+            break;
+        case ST.TEXT_END:
+            doContentEnd();
+            clearSelection(true);
+            break;
+        case ST.WINDOW_START:
+            doPageStart();
+            clearSelection(true);
+            break;
+        case ST.WINDOW_END:
+            doPageEnd();
+            clearSelection(true);
+            break;
+        // Selection
+        case ST.SELECT_LINE_UP:
+            doSelectionLineUp();
+            break;
+        case ST.SELECT_ALL:
+            selectAll();
+            break;
+        case ST.SELECT_LINE_DOWN:
+            doSelectionLineDown();
+            break;
+        case ST.SELECT_LINE_START:
+            doLineStart();
+            doSelection(ST.COLUMN_PREVIOUS);
+            break;
+        case ST.SELECT_LINE_END:
+            doLineEnd();
+            doSelection(ST.COLUMN_NEXT);
+            break;
+        case ST.SELECT_COLUMN_PREVIOUS:
+            doSelectionCursorPrevious();
+            doSelection(ST.COLUMN_PREVIOUS);
+            break;
+        case ST.SELECT_COLUMN_NEXT:
+            doSelectionCursorNext();
+            doSelection(ST.COLUMN_NEXT);
+            break;
+        case ST.SELECT_PAGE_UP:
+            doSelectionPageUp(-1);
+            break;
+        case ST.SELECT_PAGE_DOWN:
+            doSelectionPageDown(-1);
+            break;
+        case ST.SELECT_WORD_PREVIOUS:
+            doSelectionWordPrevious();
+            doSelection(ST.COLUMN_PREVIOUS);
+            break;
+        case ST.SELECT_WORD_NEXT:
+            doSelectionWordNext();
+            doSelection(ST.COLUMN_NEXT);
+            break;
+        case ST.SELECT_TEXT_START:
+            doContentStart();
+            doSelection(ST.COLUMN_PREVIOUS);
+            break;
+        case ST.SELECT_TEXT_END:
+            doContentEnd();
+            doSelection(ST.COLUMN_NEXT);
+            break;
+        case ST.SELECT_WINDOW_START:
+            doPageStart();
+            doSelection(ST.COLUMN_PREVIOUS);
+            break;
+        case ST.SELECT_WINDOW_END:
+            doPageEnd();
+            doSelection(ST.COLUMN_NEXT);
+            break;
+        // Modification
+        case ST.CUT:
+            cut();
+            break;
+        case ST.COPY:
+            copy();
+            break;
+        case ST.PASTE:
+            paste();
+            break;
+        case ST.DELETE_PREVIOUS:
+            doBackspace();
+            break;
+        case ST.DELETE_NEXT:
+            doDelete();
+            break;
+        case ST.DELETE_WORD_PREVIOUS:
+            doDeleteWordPrevious();
+            break;
+        case ST.DELETE_WORD_NEXT:
+            doDeleteWordNext();
+            break;
+        // Miscellaneous
+        case ST.TOGGLE_OVERWRITE:
+            overwrite = !overwrite;     // toggle insert/overwrite mode
+            break;
+        default:
+    }
+}
+/**
+ * Temporary until SWT provides this
+ */
+bool isBidi() {
+    return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_;
+}
+bool isBidiCaret() {
+    return BidiUtil.isBidiPlatform();
+}
+bool isFixedLineHeight() {
+    return fixedLineHeight;
+}
+/**
+ * Returns whether the given offset is inside a multi byte line delimiter.
+ * Example:
+ * "Line1\r\n" isLineDelimiter(5) is false but isLineDelimiter(6) is true
+ *
+ * @return true if the given offset is inside a multi byte line delimiter.
+ * false if the given offset is before or after a line delimiter.
+ */
+bool isLineDelimiter(int offset) {
+    int line = content.getLineAtOffset(offset);
+    int lineOffset = content.getOffsetAtLine(line);
+    int offsetInLine = offset - 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.
+    return offsetInLine > content.getLine(line).length;
+}
+/**
+ * Returns whether the widget is mirrored (right oriented/right to left
+ * writing order).
+ *
+ * @return isMirrored true=the widget is right oriented, false=the widget
+ *  is left oriented
+ */
+bool isMirrored() {
+    return isMirrored_;
+}
+/**
+ * Returns whether the widget can have only one line.
+ *
+ * @return true if widget can have only one line, false if widget can have
+ *  multiple lines
+ */
+bool isSingleLine() {
+    return (getStyle() & SWT.SINGLE) !is 0;
+}
+/**
+ * Sends the specified verify event, replace/insert text as defined by
+ * the event and send a modify event.
+ *
+ * @param event the text change event.
+ *  <ul>
+ *  <li>event.start - the replace start offset</li>
+ *  <li>event.end - the replace end offset</li>
+ *  <li>event.text - the new text</li>
+ *  </ul>
+ * @param updateCaret whether or not he caret should be set behind
+ *  the new text
+ */
+void modifyContent(Event event, bool updateCaret) {
+    event.doit = true;
+    notifyListeners(SWT.Verify, event);
+    if (event.doit) {
+        StyledTextEvent styledTextEvent = null;
+        int replacedLength = event.end - event.start;
+        if (isListening(ExtendedModify)) {
+            styledTextEvent = new StyledTextEvent(content);
+            styledTextEvent.start = event.start;
+            styledTextEvent.end = event.start + event.text.length;
+            styledTextEvent.text = content.getTextRange(event.start, replacedLength);
+        }
+        if (updateCaret) {
+            //Fix advancing flag for delete/backspace key on direction boundary
+            if (event.text.length is 0) {
+                int lineIndex = content.getLineAtOffset(event.start);
+                int lineOffset = content.getOffsetAtLine(lineIndex);
+                TextLayout layout = renderer.getTextLayout(lineIndex);
+                int levelStart = layout.getLevel(event.start - lineOffset);
+                int lineIndexEnd = content.getLineAtOffset(event.end);
+                if (lineIndex !is lineIndexEnd) {
+                    renderer.disposeTextLayout(layout);
+                    lineOffset = content.getOffsetAtLine(lineIndexEnd);
+                    layout = renderer.getTextLayout(lineIndexEnd);
+                }
+                int levelEnd = layout.getLevel(event.end - lineOffset);
+                renderer.disposeTextLayout(layout);
+                if (levelStart !is levelEnd) {
+                    caretAlignment = PREVIOUS_OFFSET_TRAILING;
+                } else {
+                    caretAlignment = OFFSET_LEADING;
+                }
+            }
+        }
+        content.replaceTextRange(event.start, replacedLength, event.text);
+        // set the caret position prior to sending the modify event.
+        // fixes 1GBB8NJ
+        if (updateCaret) {
+            // always update the caret location. fixes 1G8FODP
+            setSelection(event.start + event.text.length, 0, true);
+            showCaret();
+        }
+        sendModifyEvent(event);
+        if (isListening(ExtendedModify)) {
+            notifyListeners(ExtendedModify, styledTextEvent);
+        }
+    }
+}
+void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
+    if (isListening(PaintObject)) {
+        StyledTextEvent event = new StyledTextEvent (content) ;
+        event.gc = gc;
+        event.x = x;
+        event.y = y;
+        event.ascent = ascent;
+        event.descent = descent;
+        event.style = style;
+        event.bullet = bullet;
+        event.bulletIndex = bulletIndex;
+        notifyListeners(PaintObject, event);
+    }
+}
+/**
+ * Replaces the selection with the text on the <code>DND.CLIPBOARD</code>
+ * clipboard  or, if there is no selection,  inserts the text at the current
+ * caret offset.   If the widget has the SWT.SINGLE style and the
+ * clipboard text contains more than one line, only the first line without
+ * line delimiters is  inserted in the widget.
+ *
+ * @exception SWTException <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 paste(){
+    checkWidget();
+    String text = null;
+    if( auto o = cast(ArrayWrapperString) getClipboardContent(DND.CLIPBOARD)){
+        text = o.array;
+    }
+    if (text !is null && text.length > 0) {
+        Event event = new Event();
+        event.start = selection.x;
+        event.end = selection.y;
+        event.text = getModelDelimitedText(text);
+        sendKeyEvent(event);
+    }
+}
+/**
+ * Prints the widget's text to the default printer.
+ *
+ * @exception SWTException <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 print() {
+    checkWidget();
+    Printer printer = new Printer();
+    StyledTextPrintOptions options = new StyledTextPrintOptions();
+    options.printTextForeground = true;
+    options.printTextBackground = true;
+    options.printTextFontStyle = true;
+    options.printLineBackground = true;
+    (new Printing(this, printer, options)).run();
+    printer.dispose();
+}
+/**
+ * Returns a runnable that will print the widget's text
+ * to the specified printer.
+ * <p>
+ * The runnable may be run in a non-UI thread.
+ * </p>
+ *
+ * @param printer the printer to print to
+ *
+ * @return a <code>Runnable</code> for printing the receiver's text
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when printer is null</li>
+ * </ul>
+ */
+public Runnable print(Printer printer) {
+    checkWidget();
+    if (printer is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    StyledTextPrintOptions options = new StyledTextPrintOptions();
+    options.printTextForeground = true;
+    options.printTextBackground = true;
+    options.printTextFontStyle = true;
+    options.printLineBackground = true;
+    return print(printer, options);
+}
+/**
+ * Returns a runnable that will print the widget's text
+ * to the specified printer.
+ * <p>
+ * The runnable may be run in a non-UI thread.
+ * </p>
+ *
+ * @param printer the printer to print to
+ * @param options print options to use during printing
+ *
+ * @return a <code>Runnable</code> for printing the receiver's text
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when printer or options is null</li>
+ * </ul>
+ * @since 2.1
+ */
+public Runnable print(Printer printer, StyledTextPrintOptions options) {
+    checkWidget();
+    if (printer is null || options is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    return new Printing(this, printer, options);
+}
+/**
+ * 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.
+ * <p>
+ * Recalculates the content width for all lines in the bounds.
+ * When a <code>LineStyleListener</code> is used a redraw call
+ * is the only notification to the widget that styles have changed
+ * and that the content width may have changed.
+ * </p>
+ *
+ * @exception SWTException <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 Control#update()
+ */
+public override void redraw() {
+    super.redraw();
+    int itemCount = getPartialBottomIndex() - topIndex + 1;
+    renderer.reset(topIndex, itemCount);
+    renderer.calculate(topIndex, itemCount);
+    setScrollBars(false);
+}
+/**
+ * Causes the rectangular area of the receiver specified by
+ * the arguments to be marked as needing to be redrawn.
+ * The next time a paint request is processed, that area of
+ * the receiver will be painted. If the <code>all</code> flag
+ * is <code>true</code>, any children of the receiver which
+ * intersect with the specified area will also paint their
+ * intersecting areas. If the <code>all</code> flag is
+ * <code>false</code>, the children will not be painted.
+ * <p>
+ * Marks the content width of all lines in the specified rectangle
+ * as unknown. Recalculates the content width of all visible lines.
+ * When a <code>LineStyleListener</code> is used a redraw call
+ * is the only notification to the widget that styles have changed
+ * and that the content width may have changed.
+ * </p>
+ *
+ * @param x the x coordinate of the area to draw
+ * @param y the y coordinate of the area to draw
+ * @param width the width of the area to draw
+ * @param height the height of the area to draw
+ * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 Control#update()
+ */
+public override void redraw(int x, int y, int width, int height, bool all) {
+    super.redraw(x, y, width, height, all);
+    if (height > 0) {
+        int firstLine = getLineIndex(y);
+        int lastLine = getLineIndex(y + height);
+        resetCache(firstLine, lastLine - firstLine + 1);
+    }
+}
+void redrawLines(int startLine, int lineCount) {
+    // do nothing if redraw range is completely invisible
+    int partialBottomIndex = getPartialBottomIndex();
+    if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) {
+        return;
+    }
+    // only redraw visible lines
+    if (startLine < topIndex) {
+        lineCount -= topIndex - startLine;
+        startLine = topIndex;
+    }
+    if (startLine + lineCount - 1 > partialBottomIndex) {
+        lineCount = partialBottomIndex - startLine + 1;
+    }
+    startLine -= topIndex;
+    int redrawTop = getLinePixel(startLine);
+    int redrawBottom = getLinePixel(startLine + lineCount);
+    int redrawWidth = clientAreaWidth - leftMargin - rightMargin;
+    super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
+}
+void redrawLinesBullet (int[] redrawLines) {
+    if (redrawLines is null) return;
+    int topIndex = getPartialTopIndex();
+    int bottomIndex = getPartialBottomIndex();
+    for (int i = 0; i < redrawLines.length; i++) {
+        int lineIndex = redrawLines[i];
+        if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue;
+        int width = -1;
+        Bullet bullet = renderer.getLineBullet(lineIndex, null);
+        if (bullet !is null) {
+            StyleRange style = bullet.style;
+            GlyphMetrics metrics = style.metrics;
+            width = metrics.width;
+        }
+        if (width is -1) width = getClientArea().width;
+        int height = renderer.getLineHeight(lineIndex);
+        int y = getLinePixel(lineIndex);
+        super.redraw(0, y, width, height, false);
+    }
+}
+/**
+ * Redraws the specified text range.
+ *
+ * @param start offset of the first character to redraw
+ * @param length number of characters to redraw
+ * @param clearBackground true if the background should be cleared as
+ *  part of the redraw operation.  If true, the entire redraw range will
+ *  be cleared before anything is redrawn.  If the redraw range includes
+ *  the last character of a line (i.e., the entire line is redrawn) the
+ *  line is cleared all the way to the right border of the widget.
+ *  The redraw operation will be faster and smoother if clearBackground
+ *  is set to false.  Whether or not the flag can be set to false depends
+ *  on the type of change that has taken place.  If font styles or
+ *  background colors for the redraw range have changed, clearBackground
+ *  should be set to true.  If only foreground colors have changed for
+ *  the redraw range, clearBackground can be set to false.
+ * @exception SWTException <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 start and/or end are outside the widget content</li>
+ * </ul>
+ */
+public void redrawRange(int start, int length, bool clearBackground) {
+    checkWidget();
+    int end = start + length;
+    int contentLength = content.getCharCount();
+    if (start > end || start < 0 || end > contentLength) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    int firstLine = content.getLineAtOffset(start);
+    int lastLine = content.getLineAtOffset(end);
+    resetCache(firstLine, lastLine - firstLine + 1);
+    internalRedrawRange(start, length);
+}
+/**
+ * Removes the specified bidirectional segment listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ *
+ * @since 2.0
+ */
+public void removeBidiSegmentListener(BidiSegmentListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(LineGetSegments, listener);
+}
+/**
+ * Removes the specified extended modify listener.
+ *
+ * @param extendedModifyListener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
+    checkWidget();
+    if (extendedModifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(ExtendedModify, extendedModifyListener);
+}
+/**
+ * Removes the specified line background listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeLineBackgroundListener(LineBackgroundListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(LineGetBackground, listener);
+}
+/**
+ * Removes the specified line style listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeLineStyleListener(LineStyleListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(LineGetStyle, listener);
+}
+/**
+ * Removes the specified modify listener.
+ *
+ * @param modifyListener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeModifyListener(ModifyListener modifyListener) {
+    checkWidget();
+    if (modifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Modify, modifyListener);
+}
+/**
+ * Removes the specified listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ * @since 3.2
+ */
+public void removePaintObjectListener(PaintObjectListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(PaintObject, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Selection, listener);
+}
+/**
+ * Removes the specified verify listener.
+ *
+ * @param verifyListener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeVerifyListener(VerifyListener verifyListener) {
+    checkWidget();
+    if (verifyListener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Verify, verifyListener);
+}
+/**
+ * Removes the specified key verify listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeVerifyKeyListener(VerifyKeyListener listener) {
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(VerifyKey, listener);
+}
+/**
+ * Removes the specified word movement listener.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ *
+ * @see MovementEvent
+ * @see MovementListener
+ * @see #addWordMovementListener
+ *
+ * @since 3.3
+ */
+
+public void removeWordMovementListener(MovementListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(WordNext, listener);
+    removeListener(WordPrevious, listener);
+}
+/**
+ * Replaces the styles in the given range with new styles.  This method
+ * effectively deletes the styles in the given range and then adds the
+ * the new styles.
+ * <p>
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, <code>setStyleRanges(int, int, int[], StyleRange[])</code>
+ * can be used to share styles and reduce memory usage.
+ * </p><p>
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param start offset of first character where styles will be deleted
+ * @param length length of the range to delete styles in
+ * @param ranges StyleRange objects containing the new style information.
+ * The ranges should not overlap and should be within the specified start
+ * and length. The style rendering is undefined if the ranges do overlap
+ * or are ill-defined. Must not be null.
+ * @exception SWTException <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 either start or end is outside the valid range (0 <= offset <= getCharCount())</li>
+ * </ul>
+ *
+ * @since 2.0
+ *
+ * @see #setStyleRanges(int, int, int[], StyleRange[])
+ */
+public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    // SWT extension: allow null for zero length string
+    //if (ranges is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    setStyleRanges(start, length, null, ranges, false);
+}
+/**
+ * Replaces the given text range with new text.
+ * If the widget has the SWT.SINGLE style and "text" contains more than
+ * one line, only the first line is rendered but the text is stored
+ * unchanged. A subsequent call to getText will return the same text
+ * that was set. Note that only a single line of text should be set when
+ * the SWT.SINGLE style is used.
+ * <p>
+ * <b>NOTE:</b> During the replace operation the current selection is
+ * changed as follows:
+ * <ul>
+ * <li>selection before replaced text: selection unchanged
+ * <li>selection after replaced text: adjust the selection so that same text
+ * remains selected
+ * <li>selection intersects replaced text: selection is cleared and caret
+ * is placed after inserted text
+ * </ul>
+ * </p>
+ *
+ * @param start offset of first character to replace
+ * @param length number of characters to replace. Use 0 to insert text
+ * @param text new text. May be empty to delete text.
+ * @exception SWTException <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 either start or end is outside the valid range (0 <= offset <= getCharCount())</li>
+ *   <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter.
+ *      Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported</li>
+ * </ul>
+ */
+public void replaceTextRange(int start, int length, String text) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+//     if (text is null) {
+//         SWT.error(SWT.ERROR_NULL_ARGUMENT);
+//     }
+    int contentLength = getCharCount();
+    int end = start + length;
+    if (start > end || start < 0 || end > contentLength) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    Event event = new Event();
+    event.start = start;
+    event.end = end;
+    event.text = text;
+    modifyContent(event, false);
+}
+/**
+ * Resets the caret position, selection and scroll offsets. Recalculate
+ * the content width and scroll bars. Redraw the widget.
+ */
+void reset() {
+    ScrollBar verticalBar = getVerticalBar();
+    ScrollBar horizontalBar = getHorizontalBar();
+    caretOffset = 0;
+    topIndex = 0;
+    topIndexY = 0;
+    verticalScrollOffset = 0;
+    horizontalScrollOffset = 0;
+    resetSelection();
+    renderer.setContent(content);
+    if (verticalBar !is null) {
+        verticalBar.setSelection(0);
+    }
+    if (horizontalBar !is null) {
+        horizontalBar.setSelection(0);
+    }
+    resetCache(0, 0);
+    setCaretLocation();
+    super.redraw();
+}
+void resetCache(int firstLine, int count) {
+    int maxLineIndex = renderer.maxWidthLineIndex;
+    renderer.reset(firstLine, count);
+    renderer.calculateClientArea();
+    if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
+        renderer.calculate(maxLineIndex, 1);
+    }
+    setScrollBars(true);
+    if (!isFixedLineHeight()) {
+        if (topIndex > firstLine) {
+            verticalScrollOffset = -1;
+        }
+        renderer.calculateIdle();
+    }
+}
+/**
+ * Resets the selection.
+ */
+void resetSelection() {
+    selection.x = selection.y = caretOffset;
+    selectionAnchor = -1;
+}
+
+public override void scroll(int destX, int destY, int x, int y, int width, int height, bool all) {
+    super.scroll(destX, destY, x, y, width, height, false);
+    if (all) {
+        int deltaX = destX - x, deltaY = destY - y;
+        Control[] children = getChildren();
+        for (int i=0; i<children.length; i++) {
+            Control child = children[i];
+            Rectangle rect = child.getBounds();
+            child.setLocation(rect.x + deltaX, rect.y + deltaY);
+        }
+    }
+}
+
+/**
+ * Scrolls the widget horizontally.
+ *
+ * @param pixels number of pixels to scroll, > 0 = scroll left,
+ *  < 0 scroll right
+ * @param adjustScrollBar
+ *  true= the scroll thumb will be moved to reflect the new scroll offset.
+ *  false = the scroll thumb will not be moved
+ * @return
+ *  true=the widget was scrolled
+ *  false=the widget was not scrolled, the given offset is not valid.
+ */
+bool scrollHorizontal(int pixels, bool adjustScrollBar) {
+    if (pixels is 0) {
+        return false;
+    }
+    ScrollBar horizontalBar = getHorizontalBar();
+    if (horizontalBar !is null && adjustScrollBar) {
+        horizontalBar.setSelection(horizontalScrollOffset + pixels);
+    }
+    int scrollHeight = clientAreaHeight - topMargin - bottomMargin;
+    if (pixels > 0) {
+        int sourceX = leftMargin + pixels;
+        int scrollWidth = clientAreaWidth - sourceX - rightMargin;
+        if (scrollWidth > 0) {
+            scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true);
+        }
+        if (sourceX > scrollWidth) {
+            super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true);
+        }
+    } else {
+        int destinationX = leftMargin - pixels;
+        int scrollWidth = clientAreaWidth - destinationX - rightMargin;
+        if (scrollWidth > 0) {
+            scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true);
+        }
+        if (destinationX > scrollWidth) {
+            super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true);
+        }
+    }
+    horizontalScrollOffset += pixels;
+    setCaretLocation();
+    return true;
+}
+/**
+ * Scrolls the widget vertically.
+ *
+ * @param pixel the new vertical scroll offset
+ * @param adjustScrollBar
+ *  true= the scroll thumb will be moved to reflect the new scroll offset.
+ *  false = the scroll thumb will not be moved
+ * @return
+ *  true=the widget was scrolled
+ *  false=the widget was not scrolled
+ */
+bool scrollVertical(int pixels, bool adjustScrollBar) {
+    if (pixels is 0) {
+        return false;
+    }
+    if (verticalScrollOffset !is -1) {
+        ScrollBar verticalBar = getVerticalBar();
+        if (verticalBar !is null && adjustScrollBar) {
+            verticalBar.setSelection(verticalScrollOffset + pixels);
+        }
+        int scrollWidth = clientAreaWidth - leftMargin - rightMargin;
+        if (pixels > 0) {
+            int sourceY = topMargin + pixels;
+            int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
+            if (scrollHeight > 0) {
+                scroll(leftMargin, topMargin, leftMargin, sourceY, scrollWidth, scrollHeight, true);
+            }
+            if (sourceY > scrollHeight) {
+                int redrawY = Math.max(0, topMargin + scrollHeight);
+                int redrawHeight = Math.min(clientAreaHeight, pixels - scrollHeight);
+                super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
+            }
+        } else {
+            int destinationY = topMargin - pixels;
+            int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
+            if (scrollHeight > 0) {
+                scroll(leftMargin, destinationY, leftMargin, topMargin, scrollWidth, scrollHeight, true);
+            }
+            if (destinationY > scrollHeight) {
+                int redrawY = Math.max(0, topMargin + scrollHeight);
+                int redrawHeight = Math.min(clientAreaHeight, -pixels - scrollHeight);
+                super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
+            }
+        }
+        verticalScrollOffset += pixels;
+        calculateTopIndex(pixels);
+    } else {
+        calculateTopIndex(pixels);
+        super.redraw();
+    }
+    setCaretLocation();
+    return true;
+}
+void scrollText(int srcY, int destY) {
+    if (srcY is destY) return;
+    int deltaY = destY - srcY;
+    int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight;
+    if (deltaY > 0) {
+        scrollHeight = clientAreaHeight - srcY - bottomMargin;
+    } else {
+        scrollHeight = clientAreaHeight - destY - bottomMargin;
+    }
+    scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true);
+    if ((0 < srcY + scrollHeight) && (topMargin > srcY)) {
+        super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false);
+    }
+    if ((0 < destY + scrollHeight) && (topMargin > destY)) {
+        super.redraw(leftMargin, 0, scrollWidth, topMargin, false);
+    }
+    if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) {
+        super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false);
+    }
+    if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) {
+        super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false);
+    }
+}
+/**
+ * Selects all the text.
+ *
+ * @exception SWTException <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 selectAll() {
+    checkWidget();
+    setSelection(0, Math.max(getCharCount(),0));
+}
+/**
+ * Replaces/inserts text as defined by the event.
+ *
+ * @param event the text change event.
+ *  <ul>
+ *  <li>event.start - the replace start offset</li>
+ *  <li>event.end - the replace end offset</li>
+ *  <li>event.text - the new text</li>
+ *  </ul>
+ */
+void sendKeyEvent(Event event) {
+    if (editable) {
+        modifyContent(event, true);
+    }
+}
+/**
+ * Returns a StyledTextEvent that can be used to request data such
+ * as styles and background color for a line.
+ * <p>
+ * The specified line may be a visual (wrapped) line if in word
+ * wrap mode. The returned object will always be for a logical
+ * (unwrapped) line.
+ * </p>
+ *
+ * @param lineOffset offset of the line. This may be the offset of
+ *  a visual line if the widget is in word wrap mode.
+ * @param line line text. This may be the text of a visual line if
+ *  the widget is in word wrap mode.
+ * @return StyledTextEvent that can be used to request line data
+ *  for the given line.
+ */
+StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) {
+    StyledTextEvent event = null;
+    if (isListening(eventType)) {
+        event = new StyledTextEvent(content);
+        event.detail = lineOffset;
+        event.text = line;
+        event.alignment = alignment;
+        event.indent = indent;
+        event.justify = justify;
+        notifyListeners(eventType, event);
+    }
+    return event;
+}
+void sendModifyEvent(Event event) {
+    Accessible accessible = getAccessible();
+    if (event.text.length is 0) {
+        accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start);
+    } else {
+        if (event.start is event.end) {
+            accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length);
+        } else {
+            accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start);
+            accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length);
+        }
+    }
+    notifyListeners(SWT.Modify, event);
+}
+/**
+ * Sends the specified selection event.
+ */
+void sendSelectionEvent() {
+    getAccessible().textSelectionChanged();
+    Event event = new Event();
+    event.x = selection.x;
+    event.y = selection.y;
+    notifyListeners(SWT.Selection, event);
+}
+int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) {
+    if (isListening(eventType)) {
+        StyledTextEvent event = new StyledTextEvent(content);
+        event.detail = lineOffset;
+        event.text = lineText;
+        event.count = movement;
+        event.start = offset;
+        event.end = newOffset;
+        notifyListeners(eventType, event);
+        offset = event.end;
+        if (offset !is newOffset) {
+            int length = getCharCount();
+            if (offset < 0) {
+                offset = 0;
+            } else if (offset > length) {
+                offset = length;
+            } else {
+                if (isLineDelimiter(offset)) {
+                    SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+                }
+            }
+        }
+        return offset;
+    }
+    return newOffset;
+}
+/**
+ * Sets the alignment of the widget. The argument should be one of <code>SWT.LEFT</code>,
+ * <code>SWT.CENTER</code> or <code>SWT.RIGHT</code>. The alignment applies for all lines.
+ * </p><p>
+ * Note that if <code>SWT.MULTI</code> is set, then <code>SWT.WRAP</code> must also be set
+ * in order to stabilize the right edge before setting alignment.
+ * </p>
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <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 #setLineAlignment(int, int, int)
+ *
+ * @since 3.2
+ */
+public void setAlignment(int alignment) {
+    checkWidget();
+    alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    if (alignment is 0 || this.alignment is alignment) return;
+    this.alignment = alignment;
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    super.redraw();
+}
+/**
+ * @see Control#setBackground(Color)
+ */
+public override void setBackground(Color color) {
+    checkWidget();
+    background = color;
+    super.setBackground(color);
+    super.redraw();
+}
+/**
+ * Sets the receiver's caret.  Set the caret's height and location.
+ *
+ * </p>
+ * @param caret the new caret for the receiver
+ *
+ * @exception SWTException <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 setCaret(Caret caret) {
+    checkWidget ();
+    super.setCaret(caret);
+    caretDirection = SWT.NULL;
+    if (caret !is null) {
+        setCaretLocation();
+    }
+}
+/**
+ * Sets the BIDI coloring mode.  When true the BIDI text display
+ * algorithm is applied to segments of text that are the same
+ * color.
+ *
+ * @param mode the new coloring mode
+ * @exception SWTException <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>
+ *
+ * @deprecated use BidiSegmentListener instead.
+ */
+public void setBidiColoring(bool mode) {
+    checkWidget();
+    bidiColoring = mode;
+}
+/**
+ * Moves the Caret to the current caret offset.
+ */
+void setCaretLocation() {
+    Point newCaretPos = getPointAtOffset(caretOffset);
+    setCaretLocation(newCaretPos, getCaretDirection());
+}
+void setCaretLocation(Point location, int direction) {
+    Caret caret = getCaret();
+    if (caret !is null) {
+        bool isDefaultCaret = caret is defaultCaret;
+        int lineHeight = renderer.getLineHeight();
+        int caretHeight = lineHeight;
+        if (!isFixedLineHeight() && isDefaultCaret) {
+            caretHeight = getBoundsAtOffset(caretOffset).height;
+            if (caretHeight !is lineHeight) {
+                direction = SWT.DEFAULT;
+            }
+        }
+        int imageDirection = direction;
+        if (isMirrored()) {
+            if (imageDirection is SWT.LEFT) {
+                imageDirection = SWT.RIGHT;
+            } else if (imageDirection is SWT.RIGHT) {
+                imageDirection = SWT.LEFT;
+            }
+        }
+        if (isDefaultCaret && imageDirection is SWT.RIGHT) {
+            location.x -= (caret.getSize().x - 1);
+        }
+        if (isDefaultCaret) {
+            caret.setBounds(location.x, location.y, caretWidth, caretHeight);
+        } else {
+            caret.setLocation(location);
+        }
+        getAccessible().textCaretMoved(getCaretOffset());
+        if (direction !is caretDirection) {
+            caretDirection = direction;
+            if (isDefaultCaret) {
+                if (imageDirection is SWT.DEFAULT) {
+                    defaultCaret.setImage(null);
+                } else if (imageDirection is SWT.LEFT) {
+                    defaultCaret.setImage(leftCaretBitmap);
+                } else if (imageDirection is SWT.RIGHT) {
+                    defaultCaret.setImage(rightCaretBitmap);
+                }
+            }
+            if (caretDirection is SWT.LEFT) {
+                BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
+            } else if (caretDirection is SWT.RIGHT) {
+                BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
+            }
+        }
+    }
+    columnX = location.x;
+}
+/**
+ * Sets the caret offset.
+ *
+ * @param offset caret offset, relative to the first character in the text.
+ * @exception SWTException <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_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ * </ul>
+ */
+public void setCaretOffset(int offset) {
+    checkWidget();
+    int length = getCharCount();
+    if (length > 0 && offset !is caretOffset) {
+        if (offset < 0) {
+            caretOffset = 0;
+        } else if (offset > length) {
+            caretOffset = length;
+        } else {
+            if (isLineDelimiter(offset)) {
+                // offset is inside a multi byte line delimiter. This is an
+                // illegal operation and an exception is thrown. Fixes 1GDKK3R
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            }
+            caretOffset = offset;
+        }
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        // clear the selection if the caret is moved.
+        // don't notify listeners about the selection change.
+        clearSelection(false);
+    }
+    setCaretLocation();
+}
+/**
+ * Copies the specified text range to the clipboard.  The text will be placed
+ * in the clipboard in plain text format and RTF format.
+ *
+ * @param start start index of the text
+ * @param length length of text to place in clipboard
+ *
+ * @exception SWTError, see Clipboard.setContents
+ * @see org.eclipse.swt.dnd.Clipboard#setContents
+ */
+void setClipboardContent(int start, int length, int clipboardType) {
+    if (clipboardType is DND.SELECTION_CLIPBOARD && !(IS_MOTIF || IS_GTK)) return;
+    TextTransfer plainTextTransfer = TextTransfer.getInstance();
+    TextWriter plainTextWriter = new TextWriter(start, length);
+    String plainText = getPlatformDelimitedText(plainTextWriter);
+    Object[] data;
+    Transfer[] types;
+    if (clipboardType is DND.SELECTION_CLIPBOARD) {
+        data = [ cast(Object) new ArrayWrapperString(plainText) ];
+        types = [plainTextTransfer];
+    } else {
+        RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+        RTFWriter rtfWriter = new RTFWriter(start, length);
+        String rtfText = getPlatformDelimitedText(rtfWriter);
+        data = [ cast(Object) new ArrayWrapperString(rtfText), new ArrayWrapperString(plainText) ];
+        types = [ cast(Transfer)rtfTransfer, plainTextTransfer];
+    }
+    clipboard.setContents(data, types, clipboardType);
+}
+/**
+ * Sets the content implementation to use for text storage.
+ *
+ * @param newContent StyledTextContent implementation to use for text storage.
+ * @exception SWTException <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_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void setContent(StyledTextContent newContent) {
+    checkWidget();
+    if (newContent is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    if (content !is null) {
+        content.removeTextChangeListener(textChangeListener);
+    }
+    content = newContent;
+    content.addTextChangeListener(textChangeListener);
+    reset();
+}
+/**
+ * Sets the receiver's cursor to the cursor specified by the
+ * argument.  Overridden to handle the null case since the
+ * StyledText widget uses an ibeam as its default cursor.
+ *
+ * @see Control#setCursor(Cursor)
+ */
+public override void setCursor (Cursor cursor) {
+    if (cursor is null) {
+        Display display = getDisplay();
+        super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
+    } else {
+        super.setCursor(cursor);
+    }
+}
+/**
+ * Sets whether the widget : double click mouse behavior.
+ * </p>
+ *
+ * @param enable if true double clicking a word selects the word, if false
+ *  double clicks have the same effect as regular mouse clicks.
+ * @exception SWTException <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 setDoubleClickEnabled(bool enable) {
+    checkWidget();
+    doubleClickEnabled = enable;
+}
+public override void setDragDetect (bool dragDetect_) {
+    checkWidget ();
+    this.dragDetect_ = dragDetect_;
+}
+/**
+ * Sets whether the widget content can be edited.
+ * </p>
+ *
+ * @param editable if true content can be edited, if false content can not be
+ *  edited
+ * @exception SWTException <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 setEditable(bool editable) {
+    checkWidget();
+    this.editable = editable;
+}
+/**
+ * Sets a new font to render text with.
+ * <p>
+ * <b>NOTE:</b> Italic fonts are not supported unless they have no overhang
+ * and the same baseline as regular fonts.
+ * </p>
+ *
+ * @param font new font
+ * @exception SWTException <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 setFont(Font font) {
+    checkWidget();
+    int oldLineHeight = renderer.getLineHeight();
+    super.setFont(font);
+    renderer.setFont(getFont(), tabLength);
+    // keep the same top line visible. fixes 5815
+    if (isFixedLineHeight()) {
+        int lineHeight = renderer.getLineHeight();
+        if (lineHeight !is oldLineHeight) {
+            int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset();
+            scrollVertical(vscroll, true);
+        }
+    }
+    resetCache(0, content.getLineCount());
+    claimBottomFreeSpace();
+    calculateScrollBars();
+    if (isBidiCaret()) createCaretBitmaps();
+    caretDirection = SWT.NULL;
+    setCaretLocation();
+    super.redraw();
+}
+public override void setForeground(Color color) {
+    checkWidget();
+    foreground = color;
+    super.setForeground(getForeground());
+    super.redraw();
+}
+/**
+ * Sets the horizontal scroll offset relative to the start of the line.
+ * Do nothing if there is no text set.
+ * <p>
+ * <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the
+ * widget.
+ * </p>
+ *
+ * @param offset horizontal scroll offset relative to the start
+ *  of the line, measured in character increments starting at 0, if
+ *  equal to 0 the content is not scrolled, if > 0 = the content is scrolled.
+ * @exception SWTException <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 setHorizontalIndex(int offset) {
+    checkWidget();
+    if (getCharCount() is 0) {
+        return;
+    }
+    if (offset < 0) {
+        offset = 0;
+    }
+    offset *= getHorizontalIncrement();
+    // allow any value if client area width is unknown or 0.
+    // offset will be checked in resize handler.
+    // don't use isVisible since width is known even if widget
+    // is temporarily invisible
+    if (clientAreaWidth > 0) {
+        int width = renderer.getWidth();
+        // prevent scrolling if the content fits in the client area.
+        // align end of longest line with right border of client area
+        // if offset is out of range.
+        if (offset > width - clientAreaWidth) {
+            offset = Math.max(0, width - clientAreaWidth);
+        }
+    }
+    scrollHorizontal(offset - horizontalScrollOffset, true);
+}
+/**
+ * Sets the horizontal pixel offset relative to the start of the line.
+ * Do nothing if there is no text set.
+ * <p>
+ * <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text
+ * is set in the widget.
+ * </p>
+ *
+ * @param pixel horizontal pixel offset relative to the start
+ *  of the line.
+ * @exception SWTException <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 2.0
+ */
+public void setHorizontalPixel(int pixel) {
+    checkWidget();
+    if (getCharCount() is 0) {
+        return;
+    }
+    if (pixel < 0) {
+        pixel = 0;
+    }
+    // allow any value if client area width is unknown or 0.
+    // offset will be checked in resize handler.
+    // don't use isVisible since width is known even if widget
+    // is temporarily invisible
+    if (clientAreaWidth > 0) {
+        int width = renderer.getWidth();
+        // prevent scrolling if the content fits in the client area.
+        // align end of longest line with right border of client area
+        // if offset is out of range.
+        if (pixel > width - clientAreaWidth) {
+            pixel = Math.max(0, width - clientAreaWidth);
+        }
+    }
+    scrollHorizontal(pixel - horizontalScrollOffset, true);
+}
+/**
+ * Sets the line indentation of the widget.
+ * <p>
+ * It is the amount of blank space, in pixels, at the beginning of each line.
+ * When a line wraps in several lines only the first one is indented.
+ * </p>
+ *
+ * @param indent the new indent
+ *
+ * @exception SWTException <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 #setLineIndent(int, int, int)
+ *
+ * @since 3.2
+ */
+public void setIndent(int indent) {
+    checkWidget();
+    if (this.indent is indent || indent < 0) return;
+    this.indent = indent;
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    super.redraw();
+}
+/**
+ * Sets whether the widget should justify lines.
+ *
+ * @param justify whether lines should be justified
+ *
+ * @exception SWTException <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 #setLineJustify(int, int, bool)
+ *
+ * @since 3.2
+ */
+public void setJustify(bool justify) {
+    checkWidget();
+    if (this.justify is justify) return;
+    this.justify = justify;
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    super.redraw();
+}
+/**
+ * Maps a key to an action.
+ * <p>
+ * One action can be associated with N keys. However, each key can only
+ * have one action (key:action is N:1 relation).
+ * </p>
+ *
+ * @param key a key code defined in SWT.java or a character.
+ *  Optionally ORd with a state mask.  Preferred state masks are one or more of
+ *  SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform
+ *  differences.  However, there may be cases where using the specific state masks
+ *  (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
+ * @param action one of the predefined actions defined in ST.java.
+ *  Use SWT.NULL to remove a key binding.
+ * @exception SWTException <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 setKeyBinding(int key, int action) {
+    checkWidget();
+    int modifierValue = key & SWT.MODIFIER_MASK;
+    char keyChar = cast(char)(key & SWT.KEY_MASK);
+    if (Compatibility.isLetter(keyChar)) {
+        // make the keybinding case insensitive by adding it
+        // in its upper and lower case form
+        char ch = CharacterToUpper(keyChar);
+        int newKey = ch | modifierValue;
+        if (action is SWT.NULL) {
+            keyActionMap.remove(newKey);
+        } else {
+            keyActionMap[newKey] = action;
+        }
+        ch = CharacterToLower(keyChar);
+        newKey = ch | modifierValue;
+        if (action is SWT.NULL) {
+            keyActionMap.remove(newKey);
+        } else {
+            keyActionMap[newKey] = action;
+        }
+    } else {
+        if (action is SWT.NULL) {
+            keyActionMap.remove(key);
+        } else {
+            keyActionMap[key]=action;
+        }
+    }
+}
+/**
+ * Sets the alignment of the specified lines. The argument should be one of <code>SWT.LEFT</code>,
+ * <code>SWT.CENTER</code> or <code>SWT.RIGHT</code>.
+ * <p><p>
+ * Note that if <code>SWT.MULTI</code> is set, then <code>SWT.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>
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ * </p><p>
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ *
+ * @param startLine first line the alignment is applied to, 0 based
+ * @param lineCount number of lines the alignment applies to.
+ * @param alignment line alignment
+ *
+ * @exception SWTException <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_ARGUMENT when the specified line range is invalid</li>
+ * </ul>
+ * @see #setAlignment(int)
+ * @since 3.2
+ */
+public void setLineAlignment(int startLine, int lineCount, int alignment) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    renderer.setLineAlignment(startLine, lineCount, alignment);
+    resetCache(startLine, lineCount);
+    redrawLines(startLine, lineCount);
+    int caretLine = getCaretLine();
+    if (startLine <= caretLine && caretLine < startLine + lineCount) {
+        setCaretLocation();
+    }
+}
+/**
+ * Sets the background color of the specified lines.
+ * <p>
+ * The background color is drawn for the width of the widget. All
+ * line background colors are discarded when setText is called.
+ * The text background color if defined in a StyleRange overlays the
+ * line background color.
+ * </p><p>
+ * Should not be called if a LineBackgroundListener has been set since the
+ * listener maintains the line backgrounds.
+ * </p><p>
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ * </p><p>
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ * </p>
+ *
+ * @param startLine first line the color is applied to, 0 based
+ * @param lineCount number of lines the color applies to.
+ * @param background line background color
+ * @exception SWTException <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_ARGUMENT when the specified line range is invalid</li>
+ * </ul>
+ */
+public void setLineBackground(int startLine, int lineCount, Color background) {
+    checkWidget();
+    if (isListening(LineGetBackground)) return;
+    if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (background !is null) {
+        renderer.setLineBackground(startLine, lineCount, background);
+    } else {
+        renderer.clearLineBackground(startLine, lineCount);
+    }
+    redrawLines(startLine, lineCount);
+}
+/**
+ * Sets the bullet of the specified lines.
+ * <p>
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ * </p><p>
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ * </p><p>
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ * </p>
+ *
+ * @param startLine first line the bullet is applied to, 0 based
+ * @param lineCount number of lines the bullet applies to.
+ * @param bullet line bullet
+ *
+ * @exception SWTException <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_ARGUMENT when the specified line range is invalid</li>
+ * </ul>
+ * @since 3.2
+ */
+public void setLineBullet(int startLine, int lineCount, Bullet bullet) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    renderer.setLineBullet(startLine, lineCount, bullet);
+    resetCache(startLine, lineCount);
+    redrawLines(startLine, lineCount);
+    int caretLine = getCaretLine();
+    if (startLine <= caretLine && caretLine < startLine + lineCount) {
+        setCaretLocation();
+    }
+}
+void setVariableLineHeight () {
+    if (!fixedLineHeight) return;
+    fixedLineHeight = false;
+    renderer.calculateIdle();
+}
+/**
+ * Sets the indent of the specified lines.
+ * <p>
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ * </p><p>
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ * </p><p>
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ * </p>
+ *
+ * @param startLine first line the indent is applied to, 0 based
+ * @param lineCount number of lines the indent applies to.
+ * @param indent line indent
+ *
+ * @exception SWTException <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_ARGUMENT when the specified line range is invalid</li>
+ * </ul>
+ * @see #setIndent(int)
+ * @since 3.2
+ */
+public void setLineIndent(int startLine, int lineCount, int indent) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    renderer.setLineIndent(startLine, lineCount, indent);
+    resetCache(startLine, lineCount);
+    redrawLines(startLine, lineCount);
+    int caretLine = getCaretLine();
+    if (startLine <= caretLine && caretLine < startLine + lineCount) {
+        setCaretLocation();
+    }
+}
+/**
+ * Sets the justify of the specified lines.
+ * <p>
+ * Should not be called if a LineStyleListener has been set since the listener
+ * maintains the line attributes.
+ * </p><p>
+ * All line attributes are maintained relative to the line text, not the
+ * line index that is specified in this method call.
+ * During text changes, when entire lines are inserted or removed, the line
+ * attributes that are associated with the lines after the change
+ * will "move" with their respective text. An entire line is defined as
+ * extending from the first character on a line to the last and including the
+ * line delimiter.
+ * </p><p>
+ * When two lines are joined by deleting a line delimiter, the top line
+ * attributes take precedence and the attributes of the bottom line are deleted.
+ * For all other text changes line attributes will remain unchanged.
+ * </p>
+ *
+ * @param startLine first line the justify is applied to, 0 based
+ * @param lineCount number of lines the justify applies to.
+ * @param justify true if lines should be justified
+ *
+ * @exception SWTException <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_ARGUMENT when the specified line range is invalid</li>
+ * </ul>
+ * @see #setJustify(bool)
+ * @since 3.2
+ */
+public void setLineJustify(int startLine, int lineCount, bool justify) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    renderer.setLineJustify(startLine, lineCount, justify);
+    resetCache(startLine, lineCount);
+    redrawLines(startLine, lineCount);
+    int caretLine = getCaretLine();
+    if (startLine <= caretLine && caretLine < startLine + lineCount) {
+        setCaretLocation();
+    }
+}
+/**
+ * Sets the line spacing of the widget. The line spacing applies for all lines.
+ *
+ * @param lineSpacing the line spacing
+ * @exception SWTException <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.2
+ */
+public void setLineSpacing(int lineSpacing) {
+    checkWidget();
+    if (this.lineSpacing is lineSpacing || lineSpacing < 0) return;
+    this.lineSpacing = lineSpacing;
+    setVariableLineHeight();
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    super.redraw();
+}
+void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
+    checkWidget();
+    this.leftMargin = leftMargin;
+    this.topMargin = topMargin;
+    this.rightMargin = rightMargin;
+    this.bottomMargin = bottomMargin;
+    setCaretLocation();
+}
+/**
+ * Flips selection anchor based on word selection direction.
+ */
+void setMouseWordSelectionAnchor() {
+    if (clickCount > 1) {
+        if (caretOffset < doubleClickSelection.x) {
+            selectionAnchor = doubleClickSelection.y;
+        } else if (caretOffset > doubleClickSelection.y) {
+            selectionAnchor = doubleClickSelection.x;
+        }
+    }
+}
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public void setOrientation(int orientation) {
+    if ((orientation & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)) is 0) {
+        return;
+    }
+    if ((orientation & SWT.RIGHT_TO_LEFT) !is 0 && (orientation & SWT.LEFT_TO_RIGHT) !is 0) {
+        return;
+    }
+    if ((orientation & SWT.RIGHT_TO_LEFT) !is 0 && isMirrored()) {
+        return;
+    }
+    if ((orientation & SWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) {
+        return;
+    }
+    if (!BidiUtil.setOrientation(this, orientation)) {
+        return;
+    }
+    isMirrored_ = (orientation & SWT.RIGHT_TO_LEFT) !is 0;
+    caretDirection = SWT.NULL;
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    keyActionMap = null;
+    createKeyBindings();
+    super.redraw();
+}
+/**
+ * Adjusts the maximum and the page size of the scroll bars to
+ * reflect content width/length changes.
+ *
+ * @param vertical indicates if the vertical scrollbar also needs to be set
+ */
+void setScrollBars(bool vertical) {
+    int inactive = 1;
+    if (vertical || !isFixedLineHeight()) {
+        ScrollBar verticalBar = getVerticalBar();
+        if (verticalBar !is null) {
+            int maximum = renderer.getHeight();
+            // only set the real values if the scroll bar can be used
+            // (ie. because the thumb size is less than the scroll maximum)
+            // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
+            if (clientAreaHeight < maximum) {
+                verticalBar.setMaximum(maximum);
+                verticalBar.setThumb(clientAreaHeight);
+                verticalBar.setPageIncrement(clientAreaHeight);
+            } else if (verticalBar.getThumb() !is inactive || verticalBar.getMaximum() !is inactive) {
+                verticalBar.setValues(
+                    verticalBar.getSelection(),
+                    verticalBar.getMinimum(),
+                    inactive,
+                    inactive,
+                    verticalBar.getIncrement(),
+                    inactive);
+            }
+        }
+    }
+    ScrollBar horizontalBar = getHorizontalBar();
+    if (horizontalBar !is null && horizontalBar.getVisible()) {
+        int maximum = renderer.getWidth();
+        // only set the real values if the scroll bar can be used
+        // (ie. because the thumb size is less than the scroll maximum)
+        // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
+        if (clientAreaWidth < maximum) {
+            horizontalBar.setMaximum(maximum);
+            horizontalBar.setThumb(clientAreaWidth - leftMargin - rightMargin);
+            horizontalBar.setPageIncrement(clientAreaWidth - leftMargin - rightMargin);
+        } else if (horizontalBar.getThumb() !is inactive || horizontalBar.getMaximum() !is inactive) {
+            horizontalBar.setValues(
+                horizontalBar.getSelection(),
+                horizontalBar.getMinimum(),
+                inactive,
+                inactive,
+                horizontalBar.getIncrement(),
+                inactive);
+        }
+    }
+}
+/**
+ * Sets the selection to the given position and scrolls it into view.  Equivalent to setSelection(start,start).
+ *
+ * @param start new caret position
+ * @see #setSelection(int,int)
+ * @exception SWTException <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_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ * </ul>
+ */
+public void setSelection(int start) {
+    // checkWidget test done in setSelectionRange
+    setSelection(start, start);
+}
+/**
+ * Sets the selection and scrolls it into view.
+ * <p>
+ * Indexing is zero based.  Text selections are specified in terms of
+ * caret positions.  In a text widget that contains N characters, there are
+ * N+1 caret positions, ranging from 0..N
+ * </p>
+ *
+ * @param point x=selection start offset, y=selection end offset
+ *  The caret will be placed at the selection start when x > y.
+ * @see #setSelection(int,int)
+ * @exception SWTException <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_NULL_ARGUMENT when point is null</li>
+ *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ * </ul>
+ */
+public void setSelection(Point point) {
+    checkWidget();
+    if (point is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    setSelection(point.x, point.y);
+}
+/**
+ * Sets the receiver's selection background color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1
+ */
+public void setSelectionBackground (Color color) {
+    checkWidget ();
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    selectionBackground = color;
+    super.redraw();
+}
+/**
+ * Sets the receiver's selection 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 that this is a <em>HINT</em>. Some platforms do not allow the application
+ * to change the selection foreground color.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1
+ */
+public void setSelectionForeground (Color color) {
+    checkWidget ();
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    selectionForeground = color;
+    super.redraw();
+}
+/**
+ * Sets the selection and scrolls it into view.
+ * <p>
+ * Indexing is zero based.  Text selections are specified in terms of
+ * caret positions.  In a text widget that contains N characters, there are
+ * N+1 caret positions, ranging from 0..N
+ * </p>
+ *
+ * @param start selection start offset. The caret will be placed at the
+ *  selection start when start > end.
+ * @param end selection end offset
+ * @see #setSelectionRange(int,int)
+ * @exception SWTException <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_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ * </ul>
+ */
+public void setSelection(int start, int end) {
+    setSelectionRange(start, end - start);
+    showSelection();
+}
+/**
+ * Sets the selection.
+ * <p>
+ * The new selection may not be visible. Call showSelection to scroll
+ * the selection into view.
+ * </p>
+ *
+ * @param start offset of the first selected character, start >= 0 must be true.
+ * @param length number of characters to select, 0 <= start + length
+ *  <= getCharCount() must be true.
+ *  A negative length places the caret at the selection start.
+ * @param sendEvent a Selection event is sent when set to true and when
+ *  the selection is reset.
+ */
+void setSelection(int start, int length, bool sendEvent) {
+    int end = start + length;
+    start = content.utf8AdjustOffset(start);
+    end = content.utf8AdjustOffset(end);
+    if (start > end) {
+        int temp = end;
+        end = start;
+        start = temp;
+    }
+    // is the selection range different or is the selection direction
+    // different?
+    if (selection.x !is start || selection.y !is end ||
+        (length > 0 && selectionAnchor !is selection.x) ||
+        (length < 0 && selectionAnchor !is selection.y)) {
+        clearSelection(sendEvent);
+        if (length < 0) {
+            selectionAnchor = selection.y = end;
+            caretOffset = selection.x = start;
+        } else {
+            selectionAnchor = selection.x = start;
+            caretOffset = selection.y = end;
+        }
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
+        internalRedrawRange(selection.x, selection.y - selection.x);
+    }
+}
+/**
+ * Sets the selection.
+ * <p>
+ * The new selection may not be visible. Call showSelection to scroll the selection
+ * into view. A negative length places the caret at the visual start of the selection.
+ * </p>
+ *
+ * @param start offset of the first selected character
+ * @param length number of characters to select
+ *
+ * @exception SWTException <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_ARGUMENT when either the start or the end of the selection range is inside a
+ * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
+ * </ul>
+ */
+public void setSelectionRange(int start, int length) {
+    checkWidget();
+    int contentLength = getCharCount();
+    start = Math.max(0, Math.min (start, contentLength));
+    int end = start + length;
+    if (end < 0) {
+        length = -start;
+    } else {
+        if (end > contentLength) length = contentLength - start;
+    }
+    if (isLineDelimiter(start) || isLineDelimiter(start + length)) {
+        // the start offset or end offset of the selection range is inside a
+        // multi byte line delimiter. This is an illegal operation and an exception
+        // is thrown. Fixes 1GDKK3R
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    setSelection(start, length, false);
+    setCaretLocation();
+}
+/**
+ * Adds the specified style.
+ * <p>
+ * The new style overwrites existing styles for the specified range.
+ * Existing style ranges are adjusted if they partially overlap with
+ * the new style. To clear an individual style, call setStyleRange
+ * with a StyleRange that has null attributes.
+ * </p><p>
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param range StyleRange object containing the style information.
+ * Overwrites the old style in the given range. May be null to delete
+ * all styles.
+ * @exception SWTException <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 style range is outside the valid range (> getCharCount())</li>
+ * </ul>
+ */
+public void setStyleRange(StyleRange range) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (range !is null) {
+        if (range.isUnstyled()) {
+            setStyleRanges(range.start, range.length, null, null, false);
+        } else {
+            setStyleRanges(range.start, 0, null, [range], false);
+        }
+    } else {
+        setStyleRanges(0, 0, null, null, true);
+    }
+}
+/**
+ * Clears the styles in the range specified by <code>start</code> and
+ * <code>length</code> and adds the new styles.
+ * <p>
+ * The ranges array contains start and length pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2].  The range fields within each StyleRange are ignored.
+ * If ranges or styles is null, the specified range is cleared.
+ * </p><p>
+ * Note: It is expected that the same instance of a StyleRange will occur
+ * multiple times within the styles array, reducing memory usage.
+ * </p><p>
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param start offset of first character where styles will be deleted
+ * @param length length of the range to delete styles in
+ * @param ranges the array of ranges.  The ranges must not overlap and must be in order.
+ * @param styles the array of StyleRanges.  The range fields within the StyleRange are unused.
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when an element in the styles array is null</li>
+ *    <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li>
+ *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li>
+ *    <li>ERROR_INVALID_RANGE when a range overlaps</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (ranges is null || styles is null) {
+        setStyleRanges(start, length, null, null, false);
+    } else {
+        setStyleRanges(start, length, ranges, styles, false);
+    }
+}
+/**
+ * Sets styles to be used for rendering the widget content.
+ * <p>
+ * All styles in the widget will be replaced with the given set of ranges and styles.
+ * The ranges array contains start and length pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] with length ranges[n+1] uses the style
+ * at styles[n/2].  The range fields within each StyleRange are ignored.
+ * If either argument is null, the styles are cleared.
+ * </p><p>
+ * Note: It is expected that the same instance of a StyleRange will occur
+ * multiple times within the styles array, reducing memory usage.
+ * </p><p>
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param ranges the array of ranges.  The ranges must not overlap and must be in order.
+ * @param styles the array of StyleRanges.  The range fields within the StyleRange are unused.
+ *
+ * @exception SWTException <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_NULL_ARGUMENT when an element in the styles array is null</li>
+ *    <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li>
+ *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li>
+ *    <li>ERROR_INVALID_RANGE when a range overlaps</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setStyleRanges(int[] ranges, StyleRange[] styles) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    if (ranges is null || styles is null) {
+        setStyleRanges(0, 0, null, null, true);
+    } else {
+        setStyleRanges(0, 0, ranges, styles, true);
+    }
+}
+void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, bool reset) {
+    int charCount = content.getCharCount();
+    int end = start + length;
+    if (start > end || start < 0) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    if (styles !is null) {
+        if (end > charCount) {
+            SWT.error(SWT.ERROR_INVALID_RANGE);
+        }
+        if (ranges !is null) {
+            if (ranges.length !is styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        int lastOffset = 0;
+        bool variableHeight = false;
+        for (int i = 0; i < styles.length; i ++) {
+            if (styles[i] is null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            int rangeStart, rangeLength;
+            if (ranges !is null) {
+                rangeStart = ranges[i << 1];
+                rangeLength = ranges[(i << 1) + 1];
+            } else {
+                rangeStart = styles[i].start;
+                rangeLength = styles[i].length;
+            }
+            if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            variableHeight |= styles[i].isVariableHeight();
+            lastOffset = rangeStart + rangeLength;
+        }
+        if (variableHeight) setVariableLineHeight();
+    }
+    int rangeStart = start, rangeEnd = end;
+    if (styles !is null && styles.length > 0) {
+        if (ranges !is null) {
+            rangeStart = ranges[0];
+            rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1];
+        } else {
+            rangeStart = styles[0].start;
+            rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length;
+        }
+    }
+    int lastLineBottom = 0;
+    if (!isFixedLineHeight() && !reset) {
+        int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+        int partialTopIndex = getPartialTopIndex();
+        int partialBottomIndex = getPartialBottomIndex();
+        if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+            lastLineBottom = getLinePixel(lineEnd + 1);
+        }
+    }
+    if (reset) {
+        renderer.setStyleRanges(null, null);
+    } else {
+        renderer.updateRanges(start, length, length);
+    }
+    if (styles !is null && styles.length > 0) {
+        renderer.setStyleRanges(ranges, styles);
+    }
+    if (reset) {
+        resetCache(0, content.getLineCount());
+        super.redraw();
+    } else {
+        int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
+        int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
+        resetCache(lineStart, lineEnd - lineStart + 1);
+        int partialTopIndex = getPartialTopIndex();
+        int partialBottomIndex = getPartialBottomIndex();
+        if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
+            int y = 0;
+            int height = clientAreaHeight;
+            if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
+                int lineTop = Math.max(y, getLinePixel(lineStart));
+                y = lineTop;
+                height -= lineTop;
+            }
+            if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
+                int newLastLineBottom = getLinePixel(lineEnd + 1);
+                if (!isFixedLineHeight()) {
+                    scrollText(lastLineBottom, newLastLineBottom);
+                }
+                height = newLastLineBottom - y;
+            }
+            super.redraw(0, y, clientAreaWidth, height, false);
+        }
+    }
+    setCaretLocation();
+}
+/**
+ * Sets styles to be used for rendering the widget content. All styles
+ * in the widget will be replaced with the given set of styles.
+ * <p>
+ * Note: Because a StyleRange includes the start and length, the
+ * same instance cannot occur multiple times in the array of styles.
+ * If the same style attributes, such as font and color, occur in
+ * multiple StyleRanges, <code>setStyleRanges(int[], StyleRange[])</code>
+ * can be used to share styles and reduce memory usage.
+ * </p><p>
+ * Should not be called if a LineStyleListener has been set since the
+ * listener maintains the styles.
+ * </p>
+ *
+ * @param ranges StyleRange objects containing the style information.
+ * The ranges should not overlap. The style rendering is undefined if
+ * the ranges do overlap. Must not be null. The styles need to be in order.
+ * @exception SWTException <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 last of the style ranges is outside the valid range (> getCharCount())</li>
+ * </ul>
+ *
+ * @see #setStyleRanges(int[], StyleRange[])
+ */
+public void setStyleRanges(StyleRange[] ranges) {
+    checkWidget();
+    if (isListening(LineGetStyle)) return;
+    // SWT extension: allow null for zero length string
+    //if (ranges is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    setStyleRanges(0, 0, null, ranges, true);
+}
+/**
+ * Sets the tab width.
+ *
+ * @param tabs tab width measured in characters.
+ * @exception SWTException <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 setTabs(int tabs) {
+    checkWidget();
+    tabLength = tabs;
+    renderer.setFont(null, tabs);
+    resetCache(0, content.getLineCount());
+    setCaretLocation();
+    super.redraw();
+}
+/**
+ * Sets the widget content.
+ * If the widget has the SWT.SINGLE style and "text" contains more than
+ * one line, only the first line is rendered but the text is stored
+ * unchanged. A subsequent call to getText will return the same text
+ * that was set.
+ * <p>
+ * <b>Note:</b> Only a single line of text should be set when the SWT.SINGLE
+ * style is used.
+ * </p>
+ *
+ * @param text new widget content. Replaces existing content. Line styles
+ *  that were set using StyledText API are discarded.  The
+ *  current selection is also discarded.
+ * @exception SWTException <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 setText(String text) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+//     if (text is null) {
+//         SWT.error(SWT.ERROR_NULL_ARGUMENT);
+//     }
+    Event event = new Event();
+    event.start = 0;
+    event.end = getCharCount();
+    event.text = text;
+    event.doit = true;
+    notifyListeners(SWT.Verify, event);
+    if (event.doit) {
+        StyledTextEvent styledTextEvent = null;
+        if (isListening(ExtendedModify)) {
+            styledTextEvent = new StyledTextEvent(content);
+            styledTextEvent.start = event.start;
+            styledTextEvent.end = event.start + event.text.length;
+            styledTextEvent.text = content.getTextRange(event.start, event.end - event.start);
+        }
+        content.setText(event.text);
+        sendModifyEvent(event);
+        if (styledTextEvent !is null) {
+            notifyListeners(ExtendedModify, styledTextEvent);
+        }
+    }
+}
+/**
+ * Sets the text limit to the specified number of characters.
+ * <p>
+ * The text limit specifies the amount of text that
+ * the user can type into the widget.
+ * </p>
+ *
+ * @param limit the new text limit.
+ * @exception SWTException <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_CANNOT_BE_ZERO when limit is 0</li>
+ * </ul>
+ */
+public void setTextLimit(int limit) {
+    checkWidget();
+    if (limit is 0) {
+        SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
+    }
+    textLimit = limit;
+}
+/**
+ * Sets the top index. Do nothing if there is no text set.
+ * <p>
+ * The top index is the index of the line that is currently at the top
+ * of the widget. The top index changes when the widget is scrolled.
+ * Indexing starts from zero.
+ * Note: The top index is reset to 0 when new text is set in the widget.
+ * </p>
+ *
+ * @param topIndex new top index. Must be between 0 and
+ *  getLineCount() - fully visible lines per page. If no lines are fully
+ *  visible the maximum value is getLineCount() - 1. An out of range
+ *  index will be adjusted accordingly.
+ * @exception SWTException <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 setTopIndex(int topIndex) {
+    checkWidget();
+    if (getCharCount() is 0) {
+        return;
+    }
+    int lineCount = content.getLineCount(), pixel;
+    if (isFixedLineHeight()) {
+        int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole()));
+        if (topIndex < 0) {
+            topIndex = 0;
+        } else if (topIndex > lineCount - pageSize) {
+            topIndex = lineCount - pageSize;
+        }
+        pixel = getLinePixel(topIndex);
+    } else {
+        topIndex = Math.max(0, Math.min(lineCount - 1, topIndex));
+        pixel = getLinePixel(topIndex);
+        if (pixel > 0) {
+            pixel = getAvailableHeightBellow(pixel);
+        } else {
+            pixel = getAvailableHeightAbove(pixel);
+        }
+    }
+    scrollVertical(pixel, true);
+}
+/**
+ * Sets the top pixel offset. Do nothing if there is no text set.
+ * <p>
+ * The top pixel offset is the vertical pixel offset of the widget. The
+ * widget is scrolled so that the given pixel position is at the top.
+ * The top index is adjusted to the corresponding top line.
+ * Note: The top pixel is reset to 0 when new text is set in the widget.
+ * </p>
+ *
+ * @param pixel new top pixel offset. Must be between 0 and
+ *  (getLineCount() - visible lines per page) / getLineHeight()). An out
+ *  of range offset will be adjusted accordingly.
+ * @exception SWTException <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 2.0
+ */
+public void setTopPixel(int pixel) {
+    checkWidget();
+    if (getCharCount() is 0) {
+        return;
+    }
+    if (pixel < 0) pixel = 0;
+    int lineCount = content.getLineCount();
+    int height = clientAreaHeight - topMargin - bottomMargin;
+    int verticalOffset = getVerticalScrollOffset();
+    if (isFixedLineHeight()) {
+        int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height);
+        if (pixel > maxTopPixel) pixel = maxTopPixel;
+        pixel -= verticalOffset;
+    } else {
+        pixel -= verticalOffset;
+        if (pixel > 0) {
+            pixel = getAvailableHeightBellow(pixel);
+        }
+    }
+    scrollVertical(pixel, true);
+}
+/**
+ * Sets whether the widget wraps lines.
+ * <p>
+ * This overrides the creation style bit SWT.WRAP.
+ * </p>
+ *
+ * @param wrap true=widget wraps lines, false=widget does not wrap lines
+ * @since 2.0
+ */
+public void setWordWrap(bool wrap) {
+    checkWidget();
+    if ((getStyle() & SWT.SINGLE) !is 0) return;
+    if (wordWrap is wrap) return;
+    wordWrap = wrap;
+    setVariableLineHeight();
+    resetCache(0, content.getLineCount());
+    horizontalScrollOffset = 0;
+    ScrollBar horizontalBar = getHorizontalBar();
+    if (horizontalBar !is null) {
+        horizontalBar.setVisible(!wordWrap);
+    }
+    setScrollBars(true);
+    setCaretLocation();
+    super.redraw();
+}
+// SWT: If necessary, scroll to show the location
+bool showLocation(Rectangle rect, bool scrollPage) {
+    int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin;
+    int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
+    bool scrolled = false;
+    if (rect.y <= topMargin) {
+        scrolled = scrollVertical(rect.y - topMargin, true);
+    } else if (rect.y + rect.height > clientAreaHeight) {
+        if (clientAreaHeight is 0) {
+            scrolled = scrollVertical(rect.y, true);
+        } else {
+            scrolled = scrollVertical(rect.y + rect.height - clientAreaHeight, true);
+        }
+    }
+    if (clientAreaWidth > 0) {
+        int minScroll = scrollPage ? clientAreaWidth / 4 : 0;
+        if (rect.x < leftMargin) {
+            int scrollWidth = Math.max(leftMargin - rect.x, minScroll);
+            int maxScroll = horizontalScrollOffset;
+            scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true);
+        } else if (rect.x + rect.width > clientAreaWidth) {
+            int scrollWidth =  Math.max(rect.x + rect.width - clientAreaWidth, minScroll);
+            int maxScroll = renderer.getWidth() - horizontalScrollOffset - this.clientAreaWidth;
+            scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true);
+        }
+    }
+    return scrolled;
+}
+/**
+ * Sets the caret location and scrolls the caret offset into view.
+ */
+void showCaret() {
+    Rectangle bounds = getBoundsAtOffset(caretOffset);
+    if (!showLocation(bounds, true)) {
+        setCaretLocation();
+    }
+}
+/**
+ * Scrolls the selection into view.
+ * <p>
+ * The end of the selection will be scrolled into view.
+ * Note that if a right-to-left selection exists, the end of the selection is
+ * the visual beginning of the selection (i.e., where the caret is located).
+ * </p>
+ *
+ * @exception SWTException <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 showSelection() {
+    checkWidget();
+    // is selection from right-to-left?
+    bool rightToLeft = caretOffset is selection.x;
+    int startOffset, endOffset;
+    if (rightToLeft) {
+        startOffset = selection.y;
+        endOffset = selection.x;
+    } else {
+        startOffset = selection.x;
+        endOffset = selection.y;
+    }
+
+    Rectangle startBounds = getBoundsAtOffset(startOffset);
+    Rectangle endBounds = getBoundsAtOffset(endOffset);
+
+    // can the selection be fully displayed within the widget's visible width?
+    int w = clientAreaWidth - leftMargin - rightMargin;
+    bool selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w;
+    if (selectionFits) {
+        // show as much of the selection as possible by first showing
+        // the start of the selection
+        if (showLocation(startBounds, false)) {
+            // endX value could change if showing startX caused a scroll to occur
+            endBounds = getBoundsAtOffset(endOffset);
+        }
+        // the character at endOffset is not part of the selection
+        endBounds.width = 0;
+        showLocation(endBounds, false);
+    } else {
+        // just show the end of the selection since the selection start
+        // will not be visible
+        showLocation(endBounds, true);
+    }
+}
+/**
+ * Updates the selection and caret position depending on the text change.
+ * <p>
+ * If the selection intersects with the replaced text, the selection is
+ * reset and the caret moved to the end of the new text.
+ * If the selection is behind the replaced text it is moved so that the
+ * same text remains selected.  If the selection is before the replaced text
+ * it is left unchanged.
+ * </p>
+ *
+ * @param startOffset offset of the text change
+ * @param replacedLength length of text being replaced
+ * @param newLength length of new text
+ */
+void updateSelection(int startOffset, int replacedLength, int newLength) {
+    if (selection.y <= startOffset) {
+        // selection ends before text change
+        if (wordWrap) setCaretLocation();
+        return;
+    }
+    if (selection.x < startOffset) {
+        // clear selection fragment before text change
+        internalRedrawRange(selection.x, startOffset - selection.x);
+    }
+    if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) {
+        // clear selection fragment after text change.
+        // do this only when the selection is actually affected by the
+        // change. Selection is only affected if it intersects the change (1GDY217).
+        int netNewLength = newLength - replacedLength;
+        int redrawStart = startOffset + newLength;
+        internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart);
+    }
+    if (selection.y > startOffset && selection.x < startOffset + replacedLength) {
+        // selection intersects replaced text. set caret behind text change
+        setSelection(startOffset + newLength, 0, true);
+    } else {
+        // move selection to keep same text selected
+        setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true);
+    }
+    setCaretLocation();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextContent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextContent;
+
+import java.lang.all;
+
+import org.eclipse.swt.custom.TextChangeListener;
+/**
+ * Clients may implement the StyledTextContent interface to provide a
+ * custom store for the StyledText widget content. The StyledText widget
+ * interacts with its StyledTextContent in order to access and update
+ * the text that is being displayed and edited in the widget.
+ * A custom content implementation can be set in the widget using the
+ * StyledText.setContent API.
+ */
+public interface StyledTextContent {
+
+/**
+ * Called by StyledText to add itself as an Observer to content changes.
+ * See TextChangeListener for a description of the listener methods that
+ * are called when text changes occur.
+ * <p>
+ *
+ * @param listener the listener
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addTextChangeListener(TextChangeListener listener);
+
+/**
+ * Return the number of characters in the content.
+ * <p>
+ *
+ * @return the number of characters in the content.
+ */
+public int getCharCount();
+
+/**
+ * Return the line at the given line index without delimiters.
+ * <p>
+ *
+ * @param lineIndex index of the line to return. Does not include
+ *  delimiters of preceding lines. Index 0 is the first line of the
+ *  content.
+ * @return the line text without delimiters
+ */
+public String getLine(int lineIndex);
+
+/**
+ * Return the line index at the given character offset.
+ * <p>
+ *
+ * @param offset offset of the line to return. The first character of the
+ *  document is at offset 0.  An offset of getLength() is valid and should
+ *  answer the number of lines.
+ * @return the line index. The first line is at index 0.  If the character
+ *  at offset is a delimiter character, answer the line index of the line
+ *  that is delimited.
+ *  For example, if text = "\r\n\r\n", and delimiter = "\r\n", then:
+ * <ul>
+ * <li>getLineAtOffset(0) is 0
+ * <li>getLineAtOffset(1) is 0
+ * <li>getLineAtOffset(2) is 1
+ * <li>getLineAtOffset(3) is 1
+ * <li>getLineAtOffset(4) is 2
+ * </ul>
+ */
+public int getLineAtOffset(int offset);
+
+/**
+ * Return the number of lines.  Should answer 1 when no text is specified.
+ * The  StyledText widget relies on this behavior for drawing the cursor.
+ * <p>
+ *
+ * @return the number of lines.  For example:
+ * <ul>
+ * <li> text value is> getLineCount
+ * <li> null is> 1
+ * <li> "" is> 1
+ * <li> "a\n" is> 2
+ * <li> "\n\n" is> 3
+ * </ul>
+ */
+public int getLineCount();
+
+/**
+ * Return the line delimiter that should be used by the StyledText
+ * widget when inserting new lines. New lines entered using key strokes
+ * and paste operations use this line delimiter.
+ * Implementors may use System.getProperty("line.separator") to return
+ * the platform line delimiter.
+ * <p>
+ *
+ * @return the line delimiter that should be used by the StyledText widget
+ *  when inserting new lines.
+ */
+public String getLineDelimiter();
+
+/**
+ * Return the character offset of the first character of the given line.
+ * <p>
+ * <b>NOTE:</b> When there is no text (i.e., no lines), getOffsetAtLine(0)
+ * is a valid call that should return 0.
+ * </p>
+ *
+ * @param lineIndex index of the line. The first line is at index 0.
+ * @return offset offset of the first character of the line. The first
+ *  character of the document is at offset 0.  The return value should
+ *  include line delimiters.
+ *  For example, if text = "\r\ntest\r\n" and delimiter = "\r\n", then:
+ * <ul>
+ * <li>getOffsetAtLine(0) is 0
+ * <li>getOffsetAtLine(1) is 2
+ * <li>getOffsetAtLine(2) is 8
+ * </ul>
+ */
+public int getOffsetAtLine(int lineIndex);
+
+/**
+ * Returns a string representing the content at the given range.
+ * <p>
+ *
+ * @param start the start offset of the text to return. Offset 0 is the
+ *  first character of the document.
+ * @param length the length of the text to return
+ * @return the text at the given range
+ */
+public String getTextRange(int start, int length);
+
+/**
+ * Remove the specified text changed listener.
+ * <p>
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeTextChangeListener(TextChangeListener listener);
+
+/**
+ * Replace the text with "newText" starting at position "start"
+ * for a length of "replaceLength".
+ * <p>
+ * Implementors have to notify the TextChangeListeners that were added
+ * using <code>addTextChangeListener</code> before and after the content
+ * is changed. A <code>TextChangingEvent</code> has to be sent to the
+ * textChanging method before the content is changed and a
+ * <code>TextChangedEvent</code> has to be sent to the textChanged method
+ * after the content has changed.
+ * The text change that occurs after the <code>TextChangingEvent</code>
+ * has been sent has to be consistent with the data provided in the
+ * <code>TextChangingEvent</code>.
+ * This data will be cached by the widget and will be used when the
+ * <code>TextChangedEvent</code> is received.
+ * <p>
+ * The <code>TextChangingEvent</code> should be set as follows:
+ * <ul>
+ * <li>event.start = start of the replaced text
+ * <li>event.newText = text that is going to be inserted or empty String
+ *  if no text will be inserted
+ * <li>event.replaceCharCount = length of text that is going to be replaced
+ * <li>event.newCharCount = length of text that is going to be inserted
+ * <li>event.replaceLineCount = number of lines that are going to be replaced
+ * <li>event.newLineCount = number of new lines that are going to be inserted
+ * </ul>
+ * <b>NOTE:</b> newLineCount is the number of inserted lines and replaceLineCount
+ * is the number of deleted lines based on the change that occurs visually.
+ * For example:
+ * <ul>
+ * <li>(replaceText, newText) is> (replaceLineCount, newLineCount)
+ * <li>("", "\n") is> (0, 1)
+ * <li>("\n\n", "a") is> (2, 0)
+ * <li>("a", "\n\n") is> (0, 2)
+ * <li>("\n", "") is> (1, 0)
+ * </ul>
+ * </p>
+ *
+ * @param start start offset of text to replace, none of the offsets include
+ *  delimiters of preceding lines, offset 0 is the first character of the
+ *  document
+ * @param replaceLength length of text to replace
+ * @param text text to replace
+ * @see TextChangeListener
+ */
+public void replaceTextRange(int start, int replaceLength, String text);
+
+/**
+ * Set text to "text".
+ * Implementors have to send a <code>TextChangedEvent</code> to the
+ * textSet method of the TextChangeListeners that were added using
+ * <code>addTextChangeListener</code>.
+ * <p>
+ *
+ * @param text the new text
+ * @see TextChangeListener
+ */
+public void setText(String text);
+
+/++
+ + SWT Extension
+ +/
+int utf8AdjustOffset( int offset );
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextDropTargetEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextDropTargetEffect;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+import org.eclipse.swt.dnd.DropTargetEffect;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.StyledTextContent;
+
+static import tango.core.Exception;
+import java.lang.all;
+
+/**
+ * This adapter class provides a default drag under effect (eg. select and scroll)
+ * 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>
+ * method and override any other applicable methods in <code>StyledTextDropTargetEffect</code> to
+ * display their own drag under effect.</p>
+ *
+ * Subclasses that override any methods of this class should call the corresponding
+ * <code>super</code> method to get the default drag under effect implementation.
+ *
+ * <p>The feedback value is either one of the FEEDBACK constants defined in
+ * class <code>DND</code> which is applicable to instances of this class,
+ * or it must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> effect constants.
+ * </p>
+ * <p>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ * </p>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class StyledTextDropTargetEffect : DropTargetEffect {
+    static final int CARET_WIDTH = 2;
+    static final int SCROLL_HYSTERESIS = 100; // milli seconds
+    static final int SCROLL_TOLERANCE = 20; // pixels
+
+    int currentOffset = -1;
+    long scrollBeginTime;
+    int scrollX = -1, scrollY = -1;
+    Listener paintListener;
+
+    /**
+     * Creates a new <code>StyledTextDropTargetEffect</code> to handle the drag under effect on the specified
+     * <code>StyledText</code>.
+     *
+     * @param styledText the <code>StyledText</code> over which the user positions the cursor to drop the data
+     */
+    public this(StyledText styledText) {
+        super(styledText);
+        paintListener = new class() Listener {
+            public void handleEvent (Event event) {
+                if (currentOffset !is -1) {
+                    StyledText text = cast(StyledText) getControl();
+                    Point position = text.getLocationAtOffset(currentOffset);
+                    int height = text.getLineHeight(currentOffset);
+                    event.gc.setBackground(event.display.getSystemColor (SWT.COLOR_BLACK));
+                    event.gc.fillRectangle(position.x, position.y, CARET_WIDTH, height);
+                }
+            }
+        };
+    }
+
+    /**
+     * This implementation of <code>dragEnter</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragEnter</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragEnter(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag start event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public override void dragEnter(DropTargetEvent event) {
+        currentOffset = -1;
+        scrollBeginTime = 0;
+        scrollX = -1;
+        scrollY = -1;
+        getControl().removeListener(SWT.Paint, paintListener);
+        getControl().addListener (SWT.Paint, paintListener);
+    }
+
+    /**
+     * This implementation of <code>dragLeave</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragLeave</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragLeave(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag leave event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public override void dragLeave(DropTargetEvent event) {
+        StyledText text = cast(StyledText) getControl();
+        if (currentOffset !is -1) {
+            refreshCaret(text, currentOffset, -1);
+        }
+        text.removeListener(SWT.Paint, paintListener);
+        scrollBeginTime = 0;
+        scrollX = -1;
+        scrollY = -1;
+    }
+
+    /**
+     * This implementation of <code>dragOver</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragOver</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragOver(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag over event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     * @see DND#FEEDBACK_SELECT
+     * @see DND#FEEDBACK_SCROLL
+     */
+    public override void dragOver(DropTargetEvent event) {
+        int effect = event.feedback;
+        StyledText text = cast(StyledText) getControl();
+
+        Point pt = text.getDisplay().map(null, text, event.x, event.y);
+        if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+            scrollBeginTime = 0;
+            scrollX = scrollY = -1;
+        } else {
+            if (text.getCharCount() is 0) {
+                scrollBeginTime = 0;
+                scrollX = scrollY = -1;
+            } else {
+                if (scrollX !is -1 && scrollY !is -1 && scrollBeginTime !is 0 &&
+                    (pt.x >= scrollX && pt.x <= (scrollX + SCROLL_TOLERANCE) ||
+                     pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) {
+                    if (System.currentTimeMillis() >= scrollBeginTime) {
+                        Rectangle area = text.getClientArea();
+                        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 (pt.x > area.width - 3*charWidth) {
+                            int leftPixel = text.getHorizontalPixel();
+                            text.setHorizontalPixel(leftPixel + scrollAmount);
+                        }
+                        int lineHeight = text.getLineHeight();
+                        if (pt.y < area.y + lineHeight) {
+                            int topPixel = text.getTopPixel();
+                            text.setTopPixel(topPixel - lineHeight);
+                        }
+                        if (pt.y > area.height - lineHeight) {
+                            int topPixel = text.getTopPixel();
+                            text.setTopPixel(topPixel + lineHeight);
+                        }
+                        scrollBeginTime = 0;
+                        scrollX = scrollY = -1;
+                    }
+                } else {
+                    scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+                    scrollX = pt.x;
+                    scrollY = pt.y;
+                }
+            }
+        }
+
+        if ((effect & DND.FEEDBACK_SELECT) !is 0) {
+            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;
+            }
+        }
+    }
+
+    void refreshCaret(StyledText text, int oldOffset, int newOffset) {
+        if (oldOffset !is newOffset) {
+            if (oldOffset !is -1) {
+                Point oldPos = text.getLocationAtOffset(oldOffset);
+                int oldHeight = text.getLineHeight(oldOffset);
+                text.redraw (oldPos.x, oldPos.y, CARET_WIDTH, oldHeight, false);
+            }
+            if (newOffset !is -1) {
+                Point newPos = text.getLocationAtOffset(newOffset);
+                int newHeight = text.getLineHeight(newOffset);
+                text.redraw (newPos.x, newPos.y, CARET_WIDTH, newHeight, false);
+            }
+        }
+    }
+
+    /**
+     * This implementation of <code>dropAccept</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dropAccept</code>.
+     *
+     * Subclasses that override this method should call <code>super.dropAccept(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drop accept event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public override void dropAccept(DropTargetEvent event) {
+        if (currentOffset !is -1) {
+            StyledText text = cast(StyledText) getControl();
+            text.setSelection(currentOffset);
+            currentOffset = -1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextEvent;
+
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.Bullet;
+import org.eclipse.swt.custom.StyledTextContent;
+
+/**
+ *
+ */
+class StyledTextEvent : Event {
+    // used by LineStyleEvent
+    int[] ranges;
+    StyleRange[] styles;
+    int alignment;
+    int indent;
+    bool justify;
+    Bullet bullet;
+    int bulletIndex;
+    // used by LineBackgroundEvent
+    Color lineBackground;
+    // used by BidiSegmentEvent
+    int[] segments;
+    // used by TextChangedEvent
+    int replaceCharCount;
+    int newCharCount;
+    int replaceLineCount;
+    int newLineCount;
+    // used by PaintObjectEvent
+    int x;
+    int y;
+    int ascent;
+    int descent;
+    StyleRange style;
+
+this (StyledTextContent content) {
+    data = cast(Object)content;
+}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextListener;
+
+
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.ExtendedModifyEvent;
+import org.eclipse.swt.custom.ExtendedModifyListener;
+import org.eclipse.swt.custom.StyledTextEvent;
+import org.eclipse.swt.custom.LineBackgroundEvent;
+import org.eclipse.swt.custom.BidiSegmentEvent;
+import org.eclipse.swt.custom.LineStyleEvent;
+import org.eclipse.swt.custom.PaintObjectEvent;
+import org.eclipse.swt.custom.MovementEvent;
+import org.eclipse.swt.custom.TextChangedEvent;
+import org.eclipse.swt.custom.TextChangingEvent;
+import org.eclipse.swt.custom.LineBackgroundListener;
+import org.eclipse.swt.custom.BidiSegmentListener;
+import org.eclipse.swt.custom.LineStyleListener;
+import org.eclipse.swt.custom.PaintObjectListener;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.custom.StyledTextContent;
+import org.eclipse.swt.custom.TextChangeListener;
+import org.eclipse.swt.custom.MovementListener;
+
+
+class StyledTextListener : TypedListener {
+/**
+ */
+this(SWTEventListener listener) {
+    super(listener);
+}
+/**
+ * Process StyledText events by invoking the event's handler.
+ *
+ * @param e the event to handle
+ */
+public override void handleEvent(Event e) {
+
+    switch (e.type) {
+        case StyledText.ExtendedModify:
+            ExtendedModifyEvent extendedModifyEvent = new ExtendedModifyEvent(cast(StyledTextEvent) e);
+            (cast(ExtendedModifyListener) eventListener).modifyText(extendedModifyEvent);
+            break;
+        case StyledText.LineGetBackground:
+            LineBackgroundEvent lineBgEvent = new LineBackgroundEvent(cast(StyledTextEvent) e);
+            (cast(LineBackgroundListener) eventListener).lineGetBackground(lineBgEvent);
+            (cast(StyledTextEvent) e).lineBackground = lineBgEvent.lineBackground;
+            break;
+        case StyledText.LineGetSegments:
+            BidiSegmentEvent segmentEvent = new BidiSegmentEvent(cast(StyledTextEvent) e);
+            (cast(BidiSegmentListener) eventListener).lineGetSegments(segmentEvent);
+            (cast(StyledTextEvent) e).segments = segmentEvent.segments;
+            break;
+        case StyledText.LineGetStyle:
+            LineStyleEvent lineStyleEvent = new LineStyleEvent(cast(StyledTextEvent) e);
+            (cast(LineStyleListener) eventListener).lineGetStyle(lineStyleEvent);
+            (cast(StyledTextEvent) e).ranges = lineStyleEvent.ranges;
+            (cast(StyledTextEvent) e).styles = lineStyleEvent.styles;
+            (cast(StyledTextEvent) e).alignment = lineStyleEvent.alignment;
+            (cast(StyledTextEvent) e).indent = lineStyleEvent.indent;
+            (cast(StyledTextEvent) e).justify = lineStyleEvent.justify;
+            (cast(StyledTextEvent) e).bullet = lineStyleEvent.bullet;
+            (cast(StyledTextEvent) e).bulletIndex = lineStyleEvent.bulletIndex;
+            break;
+        case StyledText.PaintObject:
+            PaintObjectEvent paintObjectEvent = new PaintObjectEvent(cast(StyledTextEvent) e);
+            (cast(PaintObjectListener) eventListener).paintObject(paintObjectEvent);
+            break;
+        case StyledText.VerifyKey:
+            VerifyEvent verifyEvent = new VerifyEvent(e);
+            (cast(VerifyKeyListener) eventListener).verifyKey(verifyEvent);
+            e.doit = verifyEvent.doit;
+            break;
+        case StyledText.TextChanged: {
+            TextChangedEvent textChangedEvent = new TextChangedEvent(cast(StyledTextContent) e.data);
+            (cast(TextChangeListener) eventListener).textChanged(textChangedEvent);
+            break;
+        }
+        case StyledText.TextChanging:
+            TextChangingEvent textChangingEvent = new TextChangingEvent(cast(StyledTextContent) e.data, cast(StyledTextEvent) e);
+            (cast(TextChangeListener) eventListener).textChanging(textChangingEvent);
+            break;
+        case StyledText.TextSet: {
+            TextChangedEvent textChangedEvent = new TextChangedEvent(cast(StyledTextContent) e.data);
+            (cast(TextChangeListener) eventListener).textSet(textChangedEvent);
+            break;
+        }
+        case StyledText.WordNext: {
+            MovementEvent wordBoundaryEvent = new MovementEvent(cast(StyledTextEvent) e);
+            (cast(MovementListener) eventListener).getNextOffset(wordBoundaryEvent);
+            (cast(StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+            break;
+        }
+        case StyledText.WordPrevious: {
+            MovementEvent wordBoundaryEvent = new MovementEvent(cast(StyledTextEvent) e);
+            (cast(MovementListener) eventListener).getPreviousOffset(wordBoundaryEvent);
+            (cast(StyledTextEvent) e).end = wordBoundaryEvent.newOffset;
+            break;
+        }
+        default:
+    }
+}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextPrintOptions.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextPrintOptions;
+
+import java.lang.all;
+
+/**
+ * Use StyledTextPrintOptions to specify printing options for the
+ * StyledText.print(Printer, StyledTextPrintOptions) API.
+ * <p>
+ * The following example prints a right aligned page number in the footer,
+ * sets the job name to "Example" and prints line background colors but no other
+ * formatting:
+ * </p>
+ * <pre>
+ * StyledTextPrintOptions options = new StyledTextPrintOptions();
+ * options.footer = "\t\t&lt;page&gt;";
+ * options.jobName = "Example";
+ * options.printLineBackground = true;
+ *
+ * Runnable runnable = styledText.print(new Printer(), options);
+ * runnable.run();
+ * </pre>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.1
+ */
+public class StyledTextPrintOptions {
+    /**
+     * Page number placeholder constant for use in <code>header</code>
+     * and <code>footer</code>. Value is <code>&lt;page&gt;</code>
+     */
+    public static final String PAGE_TAG = "<page>";
+    /**
+     * Separator constant for use in <code>header</code> and
+     * <code>footer</code>. Value is <code>\t</code>
+     */
+    public static final String SEPARATOR = "\t";
+    /**
+     * Formatted text to print in the header of each page.
+     * <p>"left '\t' center '\t' right"</p>
+     * <p>left, center, right = &lt;page&gt; | #CDATA</p>
+     * <p>Header and footer are defined as three separate regions for arbitrary
+     * text or the page number placeholder &lt;page&gt;
+     * (<code>StyledTextPrintOptions.PAGE_TAG</code>). The three regions are
+     * left aligned, centered and right aligned. They are separated by a tab
+     * character (<code>StyledTextPrintOptions.SEPARATOR</code>).
+     */
+    public String header = null;
+    /**
+     * Formatted text to print in the footer of each page.
+     * <p>"left '\t' center '\t' right"</p>
+     * <p>left, center, right = &lt;page&gt; | #CDATA</p>
+     * <p>Header and footer are defined as three separate regions for arbitrary
+     * text or the page number placeholder &lt;page&gt;
+     * (<code>StyledTextPrintOptions.PAGE_TAG</code>). The three regions are
+     * left aligned, centered and right aligned. They are separated by a tab
+     * character (<code>StyledTextPrintOptions.SEPARATOR</code>).
+     */
+    public String footer = null;
+    /**
+     * Name of the print job.
+     */
+    public String jobName = null;
+
+    /**
+     * Print the text foreground color. Default value is <code>false</code>.
+     */
+    public bool printTextForeground = false;
+    /**
+     * Print the text background color. Default value is <code>false</code>.
+     */
+    public bool printTextBackground = false;
+    /**
+     * Print the font styles. Default value is <code>false</code>.
+     */
+    public bool printTextFontStyle = false;
+    /**
+     * Print the line background color. Default value is <code>false</code>.
+     */
+    public bool printLineBackground = false;
+
+    /**
+     * Print line numbers. Default value is <code>false</code>.
+     *
+     * @since 3.3
+     */
+    public bool printLineNumbers = false;
+
+    /**
+     * Labels used for printing line numbers.
+     * 
+     * @since 3.4
+     */
+    public String[] lineLabels = null;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/StyledTextRenderer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1552 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.StyledTextRenderer;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GlyphMetrics;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.IME;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.Bullet;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.StyledTextContent;
+import org.eclipse.swt.custom.TextChangingEvent;
+import org.eclipse.swt.custom.ST;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+import java.lang.Runnable;
+import java.lang.all;
+
+static import tango.text.Text;
+static import tango.text.Util;
+static import tango.text.convert.Utf;
+import tango.util.Convert;
+
+/**
+ * A StyledTextRenderer renders the content of a StyledText widget.
+ * This class can be used to render to the display or to a printer.
+ */
+class StyledTextRenderer {
+    Device device;
+    StyledText styledText;
+    StyledTextContent content;
+
+    /* Font info */
+    Font regularFont, boldFont, italicFont, boldItalicFont;
+    int tabWidth;
+    int ascent, descent;
+    int averageCharWidth;
+
+    /* Line data */
+    int topIndex = -1;
+    TextLayout[] layouts;
+    int lineCount;
+    int[] lineWidth;
+    int[] lineHeight;
+    LineInfo[] lines;
+    int maxWidth;
+    int maxWidthLineIndex;
+    bool idleRunning;
+
+    /* Bullet */
+    Bullet[] bullets;
+    int[] bulletsIndices;
+    int[] redrawLines;
+
+    /* Style data */
+    int[] ranges;
+    int styleCount;
+    StyleRange[] styles;
+    StyleRange[] stylesSet;
+    int stylesSetCount = 0;
+    final static int BULLET_MARGIN = 8;
+
+    final static bool COMPACT_STYLES = true;
+    final static bool MERGE_STYLES = true;
+
+    final static int GROW = 32;
+    final static int IDLE_TIME = 50;
+    final static int CACHE_SIZE = 128;
+
+    final static int BACKGROUND = 1 << 0;
+    final static int ALIGNMENT = 1 << 1;
+    final static int INDENT = 1 << 2;
+    final static int JUSTIFY = 1 << 3;
+    final static int SEGMENTS = 1 << 5;
+
+    static class LineInfo {
+        int flags;
+        Color background;
+        int alignment;
+        int indent;
+        bool justify;
+        int[] segments;
+
+        public this() {
+        }
+        public this(LineInfo info) {
+            if (info !is null) {
+                flags = info.flags;
+                background = info.background;
+                alignment = info.alignment;
+                indent = info.indent;
+                justify = info.justify;
+                segments = info.segments;
+            }
+        }
+    }
+
+this(Device device, StyledText styledText) {
+    this.device = device;
+    this.styledText = styledText;
+}
+int addMerge(int[] mergeRanges, StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+    int rangeCount = styleCount << 1;
+    StyleRange endStyle = null;
+    int endStart = 0, endLength = 0;
+    if (modifyEnd < rangeCount) {
+        endStyle = styles[modifyEnd >> 1];
+        endStart = ranges[modifyEnd];
+        endLength = ranges[modifyEnd + 1];
+    }
+    int grow = mergeCount - (modifyEnd - modifyStart);
+    if (rangeCount + grow >= ranges.length) {
+        int[] tmpRanges = new int[ranges.length + grow + (GROW << 1)];
+        System.arraycopy(ranges, 0, tmpRanges, 0, modifyStart);
+        StyleRange[] tmpStyles = new StyleRange[styles.length + (grow >> 1) + GROW];
+        System.arraycopy(styles, 0, tmpStyles, 0, modifyStart >> 1);
+        if (rangeCount > modifyEnd) {
+            System.arraycopy(ranges, modifyEnd, tmpRanges, modifyStart + mergeCount, rangeCount - modifyEnd);
+            System.arraycopy(styles, modifyEnd >> 1, tmpStyles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+        }
+        ranges = tmpRanges;
+        styles = tmpStyles;
+    } else {
+        if (rangeCount > modifyEnd) {
+            System.arraycopy(ranges, modifyEnd, ranges, modifyStart + mergeCount, rangeCount - modifyEnd);
+            System.arraycopy(styles, modifyEnd >> 1, styles, (modifyStart + mergeCount) >> 1, styleCount - (modifyEnd >> 1));
+        }
+    }
+    if (MERGE_STYLES) {
+        int j = modifyStart;
+        for (int i = 0; i < mergeCount; i += 2) {
+            if (j > 0 && ranges[j - 2] + ranges[j - 1] is mergeRanges[i] && mergeStyles[i >> 1].similarTo(styles[(j - 2) >> 1])) {
+                ranges[j - 1] += mergeRanges[i + 1];
+            } else {
+                styles[j >> 1] = mergeStyles[i >> 1];
+                ranges[j++] = mergeRanges[i];
+                ranges[j++] = mergeRanges[i + 1];
+            }
+        }
+        if (endStyle !is null && ranges[j - 2] + ranges[j - 1] is endStart && endStyle.similarTo(styles[(j - 2) >> 1])) {
+            ranges[j - 1] += endLength;
+            modifyEnd += 2;
+            mergeCount += 2;
+        }
+        if (rangeCount > modifyEnd) {
+            System.arraycopy(ranges, modifyStart + mergeCount, ranges, j, rangeCount - modifyEnd);
+            System.arraycopy(styles, (modifyStart + mergeCount) >> 1, styles, j >> 1, styleCount - (modifyEnd >> 1));
+        }
+        grow = (j - modifyStart) - (modifyEnd - modifyStart);
+    } else {
+        System.arraycopy(mergeRanges, 0, ranges, modifyStart, mergeCount);
+        System.arraycopy(mergeStyles, 0, styles, modifyStart >> 1, mergeCount >> 1);
+    }
+    styleCount += grow >> 1;
+    return grow;
+}
+int addMerge(StyleRange[] mergeStyles, int mergeCount, int modifyStart, int modifyEnd) {
+    int grow = mergeCount - (modifyEnd - modifyStart);
+    StyleRange endStyle = null;
+    if (modifyEnd < styleCount) endStyle = styles[modifyEnd];
+    if (styleCount + grow >= styles.length) {
+        StyleRange[] tmpStyles = new StyleRange[styles.length + grow + GROW];
+        System.arraycopy(styles, 0, tmpStyles, 0, modifyStart);
+        if (styleCount > modifyEnd) {
+            System.arraycopy(styles, modifyEnd, tmpStyles, modifyStart + mergeCount, styleCount - modifyEnd);
+        }
+        styles = tmpStyles;
+    } else {
+        if (styleCount > modifyEnd) {
+            System.arraycopy(styles, modifyEnd, styles, modifyStart + mergeCount, styleCount - modifyEnd);
+        }
+    }
+    if (MERGE_STYLES) {
+        int j = modifyStart;
+        for (int i = 0; i < mergeCount; i++) {
+            StyleRange newStyle = mergeStyles[i], style;
+            if (j > 0 && (style = styles[j - 1]).start + style.length is newStyle.start && newStyle.similarTo(style)) {
+                style.length += newStyle.length;
+            } else {
+                styles[j++] = newStyle;
+            }
+        }
+        StyleRange style = styles[j - 1];
+        if (endStyle !is null && style.start + style.length is endStyle.start && endStyle.similarTo(style)) {
+            style.length += endStyle.length;
+            modifyEnd++;
+            mergeCount++;
+        }
+        if (styleCount > modifyEnd) {
+            System.arraycopy(styles, modifyStart + mergeCount, styles, j, styleCount - modifyEnd);
+        }
+        grow = (j - modifyStart) - (modifyEnd - modifyStart);
+    } else {
+        System.arraycopy(mergeStyles, 0, styles, modifyStart, mergeCount);
+    }
+    styleCount += grow;
+    return grow;
+}
+void calculate(int startLine, int lineCount) {
+    int endLine = startLine + lineCount;
+    if (startLine < 0 || endLine > lineWidth.length) {
+        return;
+    }
+    int hTrim = styledText.leftMargin + styledText.rightMargin + styledText.getCaretWidth();
+    for (int i = startLine; i < endLine; i++) {
+        if (lineWidth[i] is -1 || lineHeight[i] is -1) {
+            TextLayout layout = getTextLayout(i);
+            Rectangle rect = layout.getBounds();
+            lineWidth[i] = rect.width + hTrim;
+            lineHeight[i] = rect.height;
+            disposeTextLayout(layout);
+        }
+        if (lineWidth[i] > maxWidth) {
+            maxWidth = lineWidth[i];
+            maxWidthLineIndex = i;
+        }
+    }
+}
+void calculateClientArea () {
+    int index = styledText.getTopIndex();
+    int lineCount = content.getLineCount();
+    int height = styledText.getClientArea().height;
+    int y = 0;
+    while (height > y && lineCount > index) {
+        calculate(index, 1);
+        y += lineHeight[index++];
+    }
+}
+void calculateIdle () {
+    if (idleRunning) return;
+    Runnable runnable = new class() Runnable {
+        public void run() {
+            if (styledText is null) return;
+            int i;
+            long start = System.currentTimeMillis();
+            for (i = 0; i < lineCount; i++) {
+                if (lineHeight[i] is -1 || lineWidth[i] is -1) {
+                    calculate(i, 1);
+                    if (System.currentTimeMillis() - start > IDLE_TIME) break;
+                }
+            }
+            if (i < lineCount) {
+                Display display = styledText.getDisplay();
+                display.asyncExec(this);
+            } else {
+                idleRunning = false;
+                styledText.setScrollBars(true);
+                ScrollBar bar = styledText.getVerticalBar();
+                if (bar !is null) {
+                    bar.setSelection(styledText.getVerticalScrollOffset());
+                }
+            }
+        }
+    };
+    Display display = styledText.getDisplay();
+    display.asyncExec(runnable);
+    idleRunning = true;
+}
+void clearLineBackground(int startLine, int count) {
+    if (lines is null) return;
+    for (int i = startLine; i < startLine + count; i++) {
+        LineInfo info = lines[i];
+        if (info !is null) {
+            info.flags &= ~BACKGROUND;
+            info.background = null;
+            if (info.flags is 0) lines[i] = null;
+        }
+    }
+}
+void clearLineStyle(int startLine, int count) {
+    if (lines is null) return;
+    for (int i = startLine; i < startLine + count; i++) {
+        LineInfo info = lines[i];
+        if (info !is null) {
+            info.flags &= ~(ALIGNMENT | INDENT | JUSTIFY);
+            if (info.flags is 0) lines[i] = null;
+        }
+    }
+}
+void copyInto(StyledTextRenderer renderer) {
+    if (ranges !is null) {
+        int[] newRanges = renderer.ranges = new int[styleCount << 1];
+        System.arraycopy(ranges, 0, newRanges, 0, newRanges.length);
+    }
+    if (styles !is null) {
+        StyleRange[] newStyles = renderer.styles = new StyleRange[styleCount];
+        for (int i = 0; i < newStyles.length; i++) {
+            newStyles[i] = cast(StyleRange)styles[i].clone();
+        }
+        renderer.styleCount = styleCount;
+    }
+    if (lines !is null) {
+        LineInfo[] newLines = renderer.lines = new LineInfo[lineCount];
+        for (int i = 0; i < newLines.length; i++) {
+            newLines[i] = new LineInfo(lines[i]);
+        }
+        renderer.lineCount = lineCount;
+    }
+}
+void dispose() {
+    if (boldFont !is null) boldFont.dispose();
+    if (italicFont !is null) italicFont.dispose();
+    if (boldItalicFont !is null) boldItalicFont.dispose();
+    boldFont = italicFont = boldItalicFont = null;
+    reset();
+    content = null;
+    device = null;
+    styledText = null;
+}
+void disposeTextLayout (TextLayout layout) {
+    if (layouts !is null) {
+        for (int i = 0; i < layouts.length; i++) {
+            if (layouts[i] is layout) return;
+        }
+    }
+    layout.dispose();
+}
+void drawBullet(Bullet bullet, GC gc, int paintX, int paintY, int index, int lineAscent, int lineDescent) {
+    StyleRange style = bullet.style;
+    GlyphMetrics metrics = style.metrics;
+    Color color = style.foreground;
+    if (color !is null) gc.setForeground(color);
+    if ((bullet.type & ST.BULLET_DOT) !is 0 && StyledText.IS_MOTIF) {
+        int size = Math.max(4, (lineAscent + lineDescent) / 4);
+        if ((size & 1) is 0) size++;
+        if (color is null) {
+            Display display = styledText.getDisplay();
+            color = display.getSystemColor(SWT.COLOR_BLACK);
+        }
+        gc.setBackground(color);
+        int x = paintX + Math.max(0, metrics.width - size - BULLET_MARGIN);
+        gc.fillArc(x, paintY + size, size + 1, size + 1, 0, 360);
+        return;
+    }
+    Font font = style.font;
+    if (font !is null) gc.setFont(font);
+    String string = "";
+    int type = bullet.type & (ST.BULLET_DOT|ST.BULLET_NUMBER|ST.BULLET_LETTER_LOWER|ST.BULLET_LETTER_UPPER);
+    switch (type) {
+        case ST.BULLET_DOT: string = "\u2022"; break;
+        case ST.BULLET_NUMBER: string = to!(String)(index); break;
+        case ST.BULLET_LETTER_LOWER: string = [cast(char) (index % 26 + 97)]; break;
+        case ST.BULLET_LETTER_UPPER: string = [cast(char) (index % 26 + 65)]; break;
+        default:
+    }
+    if ((bullet.type & ST.BULLET_TEXT) !is 0) string ~= bullet.text;
+    Display display = styledText.getDisplay();
+    TextLayout layout = new TextLayout(display);
+    layout.setText(string);
+    layout.setAscent(lineAscent);
+    layout.setDescent(lineDescent);
+    style = cast(StyleRange)style.clone();
+    style.metrics = null;
+    if (style.font is null) style.font = getFont(style.fontStyle);
+    layout.setStyle(style, 0, string.length);
+    int x = paintX + Math.max(0, metrics.width - layout.getBounds().width - BULLET_MARGIN);
+    layout.draw(gc, x, paintY);
+    layout.dispose();
+}
+int drawLine(int lineIndex, int paintX, int paintY, GC gc, Color widgetBackground, Color widgetForeground) {
+    TextLayout layout = getTextLayout(lineIndex);
+    String line = content.getLine(lineIndex);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    int lineLength = line.length;
+    Point selection = styledText.getSelection();
+    int selectionStart = selection.x - lineOffset;
+    int selectionEnd = selection.y - lineOffset;
+    Rectangle client = styledText.getClientArea();
+    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;
+    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);
+    if (selectionStart is selectionEnd || (selectionEnd <= 0 && selectionStart > lineLength - 1)) {
+        layout.draw(gc, paintX, paintY);
+    } else {
+        int start = Math.max(0, selectionStart);
+        int end = Math.min(lineLength, selectionEnd);
+        Color selectionFg = styledText.getSelectionForeground();
+        Color selectionBg = styledText.getSelectionBackground();
+        int flags;
+        if ((styledText.getStyle() & SWT.FULL_SELECTION) !is 0) {
+            flags = SWT.FULL_SELECTION;
+        } else {
+            flags = SWT.DELIMITER_SELECTION;
+        }
+        if (selectionStart <= lineLength && lineLength < selectionEnd ) {
+            flags |= SWT.LAST_LINE_SELECTION;
+        }
+        layout.draw(gc, paintX, paintY, start, end - 1, selectionFg, selectionBg, flags);
+    }
+
+    // draw objects
+    Bullet bullet = null;
+    int bulletIndex = -1;
+    if (bullets !is null) {
+        if (bulletsIndices !is null) {
+            int index = lineIndex - topIndex;
+            if (0 <= index && index < CACHE_SIZE) {
+                bullet = bullets[index];
+                bulletIndex = bulletsIndices[index];
+            }
+        } else {
+            for (int i = 0; i < bullets.length; i++) {
+                bullet = bullets[i];
+                bulletIndex = bullet.indexOf(lineIndex);
+                if (bulletIndex !is -1) break;
+            }
+        }
+    }
+    if (bulletIndex !is -1 && bullet !is null) {
+        FontMetrics metrics = layout.getLineMetrics(0);
+        int lineAscent = metrics.getAscent() + metrics.getLeading();
+        if (bullet.type is ST.BULLET_CUSTOM) {
+            bullet.style.start = lineOffset;
+            styledText.paintObject(gc, paintX, paintY, lineAscent, metrics.getDescent(), bullet.style, bullet, bulletIndex);
+        } else {
+            drawBullet(bullet, gc, paintX, paintY, bulletIndex, lineAscent, metrics.getDescent());
+        }
+    }
+    TextStyle[] styles = layout.getStyles();
+    int[] ranges = null;
+    for (int i = 0; i < styles.length; i++) {
+        if (styles[i].metrics !is null) {
+            if (ranges is null) ranges = layout.getRanges();
+            int start = ranges[i << 1];
+            int length = ranges[(i << 1) + 1] - start;
+            Point point = layout.getLocation(start, false);
+            FontMetrics metrics = layout.getLineMetrics(layout.getLineIndex(start));
+            StyleRange style = cast(StyleRange)(cast(StyleRange)styles[i]).clone();
+            style.start = start + lineOffset;
+            style.length = length;
+            int lineAscent = metrics.getAscent() + metrics.getLeading();
+            styledText.paintObject(gc, point.x + paintX, point.y + paintY, lineAscent, metrics.getDescent(), style, null, 0);
+        }
+    }
+    disposeTextLayout(layout);
+    return height;
+}
+int getBaseline() {
+    return ascent;
+}
+Font getFont(int style) {
+    switch (style) {
+        case SWT.BOLD:
+            if (boldFont !is null) return boldFont;
+            return boldFont = new Font(device, getFontData(style));
+        case SWT.ITALIC:
+            if (italicFont !is null) return italicFont;
+            return italicFont = new Font(device, getFontData(style));
+        case SWT.BOLD | SWT.ITALIC:
+            if (boldItalicFont !is null) return boldItalicFont;
+            return boldItalicFont = new Font(device, getFontData(style));
+        default:
+            return regularFont;
+    }
+}
+FontData[] getFontData(int style) {
+    FontData[] fontDatas = regularFont.getFontData();
+    for (int i = 0; i < fontDatas.length; i++) {
+        fontDatas[i].setStyle(style);
+    }
+    return fontDatas;
+}
+int getHeight () {
+    int defaultLineHeight = getLineHeight();
+    if (styledText.isFixedLineHeight()) {
+        return lineCount * defaultLineHeight;
+    }
+    int totalHeight = 0;
+    int width = styledText.getWrapWidth();
+    for (int i = 0; i < lineCount; i++) {
+        int height = lineHeight[i];
+        if (height is -1) {
+            if (width > 0) {
+                int length = content.getLine(i).length;
+                height = ((length * averageCharWidth / width) + 1) * defaultLineHeight;
+            } else {
+                height = defaultLineHeight;
+            }
+        }
+        totalHeight += height;
+    }
+    return totalHeight + styledText.topMargin + styledText.bottomMargin;
+}
+int getLineAlignment(int index, int defaultAlignment) {
+    if (lines is null) return defaultAlignment;
+    LineInfo info = lines[index];
+    if (info !is null && (info.flags & ALIGNMENT) !is 0) {
+        return info.alignment;
+    }
+    return defaultAlignment;
+}
+Color getLineBackground(int index, Color defaultBackground) {
+    if (lines is null) return defaultBackground;
+    LineInfo info = lines[index];
+    if (info !is null && (info.flags & BACKGROUND) !is 0) {
+        return info.background;
+    }
+    return defaultBackground;
+}
+Bullet getLineBullet (int index, Bullet defaultBullet) {
+    if (bullets is null) return defaultBullet;
+    if (bulletsIndices !is null) return defaultBullet;
+    for (int i = 0; i < bullets.length; i++) {
+        Bullet bullet = bullets[i];
+        if (bullet.indexOf(index) !is -1) return bullet;
+    }
+    return defaultBullet;
+}
+int getLineHeight() {
+    return ascent + descent;
+}
+int getLineHeight(int lineIndex) {
+    if (lineHeight[lineIndex] is -1) {
+        calculate(lineIndex, 1);
+    }
+    return lineHeight[lineIndex];
+}
+int getLineIndent(int index, int defaultIndent) {
+    if (lines is null) return defaultIndent;
+    LineInfo info = lines[index];
+    if (info !is null && (info.flags & INDENT) !is 0) {
+        return info.indent;
+    }
+    return defaultIndent;
+}
+bool getLineJustify(int index, bool defaultJustify) {
+    if (lines is null) return defaultJustify;
+    LineInfo info = lines[index];
+    if (info !is null && (info.flags & JUSTIFY) !is 0) {
+        return info.justify;
+    }
+    return defaultJustify;
+}
+int[] getLineSegments(int index, int[] defaultSegments) {
+    if (lines is null) return defaultSegments;
+    LineInfo info = lines[index];
+    if (info !is null && (info.flags & SEGMENTS) !is 0) {
+        return info.segments;
+    }
+    return defaultSegments;
+}
+int getRangeIndex(int offset, int low, int high) {
+    if (styleCount is 0) return 0;
+    if (ranges !is null)  {
+        while (high - low > 2) {
+            int index = ((high + low) / 2) / 2 * 2;
+            int end = ranges[index] + ranges[index + 1];
+            if (end > offset) {
+                high = index;
+            } else {
+                low = index;
+            }
+        }
+    } else {
+        while (high - low > 1) {
+            int index = ((high + low) / 2);
+            int end = styles[index].start + styles[index].length;
+            if (end > offset) {
+                high = index;
+            } else {
+                low = index;
+            }
+        }
+    }
+    return high;
+}
+int[] getRanges(int start, int length) {
+    int[] newRanges;
+    int end = start + length - 1;
+    if (ranges !is null) {
+        int rangeCount = styleCount << 1;
+        int rangeStart = getRangeIndex(start, -1, rangeCount);
+        if (rangeStart >= rangeCount) return null;
+        if (ranges[rangeStart] > end) return null;
+        int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+        newRanges = new int[rangeEnd - rangeStart + 2];
+        System.arraycopy(ranges, rangeStart, newRanges, 0, newRanges.length);
+    } else {
+        int rangeStart = getRangeIndex(start, -1, styleCount);
+        if (rangeStart >= styleCount) return null;
+        if (styles[rangeStart].start > end) return null;
+        int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+        newRanges = new int[(rangeEnd - rangeStart + 1) << 1];
+        for (int i = rangeStart, j = 0; i <= rangeEnd; i++, j += 2) {
+            StyleRange style = styles[i];
+            newRanges[j] = style.start;
+            newRanges[j + 1] = style.length;
+        }
+    }
+    if (start > newRanges[0]) {
+        newRanges[1] = newRanges[0] + newRanges[1] - start;
+        newRanges[0] = start;
+    }
+    if (end < newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1] - 1) {
+        newRanges[newRanges.length - 1] = end - newRanges[newRanges.length - 2] + 1;
+    }
+    return newRanges;
+}
+StyleRange[] getStyleRanges(int start, int length, bool includeRanges) {
+    StyleRange[] newStyles;
+    int end = start + length - 1;
+    if (ranges !is null) {
+        int rangeCount = styleCount << 1;
+        int rangeStart = getRangeIndex(start, -1, rangeCount);
+        if (rangeStart >= rangeCount) return null;
+        if (ranges[rangeStart] > end) return null;
+        int rangeEnd = Math.min(rangeCount - 2, getRangeIndex(end, rangeStart - 1, rangeCount) + 1);
+        newStyles = new StyleRange[((rangeEnd - rangeStart) >> 1) + 1];
+        if (includeRanges) {
+            for (int i = rangeStart, j = 0; i <= rangeEnd; i += 2, j++) {
+                newStyles[j] = cast(StyleRange)styles[i >> 1].clone();
+                newStyles[j].start = ranges[i];
+                newStyles[j].length = ranges[i + 1];
+            }
+        } else {
+            System.arraycopy(styles, rangeStart >> 1, newStyles, 0, newStyles.length);
+        }
+    } else {
+        int rangeStart = getRangeIndex(start, -1, styleCount);
+        if (rangeStart >= styleCount) return null;
+        if (styles[rangeStart].start > end) return null;
+        int rangeEnd = Math.min(styleCount - 1, getRangeIndex(end, rangeStart - 1, styleCount));
+        newStyles = new StyleRange[rangeEnd - rangeStart + 1];
+        System.arraycopy(styles, rangeStart, newStyles, 0, newStyles.length);
+    }
+    StyleRange style = newStyles[0];
+    if (start > style.start) {
+        if (!includeRanges || ranges is null) newStyles[0] = style = cast(StyleRange)style.clone();
+        style.length = style.start + style.length - start;
+        style.start = start;
+    }
+    style = newStyles[newStyles.length - 1];
+    if (end < style.start + style.length - 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;
+}
+StyleRange getStyleRange(StyleRange style) {
+    if (style.start is 0 && style.length is 0 && style.fontStyle is SWT.NORMAL) return style;
+    StyleRange clone = cast(StyleRange)style.clone();
+    clone.start = clone.length = 0;
+    clone.fontStyle = SWT.NORMAL;
+    if (clone.font is null) clone.font = getFont(style.fontStyle);
+    return clone;
+}
+TextLayout getTextLayout(int lineIndex) {
+    return getTextLayout(lineIndex, styledText.getOrientation(), styledText.getWrapWidth(), styledText.lineSpacing);
+}
+TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpacing) {
+    TextLayout layout = null;
+    if (styledText !is null) {
+        int topIndex = styledText.topIndex > 0 ? styledText.topIndex - 1 : 0;
+        if (layouts is null || topIndex !is this.topIndex) {
+            TextLayout[] newLayouts = new TextLayout[CACHE_SIZE];
+            if (layouts !is null) {
+                for (int i = 0; i < layouts.length; i++) {
+                    if (layouts[i] !is null) {
+                        int layoutIndex = (i + this.topIndex) - topIndex;
+                        if (0 <= layoutIndex && layoutIndex < newLayouts.length) {
+                            newLayouts[layoutIndex] = layouts[i];
+                        } else {
+                            layouts[i].dispose();
+                        }
+                    }
+                }
+            }
+            if (bullets !is null && bulletsIndices !is null && topIndex !is this.topIndex) {
+                int delta = topIndex - this.topIndex;
+                if (delta > 0) {
+                    if (delta < bullets.length) {
+                        System.arraycopy(bullets, delta, bullets, 0, bullets.length - delta);
+                        System.arraycopy(bulletsIndices, delta, bulletsIndices, 0, bulletsIndices.length - delta);
+                    }
+                    int startIndex = Math.max(0, bullets.length - delta);
+                    for (int i = startIndex; i < bullets.length; i++) bullets[i] = null;
+                } else {
+                    if (-delta < bullets.length) {
+                        System.arraycopy(bullets, 0, bullets, -delta, bullets.length + delta);
+                        System.arraycopy(bulletsIndices, 0, bulletsIndices, -delta, bulletsIndices.length + delta);
+                    }
+                    int endIndex = Math.min(bullets.length, -delta);
+                    for (int i = 0; i < endIndex; i++) bullets[i] = null;
+                }
+            }
+            this.topIndex = topIndex;
+            layouts = newLayouts;
+        }
+        if (layouts !is null) {
+            int layoutIndex = lineIndex - topIndex;
+            if (0 <= layoutIndex && layoutIndex < layouts.length) {
+                layout = layouts[layoutIndex];
+                if (layout !is null) {
+                    if (lineWidth[lineIndex] !is -1) return layout;
+                } else {
+                    layout = layouts[layoutIndex] = new TextLayout(device);
+                }
+            }
+        }
+    }
+    if (layout is null) layout = new TextLayout(device);
+    String line = content.getLine(lineIndex);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    int[] segments = null;
+    int indent = 0;
+    int alignment = SWT.LEFT;
+    bool justify = false;
+    Bullet bullet = null;
+    int[] ranges = null;
+    StyleRange[] styles = null;
+    int rangeStart = 0, styleCount = 0;
+    StyledTextEvent event = null;
+    if (styledText !is null) {
+        event = styledText.getLineStyleData(lineOffset, line);
+        segments = styledText.getBidiSegments(lineOffset, line);
+        indent = styledText.indent;
+        alignment = styledText.alignment;
+        justify = styledText.justify;
+    }
+    if (event !is null) {
+        indent = event.indent;
+        alignment = event.alignment;
+        justify = event.justify;
+        bullet = event.bullet;
+        ranges = event.ranges;
+        styles = event.styles;
+        if (styles !is null) {
+            styleCount = styles.length;
+            if (styledText.isFixedLineHeight()) {
+                for (int i = 0; i < styleCount; i++) {
+                    if (styles[i].isVariableHeight()) {
+                        styledText.verticalScrollOffset = -1;
+                        styledText.setVariableLineHeight();
+                        styledText.redraw();
+                        break;
+                    }
+                }
+            }
+        }
+        if (bullets is null || bulletsIndices is null) {
+            bullets = new Bullet[CACHE_SIZE];
+            bulletsIndices = new int[CACHE_SIZE];
+        }
+        int index = lineIndex - topIndex;
+        if (0 <= index && index < CACHE_SIZE) {
+            bullets[index] = bullet;
+            bulletsIndices[index] = event.bulletIndex;
+        }
+    } else {
+        if (lines !is null) {
+            LineInfo info = lines[lineIndex];
+            if (info !is null) {
+                if ((info.flags & INDENT) !is 0) indent = info.indent;
+                if ((info.flags & ALIGNMENT) !is 0) alignment = info.alignment;
+                if ((info.flags & JUSTIFY) !is 0) justify = info.justify;
+                if ((info.flags & SEGMENTS) !is 0) segments = info.segments;
+            }
+        }
+        if (bulletsIndices !is null) {
+            bullets = null;
+            bulletsIndices = null;
+        }
+        if (bullets !is null) {
+            for (int i = 0; i < bullets.length; i++) {
+                if (bullets[i].indexOf(lineIndex) !is -1) {
+                    bullet = bullets[i];
+                    break;
+                }
+            }
+        }
+        ranges = this.ranges;
+        styles = this.styles;
+        styleCount = this.styleCount;
+        if (ranges !is null) {
+            rangeStart = getRangeIndex(lineOffset, -1, styleCount << 1);
+        } else {
+            rangeStart = getRangeIndex(lineOffset, -1, styleCount);
+        }
+    }
+    if (bullet !is null) {
+        StyleRange style = bullet.style;
+        GlyphMetrics metrics = style.metrics;
+        indent += metrics.width;
+    }
+    layout.setFont(regularFont);
+    layout.setAscent(ascent);
+    layout.setDescent(descent);
+    layout.setText(line);
+    layout.setOrientation(orientation);
+    layout.setSegments(segments);
+    layout.setWidth(width);
+    layout.setSpacing(lineSpacing);
+    layout.setTabs([tabWidth]);
+    layout.setIndent(indent);
+    layout.setAlignment(alignment);
+    layout.setJustify(justify);
+
+    int lastOffset = 0;
+    int length = line.length;
+    if (styles !is null) {
+        if (ranges !is null) {
+            int rangeCount = styleCount << 1;
+            for (int i = rangeStart; i < rangeCount; i += 2) {
+                int start, end;
+                if (lineOffset > ranges[i]) {
+                    start = 0;
+                    end = Math.min (length, ranges[i + 1] - lineOffset + ranges[i]);
+                } else {
+                    start = ranges[i] - lineOffset;
+                    end = Math.min(length, start + ranges[i + 1]);
+                }
+                if (start >= length) break;
+                if (lastOffset < start) {
+                    layout.setStyle(null, lastOffset, start - 1);
+                }
+                layout.setStyle(getStyleRange(styles[i >> 1]), start, end);
+                lastOffset = Math.max(lastOffset, end);
+            }
+        } else {
+            for (int i = rangeStart; i < styleCount; i++) {
+                int start, end;
+                if (lineOffset > styles[i].start) {
+                    start = 0;
+                    end = Math.min (length, styles[i].length - lineOffset + styles[i].start);
+                } else {
+                    start = styles[i].start - lineOffset;
+                    end = Math.min(length, start + styles[i].length);
+                }
+                if (start >= length) break;
+                if (lastOffset < start) {
+                    layout.setStyle(null, lastOffset, start - 1);
+                }
+                layout.setStyle(getStyleRange(styles[i]), start, end);
+                lastOffset = Math.max(lastOffset, end);
+            }
+        }
+    }
+    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();
+        int height = getLineHeight();
+        for (int i = 0; i < lineCount; i++) {
+            int lineHeight = layout.getLineBounds(i).height;
+            if (lineHeight > height) {
+                height = lineHeight;
+                index = i;
+            }
+        }
+        if (index !is -1) {
+            FontMetrics metrics = layout.getLineMetrics(index);
+            ascent = metrics.getAscent() + metrics.getLeading();
+            descent = metrics.getDescent();
+            if (layouts !is null) {
+                for (int i = 0; i < layouts.length; i++) {
+                    if (layouts[i] !is null && layouts[i] !is layout) {
+                        layouts[i].setAscent(ascent);
+                        layouts[i].setDescent(descent);
+                    }
+                }
+            }
+            if (styledText.verticalScrollOffset !is 0) {
+                int topIndex = styledText.topIndex;
+                int topIndexY = styledText.topIndexY;
+                int lineHeight = getLineHeight();
+                if (topIndexY >= 0) {
+                    styledText.verticalScrollOffset = (topIndex - 1) * lineHeight + lineHeight - topIndexY;
+                } else {
+                    styledText.verticalScrollOffset = topIndex * lineHeight - topIndexY;
+                }
+            }
+            styledText.calculateScrollBars();
+            if (styledText.isBidiCaret()) styledText.createCaretBitmaps();
+            styledText.caretDirection = SWT.NULL;
+            styledText.setCaretLocation();
+            styledText.redraw();
+        }
+    }
+    return layout;
+}
+int getWidth() {
+    return maxWidth;
+}
+void reset() {
+    if (layouts !is null) {
+        for (int i = 0; i < layouts.length; i++) {
+            TextLayout layout = layouts[i];
+            if (layout !is null) layout.dispose();
+        }
+        layouts = null;
+    }
+    topIndex = -1;
+    stylesSetCount = styleCount = lineCount = 0;
+    ranges = null;
+    styles = null;
+    stylesSet = null;
+    lines = null;
+    lineWidth = null;
+    lineHeight = null;
+    bullets = null;
+    bulletsIndices = null;
+    redrawLines = null;
+}
+void reset(int startLine, int lineCount) {
+    int endLine = startLine + lineCount;
+    if (startLine < 0 || endLine > lineWidth.length) return;
+    for (int i = startLine; i < endLine; i++) {
+        lineWidth[i] = -1;
+        lineHeight[i] = -1;
+    }
+    if (startLine <= maxWidthLineIndex && maxWidthLineIndex < endLine) {
+        maxWidth = 0;
+        maxWidthLineIndex = -1;
+        if (lineCount !is this.lineCount) {
+            for (int i = 0; i < this.lineCount; i++) {
+                if (lineWidth[i] > maxWidth) {
+                    maxWidth = lineWidth[i];
+                    maxWidthLineIndex = i;
+                }
+            }
+        }
+    }
+}
+void setContent(StyledTextContent content) {
+    reset();
+    this.content = content;
+    lineCount = content.getLineCount();
+    lineWidth = new int[lineCount];
+    lineHeight = new int[lineCount];
+    reset(0, lineCount);
+}
+void setFont(Font font, int tabs) {
+    TextLayout layout = new TextLayout(device);
+    layout.setFont(regularFont);
+    if (font !is null) {
+        if (boldFont !is null) boldFont.dispose();
+        if (italicFont !is null) italicFont.dispose();
+        if (boldItalicFont !is null) boldItalicFont.dispose();
+        boldFont = italicFont = boldItalicFont = null;
+        regularFont = font;
+        layout.setText("    ");
+        layout.setFont(font);
+        layout.setStyle(new TextStyle(getFont(SWT.NORMAL), null, null), 0, 0);
+        layout.setStyle(new TextStyle(getFont(SWT.BOLD), null, null), 1, 1);
+        layout.setStyle(new TextStyle(getFont(SWT.ITALIC), null, null), 2, 2);
+        layout.setStyle(new TextStyle(getFont(SWT.BOLD | SWT.ITALIC), null, null), 3, 3);
+        FontMetrics metrics = layout.getLineMetrics(0);
+        ascent = metrics.getAscent() + metrics.getLeading();
+        descent = metrics.getDescent();
+        boldFont.dispose();
+        italicFont.dispose();
+        boldItalicFont.dispose();
+        boldFont = italicFont = boldItalicFont = null;
+    }
+    layout.dispose();
+    layout = new TextLayout(device);
+    layout.setFont(regularFont);
+    StringBuffer tabBuffer = new StringBuffer(tabs);
+    for (int i = 0; i < tabs; i++) {
+        tabBuffer.append(' ');
+    }
+    layout.setText(tabBuffer.toString());
+    tabWidth = layout.getBounds().width;
+    layout.dispose();
+    if (styledText !is null) {
+        GC gc = new GC(styledText);
+        averageCharWidth = gc.getFontMetrics().getAverageCharWidth();
+        gc.dispose();
+    }
+}
+void setLineAlignment(int startLine, int count, int alignment) {
+    if (lines is null) lines = new LineInfo[lineCount];
+    for (int i = startLine; i < startLine + count; i++) {
+        if (lines[i] is null) {
+            lines[i] = new LineInfo();
+        }
+        lines[i].flags |= ALIGNMENT;
+        lines[i].alignment = alignment;
+    }
+}
+void setLineBackground(int startLine, int count, Color background) {
+    if (lines is null) lines = new LineInfo[lineCount];
+    for (int i = startLine; i < startLine + count; i++) {
+        if (lines[i] is null) {
+            lines[i] = new LineInfo();
+        }
+        lines[i].flags |= BACKGROUND;
+        lines[i].background = background;
+    }
+}
+void setLineBullet(int startLine, int count, Bullet bullet) {
+    if (bulletsIndices !is null) {
+        bulletsIndices = null;
+        bullets = null;
+    }
+    if (bullets is null) {
+        if (bullet is null) return;
+        bullets = new Bullet[1];
+        bullets[0] = bullet;
+    }
+    int index = 0;
+    while (index < bullets.length) {
+        if (bullet is bullets[index]) break;
+        index++;
+    }
+    if (bullet !is null) {
+        if (index is bullets.length) {
+            Bullet[] newBulletsList = new Bullet[bullets.length + 1];
+            System.arraycopy(bullets, 0, newBulletsList, 0, bullets.length);
+            newBulletsList[index] = bullet;
+            bullets = newBulletsList;
+        }
+        bullet.addIndices(startLine, count);
+    } else {
+        updateBullets(startLine, count, 0, false);
+        styledText.redrawLinesBullet(redrawLines);
+        redrawLines = null;
+    }
+}
+void setLineIndent(int startLine, int count, int indent) {
+    if (lines is null) lines = new LineInfo[lineCount];
+    for (int i = startLine; i < startLine + count; i++) {
+        if (lines[i] is null) {
+            lines[i] = new LineInfo();
+        }
+        lines[i].flags |= INDENT;
+        lines[i].indent = indent;
+    }
+}
+void setLineJustify(int startLine, int count, bool justify) {
+    if (lines is null) lines = new LineInfo[lineCount];
+    for (int i = startLine; i < startLine + count; i++) {
+        if (lines[i] is null) {
+            lines[i] = new LineInfo();
+        }
+        lines[i].flags |= JUSTIFY;
+        lines[i].justify = justify;
+    }
+}
+void setLineSegments(int startLine, int count, int[] segments) {
+    if (lines is null) lines = new LineInfo[lineCount];
+    for (int i = startLine; i < startLine + count; i++) {
+        if (lines[i] is null) {
+            lines[i] = new LineInfo();
+        }
+        lines[i].flags |= SEGMENTS;
+        lines[i].segments = segments;
+    }
+}
+void setStyleRanges (int[] newRanges, StyleRange[] newStyles) {
+    if (newStyles is null) {
+        stylesSetCount = styleCount = 0;
+        ranges = null;
+        styles = null;
+        stylesSet = null;
+        return;
+    }
+    if (newRanges is null && COMPACT_STYLES) {
+        newRanges = new int[newStyles.length << 1];
+        StyleRange[] tmpStyles = new StyleRange[newStyles.length];
+        if (stylesSet is null) stylesSet = new StyleRange[4];
+        for (int i = 0, j = 0; i < newStyles.length; i++) {
+            StyleRange newStyle = newStyles[i];
+            newRanges[j++] = newStyle.start;
+            newRanges[j++] = newStyle.length;
+            int index = 0;
+            while (index < stylesSetCount) {
+                if (stylesSet[index].similarTo(newStyle)) break;
+                index++;
+            }
+            if (index is stylesSetCount) {
+                if (stylesSetCount is stylesSet.length) {
+                    StyleRange[] tmpStylesSet = new StyleRange[stylesSetCount + 4];
+                    System.arraycopy(stylesSet, 0, tmpStylesSet, 0, stylesSetCount);
+                    stylesSet = tmpStylesSet;
+                }
+                stylesSet[stylesSetCount++] = newStyle;
+            }
+            tmpStyles[i] = stylesSet[index];
+        }
+        newStyles = tmpStyles;
+    }
+
+    if (styleCount is 0) {
+        if (newRanges !is null) {
+            ranges = new int[newRanges.length];
+            System.arraycopy(newRanges, 0, ranges, 0, ranges.length);
+        }
+        styles = new StyleRange[newStyles.length];
+        System.arraycopy(newStyles, 0, styles, 0, styles.length);
+        styleCount = newStyles.length;
+        return;
+    }
+    if (newRanges !is null && ranges is null) {
+        ranges = new int[styles.length << 1];
+        for (int i = 0, j = 0; i < styleCount; i++) {
+            ranges[j++] = styles[i].start;
+            ranges[j++] = styles[i].length;
+        }
+    }
+    if (newRanges is null && ranges !is null) {
+        newRanges = new int[newStyles.length << 1];
+        for (int i = 0, j = 0; i < newStyles.length; i++) {
+            newRanges[j++] = newStyles[i].start;
+            newRanges[j++] = newStyles[i].length;
+        }
+    }
+    if (ranges !is null) {
+        int rangeCount = styleCount << 1;
+        int start = newRanges[0];
+        int modifyStart = getRangeIndex(start, -1, rangeCount), modifyEnd;
+        bool insert = modifyStart is rangeCount;
+        if (!insert) {
+            int end = newRanges[newRanges.length - 2] + newRanges[newRanges.length - 1];
+            modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+            insert = modifyStart is modifyEnd && ranges[modifyStart] >= end;
+        }
+        if (insert) {
+            addMerge(newRanges, newStyles, newRanges.length, modifyStart, modifyStart);
+            return;
+        }
+        modifyEnd = modifyStart;
+        int[] mergeRanges = new int[6];
+        StyleRange[] mergeStyles = new StyleRange[3];
+        for (int i = 0; i < newRanges.length; i += 2) {
+            int newStart = newRanges[i];
+            int newEnd = newStart + newRanges[i + 1];
+            if (newStart is newEnd) continue;
+            int modifyLast = 0, mergeCount = 0;
+            while (modifyEnd < rangeCount) {
+                if (newStart >= ranges[modifyStart] + ranges[modifyStart + 1]) modifyStart += 2;
+                if (ranges[modifyEnd] + ranges[modifyEnd + 1] > newEnd) break;
+                modifyEnd += 2;
+            }
+            if (ranges[modifyStart] < newStart && newStart < ranges[modifyStart] + ranges[modifyStart + 1]) {
+                mergeStyles[mergeCount >> 1] = styles[modifyStart >> 1];
+                mergeRanges[mergeCount] = ranges[modifyStart];
+                mergeRanges[mergeCount + 1] = newStart - ranges[modifyStart];
+                mergeCount += 2;
+            }
+            mergeStyles[mergeCount >> 1] = newStyles[i >> 1];
+            mergeRanges[mergeCount] = newStart;
+            mergeRanges[mergeCount + 1] = newRanges[i + 1];
+            mergeCount += 2;
+            if (modifyEnd < rangeCount && ranges[modifyEnd] < newEnd && newEnd < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+                mergeStyles[mergeCount >> 1] = styles[modifyEnd >> 1];
+                mergeRanges[mergeCount] = newEnd;
+                mergeRanges[mergeCount + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - newEnd;
+                mergeCount += 2;
+                modifyLast = 2;
+            }
+            int grow = addMerge(mergeRanges, mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+            rangeCount += grow;
+            modifyStart = modifyEnd += grow;
+        }
+    } else {
+        int start = newStyles[0].start;
+        int modifyStart = getRangeIndex(start, -1, styleCount), modifyEnd;
+        bool insert = modifyStart is styleCount;
+        if (!insert) {
+            int end = newStyles[newStyles.length - 1].start + newStyles[newStyles.length - 1].length;
+            modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+            insert = modifyStart is modifyEnd && styles[modifyStart].start >= end;
+        }
+        if (insert) {
+            addMerge(newStyles, newStyles.length, modifyStart, modifyStart);
+            return;
+        }
+        modifyEnd = modifyStart;
+        StyleRange[] mergeStyles = new StyleRange[3];
+        for (int i = 0; i < newStyles.length; i++) {
+            StyleRange newStyle = newStyles[i], style;
+            int newStart = newStyle.start;
+            int newEnd = newStart + newStyle.length;
+            if (newStart is newEnd) continue;
+            int modifyLast = 0, mergeCount = 0;
+            while (modifyEnd < styleCount) {
+                if (newStart >= styles[modifyStart].start + styles[modifyStart].length) modifyStart++;
+                if (styles[modifyEnd].start + styles[modifyEnd].length > newEnd) break;
+                modifyEnd++;
+            }
+            style = styles[modifyStart];
+            if (style.start < newStart && newStart < style.start + style.length) {
+                style = mergeStyles[mergeCount++] = cast(StyleRange)style.clone();
+                style.length = newStart - style.start;
+            }
+            mergeStyles[mergeCount++] = newStyle;
+            if (modifyEnd < styleCount) {
+                style = styles[modifyEnd];
+                if (style.start < newEnd && newEnd < style.start + style.length) {
+                    style = mergeStyles[mergeCount++] = cast(StyleRange)style.clone();
+                    style.length += style.start - newEnd;
+                    style.start = newEnd;
+                    modifyLast = 1;
+                }
+            }
+            int grow = addMerge(mergeStyles, mergeCount, modifyStart, modifyEnd + modifyLast);
+            modifyStart = modifyEnd += grow;
+        }
+    }
+}
+void textChanging(TextChangingEvent event) {
+    int start = event.start;
+    int newCharCount = event.newCharCount, replaceCharCount = event.replaceCharCount;
+    int newLineCount = event.newLineCount, replaceLineCount = event.replaceLineCount;
+
+    updateRanges(start, replaceCharCount, newCharCount);
+
+    int startLine = content.getLineAtOffset(start);
+    if (replaceCharCount is content.getCharCount()) lines = null;
+    if (replaceLineCount is lineCount) {
+        lineCount = newLineCount;
+        lineWidth = new int[lineCount];
+        lineHeight = new int[lineCount];
+        reset(0, lineCount);
+    } else {
+        int delta = newLineCount - replaceLineCount;
+        if (lineCount + delta > lineWidth.length) {
+            int[] newWidths = new int[lineCount + delta + GROW];
+            System.arraycopy(lineWidth, 0, newWidths, 0, lineCount);
+            lineWidth = newWidths;
+            int[] newHeights = new int[lineCount + delta + GROW];
+            System.arraycopy(lineHeight, 0, newHeights, 0, lineCount);
+            lineHeight = newHeights;
+        }
+        if (lines !is null) {
+            if (lineCount + delta > lines.length) {
+                LineInfo[] newLines = new LineInfo[lineCount + delta + GROW];
+                System.arraycopy(lines, 0, newLines, 0, lineCount);
+                lines = newLines;
+            }
+        }
+        int startIndex = startLine + replaceLineCount + 1;
+        int endIndex = startLine + newLineCount + 1;
+        System.arraycopy(lineWidth, startIndex, lineWidth, endIndex, lineCount - startIndex);
+        System.arraycopy(lineHeight, startIndex, lineHeight, endIndex, lineCount - startIndex);
+        for (int i = startLine; i < endIndex; i++) {
+            lineWidth[i] = lineHeight[i] = -1;
+        }
+        for (int i = lineCount + delta; i < lineCount; i++) {
+            lineWidth[i] = lineHeight[i] = -1;
+        }
+        if (layouts !is null) {
+            int layoutStartLine = startLine - topIndex;
+            int layoutEndLine = layoutStartLine + replaceLineCount + 1;
+            for (int i = layoutStartLine; i < layoutEndLine; i++) {
+                if (0 <= i && i < layouts.length) {
+                    if (layouts[i] !is null) layouts[i].dispose();
+                    layouts[i] = null;
+                    if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+                }
+            }
+            if (delta > 0) {
+                for (int i = layouts.length - 1; i >= layoutEndLine; i--) {
+                    if (0 <= i && i < layouts.length) {
+                        endIndex = i + delta;
+                        if (0 <= endIndex && endIndex < layouts.length) {
+                            layouts[endIndex] = layouts[i];
+                            layouts[i] = null;
+                            if (bullets !is null && bulletsIndices !is null) {
+                                bullets[endIndex] = bullets[i];
+                                bulletsIndices[endIndex] = bulletsIndices[i];
+                                bullets[i] = null;
+                            }
+                        } else {
+                            if (layouts[i] !is null) layouts[i].dispose();
+                            layouts[i] = null;
+                            if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+                        }
+                    }
+                }
+            } else if (delta < 0) {
+                for (int i = layoutEndLine; i < layouts.length; i++) {
+                    if (0 <= i && i < layouts.length) {
+                        endIndex = i + delta;
+                        if (0 <= endIndex && endIndex < layouts.length) {
+                            layouts[endIndex] = layouts[i];
+                            layouts[i] = null;
+                            if (bullets !is null && bulletsIndices !is null) {
+                                bullets[endIndex] = bullets[i];
+                                bulletsIndices[endIndex] = bulletsIndices[i];
+                                bullets[i] = null;
+                            }
+                        } else {
+                            if (layouts[i] !is null) layouts[i].dispose();
+                            layouts[i] = null;
+                            if (bullets !is null && bulletsIndices !is null) bullets[i] = null;
+                        }
+                    }
+                }
+            }
+        }
+        if (replaceLineCount !is 0 || newLineCount !is 0) {
+            int startLineOffset = content.getOffsetAtLine(startLine);
+            if (startLineOffset !is start) startLine++;
+            updateBullets(startLine, replaceLineCount, newLineCount, true);
+            if (lines !is null) {
+                startIndex = startLine + replaceLineCount;
+                endIndex = startLine + newLineCount;
+                System.arraycopy(lines, startIndex, lines, endIndex, lineCount - startIndex);
+                for (int i = startLine; i < endIndex; i++) {
+                    lines[i] = null;
+                }
+                for (int i = lineCount + delta; i < lineCount; i++) {
+                    lines[i] = null;
+                }
+            }
+        }
+        lineCount += delta;
+        if (maxWidthLineIndex !is -1 && startLine <= maxWidthLineIndex && maxWidthLineIndex <= startLine + replaceLineCount) {
+            maxWidth = 0;
+            maxWidthLineIndex = -1;
+            for (int i = 0; i < lineCount; i++) {
+                if (lineWidth[i] > maxWidth) {
+                    maxWidth = lineWidth[i];
+                    maxWidthLineIndex = i;
+                }
+            }
+        }
+    }
+}
+void updateBullets(int startLine, int replaceLineCount, int newLineCount, bool update) {
+    if (bullets is null) return;
+    if (bulletsIndices !is null) return;
+    for (int i = 0; i < bullets.length; i++) {
+        Bullet bullet = bullets[i];
+        int[] lines = bullet.removeIndices(startLine, replaceLineCount, newLineCount, update);
+        if (lines !is null) {
+            if (redrawLines is null) {
+                redrawLines = lines;
+            } else {
+                int[] newRedrawBullets = new int[redrawLines.length + lines.length];
+                System.arraycopy(redrawLines, 0, newRedrawBullets, 0, redrawLines.length);
+                System.arraycopy(lines, 0, newRedrawBullets, redrawLines.length, lines.length);
+                redrawLines = newRedrawBullets;
+            }
+        }
+    }
+    int removed = 0;
+    for (int i = 0; i < bullets.length; i++) {
+        if (bullets[i].size() is 0) removed++;
+    }
+    if (removed > 0) {
+        if (removed is bullets.length) {
+            bullets = null;
+        } else {
+            Bullet[] newBulletsList = new Bullet[bullets.length - removed];
+            for (int i = 0, j = 0; i < bullets.length; i++) {
+                Bullet bullet = bullets[i];
+                if (bullet.size() > 0) newBulletsList[j++] = bullet;
+            }
+            bullets = newBulletsList;
+        }
+    }
+}
+void updateRanges(int start, int replaceCharCount, int newCharCount) {
+    if (styleCount is 0 || (replaceCharCount is 0 && newCharCount is 0)) return;
+    if (ranges !is null) {
+        int rangeCount = styleCount << 1;
+        int modifyStart = getRangeIndex(start, -1, rangeCount);
+        if (modifyStart is rangeCount) return;
+        int end = start + replaceCharCount;
+        int modifyEnd = getRangeIndex(end, modifyStart - 1, rangeCount);
+        int offset = newCharCount - replaceCharCount;
+        if (modifyStart is modifyEnd && ranges[modifyStart] < start && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+            if (newCharCount is 0) {
+                ranges[modifyStart + 1] -= replaceCharCount;
+                modifyEnd += 2;
+            } else {
+                if (rangeCount + 2 > ranges.length) {
+                    int[] newRanges = new int[ranges.length + (GROW << 1)];
+                    System.arraycopy(ranges, 0, newRanges, 0, rangeCount);
+                    ranges = newRanges;
+                    StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+                    System.arraycopy(styles, 0, newStyles, 0, styleCount);
+                    styles = newStyles;
+                }
+                System.arraycopy(ranges, modifyStart + 2, ranges, modifyStart + 4, rangeCount - (modifyStart + 2));
+                System.arraycopy(styles, (modifyStart + 2) >> 1, styles, (modifyStart + 4) >> 1, styleCount - ((modifyStart + 2) >> 1));
+                ranges[modifyStart + 3] = ranges[modifyStart] + ranges[modifyStart + 1] - end;
+                ranges[modifyStart + 2] = start + newCharCount;
+                ranges[modifyStart + 1] = start - ranges[modifyStart];
+                styles[(modifyStart >> 1) + 1] = styles[modifyStart >> 1];
+                rangeCount += 2;
+                styleCount++;
+                modifyEnd += 4;
+            }
+            if (offset !is 0) {
+                for (int i = modifyEnd; i < rangeCount; i += 2) {
+                    ranges[i] += offset;
+                }
+            }
+        } else {
+            if (ranges[modifyStart] < start && start < ranges[modifyStart] + ranges[modifyStart + 1]) {
+                ranges[modifyStart + 1] = start - ranges[modifyStart];
+                modifyStart += 2;
+            }
+            if (modifyEnd < rangeCount && ranges[modifyEnd] < end && end < ranges[modifyEnd] + ranges[modifyEnd + 1]) {
+                ranges[modifyEnd + 1] = ranges[modifyEnd] + ranges[modifyEnd + 1] - end;
+                ranges[modifyEnd] = end;
+            }
+            if (offset !is 0) {
+                for (int i = modifyEnd; i < rangeCount; i += 2) {
+                    ranges[i] += offset;
+                }
+            }
+            System.arraycopy(ranges, modifyEnd, ranges, modifyStart, rangeCount - modifyEnd);
+            System.arraycopy(styles, modifyEnd >> 1, styles, modifyStart >> 1, styleCount - (modifyEnd >> 1));
+            styleCount -= (modifyEnd - modifyStart) >> 1;
+        }
+    } else {
+        int modifyStart = getRangeIndex(start, -1, styleCount);
+        if (modifyStart is styleCount) return;
+        int end = start + replaceCharCount;
+        int modifyEnd = getRangeIndex(end, modifyStart - 1, styleCount);
+        int offset = newCharCount - replaceCharCount;
+        if (modifyStart is modifyEnd && styles[modifyStart].start < start && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+            if (newCharCount is 0) {
+                styles[modifyStart].length -= replaceCharCount;
+                modifyEnd++;
+            } else {
+                if (styleCount + 1 > styles.length) {
+                    StyleRange[] newStyles = new StyleRange[styles.length + GROW];
+                    System.arraycopy(styles, 0, newStyles, 0, styleCount);
+                    styles = newStyles;
+                }
+                System.arraycopy(styles, modifyStart + 1, styles, modifyStart + 2, styleCount - (modifyStart + 1));
+                styles[modifyStart + 1] = cast(StyleRange)styles[modifyStart].clone();
+                styles[modifyStart + 1].length = styles[modifyStart].start + styles[modifyStart].length - end;
+                styles[modifyStart + 1].start = start + newCharCount;
+                styles[modifyStart].length = start - styles[modifyStart].start;
+                styleCount++;
+                modifyEnd += 2;
+            }
+            if (offset !is 0) {
+                for (int i = modifyEnd; i < styleCount; i++) {
+                    styles[i].start += offset;
+                }
+            }
+        } else {
+            if (styles[modifyStart].start < start && start < styles[modifyStart].start + styles[modifyStart].length) {
+                styles[modifyStart].length = start - styles[modifyStart].start;
+                modifyStart++;
+            }
+            if (modifyEnd < styleCount && styles[modifyEnd].start < end && end < styles[modifyEnd].start + styles[modifyEnd].length) {
+                styles[modifyEnd].length = styles[modifyEnd].start + styles[modifyEnd].length - end;
+                styles[modifyEnd].start = end;
+            }
+            if (offset !is 0) {
+                for (int i = modifyEnd; i < styleCount; i++) {
+                    styles[i].start += offset;
+                }
+            }
+            System.arraycopy(styles, modifyEnd, styles, modifyStart, styleCount - modifyEnd);
+            styleCount -= modifyEnd - modifyStart;
+        }
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableCursor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,789 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TableCursor;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * A TableCursor provides a way for the user to navigate around a Table
+ * using the keyboard.  It also provides a mechanism for selecting an
+ * individual cell in a table.
+ *
+ * <p> Here is an example of using a TableCursor to navigate to a cell and then edit it.
+ *
+ * <code><pre>
+ *  public static void main(String[] args) {
+ *      Display display = new Display();
+ *      Shell shell = new Shell(display);
+ *      shell.setLayout(new GridLayout());
+ *
+ *      // create a a table with 3 columns and fill with data
+ *      final Table table = new Table(shell, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
+ *      table.setLayoutData(new GridData(GridData.FILL_BOTH));
+ *      TableColumn column1 = new TableColumn(table, SWT.NONE);
+ *      TableColumn column2 = new TableColumn(table, SWT.NONE);
+ *      TableColumn column3 = new TableColumn(table, SWT.NONE);
+ *      for (int i = 0; i &lt; 100; i++) {
+ *          TableItem item = new TableItem(table, SWT.NONE);
+ *          item.setText(new String[] { "cell "+i+" 0", "cell "+i+" 1", "cell "+i+" 2"});
+ *      }
+ *      column1.pack();
+ *      column2.pack();
+ *      column3.pack();
+ *
+ *      // create a TableCursor to navigate around the table
+ *      final TableCursor cursor = new TableCursor(table, SWT.NONE);
+ *      // create an editor to edit the cell when the user hits "ENTER"
+ *      // while over a cell in the table
+ *      final ControlEditor editor = new ControlEditor(cursor);
+ *      editor.grabHorizontal = true;
+ *      editor.grabVertical = true;
+ *
+ *      cursor.addSelectionListener(new SelectionAdapter() {
+ *          // when the TableEditor is over a cell, select the corresponding row in
+ *          // the table
+ *          public void widgetSelected(SelectionEvent e) {
+ *              table.setSelection(new TableItem[] {cursor.getRow()});
+ *          }
+ *          // when the user hits "ENTER" in the TableCursor, pop up a text editor so that
+ *          // they can change the text of the cell
+ *          public void widgetDefaultSelected(SelectionEvent e){
+ *              final Text text = new Text(cursor, SWT.NONE);
+ *              TableItem row = cursor.getRow();
+ *              int column = cursor.getColumn();
+ *              text.setText(row.getText(column));
+ *              text.addKeyListener(new KeyAdapter() {
+ *                  public void keyPressed(KeyEvent e) {
+ *                      // close the text editor and copy the data over
+ *                      // when the user hits "ENTER"
+ *                      if (e.character is SWT.CR) {
+ *                          TableItem row = cursor.getRow();
+ *                          int column = cursor.getColumn();
+ *                          row.setText(column, text.getText());
+ *                          text.dispose();
+ *                      }
+ *                      // close the text editor when the user hits "ESC"
+ *                      if (e.character is SWT.ESC) {
+ *                          text.dispose();
+ *                      }
+ *                  }
+ *              });
+ *              editor.setEditor(text);
+ *              text.setFocus();
+ *          }
+ *      });
+ *      // Hide the TableCursor when the user hits the "MOD1" or "MOD2" key.
+ *      // This allows the user to select multiple items in the table.
+ *      cursor.addKeyListener(new KeyAdapter() {
+ *          public void keyPressed(KeyEvent e) {
+ *              if (e.keyCode is SWT.MOD1 ||
+ *                  e.keyCode is SWT.MOD2 ||
+ *                  (e.stateMask & SWT.MOD1) !is 0 ||
+ *                  (e.stateMask & SWT.MOD2) !is 0) {
+ *                  cursor.setVisible(false);
+ *              }
+ *          }
+ *      });
+ *      // Show the TableCursor when the user releases the "MOD2" or "MOD1" key.
+ *      // This signals the end of the multiple selection task.
+ *      table.addKeyListener(new KeyAdapter() {
+ *          public void keyReleased(KeyEvent e) {
+ *              if (e.keyCode is SWT.MOD1 && (e.stateMask & SWT.MOD2) !is 0) return;
+ *              if (e.keyCode is SWT.MOD2 && (e.stateMask & SWT.MOD1) !is 0) return;
+ *              if (e.keyCode !is SWT.MOD1 && (e.stateMask & SWT.MOD1) !is 0) return;
+ *              if (e.keyCode !is SWT.MOD2 && (e.stateMask & SWT.MOD2) !is 0) return;
+ *
+ *              TableItem[] selection = table.getSelection();
+ *              TableItem row = (selection.length is 0) ? table.getItem(table.getTopIndex()) : selection[0];
+ *              table.showItem(row);
+ *              cursor.setSelection(row, 0);
+ *              cursor.setVisible(true);
+ *              cursor.setFocus();
+ *          }
+ *      });
+ *
+ *      shell.open();
+ *      while (!shell.isDisposed()) {
+ *          if (!display.readAndDispatch())
+ *              display.sleep();
+ *      }
+ *      display.dispose();
+ *  }
+ * </pre></code>
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection</dd>
+ * </dl>
+ *
+ * @since 2.0
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tablecursor">TableCursor snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 
+ */
+public class TableCursor : Canvas {
+
+    alias Canvas.dispose dispose;
+
+    Table table;
+    TableItem row = null;
+    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 = SWT.COLOR_LIST_SELECTION_TEXT;
+    static final int FOREGROUND = SWT.COLOR_LIST_SELECTION;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * table and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a Table control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see Widget#checkSubclass()
+ * @see Widget#getStyle()
+ */
+public this(Table parent, int style) {
+    super(parent, style);
+    table = parent;
+    setBackground(null);
+    setForeground(null);
+
+    Listener listener = new class() Listener {
+        public void handleEvent(Event event) {
+            switch (event.type) {
+                case SWT.Dispose :
+                    dispose(event);
+                    break;
+                case SWT.FocusIn :
+                case SWT.FocusOut :
+                    redraw();
+                    break;
+                case SWT.KeyDown :
+                    keyDown(event);
+                    break;
+                case SWT.Paint :
+                    paint(event);
+                    break;
+                case SWT.Traverse : {
+                    event.doit = true;
+                    switch (event.detail) {
+                        case SWT.TRAVERSE_ARROW_NEXT :
+                        case SWT.TRAVERSE_ARROW_PREVIOUS :
+                        case SWT.TRAVERSE_RETURN :
+                            event.doit = false;
+                            break;
+                        default:
+                    }
+                    break;
+                }
+                default:
+            }
+        }
+    };
+    int[] events = [SWT.Dispose, SWT.FocusIn, SWT.FocusOut, SWT.KeyDown, SWT.Paint, SWT.Traverse];
+    for (int i = 0; i < events.length; i++) {
+        addListener(events[i], listener);
+    }
+
+    tableListener = new class() Listener {
+        public void handleEvent(Event event) {
+            switch (event.type) {
+                case SWT.MouseDown :
+                    tableMouseDown(event);
+                    break;
+                case SWT.FocusIn :
+                    tableFocusIn(event);
+                    break;
+                default:
+            }
+        }
+    };
+    table.addListener(SWT.FocusIn, tableListener);
+    table.addListener(SWT.MouseDown, tableListener);
+
+    disposeItemListener = new class() Listener {
+        public void handleEvent(Event event) {
+            unhookRowColumnListeners();
+            row = null;
+            column = null;
+            _resize();
+        }
+    };
+    disposeColumnListener = new class() Listener {
+        public void handleEvent(Event event) {
+            unhookRowColumnListeners();
+            row = null;
+            column = null;
+            _resize();
+        }
+    };
+    resizeListener = new class() Listener {
+        public void handleEvent(Event event) {
+            _resize();
+        }
+    };
+    ScrollBar hBar = table.getHorizontalBar();
+    if (hBar !is null) {
+        hBar.addListener(SWT.Selection, resizeListener);
+    }
+    ScrollBar vBar = table.getVerticalBar();
+    if (vBar !is null) {
+        vBar.addListener(SWT.Selection, resizeListener);
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has <code>SWT.CHECK</code> style set and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see SelectionEvent
+ * @see #removeSelectionListener(SelectionListener)
+ *
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null)
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener(SWT.Selection, typedListener);
+    addListener(SWT.DefaultSelection, typedListener);
+}
+
+void dispose(Event event) {
+    table.removeListener(SWT.FocusIn, tableListener);
+    table.removeListener(SWT.MouseDown, tableListener);
+    unhookRowColumnListeners();
+    ScrollBar hBar = table.getHorizontalBar();
+    if (hBar !is null) {
+        hBar.removeListener(SWT.Selection, resizeListener);
+    }
+    ScrollBar vBar = table.getVerticalBar();
+    if (vBar !is null) {
+        vBar.removeListener(SWT.Selection, resizeListener);
+    }
+}
+
+void keyDown(Event event) {
+    if (row is null) return;
+    switch (event.character) {
+        case SWT.CR :
+            notifyListeners(SWT.DefaultSelection, new Event());
+            return;
+        default:
+    }
+    int rowIndex = table.indexOf(row);
+    int columnIndex = column is null ? 0 : table.indexOf(column);
+    switch (event.keyCode) {
+        case SWT.ARROW_UP :
+            setRowColumn(Math.max(0, rowIndex - 1), columnIndex, true);
+            break;
+        case SWT.ARROW_DOWN :
+            setRowColumn(Math.min(rowIndex + 1, table.getItemCount() - 1), columnIndex, true);
+            break;
+        case SWT.ARROW_LEFT :
+        case SWT.ARROW_RIGHT :
+            {
+                int columnCount = table.getColumnCount();
+                if (columnCount is 0) break;
+                int[] order = table.getColumnOrder();
+                int index = 0;
+                while (index < order.length) {
+                    if (order[index] is columnIndex) break;
+                    index++;
+                }
+                if (index is order.length) index = 0;
+                int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) !is 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+                if (event.keyCode is leadKey) {
+                   setRowColumn(rowIndex, order[Math.max(0, index - 1)], true);
+                } else {
+                   setRowColumn(rowIndex, order[Math.min(columnCount - 1, index + 1)], true);
+                }
+                break;
+            }
+        case SWT.HOME :
+            setRowColumn(0, columnIndex, true);
+            break;
+        case SWT.END :
+            {
+                int i = table.getItemCount() - 1;
+                setRowColumn(i, columnIndex, true);
+                break;
+            }
+        case SWT.PAGE_UP :
+            {
+                int index = table.getTopIndex();
+                if (index is rowIndex) {
+                    Rectangle rect = table.getClientArea();
+                    TableItem item = table.getItem(index);
+                    Rectangle itemRect = item.getBounds(0);
+                    rect.height -= itemRect.y;
+                    int height = table.getItemHeight();
+                    int page = Math.max(1, rect.height / height);
+                    index = Math.max(0, index - page + 1);
+                }
+                setRowColumn(index, columnIndex, true);
+                break;
+            }
+        case SWT.PAGE_DOWN :
+            {
+                int index = table.getTopIndex();
+                Rectangle rect = table.getClientArea();
+                TableItem item = table.getItem(index);
+                Rectangle itemRect = item.getBounds(0);
+                rect.height -= itemRect.y;
+                int height = table.getItemHeight();
+                int page = Math.max(1, rect.height / height);
+                int end = table.getItemCount() - 1;
+                index = Math.min(end, index + page - 1);
+                if (index is rowIndex) {
+                    index = Math.min(end, index + page - 1);
+                }
+                setRowColumn(index, columnIndex, true);
+                break;
+            }
+        default:
+    }
+}
+
+void paint(Event event) {
+    if (row is null) return;
+    int columnIndex = column is null ? 0 : table.indexOf(column);
+    GC gc = event.gc;
+    Display display = getDisplay();
+    gc.setBackground(getBackground());
+    gc.setForeground(getForeground());
+    gc.fillRectangle(event.x, event.y, event.width, event.height);
+    int x = 0;
+    Point size = getSize();
+    Image image = row.getImage(columnIndex);
+    if (image !is null) {
+        Rectangle imageSize = image.getBounds();
+        int imageY = (size.y - imageSize.height) / 2;
+        gc.drawImage(image, x, imageY);
+        x += imageSize.width;
+    }
+    String text = row.getText(columnIndex);
+    if (text.length > 0) {
+        Rectangle bounds = row.getBounds(columnIndex);
+        Point extent = gc.stringExtent(text);
+        // Temporary code - need a better way to determine table trim
+        String platform = SWT.getPlatform();
+        if ("win32"==platform) { //$NON-NLS-1$
+            if (table.getColumnCount() is 0 || columnIndex is 0) {
+                x += 2;
+            } else {
+                int alignmnent = column.getAlignment();
+                switch (alignmnent) {
+                    case SWT.LEFT:
+                        x += 6;
+                        break;
+                    case SWT.RIGHT:
+                        x = bounds.width - extent.x - 6;
+                        break;
+                    case SWT.CENTER:
+                        x += (bounds.width - x - extent.x) / 2;
+                        break;
+                    default:
+                }
+            }
+        }  else {
+            if (table.getColumnCount() is 0) {
+                x += 5;
+            } else {
+                int alignmnent = column.getAlignment();
+                switch (alignmnent) {
+                    case SWT.LEFT:
+                        x += 5;
+                        break;
+                    case SWT.RIGHT:
+                        x = bounds.width- extent.x - 2;
+                        break;
+                    case SWT.CENTER:
+                        x += (bounds.width - x - extent.x) / 2 + 2;
+                        break;
+                    default:
+                }
+            }
+        }
+        int textY = (size.y - extent.y) / 2;
+        gc.drawString(text, x, textY);
+    }
+    if (isFocusControl()) {
+        gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+        gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
+        gc.drawFocus(0, 0, size.x, size.y);
+    }
+}
+
+void tableFocusIn(Event event) {
+    if (isDisposed()) return;
+    if (isVisible()) {
+        if (row is null && column is null) return;
+        setFocus();
+    }
+}
+
+void tableMouseDown(Event event) {
+    if (isDisposed() || !isVisible()) return;
+    Point pt = new Point(event.x, event.y);
+    int lineWidth = table.getLinesVisible() ? table.getGridLineWidth() : 0;
+    TableItem item = table.getItem(pt);
+    if ((table.getStyle() & SWT.FULL_SELECTION) !is 0) {
+        if (item is null) return;
+    } else {
+        int start = item !is null ? table.indexOf(item) : table.getTopIndex();
+        int end = table.getItemCount();
+        Rectangle clientRect = table.getClientArea();
+        for (int i = start; i < end; i++) {
+            TableItem nextItem = table.getItem(i);
+            Rectangle rect = nextItem.getBounds(0);
+            if (pt.y >= rect.y && pt.y < rect.y + rect.height + lineWidth) {
+                item = nextItem;
+                break;
+            }
+            if (rect.y > clientRect.y + clientRect.height)  return;
+        }
+        if (item is null) return;
+    }
+    TableColumn newColumn = null;
+    int columnCount = table.getColumnCount();
+    if (columnCount is 0) {
+        if ((table.getStyle() & SWT.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;
+            rect.height += lineWidth;
+            if (rect.contains(pt)) {
+                newColumn = table.getColumn(i);
+                break;
+            }
+        }
+        if (newColumn is null) {
+            if ((table.getStyle() & SWT.FULL_SELECTION) is 0) return;
+            newColumn = table.getColumn(0);
+        }
+    }
+    setRowColumn(item, newColumn, true);
+    setFocus();
+    return;
+}
+void setRowColumn(int row, int column, bool notify) {
+    TableItem item = row is -1 ? null : table.getItem(row);
+    TableColumn col = column is -1 || table.getColumnCount() is 0 ? null : table.getColumn(column);
+    setRowColumn(item, col, notify);
+}
+void setRowColumn(TableItem row, TableColumn column, bool notify) {
+    if (this.row is row && this.column is column) {
+        return;
+    }
+    if (this.row !is null && this.row !is row) {
+        this.row.removeListener(SWT.Dispose, disposeItemListener);
+        this.row = null;
+    }
+    if (this.column !is null && this.column !is column) {
+        this.column.removeListener(SWT.Dispose, disposeColumnListener);
+        this.column.removeListener(SWT.Move, resizeListener);
+        this.column.removeListener(SWT.Resize, resizeListener);
+        this.column = null;
+    }
+    if (row !is null) {
+        if (this.row !is row) {
+            this.row = row;
+            row.addListener(SWT.Dispose, disposeItemListener);
+            table.showItem(row);
+        }
+        if (this.column !is column && column !is null) {
+            this.column = column;
+            column.addListener(SWT.Dispose, disposeColumnListener);
+            column.addListener(SWT.Move, resizeListener);
+            column.addListener(SWT.Resize, resizeListener);
+            table.showColumn(column);
+        }
+        int columnIndex = column is null ? 0 : table.indexOf(column);
+        setBounds(row.getBounds(columnIndex));
+        redraw();
+        if (notify) {
+            notifyListeners(SWT.Selection, new Event());
+        }
+    }
+}
+
+public override void setVisible(bool visible) {
+    checkWidget();
+    if (visible) _resize();
+    super.setVisible(visible);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ *
+ * @since 3.0
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) {
+        SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    }
+    removeListener(SWT.Selection, listener);
+    removeListener(SWT.DefaultSelection, listener);
+}
+
+void _resize() {
+    if (row is null) {
+        setBounds(-200, -200, 0, 0);
+    } else {
+        int columnIndex = column is null ? 0 : table.indexOf(column);
+        setBounds(row.getBounds(columnIndex));
+    }
+}
+/**
+ * Returns the column over which the TableCursor is positioned.
+ *
+ * @return the column for the current position
+ *
+ * @exception SWTException <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 int getColumn() {
+    checkWidget();
+    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
+ *
+ * @exception SWTException <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 TableItem getRow() {
+    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 SWTException <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) {
+    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 SWTException <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) {
+    foreground = color;
+    super.setForeground(getForeground());
+    redraw();
+}
+/**
+ * Positions the TableCursor over the cell at the given row and column in the parent table.
+ *
+ * @param row the index of the row for the cell to select
+ * @param column the index of column for the cell to select
+ *
+ * @exception SWTException <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 setSelection(int row, int column) {
+    checkWidget();
+    int columnCount = table.getColumnCount();
+    int maxColumnIndex =  columnCount is 0 ? 0 : columnCount - 1;
+    if (row < 0
+        || row >= table.getItemCount()
+        || column < 0
+        || column > maxColumnIndex)
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    setRowColumn(row, column, false);
+}
+/**
+ * Positions the TableCursor over the cell at the given row and column in the parent table.
+ *
+ * @param row the TableItem of the row for the cell to select
+ * @param column the index of column for the cell to select
+ *
+ * @exception SWTException <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 setSelection(TableItem row, int column) {
+    checkWidget();
+    int columnCount = table.getColumnCount();
+    int maxColumnIndex =  columnCount is 0 ? 0 : columnCount - 1;
+    if (row is null
+        || row.isDisposed()
+        || column < 0
+        || column > maxColumnIndex)
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    setRowColumn(table.indexOf(row), column, false);
+}
+void unhookRowColumnListeners() {
+    if (column !is null) {
+        column.removeListener(SWT.Dispose, disposeColumnListener);
+        column.removeListener(SWT.Move, resizeListener);
+        column.removeListener(SWT.Resize, resizeListener);
+        column = null;
+    }
+    if (row !is null) {
+        row.removeListener(SWT.Dispose, disposeItemListener);
+        row = null;
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableEditor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TableEditor;
+
+import java.lang.all;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.custom.ControlEditor;
+import java.lang.Runnable;
+
+/**
+*
+* A TableEditor is a manager for a Control that appears above a cell in a Table and tracks with the
+* moving and resizing of that cell.  It can be used to display a text widget above a cell
+* in a Table so that the user can edit the contents of that cell.  It can also be used to display
+* a button that can launch a dialog for modifying the contents of the associated cell.
+*
+* <p> Here is an example of using a TableEditor:
+* <code><pre>
+*   final Table table = new Table(shell, SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
+*   TableColumn column1 = new TableColumn(table, SWT.NONE);
+*   TableColumn column2 = new TableColumn(table, SWT.NONE);
+*   for (int i = 0; i &lt; 10; i++) {
+*       TableItem item = new TableItem(table, SWT.NONE);
+*       item.setText(new String[] {"item " + i, "edit this value"});
+*   }
+*   column1.pack();
+*   column2.pack();
+*
+*   final TableEditor editor = new TableEditor(table);
+*   //The editor must have the same size as the cell and must
+*   //not be any smaller than 50 pixels.
+*   editor.horizontalAlignment = SWT.LEFT;
+*   editor.grabHorizontal = true;
+*   editor.minimumWidth = 50;
+*   // editing the second column
+*   final int EDITABLECOLUMN = 1;
+*
+*   table.addSelectionListener(new SelectionAdapter() {
+*       public void widgetSelected(SelectionEvent e) {
+*           // Clean up any previous editor control
+*           Control oldEditor = editor.getEditor();
+*           if (oldEditor !is null) oldEditor.dispose();
+*
+*           // Identify the selected row
+*           TableItem item = (TableItem)e.item;
+*           if (item is null) return;
+*
+*           // The control that will be the editor must be a child of the Table
+*           Text newEditor = new Text(table, SWT.NONE);
+*           newEditor.setText(item.getText(EDITABLECOLUMN));
+*           newEditor.addModifyListener(new ModifyListener() {
+*               public void modifyText(ModifyEvent e) {
+*                   Text text = (Text)editor.getEditor();
+*                   editor.getItem().setText(EDITABLECOLUMN, text.getText());
+*               }
+*           });
+*           newEditor.selectAll();
+*           newEditor.setFocus();
+*           editor.setEditor(newEditor, item, EDITABLECOLUMN);
+*       }
+*   });
+* </pre></code>
+*
+* @see <a href="http://www.eclipse.org/swt/snippets/#tableeditor">TableEditor snippets</a>
+* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+*/
+public class TableEditor : ControlEditor {
+    Table table;
+    TableItem item;
+    int column = -1;
+    ControlListener columnListener;
+    Runnable timer;
+    static final int TIMEOUT = 1500;
+/**
+* Creates a TableEditor for the specified Table.
+*
+* @param table the Table Control above which this editor will be displayed
+*
+*/
+public this (Table table) {
+    super(table);
+    this.table = table;
+
+    columnListener = new class() ControlListener {
+        public void controlMoved(ControlEvent e){
+            layout ();
+        }
+        public void controlResized(ControlEvent e){
+            layout ();
+        }
+    };
+    timer = new class() Runnable {
+        public void run() {
+            layout ();
+        }
+    };
+
+    // To be consistent with older versions of SWT, grabVertical defaults to true
+    grabVertical = true;
+}
+override Rectangle computeBounds () {
+    if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0);
+    Rectangle cell = item.getBounds(column);
+    Rectangle rect = item.getImageBounds(column);
+    cell.x = rect.x + rect.width;
+    cell.width -= rect.width;
+    Rectangle area = table.getClientArea();
+    if (cell.x < area.x + area.width) {
+        if (cell.x + cell.width > area.x + area.width) {
+            cell.width = area.x + area.width - cell.x;
+        }
+    }
+    Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+    if (grabHorizontal) {
+        editorRect.width = Math.max(cell.width, minimumWidth);
+    }
+
+    if (grabVertical) {
+        editorRect.height = Math.max(cell.height, minimumHeight);
+    }
+
+    if (horizontalAlignment is SWT.RIGHT) {
+        editorRect.x += cell.width - editorRect.width;
+    } else if (horizontalAlignment is SWT.LEFT) {
+        // do nothing - cell.x is the right answer
+    } else { // default is CENTER
+        editorRect.x += (cell.width - editorRect.width)/2;
+    }
+
+    if (verticalAlignment is SWT.BOTTOM) {
+        editorRect.y += cell.height - editorRect.height;
+    } else if (verticalAlignment is SWT.TOP) {
+        // do nothing - cell.y is the right answer
+    } else { // default is CENTER
+        editorRect.y += (cell.height - editorRect.height)/2;
+    }
+    return editorRect;
+}
+/**
+ * Removes all associations between the TableEditor and the cell in the table.  The
+ * Table and the editor Control are <b>not</b> disposed.
+ */
+public override void dispose () {
+    if (table !is null && !table.isDisposed()) {
+        if (this.column > -1 && this.column < table.getColumnCount()){
+            TableColumn tableColumn = table.getColumn(this.column);
+            tableColumn.removeControlListener(columnListener);
+        }
+    }
+    columnListener = null;
+    table = null;
+    item = null;
+    column = -1;
+    timer = null;
+    super.dispose();
+}
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*/
+public int getColumn () {
+    return column;
+}
+/**
+* Returns the TableItem for the row of the cell being tracked by this editor.
+*
+* @return the TableItem for the row of the cell being tracked by this editor
+*/
+public TableItem getItem () {
+    return item;
+}
+void resize () {
+    layout();
+    /*
+     * On some platforms, the table scrolls when an item that
+     * is partially visible at the bottom of the table is
+     * selected.  Ensure that the correct row is edited by
+     * laying out one more time in a timerExec().
+     */
+    if (table !is null) {
+        Display display = table.getDisplay();
+        display.timerExec(-1, timer);
+        display.timerExec(TIMEOUT, timer);
+    }
+}
+/**
+* Sets the zero based index of the column of the cell being tracked by this editor.
+*
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+public void setColumn(int column) {
+    int columnCount = table.getColumnCount();
+    // Separately handle the case where the table has no TableColumns.
+    // In this situation, there is a single default column.
+    if (columnCount is 0) {
+        this.column = (column is 0) ? 0 : -1;
+        resize();
+        return;
+    }
+    if (this.column > -1 && this.column < columnCount){
+        TableColumn tableColumn = table.getColumn(this.column);
+        tableColumn.removeControlListener(columnListener);
+        this.column = -1;
+    }
+
+    if (column < 0  || column >= table.getColumnCount()) return;
+
+    this.column = column;
+    TableColumn tableColumn = table.getColumn(this.column);
+    tableColumn.addControlListener(columnListener);
+    resize();
+}
+/**
+* Specifies the <code>TableItem</code> that is to be edited.
+*
+* @param item the item to be edited
+*/
+public void setItem (TableItem item) {
+    this.item = item;
+    resize();
+}
+public override void setEditor (Control editor) {
+    super.setEditor(editor);
+    resize();
+}
+/**
+* Specify the Control that is to be displayed and the cell in the table that it is to be positioned above.
+*
+* <p>Note: The Control provided as the editor <b>must</b> be created with its parent being the Table control
+* specified in the TableEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TableItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+public void setEditor (Control editor, TableItem item, int column) {
+    setItem(item);
+    setColumn(column);
+    setEditor(editor);
+}
+public override void layout () {
+    if (table is null || table.isDisposed()) return;
+    if (item is null || item.isDisposed()) return;
+    int columnCount = table.getColumnCount();
+    if (columnCount is 0 && column !is 0) return;
+    if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+    super.layout();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTree.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,842 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TableTree;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.custom.TableTreeItem;
+import java.lang.all;
+
+/**
+ * A TableTree is a selectable user interface object
+ * that displays a hierarchy of items, and issues
+ * notification when an item is selected.
+ * A TableTree may be single or multi select.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TableTreeItem</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.
+ * </p><p>
+ * <dl>
+ *  <dt><b>Styles:</b> <dd> SINGLE, MULTI, CHECK, FULL_SELECTION
+ *  <dt><b>Events:</b> <dd> Selection, DefaultSelection, Collapse, Expand
+ * </dl>
+ * <p>
+ * Note: Only one of the styles SINGLE, and MULTI may be specified.
+ * </p>
+ *
+ * @deprecated As of 3.1 use Tree, TreeItem and TreeColumn
+ */
+public class TableTree : Composite {
+
+    alias Composite.computeSize computeSize;
+
+    Table table;
+    TableTreeItem[] items;
+    Image plusImage, minusImage, sizeImage;
+
+    /*
+    * TableTreeItems are not treated as children but rather as items.
+    * When the TableTree is disposed, all children are disposed because
+    * TableTree inherits this behaviour from Composite.  The items
+    * must be disposed separately.  Because TableTree is not part of
+    * the org.eclipse.swt.widgets module, the method releaseWidget can
+    * not be overridden (this is how items are disposed of in Table and Tree).
+    * Instead, the items are disposed of in response to the dispose event on the
+    * TableTree.  The "inDispose" flag is used to distinguish between disposing
+    * one TableTreeItem (e.g. when removing an entry from the TableTree) and
+    * disposing the entire TableTree.
+    */
+    bool inDispose = false;
+
+    static final TableTreeItem[] EMPTY_ITEMS;
+    static final String[] EMPTY_TEXTS;
+    static final Image[] EMPTY_IMAGES;
+    static final String ITEMID = "TableTreeItemID"; //$NON-NLS-1$
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see #getStyle
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle (style));
+    items = EMPTY_ITEMS;
+    table = new Table(this, style);
+    Listener tableListener = new class() Listener {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+            case SWT.MouseDown: onMouseDown(e); break;
+            case SWT.Selection: onSelection(e); break;
+            case SWT.DefaultSelection: onSelection(e); break;
+            case SWT.KeyDown: onKeyDown(e); break;
+            default:
+            }
+        }
+    };
+    int[] tableEvents = [SWT.MouseDown,
+                                   SWT.Selection,
+                                   SWT.DefaultSelection,
+                                   SWT.KeyDown];
+    for (int i = 0; i < tableEvents.length; i++) {
+        table.addListener(tableEvents[i], tableListener);
+    }
+
+    Listener listener = new class() Listener {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+            case SWT.Dispose: onDispose(e); break;
+            case SWT.Resize:  onResize(e); break;
+            case SWT.FocusIn: onFocusIn(e); break;
+            default:
+            }
+        }
+    };
+    int[] events = [SWT.Dispose,
+                              SWT.Resize,
+                              SWT.FocusIn];
+    for (int i = 0; i < events.length; i++) {
+        addListener(events[i], listener);
+    }
+}
+
+int addItem(TableTreeItem item, int index) {
+    if (index < 0 || index > items.length) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    TableTreeItem[] newItems = new TableTreeItem[items.length + 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    newItems[index] = item;
+    System.arraycopy(items, index, newItems, index + 1, items.length - index);
+    items = newItems;
+
+    /* Return the index in the table where this table should be inserted */
+    if (index is items.length - 1 )
+        return table.getItemCount();
+    else
+        return table.indexOf(items[index+1].tableItem);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has <code>SWT.CHECK</code> style set and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the <code>TreeListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TreeListener
+ * @see #removeTreeListener
+ */
+public void addTreeListener(TreeListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Expand, typedListener);
+    addListener (SWT.Collapse, typedListener);
+}
+private static int checkStyle (int style) {
+    int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    style = style & mask;
+    return style;
+}
+public override Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget();
+    return table.computeSize (wHint, hHint, changed);
+}
+public override Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget();
+    return table.computeTrim(x, y, width, height);
+}
+
+/**
+ * Deselects all items.
+ * <p>
+ * If an item is selected, it is deselected.
+ * If an item is not selected, it remains unselected.
+ *
+ * @exception SWTException <ul>
+ *  <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *  <li>ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * </ul>
+ */
+public void deselectAll () {
+    checkWidget();
+    table.deselectAll();
+}
+
+/* Expand upward from the specified leaf item. */
+void expandItem (TableTreeItem item) {
+    if (item is null) return;
+    expandItem(item.parentItem);
+    if (!item.getVisible()) item.setVisible(true);
+    if ( !item.expanded && item.items.length > 0) {
+        item.setExpanded(true);
+        Event event = new Event();
+        event.item = item;
+        notifyListeners(SWT.Expand, event);
+    }
+}
+public override Color getBackground () {
+    // This method must be overridden otherwise, in a TableTree in which the first
+    // item has no sub items, a grey (Widget background colour) square will appear in
+    // the first column of the first item.
+    // It is not possible in the constructor to set the background of the TableTree
+    // to be the same as the background of the Table because this interferes with
+    // the TableTree adapting to changes in the System color settings.
+    return table.getBackground();
+}
+public override Rectangle getClientArea () {
+    return table.getClientArea();
+}
+public override Color getForeground () {
+    return table.getForeground();
+}
+public override Font getFont () {
+    return table.getFont();
+}
+/**
+ * Gets the number of items.
+ * <p>
+ * @return the number of items in the widget
+ */
+public int getItemCount () {
+    //checkWidget();
+    return items.length;
+}
+
+/**
+ * Gets the height of one item.
+ * <p>
+ * This operation will fail if the height of
+ * one item could not be queried from the OS.
+ *
+ * @return the height of one item in the widget
+ *
+ * @exception SWTException <ul>
+ *  <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *  <li>ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * </ul>
+ */
+public int getItemHeight () {
+    checkWidget();
+    return table.getItemHeight();
+}
+
+/**
+ * Gets the items.
+ * <p>
+ * @return the items in the widget
+ */
+public TableTreeItem [] getItems () {
+    //checkWidget();
+    TableTreeItem[] newItems = new TableTreeItem[items.length];
+    System.arraycopy(items, 0, newItems, 0, items.length);
+    return newItems;
+}
+
+/**
+ * Gets the selected items.
+ * <p>
+ * This operation will fail if the selected
+ * items cannot be queried from the OS.
+ *
+ * @return the selected items in the widget
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public TableTreeItem [] getSelection () {
+    checkWidget();
+    TableItem[] selection = table.getSelection();
+    TableTreeItem [] result = new TableTreeItem[selection.length];
+    for (int i = 0; i < selection.length; i++){
+        result[i] = cast(TableTreeItem) selection[i].getData(ITEMID);
+    }
+    return result;
+}
+
+/**
+ * Gets the number of selected items.
+ * <p>
+ * This operation will fail if the number of selected
+ * items cannot be queried from the OS.
+ *
+ * @return the number of selected items in the widget
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public int getSelectionCount () {
+    checkWidget();
+    return table.getSelectionCount();
+}
+
+public override int getStyle () {
+    checkWidget();
+    return table.getStyle();
+}
+
+/**
+ * Returns the underlying Table control.
+ *
+ * @return the underlying Table control
+ */
+public Table getTable () {
+    //checkWidget();
+    return table;
+}
+
+void createImages () {
+
+    int itemHeight = sizeImage.getBounds().height;
+    // Calculate border around image.
+    // At least 9 pixels are needed to draw the image
+    // Leave at least a 6 pixel border.
+    int indent = Math.min(6, (itemHeight - 9) / 2);
+    indent = Math.max(0, indent);
+    int size = Math.max (10, itemHeight - 2 * indent);
+    size = ((size + 1) / 2) * 2; // size must be an even number
+    int midpoint = indent + size / 2;
+
+    Color foreground = getForeground();
+    Color plusMinus = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+    Color background = getBackground();
+
+    /* Plus image */
+    PaletteData palette = new PaletteData( [ foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]);
+    ImageData imageData = new ImageData(itemHeight, itemHeight, 4, palette);
+    imageData.transparentPixel = 1;
+    plusImage = new Image(getDisplay(), imageData);
+    GC gc = new GC(plusImage);
+    gc.setBackground(background);
+    gc.fillRectangle(0, 0, itemHeight, itemHeight);
+    gc.setForeground(plusMinus);
+    gc.drawRectangle(indent, indent, size, size);
+    gc.setForeground(foreground);
+    gc.drawLine(midpoint, indent + 2, midpoint, indent + size - 2);
+    gc.drawLine(indent + 2, midpoint, indent + size - 2, midpoint);
+    gc.dispose();
+
+    /* Minus image */
+    palette = new PaletteData([foreground.getRGB(), background.getRGB(), plusMinus.getRGB()]);
+    imageData = new ImageData(itemHeight, itemHeight, 4, palette);
+    imageData.transparentPixel = 1;
+    minusImage = new Image(getDisplay(), imageData);
+    gc = new GC(minusImage);
+    gc.setBackground(background);
+    gc.fillRectangle(0, 0, itemHeight, itemHeight);
+    gc.setForeground(plusMinus);
+    gc.drawRectangle(indent, indent, size, size);
+    gc.setForeground(foreground);
+    gc.drawLine(indent + 2, midpoint, indent + size - 2, midpoint);
+    gc.dispose();
+}
+
+Image getPlusImage() {
+    if (plusImage is null) createImages();
+    return plusImage;
+}
+
+Image getMinusImage() {
+    if (minusImage is null) createImages();
+    return minusImage;
+}
+
+/**
+ * Gets the index of an item.
+ *
+ * <p>The widget is searched starting at 0 until an
+ * item is found that is equal to the search item.
+ * If no item is found, -1 is returned.  Indexing
+ * is zero based.  This index is relative to the parent only.
+ *
+ * @param item the search item
+ * @return the index of the item or -1
+ */
+public int indexOf (TableTreeItem item) {
+    //checkWidget();
+    for (int i = 0; i < items.length; i++) {
+        if (item is items[i]) return i;
+    }
+    return -1;
+}
+
+void onDispose(Event e) {
+    /*
+     * Usually when an item is disposed, destroyItem will change the size of the items array
+     * and dispose of the underlying table items.
+     * Since the whole table tree is being disposed, this is not necessary.  For speed
+     * the inDispose flag is used to skip over this part of the item dispose.
+     */
+    inDispose = true;
+    for (int i = 0; i < items.length; i++) {
+        items[i].dispose();
+    }
+    inDispose = false;
+    if (plusImage !is null) plusImage.dispose();
+    if (minusImage !is null) minusImage.dispose();
+    if (sizeImage !is null) sizeImage.dispose();
+    plusImage = minusImage = sizeImage = null;
+}
+
+void onResize(Event e) {
+    Point size = getSize();
+    table.setBounds(0, 0, size.x, size.y);
+}
+
+void onSelection(Event e) {
+    Event event = new Event();
+    TableItem tableItem = cast(TableItem)e.item;
+    TableTreeItem item = getItem(tableItem);
+    event.item = item;
+
+    if (e.type is SWT.Selection && e.detail is SWT.CHECK && item !is null) {
+        event.detail = SWT.CHECK;
+        item.checked = tableItem.getChecked();
+    }
+    notifyListeners(e.type, event);
+}
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public TableTreeItem getItem (int index) {
+    checkWidget();
+    int count = items.length;
+    if (!(0 <= index && index < count)) SWT.error (SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+
+/**
+ * Returns the 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 item at the given point
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 TableTreeItem getItem(Point point) {
+    checkWidget();
+    TableItem item = table.getItem(point);
+    if (item is null) return null;
+    return getItem(item);
+
+}
+TableTreeItem getItem(TableItem tableItem) {
+    if (tableItem is null) return null;
+    for (int i = 0; i < items.length; i++) {
+            TableTreeItem item = items[i].getItem(tableItem);
+            if (item !is null) return item;
+    }
+    return null;
+}
+void onFocusIn (Event e) {
+    table.setFocus();
+}
+
+void onKeyDown (Event e) {
+    TableTreeItem[] selection = getSelection();
+    if (selection.length is 0) return;
+    TableTreeItem item = selection[0];
+    int type = 0;
+    if (e.keyCode is SWT.ARROW_RIGHT || e.keyCode is SWT.ARROW_LEFT) {
+        int trailKey = (getStyle() & SWT.MIRRORED) !is 0 ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+        if (e.keyCode is trailKey) {
+            if (item.getItemCount() is 0) return;
+            if (item.getExpanded()) {
+                TableTreeItem newSelection = item.getItems()[0];
+                table.setSelection([newSelection.tableItem]);
+                showItem(newSelection);
+                type = SWT.Selection;
+            } else {
+                item.setExpanded(true);
+                type = SWT.Expand;
+            }
+        } else {
+            if (item.getExpanded()) {
+                item.setExpanded(false);
+                type = SWT.Collapse;
+            } else {
+                TableTreeItem parent = item.getParentItem();
+                if (parent !is null) {
+                    int index = parent.indexOf(item);
+                    if (index !is 0) return;
+                    table.setSelection([parent.tableItem]);
+                    type = SWT.Selection;
+                }
+            }
+        }
+    }
+    if (e.character is '*') {
+        item.expandAll(true);
+    }
+    if (e.character is '-') {
+        if (item.getExpanded()) {
+            item.setExpanded(false);
+            type = SWT.Collapse;
+        }
+    }
+    if (e.character is '+') {
+        if (item.getItemCount() > 0 && !item.getExpanded()) {
+            item.setExpanded(true);
+            type = SWT.Expand;
+        }
+    }
+    if (type is 0) return;
+    Event event = new Event();
+    event.item = item;
+    notifyListeners(type, event);
+}
+void onMouseDown(Event event) {
+    /* If user clicked on the [+] or [-], expand or collapse the tree. */
+    TableItem[] items = table.getItems();
+    for (int i = 0; i < items.length; i++) {
+        Rectangle rect = items[i].getImageBounds(0);
+        if (rect.contains(event.x, event.y)) {
+            TableTreeItem item = cast(TableTreeItem) items[i].getData(ITEMID);
+            event = new Event();
+            event.item = item;
+            item.setExpanded(!item.getExpanded());
+            if (item.getExpanded()) {
+                notifyListeners(SWT.Expand, event);
+            } else {
+                notifyListeners(SWT.Collapse, event);
+            }
+            return;
+        }
+    }
+}
+
+/**
+ * Removes all items.
+ * <p>
+ * This operation will fail when an item
+ * could not be removed in the OS.
+ *
+ * @exception SWTException <ul>
+ *  <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *  <li>ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * </ul>
+ */
+public void removeAll () {
+    checkWidget();
+    setRedraw(false);
+    for (int i = items.length - 1; i >= 0; i--) {
+        items[i].dispose();
+    }
+    items = EMPTY_ITEMS;
+    setRedraw(true);
+}
+
+void removeItem(TableTreeItem item) {
+    int index = 0;
+    while (index < items.length && items[index] !is item) index++;
+    if (index is items.length) return;
+    TableTreeItem[] newItems = new TableTreeItem[items.length - 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
+    items = newItems;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Selection, listener);
+    removeListener(SWT.DefaultSelection, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TreeListener
+ * @see #addTreeListener
+ */
+public void removeTreeListener (TreeListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener(SWT.Expand, listener);
+    removeListener(SWT.Collapse, listener);
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ *
+ * @exception SWTException <ul>
+ *  <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *  <li>ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * </ul>
+ */
+public void selectAll () {
+    checkWidget();
+    table.selectAll();
+}
+public override void setBackground (Color color) {
+    super.setBackground(color);
+    table.setBackground(color);
+    if (sizeImage !is null) {
+        GC gc = new GC (sizeImage);
+        gc.setBackground(getBackground());
+        Rectangle size = sizeImage.getBounds();
+        gc.fillRectangle(size);
+        gc.dispose();
+    }
+}
+public override void setEnabled (bool enabled) {
+    super.setEnabled(enabled);
+    table.setEnabled(enabled);
+}
+public override void setFont (Font font) {
+    super.setFont(font);
+    table.setFont(font);
+}
+public override void setForeground (Color color) {
+    super.setForeground(color);
+    table.setForeground(color);
+}
+public override void setMenu (Menu menu) {
+    super.setMenu(menu);
+    table.setMenu(menu);
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the item has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 TableTree#deselectAll()
+ */
+public void setSelection (TableTreeItem[] items) {
+    checkWidget ();
+    // SWT extension: allow null for zero length string
+    //if (items is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    int length = items.length;
+    if (length is 0 || ((table.getStyle() & SWT.SINGLE) !is 0 && length > 1)) {
+        deselectAll();
+        return;
+    }
+    TableItem[] tableItems = new TableItem[length];
+    for (int i = 0; i < length; i++) {
+        if (items[i] is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        if (!items[i].getVisible()) expandItem (items[i]);
+        tableItems[i] = items[i].tableItem;
+    }
+    table.setSelection(tableItems);
+}
+public override void setToolTipText (String string) {
+    super.setToolTipText(string);
+    table.setToolTipText(string);
+}
+
+/**
+ * Shows the item.  If the item is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled
+ * and expanded until the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @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 SWTException <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 TableTree#showSelection()
+ */
+public void showItem (TableTreeItem item) {
+    checkWidget();
+    if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (!item.getVisible()) expandItem (item);
+    TableItem tableItem = item.tableItem;
+    table.showItem(tableItem);
+}
+
+/**
+ * Shows the selection.
+ * <p>
+ * If there is no selection or the selection
+ * is already visible, this method does nothing.
+ * If the selection is scrolled out of view,
+ * the top index of the widget is changed such
+ * that selection becomes visible.
+ *
+ * @exception SWTException <ul>
+ *  <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *  <li>ERROR_WIDGET_DISPOSED when the widget has been disposed
+ * </ul>
+ */
+public void showSelection () {
+    checkWidget();
+    table.showSelection();
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeEditor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TableTreeEditor;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.custom.ControlEditor;
+import org.eclipse.swt.custom.TableTree;
+import org.eclipse.swt.custom.TableTreeItem;
+
+import java.lang.Runnable;
+
+/**
+*
+* A TableTreeEditor is a manager for a Control that appears above a cell in a TableTree
+* and tracks with the moving and resizing of that cell.  It can be used to display a
+* text widget above a cell in a TableTree so that the user can edit the contents of
+* that cell.  It can also be used to display a button that can launch a dialog for
+* modifying the contents of the associated cell.
+*
+* <p> Here is an example of using a TableTreeEditor:
+* <code><pre>
+*   final TableTree tableTree = new TableTree(shell, SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
+*   final Table table = tableTree.getTable();
+*   TableColumn column1 = new TableColumn(table, SWT.NONE);
+*   TableColumn column2 = new TableColumn(table, SWT.NONE);
+*   for (int i = 0; i &lt; 10; i++) {
+*       TableTreeItem item = new TableTreeItem(tableTree, SWT.NONE);
+*       item.setText(0, "item " + i);
+*       item.setText(1, "edit this value");
+*       for (int j = 0; j &lt; 3; j++) {
+*           TableTreeItem subitem = new TableTreeItem(item, SWT.NONE);
+*           subitem.setText(0, "subitem " + i + " " + j);
+*           subitem.setText(1, "edit this value");
+*       }
+*   }
+*   column1.setWidth(100);
+*   column2.pack();
+*
+*   final TableTreeEditor editor = new TableTreeEditor(tableTree);
+*   //The editor must have the same size as the cell and must
+*   //not be any smaller than 50 pixels.
+*   editor.horizontalAlignment = SWT.LEFT;
+*   editor.grabHorizontal = true;
+*   editor.minimumWidth = 50;
+*   // editing the second column
+*   final int EDITABLECOLUMN = 1;
+*
+*   tableTree.addSelectionListener(new SelectionAdapter() {
+*       public void widgetSelected(SelectionEvent e) {
+*           // Clean up any previous editor control
+*           Control oldEditor = editor.getEditor();
+*           if (oldEditor !is null) oldEditor.dispose();
+*
+*           // Identify the selected row
+*           TableTreeItem item = (TableTreeItem)e.item;
+*           if (item is null) return;
+*
+*           // The control that will be the editor must be a child of the Table
+*           Text newEditor = new Text(table, SWT.NONE);
+*           newEditor.setText(item.getText(EDITABLECOLUMN));
+*           newEditor.addModifyListener(new ModifyListener() {
+*               public void modifyText(ModifyEvent e) {
+*                   Text text = (Text)editor.getEditor();
+*                   editor.getItem().setText(EDITABLECOLUMN, text.getText());
+*               }
+*           });
+*           newEditor.selectAll();
+*           newEditor.setFocus();
+*           editor.setEditor(newEditor, item, EDITABLECOLUMN);
+*       }
+*   });
+* </pre></code>
+*
+* @deprecated As of 3.1 use TreeEditor with Tree, TreeItem and TreeColumn
+*/
+public class TableTreeEditor : ControlEditor {
+
+    alias ControlEditor.setEditor setEditor;
+
+    TableTree tableTree;
+    TableTreeItem item;
+    int column = -1;
+    ControlListener columnListener;
+    TreeListener treeListener;
+/**
+* Creates a TableTreeEditor for the specified TableTree.
+*
+* @param tableTree the TableTree Control above which this editor will be displayed
+*
+*/
+public this (TableTree tableTree) {
+    super(tableTree.getTable());
+    this.tableTree = tableTree;
+
+    treeListener = new class() TreeListener  {
+        Runnable runnable;
+        this() {
+            runnable = new class() Runnable {
+                public void run() {
+                    if (editor is null || editor.isDisposed()) return;
+                    if (this.outer.outer.tableTree.isDisposed()) return;
+                    layout();
+                    editor.setVisible(true);
+                }
+            };
+        }
+        public void treeCollapsed(TreeEvent e) {
+            if (editor is null || editor.isDisposed ()) return;
+            editor.setVisible(false);
+            e.display.asyncExec(runnable);
+        }
+        public void treeExpanded(TreeEvent e) {
+            if (editor is null || editor.isDisposed ()) return;
+            editor.setVisible(false);
+            e.display.asyncExec(runnable);
+        }
+    };
+    tableTree.addTreeListener(treeListener);
+
+    columnListener = new class() ControlListener {
+        public void controlMoved(ControlEvent e){
+            layout ();
+        }
+        public void controlResized(ControlEvent e){
+            layout ();
+        }
+    };
+
+    // To be consistent with older versions of SWT, grabVertical defaults to true
+    grabVertical = true;
+}
+
+override Rectangle computeBounds () {
+    if (item is null || column is -1 || item.isDisposed() || item.tableItem is null) return new Rectangle(0, 0, 0, 0);
+    Rectangle cell = item.getBounds(column);
+    Rectangle area = tableTree.getClientArea();
+    if (cell.x < area.x + area.width) {
+        if (cell.x + cell.width > area.x + area.width) {
+            cell.width = area.x + area.width - cell.x;
+        }
+    }
+    Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+    if (grabHorizontal) {
+        editorRect.width = Math.max(cell.width, minimumWidth);
+    }
+
+    if (grabVertical) {
+        editorRect.height = Math.max(cell.height, minimumHeight);
+    }
+
+    if (horizontalAlignment is SWT.RIGHT) {
+        editorRect.x += cell.width - editorRect.width;
+    } else if (horizontalAlignment is SWT.LEFT) {
+        // do nothing - cell.x is the right answer
+    } else { // default is CENTER
+        editorRect.x += (cell.width - editorRect.width)/2;
+    }
+
+    if (verticalAlignment is SWT.BOTTOM) {
+        editorRect.y += cell.height - editorRect.height;
+    } else if (verticalAlignment is SWT.TOP) {
+        // do nothing - cell.y is the right answer
+    } else { // default is CENTER
+        editorRect.y += (cell.height - editorRect.height)/2;
+    }
+    return editorRect;
+}
+/**
+ * Removes all associations between the TableTreeEditor and the cell in the table tree.  The
+ * TableTree and the editor Control are <b>not</b> disposed.
+ */
+public override void dispose () {
+    if (tableTree !is null && !tableTree.isDisposed()) {
+        Table table = tableTree.getTable();
+        if (table !is null && !table.isDisposed()) {
+            if (this.column > -1 && this.column < table.getColumnCount()){
+                TableColumn tableColumn = table.getColumn(this.column);
+                tableColumn.removeControlListener(columnListener);
+            }
+        }
+        if (treeListener !is null) tableTree.removeTreeListener(treeListener);
+    }
+    treeListener = null;
+    columnListener = null;
+    tableTree = null;
+    item = null;
+    column = -1;
+    super.dispose();
+}
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*/
+public int getColumn () {
+    return column;
+}
+/**
+* Returns the TableTreeItem for the row of the cell being tracked by this editor.
+*
+* @return the TableTreeItem for the row of the cell being tracked by this editor
+*/
+public TableTreeItem getItem () {
+    return item;
+}
+public void setColumn(int column) {
+    Table table = tableTree.getTable();
+    int columnCount = table.getColumnCount();
+    // Separately handle the case where the table has no TableColumns.
+    // In this situation, there is a single default column.
+    if (columnCount is 0) {
+        this.column = (column is 0) ? 0 : -1;
+        layout();
+        return;
+    }
+    if (this.column > -1 && this.column < columnCount){
+        TableColumn tableColumn = table.getColumn(this.column);
+        tableColumn.removeControlListener(columnListener);
+        this.column = -1;
+    }
+
+    if (column < 0  || column >= table.getColumnCount()) return;
+
+    this.column = column;
+    TableColumn tableColumn = table.getColumn(this.column);
+    tableColumn.addControlListener(columnListener);
+    layout();
+}
+public void setItem (TableTreeItem item) {
+    this.item = item;
+    layout();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the table that it is to be positioned above.
+*
+* <p>Note: The Control provided as the editor <b>must</b> be created with its parent being the Table control
+* specified in the TableEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TableItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*/
+alias ControlEditor.setEditor setEditor;
+public void setEditor (Control editor, TableTreeItem item, int column) {
+    setItem(item);
+    setColumn(column);
+    setEditor(editor);
+}
+public override void layout () {
+    if (tableTree is null || tableTree.isDisposed()) return;
+    if (item is null || item.isDisposed()) return;
+    Table table = tableTree.getTable();
+    int columnCount = table.getColumnCount();
+    if (columnCount is 0 && column !is 0) return;
+    if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+    super.layout();
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TableTreeItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,894 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TableTreeItem;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.custom.TableTree;
+import java.lang.all;
+
+
+/**
+ * A TableTreeItem is a selectable user interface object
+ * that represents an item in a hierarchy of items in a
+ * TableTree.
+ *
+ * @deprecated As of 3.1 use Tree, TreeItem and TreeColumn
+ */
+public class TableTreeItem : Item {
+    TableItem tableItem;
+    TableTree parent;
+    TableTreeItem parentItem;
+    TableTreeItem [] items;
+    String[] texts;
+    Image[] images;
+    Color background;
+    Color foreground;
+    Font font;
+    bool expanded;
+    bool checked;
+    bool grayed;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TableTree</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTree parent, int style) {
+    this (parent, style, parent.getItemCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TableTree</code>,
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTree parent, int style, int index) {
+    this (parent, null, style, index);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TableTreeItem</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTreeItem parent, int style) {
+    this (parent, style, parent.getItemCount());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TableTreeItem</code>),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 index to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle()
+ */
+public this(TableTreeItem parent, int style, int index) {
+    this (parent.getParent(), parent, style, index);
+}
+
+this(TableTree parent, TableTreeItem parentItem, int style, int index) {
+
+    items = TableTree.EMPTY_ITEMS;
+    texts = TableTree.EMPTY_TEXTS;
+    images = TableTree.EMPTY_IMAGES;
+
+    super(parent, style);
+    this.parent = parent;
+    this.parentItem = parentItem;
+    if (parentItem is null) {
+
+        /* Root items are visible immediately */
+        int tableIndex = parent.addItem(this, index);
+        tableItem = new TableItem(parent.getTable(), style, tableIndex);
+        tableItem.setData(TableTree.ITEMID, this);
+        addCheck();
+        /*
+        * Feature in the Table.  The table uses the first image that
+        * is inserted into the table to size the table rows.  If the
+        * user is allowed to insert the first image, this will cause
+        * the +/- images to be scaled.  The fix is to insert a dummy
+        * image to force the size.
+        */
+        if (parent.sizeImage is null) {
+            int itemHeight = parent.getItemHeight();
+            parent.sizeImage = new Image(parent.getDisplay(), itemHeight, itemHeight);
+            GC gc = new GC (parent.sizeImage);
+            gc.setBackground(parent.getBackground());
+            gc.fillRectangle(0, 0, itemHeight, itemHeight);
+            gc.dispose();
+            tableItem.setImage(0, parent.sizeImage);
+        }
+    } else {
+        parentItem.addItem(this, index);
+    }
+}
+void addCheck() {
+    Table table = parent.getTable();
+    if ((table.getStyle() & SWT.CHECK) is 0) return;
+    tableItem.setChecked(checked);
+    tableItem.setGrayed(grayed);
+}
+void addItem(TableTreeItem item, int index) {
+    if (item is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (index < 0 || index > items.length) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    /* Now that item has a sub-node it must indicate that it can be expanded */
+    if (items.length is 0 && index is 0) {
+        if (tableItem !is null) {
+            Image image = expanded ? parent.getMinusImage() : parent.getPlusImage();
+            tableItem.setImage(0, image);
+        }
+    }
+
+    /* Put the item in the items list */
+    TableTreeItem[] newItems = new TableTreeItem[items.length + 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    newItems[index] = item;
+    System.arraycopy(items, index, newItems, index + 1, items.length - index);
+    items = newItems;
+    if (expanded) item.setVisible(true);
+}
+
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @exception SWTException <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 2.0
+ *
+ */
+public Color getBackground () {
+    checkWidget ();
+    return (background is null) ? parent.getBackground() : background;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds (int index) {
+    checkWidget();
+    if (tableItem !is null) {
+        return tableItem.getBounds(index);
+    } else {
+        return new Rectangle(0, 0, 0, 0);
+    }
+}
+/**
+ * Returns <code>true</code> if the receiver is checked,
+ * and false otherwise.  When the parent does not have
+ * the <code>CHECK style, return false.
+ *
+ * @return the checked state of the checkbox
+ *
+ * @exception SWTException <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 getChecked () {
+    checkWidget();
+    if (tableItem is null) return checked;
+    return tableItem.getChecked();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception SWTException <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 2.1
+ */
+public bool getGrayed () {
+    checkWidget();
+    if (tableItem is null) return grayed;
+    return tableItem.getGrayed();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is expanded,
+ * and false otherwise.
+ * <p>
+ *
+ * @return the expanded state
+ */
+public bool getExpanded () {
+    //checkWidget();
+    return expanded;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.0
+ */
+public Font getFont () {
+    checkWidget ();
+    return (font is null) ? parent.getFont() : font;
+}
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException <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 2.0
+ *
+ */
+public Color getForeground () {
+    checkWidget ();
+    return (foreground is null) ? parent.getForeground() : foreground;
+}
+/**
+ * Gets the first image.
+ * <p>
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore getImage(0) will return null.
+ *
+ * @return the image at index 0
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget();
+    return getImage(0);
+}
+
+/**
+ * Gets the image at the specified index.
+ * <p>
+ * Indexing is zero based. The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore getImage(0) will return null.
+ * Return null if the index is out of range.
+ *
+ * @param index the index of the image
+ * @return the image at the specified index or null
+ */
+public Image getImage (int index) {
+    //checkWidget();
+    if (0 < index && index < images.length) return images[index];
+    return null;
+}
+
+int getIndent() {
+    if (parentItem is null) return 0;
+    return parentItem.getIndent() + 1;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public TableTreeItem getItem (int index) {
+    checkWidget();
+    int count = items.length;
+    if (!(0 <= index && index < count)) SWT.error (SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.
+ *
+ * @return the number of items
+ */
+public int getItemCount () {
+    //checkWidget();
+    return items.length;
+}
+
+/**
+ * Returns an array of <code>TableTreeItem</code>s which are the
+ * direct item children of the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the receiver's items
+ */
+public TableTreeItem[] getItems () {
+    //checkWidget();
+    TableTreeItem[] newItems = new TableTreeItem[items.length];
+    System.arraycopy(items, 0, newItems, 0, items.length);
+    return newItems;
+}
+
+TableTreeItem getItem(TableItem tableItem) {
+    if (tableItem is null) return null;
+    if (this.tableItem is tableItem) return this;
+    for (int i = 0; i < items.length; i++) {
+        TableTreeItem item =  items[i].getItem(tableItem);
+            if (item !is null) return item;
+    }
+    return null;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>TableTree</code>.
+ *
+ * @return the receiver's parent
+ */
+public TableTree getParent () {
+    //checkWidget();
+    return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>TableTreeItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ */
+public TableTreeItem getParentItem () {
+    //checkWidget();
+    return parentItem;
+}
+public override String getText () {
+    checkWidget();
+    return getText(0);
+}
+
+/**
+ * Gets the item text at the specified index.
+ * <p>
+ * Indexing is zero based.
+ *
+ * This operation will fail when the index is out
+ * of range or an item could not be queried from
+ * the OS.
+ *
+ * @param index the index of the item
+ * @return the item text at the specified index, which can be null
+ */
+public String getText(int index) {
+    //checkWidget();
+    if (0 <= index && index < texts.length) return texts[index];
+    return null;
+}
+
+bool getVisible () {
+    return tableItem !is null;
+}
+
+/**
+ * Gets the index of the specified item.
+ *
+ * <p>The widget is searched starting at 0 until an
+ * item is found that is equal to the search item.
+ * If no item is found, -1 is returned.  Indexing
+ * is zero based.  This index is relative to the parent only.
+ *
+ * @param item the search item
+ * @return the index of the item or -1 if the item is not found
+ *
+ */
+public int indexOf (TableTreeItem item) {
+    //checkWidget();
+    for (int i = 0; i < items.length; i++) {
+        if (items[i] is item) return i;
+    }
+    return -1;
+}
+
+void expandAll(bool notify) {
+    if (items.length is 0) return;
+    if (!expanded) {
+        setExpanded(true);
+        if (notify) {
+            Event event = new Event();
+            event.item = this;
+            parent.notifyListeners(SWT.Expand, event);
+        }
+    }
+    for (int i = 0; i < items.length; i++) {
+        items[i].expandAll(notify);
+    }
+}
+int expandedIndexOf (TableTreeItem item) {
+    int index = 0;
+    for (int i = 0; i < items.length; i++) {
+        if (items[i] is item) return index;
+        if (items[i].expanded) index += items[i].visibleChildrenCount ();
+        index++;
+    }
+    return -1;
+}
+
+int visibleChildrenCount () {
+    int count = 0;
+    for (int i = 0; i < items.length; i++) {
+        if (items[i].getVisible ()) {
+            count += 1 + items[i].visibleChildrenCount ();
+        }
+    }
+    return count;
+}
+
+public override void dispose () {
+    if (isDisposed()) return;
+    for (int i = items.length - 1; i >= 0; i--) {
+        items[i].dispose();
+    }
+    super.dispose();
+    if (!parent.inDispose) {
+        if (parentItem !is null) {
+            parentItem.removeItem(this);
+        } else {
+            parent.removeItem(this);
+        }
+        if (tableItem !is null) tableItem.dispose();
+    }
+    items = null;
+    parentItem = null;
+    parent = null;
+    images = null;
+    texts = null;
+    tableItem = null;
+    foreground = null;
+    background = null;
+    font = null;
+}
+
+void removeItem(TableTreeItem item) {
+    int index = 0;
+    while (index < items.length && items[index] !is item) index++;
+    if (index is items.length) return;
+    TableTreeItem[] newItems = new TableTreeItem[items.length - 1];
+    System.arraycopy(items, 0, newItems, 0, index);
+    System.arraycopy(items, index + 1, newItems, index, items.length - index - 1);
+    items = newItems;
+    if (items.length is 0) {
+        if (tableItem !is null) tableItem.setImage(0, null);
+    }
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ *
+ */
+public void setBackground (Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (tableItem !is null) {
+        tableItem.setBackground(color);
+    }
+    background = color;
+}
+
+/**
+ * Sets the checked state of the checkbox for this item.  This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param checked the new checked state of the checkbox
+ *
+ * @exception SWTException <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 setChecked (bool checked) {
+    checkWidget();
+    Table table = parent.getTable();
+    if ((table.getStyle() & SWT.CHECK) is 0) return;
+    if (tableItem !is null) {
+        tableItem.setChecked(checked);
+    }
+    this.checked = checked;
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item.  This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox;
+ *
+ * @exception SWTException <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 2.1
+ */
+public void setGrayed (bool grayed) {
+    checkWidget();
+    Table table = parent.getTable();
+    if ((table.getStyle() & SWT.CHECK) is 0) return;
+    if (tableItem !is null) {
+        tableItem.setGrayed(grayed);
+    }
+    this.grayed = grayed;
+}
+
+/**
+ * Sets the expanded state.
+ * <p>
+ * @param expanded the new expanded state.
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public void setExpanded (bool expanded) {
+    checkWidget();
+    if (items.length is 0) return;
+    if (this.expanded is expanded) return;
+    this.expanded = expanded;
+    if (tableItem is null) return;
+    parent.setRedraw(false);
+    for (int i = 0; i < items.length; i++) {
+        items[i].setVisible(expanded);
+    }
+    Image image = expanded ? parent.getMinusImage() : parent.getPlusImage();
+    tableItem.setImage(0, image);
+    parent.setRedraw(true);
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setFont (Font font){
+    checkWidget ();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (tableItem !is null) {
+        tableItem.setFont(font);
+    }
+    this.font = font;
+}
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @since 2.0
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ *
+ */
+public void setForeground (Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (tableItem !is null) {
+        tableItem.setForeground(color);
+    }
+    foreground = color;
+}
+
+/**
+ * Sets the image at an index.
+ * <p>
+ * The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore do nothing if index is 0.
+ *
+ * @param image the new image or null
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public void setImage (int index, Image image) {
+    checkWidget();
+    int columnCount = Math.max(parent.getTable().getColumnCount(), 1);
+    if (index <= 0 || index >= columnCount) return;
+    if (images.length < columnCount) {
+        Image[] newImages = new Image[columnCount];
+        System.arraycopy(images, 0, newImages, 0, images.length);
+        images = newImages;
+    }
+    images[index] = image;
+    if (tableItem !is null) tableItem.setImage(index, image);
+}
+
+/**
+ * Sets the first image.
+ * <p>
+ * The image can be null.
+ * The image in column 0 is reserved for the [+] and [-]
+ * images of the tree, therefore do nothing.
+ *
+ * @param image the new image or null
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public override void setImage (Image image) {
+    setImage(0, image);
+}
+
+/**
+ * Sets the widget text.
+ * <p>
+ *
+ * The widget text for an item is the label of the
+ * item or the label of the text specified by a column
+ * number.
+ *
+ * @param index the column number
+ * @param text the new text
+ *
+ * @exception SWTException <ul>
+ *      <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+ *      <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+ *  </ul>
+ */
+public void setText(int index, String text) {
+    checkWidget();
+    // SWT extension: allow null for zero length string
+    //if (text is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    int columnCount = Math.max(parent.getTable().getColumnCount(), 1);
+    if (index < 0 || index >= columnCount) return;
+    if (texts.length < columnCount) {
+        String[] newTexts = new String[columnCount];
+        System.arraycopy(texts, 0, newTexts, 0, texts.length);
+        texts = newTexts;
+    }
+    texts[index] = text;
+    if (tableItem !is null) tableItem.setText(index, text);
+}
+public override void setText (String string) {
+    setText(0, string);
+}
+
+void setVisible (bool show) {
+    if (parentItem is null) return; // this is a root and can not be toggled between visible and hidden
+    if (getVisible() is show) return;
+
+    if (show) {
+        if (!parentItem.getVisible()) return; // parentItem must already be visible
+        // create underlying table item and set data in table item to stored data
+        Table table = parent.getTable();
+        int parentIndex = table.indexOf(parentItem.tableItem);
+        int index = parentItem.expandedIndexOf(this) + parentIndex + 1;
+        if (index < 0) return;
+        tableItem = new TableItem(table, getStyle(), index);
+        tableItem.setData(TableTree.ITEMID, this);
+        tableItem.setImageIndent(getIndent());
+        if (background !is null) tableItem.setBackground(background);
+        if (foreground !is null) tableItem.setForeground(foreground);
+        if (font !is null) tableItem.setFont(font);
+        addCheck();
+
+        // restore fields to item
+        // ignore any images in the first column
+        int columnCount = Math.max(table.getColumnCount(), 1);
+        for (int i = 0; i < columnCount; i++) {
+            if (i < texts.length && texts[i] !is null) setText(i, texts[i]);
+            if (i < images.length && images[i] !is null) setImage(i, images[i]);
+        }
+
+        // display the children and the appropriate [+]/[-] symbol as required
+        if (items.length !is 0) {
+            if (expanded) {
+                tableItem.setImage(0, parent.getMinusImage());
+                for (int i = 0, length = items.length; i < length; i++) {
+                    items[i].setVisible(true);
+                }
+            } else {
+                tableItem.setImage(0, parent.getPlusImage());
+            }
+        }
+
+    } else {
+
+        for (int i = 0, length = items.length; i < length; i++) {
+            items[i].setVisible(false);
+        }
+        // remove row from table
+        tableItem.dispose();
+        tableItem = null;
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangeListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TextChangeListener;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.custom.TextChangingEvent;
+import org.eclipse.swt.custom.TextChangedEvent;
+
+/**
+ * The StyledText widget implements this listener to receive
+ * notifications when changes to the model occur.
+ * It is not intended to be implemented by clients or by
+ * implementors of StyledTextContent.
+ * Clients should listen to the ModifyEvent or ExtendedModifyEvent
+ * that is sent by the StyledText widget to receive text change
+ * notifications.
+ * Implementors of StyledTextContent should call the textChanging
+ * and textChanged methods when text changes occur as described
+ * below. If the entire text is replaced the textSet method
+ * should be called instead.
+ */
+public interface TextChangeListener : SWTEventListener {
+
+/**
+ * This method is called when the content is about to be changed.
+ * Callers also need to call the textChanged method after the
+ * content change has been applied. The widget only updates the
+ * screen properly when it receives both events.
+ *
+ * @param event the text changing event. All event fields need
+ *  to be set by the sender.
+ * @see TextChangingEvent
+ */
+public void textChanging(TextChangingEvent event);
+/**
+ * This method is called when the content has changed.
+ * Callers need to have called the textChanging method prior to
+ * applying the content change and calling this method. The widget
+ * only updates the screen properly when it receives both events.
+ *
+ * @param event the text changed event
+ */
+public void textChanged(TextChangedEvent event);
+/**
+ * This method is called instead of the textChanging/textChanged
+ * combination when the entire old content has been replaced
+ * (e.g., by a call to StyledTextContent.setText()).
+ *
+ * @param event the text changed event
+ */
+public void textSet(TextChangedEvent event);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangedEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TextChangedEvent;
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyledTextContent;
+/**
+ * This event is sent by the StyledTextContent implementor when a change to
+ * the text occurs.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TextChangedEvent : TypedEvent {
+
+/**
+ * Create the TextChangedEvent to be used by the StyledTextContent implementor.
+ * <p>
+ *
+ * @param source the object that will be sending the TextChangedEvent,
+ *  cannot be null
+ */
+public this(StyledTextContent source) {
+    super(cast(Object)source);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TextChangingEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TextChangingEvent;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.custom.StyledTextContent;
+import org.eclipse.swt.custom.StyledTextEvent;
+
+/**
+ * This event is sent by the StyledTextContent implementor when a change
+ * to the text is about to occur.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TextChangingEvent : TypedEvent {
+    /**
+     * Start offset of the text that is going to be replaced
+     */
+    public int start;
+    /**
+     * Text that is going to be inserted or empty string
+     * if no text will be inserted
+     */
+    public String newText;
+    /**
+     * Length of text that is going to be replaced
+     */
+    public int replaceCharCount;
+    /**
+     * Length of text that is going to be inserted
+     */
+    public int newCharCount;
+    /**
+     * Number of lines that are going to be replaced
+     */
+    public int replaceLineCount;
+    /**
+     * Number of new lines that are going to be inserted
+     */
+    public int newLineCount;
+
+    static final long serialVersionUID = 3257290210114352439L;
+
+/**
+ * Create the TextChangedEvent to be used by the StyledTextContent implementor.
+ * <p>
+ *
+ * @param source the object that will be sending the new TextChangingEvent,
+ *  cannot be null
+ */
+public this(StyledTextContent source) {
+    super( cast(Object)source);
+}
+this(StyledTextContent source, StyledTextEvent e) {
+    super( cast(Object)source);
+    start = e.start;
+    replaceCharCount = e.replaceCharCount;
+    newCharCount = e.newCharCount;
+    replaceLineCount = e.replaceLineCount;
+    newLineCount = e.newLineCount;
+    newText = e.text;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/TreeEditor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.TreeEditor;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.custom.ControlEditor;
+import java.lang.Runnable;
+
+/**
+*
+* A TreeEditor is a manager for a Control that appears above a cell in a Tree and tracks with the
+* moving and resizing of that cell.  It can be used to display a text widget above a cell
+* in a Tree so that the user can edit the contents of that cell.  It can also be used to display
+* a button that can launch a dialog for modifying the contents of the associated cell.
+*
+* <p> Here is an example of using a TreeEditor:
+* <code><pre>
+*   final Tree tree = new Tree(shell, SWT.BORDER);
+*   for (int i = 0; i &lt; 3; i++) {
+*       TreeItem item = new TreeItem(tree, SWT.NONE);
+*       item.setText("item " + i);
+*       for (int j = 0; j &lt; 3; j++) {
+*           TreeItem subItem = new TreeItem(item, SWT.NONE);
+*           subItem.setText("item " + i + " " + j);
+*       }
+*   }
+*
+*   final TreeEditor editor = new TreeEditor(tree);
+*   //The editor must have the same size as the cell and must
+*   //not be any smaller than 50 pixels.
+*   editor.horizontalAlignment = SWT.LEFT;
+*   editor.grabHorizontal = true;
+*   editor.minimumWidth = 50;
+*
+*   tree.addSelectionListener(new SelectionAdapter() {
+*       public void widgetSelected(SelectionEvent e) {
+*           // Clean up any previous editor control
+*           Control oldEditor = editor.getEditor();
+*           if (oldEditor !is null) oldEditor.dispose();
+*
+*           // Identify the selected row
+*           TreeItem item = (TreeItem)e.item;
+*           if (item is null) return;
+*
+*           // The control that will be the editor must be a child of the Tree
+*           Text newEditor = new Text(tree, SWT.NONE);
+*           newEditor.setText(item.getText());
+*           newEditor.addModifyListener(new ModifyListener() {
+*               public void modifyText(ModifyEvent e) {
+*                   Text text = (Text)editor.getEditor();
+*                   editor.getItem().setText(text.getText());
+*               }
+*           });
+*           newEditor.selectAll();
+*           newEditor.setFocus();
+*           editor.setEditor(newEditor, item);
+*       }
+*   });
+* </pre></code>
+*
+* @see <a href="http://www.eclipse.org/swt/snippets/#treeeditor">TreeEditor snippets</a>
+* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+*/
+
+public class TreeEditor : ControlEditor {
+    Tree tree;
+    TreeItem item;
+    int column = 0;
+    ControlListener columnListener;
+    TreeListener treeListener;
+    Runnable timer;
+    static const int TIMEOUT = 1500;
+
+/**
+* Creates a TreeEditor for the specified Tree.
+*
+* @param tree the Tree Control above which this editor will be displayed
+*
+*/
+public this (Tree tree) {
+    super(tree);
+    this.tree = tree;
+
+    columnListener = new class() ControlListener {
+        public void controlMoved(ControlEvent e){
+            layout();
+        }
+        public void controlResized(ControlEvent e){
+            layout();
+        }
+    };
+    timer = new class() Runnable {
+        public void run() {
+            layout ();
+        }
+    };
+    treeListener = new class() TreeListener {
+        Runnable runnable;
+        this(){
+            runnable = new class() Runnable {
+                public void run() {
+                    if (this.outer.outer.editor is null || this.outer.outer.editor.isDisposed()) return;
+                    if (this.outer.outer.tree.isDisposed()) return;
+                    layout();
+                    this.outer.outer.editor.setVisible(true);
+                }
+            };
+        }
+        public void treeCollapsed(TreeEvent e) {
+            if (this.outer.editor is null || this.outer.editor.isDisposed ()) return;
+            this.outer.editor.setVisible(false);
+            e.display.asyncExec(runnable);
+        }
+        public void treeExpanded(TreeEvent e) {
+            if (this.outer.editor is null || this.outer.editor.isDisposed ()) return;
+            this.outer.editor.setVisible(false);
+            e.display.asyncExec(runnable);
+        }
+    };
+    tree.addTreeListener(treeListener);
+
+    // To be consistent with older versions of SWT, grabVertical defaults to true
+    grabVertical = true;
+}
+
+override Rectangle computeBounds () {
+    if (item is null || column is -1 || item.isDisposed()) return new Rectangle(0, 0, 0, 0);
+    Rectangle cell = item.getBounds(column);
+    Rectangle rect = item.getImageBounds(column);
+    cell.x = rect.x + rect.width;
+    cell.width -= rect.width;
+    Rectangle area = tree.getClientArea();
+    if (cell.x < area.x + area.width) {
+        if (cell.x + cell.width > area.x + area.width) {
+            cell.width = area.x + area.width - cell.x;
+        }
+    }
+    Rectangle editorRect = new Rectangle(cell.x, cell.y, minimumWidth, minimumHeight);
+
+    if (grabHorizontal) {
+        if (tree.getColumnCount() is 0) {
+            // Bounds of tree item only include the text area - stretch out to include
+            // entire client area
+            cell.width = area.x + area.width - cell.x;
+        }
+        editorRect.width = Math.max(cell.width, minimumWidth);
+    }
+
+    if (grabVertical) {
+        editorRect.height = Math.max(cell.height, minimumHeight);
+    }
+
+    if (horizontalAlignment is SWT.RIGHT) {
+        editorRect.x += cell.width - editorRect.width;
+    } else if (horizontalAlignment is SWT.LEFT) {
+        // do nothing - cell.x is the right answer
+    } else { // default is CENTER
+        editorRect.x += (cell.width - editorRect.width)/2;
+    }
+    // don't let the editor overlap with the + / - of the tree
+    editorRect.x = Math.max(cell.x, editorRect.x);
+
+    if (verticalAlignment is SWT.BOTTOM) {
+        editorRect.y += cell.height - editorRect.height;
+    } else if (verticalAlignment is SWT.TOP) {
+        // do nothing - cell.y is the right answer
+    } else { // default is CENTER
+        editorRect.y += (cell.height - editorRect.height)/2;
+    }
+    return editorRect;
+}
+
+/**
+ * Removes all associations between the TreeEditor and the row in the tree.  The
+ * tree and the editor Control are <b>not</b> disposed.
+ */
+public override void dispose () {
+    if (tree !is null && !tree.isDisposed()) {
+        if (this.column > -1 && this.column < tree.getColumnCount()){
+            TreeColumn treeColumn = tree.getColumn(this.column);
+            treeColumn.removeControlListener(columnListener);
+        }
+        if (treeListener !is null) tree.removeTreeListener(treeListener);
+    }
+    columnListener = null;
+    treeListener = null;
+    tree = null;
+    item = null;
+    column = 0;
+    timer = null;
+    super.dispose();
+}
+
+/**
+* Returns the zero based index of the column of the cell being tracked by this editor.
+*
+* @return the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public int getColumn () {
+    return column;
+}
+
+/**
+* Returns the TreeItem for the row of the cell being tracked by this editor.
+*
+* @return the TreeItem for the row of the cell being tracked by this editor
+*/
+public TreeItem getItem () {
+    return item;
+}
+
+void resize () {
+    layout();
+    /*
+     * On some platforms, the table scrolls when an item that
+     * is partially visible at the bottom of the table is
+     * selected.  Ensure that the correct row is edited by
+     * laying out one more time in a timerExec().
+     */
+    if (tree !is null) {
+        Display display = tree.getDisplay();
+        display.timerExec(-1, timer);
+        display.timerExec(TIMEOUT, timer);
+    }
+}
+
+/**
+* Sets the zero based index of the column of the cell being tracked by this editor.
+*
+* @param column the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public void setColumn(int column) {
+    int columnCount = tree.getColumnCount();
+    // Separately handle the case where the tree has no TreeColumns.
+    // In this situation, there is a single default column.
+    if (columnCount is 0) {
+        this.column = (column is 0) ? 0 : -1;
+        resize();
+        return;
+    }
+    if (this.column > -1 && this.column < columnCount){
+        TreeColumn treeColumn = tree.getColumn(this.column);
+        treeColumn.removeControlListener(columnListener);
+        this.column = -1;
+    }
+
+    if (column < 0  || column >= tree.getColumnCount()) return;
+
+    this.column = column;
+    TreeColumn treeColumn = tree.getColumn(this.column);
+    treeColumn.addControlListener(columnListener);
+    resize();
+}
+
+/**
+* Specifies the <code>TreeItem</code> that is to be edited.
+*
+* @param item the item to be edited
+*/
+public void setItem (TreeItem item) {
+    this.item = item;
+    resize();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the tree that it is to be positioned above.
+*
+* <p>Note: The Control provided as the editor <b>must</b> be created with its parent being the Tree control
+* specified in the TreeEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TreeItem for the row of the cell being tracked by this editor
+* @param column the zero based index of the column of the cell being tracked by this editor
+*
+* @since 3.1
+*/
+public void setEditor (Control editor, TreeItem item, int column) {
+    setItem(item);
+    setColumn(column);
+    setEditor(editor);
+}
+public override void setEditor (Control editor) {
+    super.setEditor(editor);
+    resize();
+}
+
+/**
+* Specify the Control that is to be displayed and the cell in the tree that it is to be positioned above.
+*
+* <p>Note: The Control provided as the editor <b>must</b> be created with its parent being the Tree control
+* specified in the TreeEditor constructor.
+*
+* @param editor the Control that is displayed above the cell being edited
+* @param item the TreeItem for the row of the cell being tracked by this editor
+*/
+public void setEditor (Control editor, TreeItem item) {
+    setItem(item);
+    setEditor(editor);
+}
+
+public override void layout () {
+    if (tree is null || tree.isDisposed()) return;
+    if (item is null || item.isDisposed()) return;
+    int columnCount = tree.getColumnCount();
+    if (columnCount is 0 && column !is 0) return;
+    if (columnCount > 0 && (column < 0 || column >= columnCount)) return;
+    super.layout();
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/VerifyKeyListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.VerifyKeyListener;
+
+
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a
+ * key is pressed.
+ *
+ * @see VerifyEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public interface VerifyKeyListener : SWTEventListener {
+/**
+ * The following event fields are used:<ul>
+ * <li>event.character is the character that was typed (input)</li>
+ * <li>event.keyCode is the key code that was typed (input)</li>
+ * <li>event.stateMask is the state of the keyboard (input)</li>
+ * <li>event.doit is processed or not (output)</li>
+ * </ul>
+ * @param event the verify event
+ * @see VerifyEvent
+ */
+public void verifyKey (VerifyEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewForm.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,493 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ViewForm;
+
+import java.lang.all;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.custom.ViewFormLayout;
+
+/**
+ * Instances of this class implement a Composite that positions and sizes
+ * children and allows programmatic control of layout and border parameters.
+ * ViewForm is used in the workbench to lay out a view's label/menu/toolbar
+ * local bar.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER, FLAT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(None)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class ViewForm : Composite {
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the form.
+     *
+     * The default value is 0.
+     */
+    public int marginWidth = 0;
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the form.
+     *
+     * The default value is 0.
+     */
+    public int marginHeight = 0;
+    /**
+     * horizontalSpacing specifies the number of pixels between the right
+     * edge of one cell and the left edge of its neighbouring cell to
+     * the right.
+     *
+     * The default value is 1.
+     */
+    public int horizontalSpacing = 1;
+    /**
+     * verticalSpacing specifies the number of pixels between the bottom
+     * edge of one cell and the top edge of its neighbouring cell underneath.
+     *
+     * The default value is 1.
+     */
+    public int verticalSpacing = 1;
+
+    /**
+     * Color of innermost line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated
+     */
+    public static RGB borderInsideRGB;
+    /**
+     * Color of middle line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated
+     */
+    public static RGB borderMiddleRGB;
+    /**
+     * Color of outermost line of drop shadow border.
+     *
+     * NOTE This field is badly named and can not be fixed for backwards compatibility.
+     * It should be capitalized.
+     *
+     * @deprecated
+     */
+    public static RGB borderOutsideRGB;
+
+    // SWT widgets
+    Control topLeft;
+    Control topCenter;
+    Control topRight;
+    Control content;
+
+    // Configuration and state info
+    bool separateTopCenter = false;
+    bool showBorder = false;
+
+    int separator = -1;
+    int borderTop = 0;
+    int borderBottom = 0;
+    int borderLeft = 0;
+    int borderRight = 0;
+    int highlight = 0;
+    Point oldSize;
+
+    Color selectionBackground;
+
+    static final int OFFSCREEN = -200;
+    static final int BORDER1_COLOR = SWT.COLOR_WIDGET_NORMAL_SHADOW;
+    static final int SELECTION_BACKGROUND = SWT.COLOR_LIST_BACKGROUND;
+
+
+    static this(){
+        borderInsideRGB  = new RGB (132, 130, 132);
+        borderMiddleRGB  = new RGB (143, 141, 138);
+        borderOutsideRGB = new RGB (171, 168, 165);
+    }
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#FLAT
+ * @see #getStyle()
+ */
+public this(Composite parent, int style) {
+    super(parent, checkStyle(style));
+    super.setLayout(new ViewFormLayout());
+
+    setBorderVisible((style & SWT.BORDER) !is 0);
+
+    Listener listener = new class() Listener {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+                case SWT.Dispose: onDispose(); break;
+                case SWT.Paint: onPaint(e.gc); break;
+                case SWT.Resize: onResize(); break;
+                default:
+            }
+        }
+    };
+
+    int[] events = [SWT.Dispose, SWT.Paint, SWT.Resize];
+
+    for (int i = 0; i < events.length; i++) {
+        addListener(events[i], listener);
+    }
+}
+
+static int checkStyle (int style) {
+    int mask = SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    return style & mask | SWT.NO_REDRAW_RESIZE;
+}
+
+//protected void checkSubclass () {
+//  String name = getClass().getName ();
+//  String validName = ViewForm.class.getName();
+//  if (!validName.equals(name)) {
+//      SWT.error (SWT.ERROR_INVALID_SUBCLASS);
+//  }
+//}
+
+public override Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    int trimX = x - borderLeft - highlight;
+    int trimY = y - borderTop - highlight;
+    int trimWidth = width + borderLeft + borderRight + 2*highlight;
+    int trimHeight = height + borderTop + borderBottom + 2*highlight;
+    return new Rectangle(trimX, trimY, trimWidth, trimHeight);
+}
+public override Rectangle getClientArea() {
+    checkWidget();
+    Rectangle clientArea = super.getClientArea();
+    clientArea.x += borderLeft;
+    clientArea.y += borderTop;
+    clientArea.width -= borderLeft + borderRight;
+    clientArea.height -= borderTop + borderBottom;
+    return clientArea;
+}
+/**
+* Returns the content area.
+*
+* @return the control in the content area of the pane or null
+*/
+public Control getContent() {
+    //checkWidget();
+    return content;
+}
+/**
+* Returns Control that appears in the top center of the pane.
+* Typically this is a toolbar.
+*
+* @return the control in the top center of the pane or null
+*/
+public Control getTopCenter() {
+    //checkWidget();
+    return topCenter;
+}
+/**
+* Returns the Control that appears in the top left corner of the pane.
+* Typically this is a label such as CLabel.
+*
+* @return the control in the top left corner of the pane or null
+*/
+public Control getTopLeft() {
+    //checkWidget();
+    return topLeft;
+}
+/**
+* Returns the control in the top right corner of the pane.
+* Typically this is a Close button or a composite with a Menu and Close button.
+*
+* @return the control in the top right corner of the pane or null
+*/
+public Control getTopRight() {
+    //checkWidget();
+    return topRight;
+}
+void onDispose() {
+    topLeft = null;
+    topCenter = null;
+    topRight = null;
+    content = null;
+    oldSize = null;
+    selectionBackground = null;
+}
+void onPaint(GC gc) {
+    Color gcForeground = gc.getForeground();
+    Point size = getSize();
+    Color border = getDisplay().getSystemColor(BORDER1_COLOR);
+    if (showBorder) {
+        gc.setForeground(border);
+        gc.drawRectangle(0, 0, size.x - 1, size.y - 1);
+        if (highlight > 0) {
+            int x1 = 1;
+            int y1 = 1;
+            int x2 = size.x - 1;
+            int y2 = size.y - 1;
+            int[] shape = [x1,y1, x2,y1, x2,y2, x1,y2, x1,y1+highlight,
+                               x1+highlight,y1+highlight, x1+highlight,y2-highlight,
+                               x2-highlight,y2-highlight, x2-highlight,y1+highlight, x1,y1+highlight];
+            Color highlightColor = getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
+            gc.setBackground(highlightColor);
+            gc.fillPolygon(shape);
+        }
+    }
+    if (separator > -1) {
+        gc.setForeground(border);
+        gc.drawLine(borderLeft + highlight, separator, size.x - borderLeft - borderRight - highlight, separator);
+    }
+    gc.setForeground(gcForeground);
+}
+void onResize() {
+    Point size = getSize();
+    if (oldSize is null || oldSize.x is 0 || oldSize.y is 0) {
+        redraw();
+    } else {
+        int width = 0;
+        if (oldSize.x < size.x) {
+            width = size.x - oldSize.x + borderRight + highlight;
+        } else if (oldSize.x > size.x) {
+            width = borderRight + highlight;
+        }
+        redraw(size.x - width, 0, width, size.y, false);
+
+        int height = 0;
+        if (oldSize.y < size.y) {
+            height = size.y - oldSize.y + borderBottom + highlight;
+        }
+        if (oldSize.y > size.y) {
+            height = borderBottom + highlight;
+        }
+        redraw(0, size.y - height, size.x, height, false);
+    }
+    oldSize = size;
+}
+/**
+* Sets the content.
+* Setting the content to null will remove it from
+* the pane - however, the creator of the content must dispose of the content.
+*
+* @param content the control to be displayed in the content area or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm</li>
+* </ul>
+*/
+public void setContent(Control content) {
+    checkWidget();
+    if (content !is null && content.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (this.content !is null && !this.content.isDisposed()) {
+        this.content.setBounds(OFFSCREEN, OFFSCREEN, 0, 0);
+    }
+    this.content = content;
+    layout(false);
+}
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ * <p>
+ * Note: No Layout can be set on this Control because it already
+ * manages the size and position of its children.
+ * </p>
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout) {
+    checkWidget();
+    return;
+}
+void setSelectionBackground (Color color) {
+    checkWidget();
+    if (selectionBackground is color) return;
+    if (color is null) color = getDisplay().getSystemColor(SELECTION_BACKGROUND);
+    selectionBackground = color;
+    redraw();
+}
+/**
+* Set the control that appears in the top center of the pane.
+* Typically this is a toolbar.
+* The topCenter is optional.  Setting the topCenter to null will remove it from
+* the pane - however, the creator of the topCenter must dispose of the topCenter.
+*
+* @param topCenter the control to be displayed in the top center or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm</li>
+* </ul>
+*/
+public void setTopCenter(Control topCenter) {
+    checkWidget();
+    if (topCenter !is null && topCenter.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (this.topCenter !is null && !this.topCenter.isDisposed()) {
+        Point size = this.topCenter.getSize();
+        this.topCenter.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    this.topCenter = topCenter;
+    layout(false);
+}
+/**
+* Set the control that appears in the top left corner of the pane.
+* Typically this is a label such as CLabel.
+* The topLeft is optional.  Setting the top left control to null will remove it from
+* the pane - however, the creator of the control must dispose of the control.
+*
+* @param c the control to be displayed in the top left corner or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm</li>
+* </ul>
+*/
+public void setTopLeft(Control c) {
+    checkWidget();
+    if (c !is null && c.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (this.topLeft !is null && !this.topLeft.isDisposed()) {
+        Point size = this.topLeft.getSize();
+        this.topLeft.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    this.topLeft = c;
+    layout(false);
+}
+/**
+* Set the control that appears in the top right corner of the pane.
+* Typically this is a Close button or a composite with a Menu and Close button.
+* The topRight is optional.  Setting the top right control to null will remove it from
+* the pane - however, the creator of the control must dispose of the control.
+*
+* @param c the control to be displayed in the top right corner or null
+*
+* @exception SWTException <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>
+*    <li>ERROR_INVALID_ARGUMENT - if the control is not a child of this ViewForm</li>
+* </ul>
+*/
+public void setTopRight(Control c) {
+    checkWidget();
+    if (c !is null && c.getParent() !is this) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (this.topRight !is null && !this.topRight.isDisposed()) {
+        Point size = this.topRight.getSize();
+        this.topRight.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
+    }
+    this.topRight = c;
+    layout(false);
+}
+/**
+* Specify whether the border should be displayed or not.
+*
+* @param show true if the border should be displayed
+*
+* @exception SWTException <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 setBorderVisible(bool show) {
+    checkWidget();
+    if (showBorder is show) return;
+
+    showBorder = show;
+    if (showBorder) {
+        borderLeft = borderTop = borderRight = borderBottom = 1;
+        if ((getStyle() & SWT.FLAT)is 0) highlight = 2;
+    } else {
+        borderBottom = borderTop = borderLeft = borderRight = 0;
+        highlight = 0;
+    }
+    layout(false);
+    redraw();
+}
+/**
+* If true, the topCenter will always appear on a separate line by itself, otherwise the
+* topCenter will appear in the top row if there is room and will be moved to the second row if
+* required.
+*
+* @param show true if the topCenter will always appear on a separate line by itself
+*
+* @exception SWTException <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 setTopCenterSeparate(bool show) {
+    checkWidget();
+    separateTopCenter = show;
+    layout(false);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/ViewFormLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.custom.ViewFormLayout;
+
+import java.lang.all;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.custom.ViewForm;
+import org.eclipse.swt.custom.CLayoutData;
+
+/**
+ * This class provides the layout for ViewForm
+ *
+ * @see ViewForm
+ */
+class ViewFormLayout : Layout {
+
+protected override Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
+    ViewForm form = cast(ViewForm)composite;
+    Control left = form.topLeft;
+    Control center = form.topCenter;
+    Control right = form.topRight;
+    Control content = form.content;
+
+    Point leftSize = new Point(0, 0);
+    if (left !is null) {
+        leftSize = computeChildSize(left, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+    Point centerSize = new Point(0, 0);
+    if (center !is null) {
+         centerSize = computeChildSize(center, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+    Point rightSize = new Point(0, 0);
+    if (right !is null) {
+         rightSize = computeChildSize(right, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+    Point size = new Point(0, 0);
+    // calculate width of title bar
+    if (form.separateTopCenter ||
+        (wHint !is SWT.DEFAULT &&  leftSize.x + centerSize.x + rightSize.x > wHint)) {
+        size.x = leftSize.x + rightSize.x;
+        if (leftSize.x > 0 && rightSize.x > 0) size.x += form.horizontalSpacing;
+        size.x = Math.max(centerSize.x, size.x);
+        size.y = Math.max(leftSize.y, rightSize.y);
+        if (center !is null){
+            size.y += centerSize.y;
+            if (left !is null ||right !is null)size.y += form.verticalSpacing;
+        }
+    } else {
+        size.x = leftSize.x + centerSize.x + rightSize.x;
+        int count = -1;
+        if (leftSize.x > 0) count++;
+        if (centerSize.x > 0) count++;
+        if (rightSize.x > 0) count++;
+        if (count > 0) size.x += count * form.horizontalSpacing;
+        size.y = Math.max(leftSize.y, Math.max(centerSize.y, rightSize.y));
+    }
+
+    if (content !is null) {
+        if (left !is null || right !is null || center !is null) size.y += 1; // allow space for a vertical separator
+        Point contentSize = new Point(0, 0);
+        contentSize = computeChildSize(content, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+        size.x = Math.max (size.x, contentSize.x);
+        size.y += contentSize.y;
+        if (size.y > contentSize.y) size.y += form.verticalSpacing;
+    }
+
+    size.x += 2*form.marginWidth;
+    size.y += 2*form.marginHeight;
+
+    if (wHint !is SWT.DEFAULT) size.x  = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+
+    return size;
+}
+
+Point computeChildSize(Control control, int wHint, int hHint, bool flushCache) {
+    Object data = control.getLayoutData();
+    if (data is null || !( null !is cast(CLayoutData)data )) {
+        data = new CLayoutData();
+        control.setLayoutData(data);
+    }
+    return (cast(CLayoutData)data).computeSize(control, wHint, hHint, flushCache);
+}
+
+int computeTrim(Control c) {
+    if ( auto sa = cast(Scrollable)c) {
+        Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+        return rect.width;
+    }
+    return c.getBorderWidth () * 2;
+}
+
+protected override bool flushCache(Control control) {
+    Object data = control.getLayoutData();
+    if ( auto ld = cast(CLayoutData)data ) ld.flushCache();
+    return true;
+}
+
+protected override void layout(Composite composite, bool flushCache) {
+    ViewForm form = cast(ViewForm)composite;
+    Control left = form.topLeft;
+    Control center = form.topCenter;
+    Control right = form.topRight;
+    Control content = form.content;
+
+    Rectangle rect = composite.getClientArea();
+
+    Point leftSize = new Point(0, 0);
+    if (left !is null && !left.isDisposed()) {
+        leftSize = computeChildSize(left, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+    Point centerSize = new Point(0, 0);
+    if (center !is null && !center.isDisposed()) {
+         centerSize = computeChildSize(center, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+    Point rightSize = new Point(0, 0);
+    if (right !is null && !right.isDisposed()) {
+         rightSize = computeChildSize(right, SWT.DEFAULT, SWT.DEFAULT, flushCache);
+    }
+
+    int minTopWidth = leftSize.x + centerSize.x + rightSize.x + 2*form.marginWidth + 2*form.highlight;
+    int count = -1;
+    if (leftSize.x > 0) count++;
+    if (centerSize.x > 0) count++;
+    if (rightSize.x > 0) count++;
+    if (count > 0) minTopWidth += count * form.horizontalSpacing;
+
+    int x = rect.x + rect.width - form.marginWidth - form.highlight;
+    int y = rect.y + form.marginHeight + form.highlight;
+
+    bool top = false;
+    if (form.separateTopCenter || minTopWidth > rect.width) {
+        int topHeight = Math.max(rightSize.y, leftSize.y);
+        if (right !is null && !right.isDisposed()) {
+            top = true;
+            x -= rightSize.x;
+            right.setBounds(x, y, rightSize.x, topHeight);
+            x -= form.horizontalSpacing;
+        }
+        if (left !is null && !left.isDisposed()) {
+            top = true;
+            int trim = computeTrim(left);
+            int leftW = x - rect.x - form.marginWidth - form.highlight - trim;
+            leftSize = computeChildSize(left, leftW, SWT.DEFAULT, false);
+            left.setBounds(rect.x + form.marginWidth + form.highlight, y, leftSize.x, topHeight);
+        }
+        if (top) y += topHeight + form.verticalSpacing;
+        if (center !is null && !center.isDisposed()) {
+            top = true;
+            int trim = computeTrim(center);
+            int w = rect.width - 2*form.marginWidth - 2*form.highlight - trim;
+            centerSize = computeChildSize(center, w, SWT.DEFAULT, false);
+            center.setBounds(rect.x + rect.width - form.marginWidth - form.highlight - centerSize.x, y, centerSize.x, centerSize.y);
+            y += centerSize.y + form.verticalSpacing;
+        }
+    } else {
+        int topHeight = Math.max(rightSize.y, Math.max(centerSize.y, leftSize.y));
+        if (right !is null && !right.isDisposed()) {
+            top = true;
+            x -= rightSize.x;
+            right.setBounds(x, y, rightSize.x, topHeight);
+            x -= form.horizontalSpacing;
+        }
+        if (center !is null && !center.isDisposed()) {
+            top = true;
+            x -= centerSize.x;
+            center.setBounds(x, y, centerSize.x, topHeight);
+            x -= form.horizontalSpacing;
+        }
+        if (left !is null && !left.isDisposed()) {
+            top = true;
+            Rectangle trim = ( null !is cast(Composite)left ) ? (cast(Composite)left).computeTrim(0, 0, 0, 0) : new Rectangle(0, 0, 0, 0);
+            int w = x - rect.x - form.marginWidth - form.highlight - trim.width;
+            int h = topHeight - trim.height;
+            leftSize = computeChildSize(left, w, h, false);
+            left.setBounds(rect.x + form.marginWidth + form.highlight, y, leftSize.x, topHeight);
+        }
+        if (top)y += topHeight + form.verticalSpacing;
+    }
+    int oldSeperator = form.separator;
+    form.separator = -1;
+    if (content !is null && !content.isDisposed()) {
+        if (left !is null || right !is null || center !is null){
+            form.separator = y;
+            y++;
+        }
+         content.setBounds(rect.x + form.marginWidth + form.highlight, y, rect.width - 2 * form.marginWidth - 2*form.highlight, rect.y + rect.height - y - form.marginHeight - form.highlight);
+    }
+    if (oldSeperator !is -1 && form.separator !is -1) {
+        int t = Math.min(form.separator, oldSeperator);
+        int b = Math.max(form.separator, oldSeperator);
+        form.redraw(form.borderLeft, t, form.getSize().x - form.borderLeft - form.borderRight, b - t, false);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/custom/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,62 @@
+module org.eclipse.swt.custom.all;
+
+public import org.eclipse.swt.custom.AnimatedProgress;
+public import org.eclipse.swt.custom.BidiSegmentEvent;
+public import org.eclipse.swt.custom.BidiSegmentListener;
+public import org.eclipse.swt.custom.Bullet;
+public import org.eclipse.swt.custom.BusyIndicator;
+public import org.eclipse.swt.custom.CBanner;
+public import org.eclipse.swt.custom.CBannerLayout;
+public import org.eclipse.swt.custom.CCombo;
+public import org.eclipse.swt.custom.CLabel;
+public import org.eclipse.swt.custom.CLayoutData;
+public import org.eclipse.swt.custom.CTabFolder2Adapter;
+public import org.eclipse.swt.custom.CTabFolder2Listener;
+public import org.eclipse.swt.custom.CTabFolder;
+public import org.eclipse.swt.custom.CTabFolderAdapter;
+public import org.eclipse.swt.custom.CTabFolderEvent;
+public import org.eclipse.swt.custom.CTabFolderLayout;
+public import org.eclipse.swt.custom.CTabFolderListener;
+public import org.eclipse.swt.custom.CTabItem;
+public import org.eclipse.swt.custom.ControlEditor;
+public import org.eclipse.swt.custom.DefaultContent;
+public import org.eclipse.swt.custom.ExtendedModifyEvent;
+public import org.eclipse.swt.custom.ExtendedModifyListener;
+public import org.eclipse.swt.custom.LineBackgroundEvent;
+public import org.eclipse.swt.custom.LineBackgroundListener;
+public import org.eclipse.swt.custom.LineStyleEvent;
+public import org.eclipse.swt.custom.LineStyleListener;
+public import org.eclipse.swt.custom.MovementEvent;
+public import org.eclipse.swt.custom.MovementListener;
+public import org.eclipse.swt.custom.PaintObjectEvent;
+public import org.eclipse.swt.custom.PaintObjectListener;
+public import org.eclipse.swt.custom.PopupList;
+public import org.eclipse.swt.custom.ST;
+public import org.eclipse.swt.custom.SashForm;
+public import org.eclipse.swt.custom.SashFormData;
+public import org.eclipse.swt.custom.SashFormLayout;
+public import org.eclipse.swt.custom.ScrolledComposite;
+public import org.eclipse.swt.custom.ScrolledCompositeLayout;
+public import org.eclipse.swt.custom.StackLayout;
+public import org.eclipse.swt.custom.StyleRange;
+public import org.eclipse.swt.custom.StyledText;
+public import org.eclipse.swt.custom.StyledTextContent;
+public import org.eclipse.swt.custom.StyledTextDropTargetEffect;
+public import org.eclipse.swt.custom.StyledTextEvent;
+public import org.eclipse.swt.custom.StyledTextListener;
+public import org.eclipse.swt.custom.StyledTextPrintOptions;
+public import org.eclipse.swt.custom.StyledTextRenderer;
+public import org.eclipse.swt.custom.TableCursor;
+public import org.eclipse.swt.custom.TableEditor;
+public import org.eclipse.swt.custom.TableTree;
+public import org.eclipse.swt.custom.TableTreeEditor;
+public import org.eclipse.swt.custom.TableTreeItem;
+public import org.eclipse.swt.custom.TextChangeListener;
+public import org.eclipse.swt.custom.TextChangedEvent;
+public import org.eclipse.swt.custom.TextChangingEvent;
+public import org.eclipse.swt.custom.TreeEditor;
+public import org.eclipse.swt.custom.VerifyKeyListener;
+public import org.eclipse.swt.custom.ViewForm;
+public import org.eclipse.swt.custom.ViewFormLayout;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ByteArrayTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.ByteArrayTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+
+import java.lang.all;
+
+/**
+ * The class <code>ByteArrayTransfer</code> provides a platform specific
+ * mechanism for converting a java <code>byte[]</code> to a platform
+ * specific representation of the byte array and vice versa.
+ *
+ * <p><code>ByteArrayTransfer</code> is never used directly but is sub-classed
+ * by transfer agents that convert between data in a java format such as a
+ * <code>String</code> and a platform specific byte array.
+ *
+ * <p>If the data you are converting <b>does not</b> map to a
+ * <code>byte[]</code>, you should sub-class <code>Transfer</code> directly
+ * and do your own mapping to a platform data type.</p>
+ *
+ * <p>The following snippet shows a subclass of ByteArrayTransfer that transfers
+ * data defined by the class <code>MyType</code>.</p>
+ *
+ * <pre><code>
+ * public class MyType {
+ *  public String fileName;
+ *  public long fileLength;
+ *  public long lastModified;
+ * }
+ * </code></pre>
+ *
+ * <pre><code>
+ * public class MyTypeTransfer extends ByteArrayTransfer {
+ *
+ *  private static final String MYTYPENAME = "my_type_name";
+ *  private static final int MYTYPEID = registerType(MYTYPENAME);
+ *  private static MyTypeTransfer _instance = new MyTypeTransfer();
+ *
+ * private MyTypeTransfer() {}
+ *
+ * public static MyTypeTransfer getInstance () {
+ *  return _instance;
+ * }
+ * public void javaToNative (Object object, TransferData transferData) {
+ *  if (object is null || !(object instanceof MyType[])) return;
+ *
+ *  if (isSupportedType(transferData)) {
+ *      MyType[] myTypes = (MyType[]) object;
+ *      try {
+ *          // write data to a byte array and then ask super to convert to pMedium
+ *          ByteArrayOutputStream out = new ByteArrayOutputStream();
+ *          DataOutputStream writeOut = new DataOutputStream(out);
+ *          for (int i = 0, length = myTypes.length; i &lt; length;  i++){
+ *              byte[] buffer = myTypes[i].fileName.getBytes();
+ *              writeOut.writeInt(buffer.length);
+ *              writeOut.write(buffer);
+ *              writeOut.writeLong(myTypes[i].fileLength);
+ *              writeOut.writeLong(myTypes[i].lastModified);
+ *          }
+ *          byte[] buffer = out.toByteArray();
+ *          writeOut.close();
+ *
+ *          super.javaToNative(buffer, transferData);
+ *
+ *      } catch (IOException e) {
+ *      }
+ *  }
+ * }
+ * public Object nativeToJava(TransferData transferData){
+ *
+ *  if (isSupportedType(transferData)) {
+ *
+ *      byte[] buffer = (byte[])super.nativeToJava(transferData);
+ *      if (buffer is null) return null;
+ *
+ *      MyType[] myData = new MyType[0];
+ *      try {
+ *          ByteArrayInputStream in = new ByteArrayInputStream(buffer);
+ *          DataInputStream readIn = new DataInputStream(in);
+ *          while(readIn.available() > 20) {
+ *              MyType datum = new MyType();
+ *              int size = readIn.readInt();
+ *              byte[] name = new byte[size];
+ *              readIn.read(name);
+ *              datum.fileName = new String(name);
+ *              datum.fileLength = readIn.readLong();
+ *              datum.lastModified = readIn.readLong();
+ *              MyType[] newMyData = new MyType[myData.length + 1];
+ *              System.arraycopy(myData, 0, newMyData, 0, myData.length);
+ *              newMyData[myData.length] = datum;
+ *              myData = newMyData;
+ *          }
+ *          readIn.close();
+ *      } catch (IOException ex) {
+ *          return null;
+ *      }
+ *      return myData;
+ *  }
+ *
+ *  return null;
+ * }
+ * protected String[] getTypeNames(){
+ *  return new String[]{MYTYPENAME};
+ * }
+ * protected int[] getTypeIds(){
+ *  return new int[] {MYTYPEID};
+ * }
+ * }
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public abstract class ByteArrayTransfer : Transfer {
+
+public TransferData[] getSupportedTypes() {
+    int[] types = getTypeIds();
+    TransferData[] data = new TransferData[types.length];
+    for (int i = 0; i < types.length; i++) {
+        data[i] = new TransferData();
+        data[i].type = types[i];
+        data[i].formatetc = new FORMATETC();
+        data[i].formatetc.cfFormat = types[i];
+        data[i].formatetc.dwAspect = COM.DVASPECT_CONTENT;
+        data[i].formatetc.lindex = -1;
+        data[i].formatetc.tymed = COM.TYMED_HGLOBAL;
+    }
+    return data;
+}
+
+public bool isSupportedType(TransferData transferData){
+    if (transferData is null) return false;
+    int[] types = getTypeIds();
+    for (int i = 0; i < types.length; i++) {
+        FORMATETC* format = transferData.formatetc;
+        if (format.cfFormat is types[i] &&
+            (format.dwAspect & COM.DVASPECT_CONTENT) is COM.DVASPECT_CONTENT &&
+            (format.tymed & COM.TYMED_HGLOBAL) is COM.TYMED_HGLOBAL  )
+            return true;
+    }
+    return false;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts a java
+ * <code>byte[]</code> to a platform specific representation.
+ * 
+ * @param object a java <code>byte[]</code> containing the data to be converted
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+protected void javaToNative (Object object, TransferData transferData) {
+    if (!checkByteArray(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    // Allocate the memory because the caller (DropTarget) has not handed it in
+    // The caller of this method must release the data when it is done with it.
+    byte[] data = (cast(ArrayWrapperByte)object).array;
+    int size = data.length;
+    auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
+    OS.MoveMemory(newPtr, data.ptr, size);
+    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 a byte array to a java <code>byte[]</code>.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>byte[]</code> containing the converted data if the conversion was
+ *      successful; otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+protected Object nativeToJava(TransferData transferData) {
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null)  return null;
+
+    IDataObject data = transferData.pIDataObject;
+    data.AddRef();
+    FORMATETC* formatetc = transferData.formatetc;
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = getData(data, formatetc, stgmedium);
+    data.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    auto hMem = stgmedium.unionField;
+    int size = OS.GlobalSize(hMem);
+    byte[] buffer = new byte[size];
+    auto ptr = OS.GlobalLock(hMem);
+    OS.MoveMemory(buffer.ptr, ptr, size);
+    OS.GlobalUnlock(hMem);
+    OS.GlobalFree(hMem);
+    return new ArrayWrapperByte(buffer);
+}
+
+bool checkByteArray(Object object) {
+    return (object !is null && ( null !is cast(ArrayWrapperByte)object) && (cast(ArrayWrapperByte)object).array.length > 0);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Clipboard.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,819 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.Clipboard;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.OleEnumFORMATETC;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+import tango.core.Thread;
+
+/**
+ * The <code>Clipboard</code> provides a mechanism for transferring data from one
+ * application to another or within an application.
+ *
+ * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#clipboard">Clipboard snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ClipboardExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Clipboard {
+
+    private Display display;
+
+    // ole interfaces
+    private _IDataObjectImpl iDataObject;
+    private int refCount;
+    private Transfer[] transferAgents;
+    private Object[] data;
+    private int CFSTR_PREFERREDDROPEFFECT;
+
+/**
+ * Constructs a new instance of this class.  Creating an instance of a Clipboard
+ * may cause system resources to be allocated depending on the platform.  It is therefore
+ * mandatory that the Clipboard instance be disposed when no longer required.
+ *
+ * @param display the display on which to allocate the clipboard
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Clipboard#dispose
+ * @see Clipboard#checkSubclass
+ */
+public this(Display display) {
+    checkSubclass ();
+    if (display is null) {
+        display = Display.getCurrent();
+        if (display is null) {
+            display = Display.getDefault();
+        }
+    }
+    if (display.getThread() !is Thread.getThis()) {
+        DND.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+    }
+    this.display = display;
+    TCHAR* chFormatName = StrToTCHARz(0, "Preferred DropEffect"); //$NON-NLS-1$
+    CFSTR_PREFERREDDROPEFFECT = OS.RegisterClipboardFormat(chFormatName);
+    createCOMInterfaces();
+    this.AddRef();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * The SWT class library is intended to be subclassed
+ * only at specific, controlled points. This method enforces this
+ * rule unless it is overridden.
+ * </p><p>
+ * <em>IMPORTANT:</em> By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between SWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ * </p><p>
+ * The ability to subclass outside of the allowed SWT classes
+ * is intended purely to enable those not on the SWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+protected void checkSubclass () {
+    String name = this.classinfo.name;
+    String validName = Clipboard.classinfo.name;
+    if (validName!=/*eq*/name) {
+        DND.error (SWT.ERROR_INVALID_SUBCLASS);
+    }
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * widget implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code>) on a widget that has had its
+ * <code>dispose()</code> method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * </p>
+ *
+ * @exception SWTException <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>
+ */
+protected void checkWidget () {
+    Display display = this.display;
+    if (display is null) DND.error (SWT.ERROR_WIDGET_DISPOSED);
+    if (display.getThread() !is Thread.getThis ()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    if (display.isDisposed()) DND.error(SWT.ERROR_WIDGET_DISPOSED);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the system clipboard,
+ * clear the contents.  If this clipboard is not the owner, then nothing is done.
+ * Note that there are clipboard assistant applications that take ownership of
+ * data or make copies of data when it is placed on the clipboard.  In these
+ * cases, it may not be possible to clear the clipboard.
+ *
+ * @exception SWTException <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.1
+ */
+public void clearContents() {
+    clearContents(DND.CLIPBOARD);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the specified
+ * clipboard, clear the contents.  If this clipboard is not the owner, then
+ * nothing is done.
+ *
+ * <p>Note that there are clipboard assistant applications that take ownership
+ * of data or make copies of data when it is placed on the clipboard.  In these
+ * cases, it may not be possible to clear the clipboard.</p>
+ *
+ * <p>The clipboards value is either one of the clipboard constants defined in
+ * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> clipboard constants.</p>
+ *
+ * @param clipboards to be cleared
+ *
+ * @exception SWTException <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 DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void clearContents(int clipboards) {
+    checkWidget();
+    if ((clipboards & DND.CLIPBOARD) !is 0) {
+        /* OleIsCurrentClipboard([in] pDataObject)
+         * The argument pDataObject is owned by the caller so reference count does not
+         * need to be incremented.
+         */
+        if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+            /* OleSetClipboard([in] pDataObject)
+             * The argument pDataObject is owned by the caller so reference count does not
+             * need to be incremented.
+             */
+            COM.OleSetClipboard(null);
+        }
+    }
+}
+
+/**
+ * Disposes of the operating system resources associated with the clipboard.
+ * The data will still be available on the system clipboard after the dispose
+ * method is called.
+ *
+ * <p>NOTE: On some platforms the data will not be available once the application
+ * has exited or the display has been disposed.</p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ */
+public void dispose () {
+    if (isDisposed()) return;
+    if (display.getThread() !is Thread.getThis ()) DND.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+    /* OleIsCurrentClipboard([in] pDataObject)
+     * The argument pDataObject is owned by the caller so reference count does not
+     * need to be incremented.
+     */
+    if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+        COM.OleFlushClipboard();
+    }
+    this.Release();
+    display = null;
+}
+
+/**
+ * Retrieve the data of the specified type currently available on the system
+ * clipboard.  Refer to the specific subclass of <code>Transfer</code> to
+ * determine the type of object returned.
+ *
+ * <p>The following snippet shows text and RTF text being retrieved from the
+ * clipboard:</p>
+ *
+ *    <code><pre>
+ *    Clipboard clipboard = new Clipboard(display);
+ *    TextTransfer textTransfer = TextTransfer.getInstance();
+ *    String textData = (String)clipboard.getContents(textTransfer);
+ *    if (textData !is null) System.out.println("Text is "+textData);
+ *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *    String rtfData = (String)clipboard.getContents(rtfTransfer);
+ *    if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ *    clipboard.dispose();
+ *    </code></pre>
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception SWTException <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_NULL_ARGUMENT - if transfer is null</li>
+ * </ul>
+ *
+ * @see Transfer
+ */
+public Object getContents(Transfer transfer) {
+    return getContents(transfer, DND.CLIPBOARD);
+}
+/**
+ * Retrieve the data of the specified type currently available on the specified
+ * clipboard.  Refer to the specific subclass of <code>Transfer</code> to
+ * determine the type of object returned.
+ *
+ * <p>The following snippet shows text and RTF text being retrieved from the
+ * clipboard:</p>
+ *
+ *    <code><pre>
+ *    Clipboard clipboard = new Clipboard(display);
+ *    TextTransfer textTransfer = TextTransfer.getInstance();
+ *    String textData = (String)clipboard.getContents(textTransfer);
+ *    if (textData !is null) System.out.println("Text is "+textData);
+ *    RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *    String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
+ *    if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ *    clipboard.dispose();
+ *    </code></pre>
+ *
+ * <p>The clipboards value is either one of the clipboard constants defined in
+ * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> clipboard constants.</p>
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @param clipboards on which to look for data
+ *
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception SWTException <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_NULL_ARGUMENT - if transfer is null</li>
+ * </ul>
+ *
+ * @see Transfer
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public Object getContents(Transfer transfer, int clipboards) {
+    checkWidget();
+    if (transfer is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+    if ((clipboards & DND.CLIPBOARD) is 0) return null;
+    /*
+    * Bug in Windows. When a new application takes control
+    * of the clipboard, other applications may open the
+    * clipboard to determine if they want to record the
+    * clipboard updates.  When this happens, the clipboard
+    * can not be accessed until the other application is
+    * finished.  To allow the other applications to release
+    * the clipboard, use PeekMessage() to enable cross thread
+    * message sends.
+    */
+    IDataObject dataObject;
+    int retryCount = 0;
+    /* OleGetClipboard([out] ppDataObject).
+     * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+     */
+    int result = COM.OleGetClipboard(&dataObject);
+    while (result !is COM.S_OK && retryCount++ < 10) {
+        try {Thread.sleep(0.050);} catch (Exception t) {}
+        MSG msg;
+        OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+        result = COM.OleGetClipboard(&dataObject);
+    }
+    if (result !is COM.S_OK) return null;
+    try {
+        TransferData[] allowed = transfer.getSupportedTypes();
+        for (int i = 0; i < allowed.length; i++) {
+            if (dataObject.QueryGetData(allowed[i].formatetc) is COM.S_OK) {
+                TransferData data = allowed[i];
+                data.pIDataObject = dataObject;
+                return transfer.nativeToJava(data);
+            }
+        }
+    } finally {
+        dataObject.Release();
+    }
+    return null; // No data available for this transfer
+}
+/**
+ * Returns <code>true</code> if the clipboard has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the clipboard.
+ * When a clipboard has been disposed, it is an error to
+ * invoke any other method using the clipboard.
+ * </p>
+ *
+ * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
+ *
+ * @since 3.0
+ */
+public bool isDisposed () {
+    return (display is null);
+}
+
+/**
+ * Place data of the specified type on the system clipboard.  More than one type
+ * of data can be placed on the system clipboard at the same time.  Setting the
+ * data clears any previous data from the system clipboard, regardless of type.
+ *
+ * <p>NOTE: On some platforms, the data is immediately copied to the system
+ * clipboard but on other platforms it is provided upon request.  As a result,
+ * if the application modifies the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested.</p>
+ *
+ * <p>The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ * </p>
+ *
+ * <code><pre>
+ *  Clipboard clipboard = new Clipboard(display);
+ *  String textData = "Hello World";
+ *  String rtfData = "{\\rtf1\\b\\i Hello World}";
+ *  TextTransfer textTransfer = TextTransfer.getInstance();
+ *  RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *  Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ *  Object[] data = new Object[]{textData, rtfData};
+ *  clipboard.setContents(data, transfers);
+ *  clipboard.dispose();
+ * </code></pre>
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ *          or the length of data is not the same as the length of dataTypes</li>
+ * </ul>
+ * @exception SWTException <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 SWTError <ul>
+ *    <li>ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable</li>
+ * </ul>
+ *
+ * <p>NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.</p>
+ */
+public void setContents(Object[] data, Transfer[] dataTypes) {
+    setContents(data, dataTypes, DND.CLIPBOARD);
+}
+
+/**
+ * Place data of the specified type on the specified clipboard.  More than one
+ * type of data can be placed on the specified clipboard at the same time.
+ * Setting the data clears any previous data from the specified
+ * clipboard, regardless of type.
+ *
+ * <p>NOTE: On some platforms, the data is immediately copied to the specified
+ * clipboard but on other platforms it is provided upon request.  As a result,
+ * if the application modifies the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested.</p>
+ *
+ * <p>The clipboards value is either one of the clipboard constants defined in
+ * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> clipboard constants.</p>
+ *
+ * <p>The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ * </p>
+ *
+ * <code><pre>
+ *  Clipboard clipboard = new Clipboard(display);
+ *  String textData = "Hello World";
+ *  String rtfData = "{\\rtf1\\b\\i Hello World}";
+ *  TextTransfer textTransfer = TextTransfer.getInstance();
+ *  RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ *  Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ *  Object[] data = new Object[]{textData, rtfData};
+ *  clipboard.setContents(data, transfers, DND.CLIPBOARD);
+ *  clipboard.dispose();
+ * </code></pre>
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ * @param clipboards on which to set the data
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if data is null or datatypes is null
+ *          or the length of data is not the same as the length of dataTypes</li>
+ * </ul>
+ * @exception SWTException <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 SWTError <ul>
+ *    <li>ERROR_CANNOT_SET_CLIPBOARD - if the clipboard is locked or otherwise unavailable</li>
+ * </ul>
+ *
+ * <p>NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.</p>
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void setContents(Object[] data, Transfer[] dataTypes, int clipboards) {
+    checkWidget();
+    if (data is null || dataTypes is null || data.length !is dataTypes.length || data.length is 0) {
+        DND.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    for (int i = 0; i < data.length; i++) {
+        if (data[i] is null || dataTypes[i] is null || !dataTypes[i].validate(data[i])) {
+            DND.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+    if ((clipboards & DND.CLIPBOARD) is 0) return;
+    this.data = data;
+    this.transferAgents = dataTypes;
+    /* OleSetClipboard([in] pDataObject)
+     * The argument pDataObject is owned by the caller so the reference count does not
+     * need to be incremented.
+     */
+    int result = COM.OleSetClipboard(iDataObject);
+
+    /*
+    * Bug in Windows. When a new application takes control
+    * of the clipboard, other applications may open the
+    * clipboard to determine if they want to record the
+    * clipboard updates.  When this happens, the clipboard
+    * can not be flushed until the other application is
+    * finished.  To allow other applications to get the
+    * data, use PeekMessage() to enable cross thread
+    * message sends.
+    */
+    int retryCount = 0;
+    while (result !is COM.S_OK && retryCount++ < 10) {
+        try {Thread.sleep(0.050);} catch (Exception t) {}
+        MSG msg;
+        OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+        result = COM.OleSetClipboard(iDataObject);
+    }
+    if (result !is COM.S_OK) {
+        DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+    }
+}
+private int AddRef() {
+    refCount++;
+    return refCount;
+}
+private void createCOMInterfaces() {
+    // register each of the interfaces that this object implements
+    iDataObject = new _IDataObjectImpl( this );
+}
+private void disposeCOMInterfaces() {
+    iDataObject = null;
+}
+/*
+ * EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+ * Ownership of ppenumFormatetc transfers from callee to caller so reference count on ppenumFormatetc
+ * must be incremented before returning.  Caller is responsible for releasing ppenumFormatetc.
+ */
+LRESULT EnumFormatEtc(int dwDirection, IEnumFORMATETC* ppenumFormatetc) {
+    // only allow getting of data - SetData is not currently supported
+    if (dwDirection is COM.DATADIR_SET) return COM.E_NOTIMPL;
+    // what types have been registered?
+    TransferData[] allowedDataTypes = new TransferData[0];
+    for (int i = 0; i < transferAgents.length; i++){
+        TransferData[] formats = transferAgents[i].getSupportedTypes();
+        TransferData[] newAllowedDataTypes = new TransferData[allowedDataTypes.length + formats.length];
+        System.arraycopy(allowedDataTypes, 0, newAllowedDataTypes, 0, allowedDataTypes.length);
+        System.arraycopy(formats, 0, newAllowedDataTypes, allowedDataTypes.length, formats.length);
+        allowedDataTypes = newAllowedDataTypes;
+    }
+    OleEnumFORMATETC enumFORMATETC = new OleEnumFORMATETC();
+    enumFORMATETC.AddRef();
+    FORMATETC*[] formats = new FORMATETC*[allowedDataTypes.length + 1];
+    for (int i = 0; i < allowedDataTypes.length; i++){
+        formats[i] = allowedDataTypes[i].formatetc;
+    }
+    // include the drop effect format to specify a copy operation
+    FORMATETC* dropeffect = new FORMATETC();
+    dropeffect.cfFormat = CFSTR_PREFERREDDROPEFFECT;
+    dropeffect.dwAspect = COM.DVASPECT_CONTENT;
+    dropeffect.lindex = -1;
+    dropeffect.tymed = COM.TYMED_HGLOBAL;
+    formats[formats.length -1] = dropeffect;
+    enumFORMATETC.setFormats(formats);
+
+    // TODO: <shawn liu> do we need AddRef() here
+    *ppenumFormatetc = enumFORMATETC.getAddress();
+    return COM.S_OK;
+}
+
+private IDataObject getAddress(){
+    return iDataObject;
+}
+
+LRESULT GetData(FORMATETC *pFormatetc, STGMEDIUM *pmedium) {
+    /* Called by a data consumer to obtain data from a source data object.
+       The GetData method renders the data described in the specified FORMATETC
+       structure and transfers it through the specified STGMEDIUM structure.
+       The caller then assumes responsibility for releasing the STGMEDIUM structure.
+    */
+    if (pFormatetc is null || pmedium is null) return COM.E_INVALIDARG;
+    if (QueryGetData(pFormatetc) !is COM.S_OK) return COM.DV_E_FORMATETC;
+
+    TransferData transferData = new TransferData();
+    transferData.formatetc = new FORMATETC();
+    COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+    transferData.type = transferData.formatetc.cfFormat;
+    transferData.stgmedium = new STGMEDIUM();
+    transferData.result = COM.E_FAIL;
+
+    if (transferData.type is CFSTR_PREFERREDDROPEFFECT) {
+        // specify that a copy operation is to be performed
+        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);
+        return COM.S_OK;
+    }
+
+    // get matching transfer agent to perform conversion
+    int transferIndex = -1;
+    for (int i = 0; i < transferAgents.length; i++){
+        if (transferAgents[i].isSupportedType(transferData)){
+            transferIndex = i;
+            break;
+        }
+    }
+    if (transferIndex is -1) return COM.DV_E_FORMATETC;
+    transferAgents[transferIndex].javaToNative(data[transferIndex], transferData);
+    COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof);
+    return transferData.result;
+}
+
+LRESULT QueryGetData(FORMATETC * pFormatetc) {
+    if (transferAgents is null) return COM.E_FAIL;
+    TransferData transferData = new TransferData();
+    transferData.formatetc = new FORMATETC();
+    COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+    transferData.type = transferData.formatetc.cfFormat;
+    if (transferData.type is CFSTR_PREFERREDDROPEFFECT) return COM.S_OK;
+    // is this type supported by the transfer agent?
+    for (int i = 0; i < transferAgents.length; i++){
+        if (transferAgents[i].isSupportedType(transferData))
+            return COM.S_OK;
+    }
+
+    return COM.DV_E_FORMATETC;
+}
+/* QueryInterface([in] iid, [out] ppvObject)
+ * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
+ * must be incremented before returning.  Caller is responsible for releasing ppvObject.
+ */
+HRESULT QueryInterface(GUID* riid, void ** ppvObject) {
+    if (riid is null || ppvObject is null) return COM.E_INVALIDARG;
+    if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDataObject) ) {
+        *ppvObject = cast(void*)cast(IUnknown)iDataObject;
+        AddRef();
+        return COM.S_OK;
+    }
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+private ULONG Release() {
+    refCount--;
+    if (refCount is 0) {
+        this.data = null;
+        this.transferAgents = null;
+        disposeCOMInterfaces();
+        COM.CoFreeUnusedLibraries();
+    }
+    return refCount;
+}
+
+/**
+ * Returns an array of the data types currently available on the system
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ * @return array of data types currently available on the system clipboard
+ *
+ * @exception SWTException <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 Transfer#isSupportedType
+ *
+ * @since 3.0
+ */
+public TransferData[] getAvailableTypes() {
+    return getAvailableTypes(DND.CLIPBOARD);
+}
+
+/**
+ * Returns an array of the data types currently available on the specified
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ * <p>The clipboards value is either one of the clipboard constants defined in
+ * class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> clipboard constants.</p>
+ *
+ * @param clipboards from which to get the data types
+ * @return array of data types currently available on the specified clipboard
+ *
+ * @exception SWTException <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 Transfer#isSupportedType
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public TransferData[] getAvailableTypes(int clipboards) {
+    checkWidget();
+    if ((clipboards & DND.CLIPBOARD) is 0) return null;
+    FORMATETC*[] types = _getAvailableTypes();
+    TransferData[] data = new TransferData[types.length];
+    for (int i = 0; i < types.length; i++) {
+        data[i] = new TransferData();
+        data[i].type = types[i].cfFormat;
+        data[i].formatetc = types[i];
+    }
+    return data;
+}
+
+/**
+ * Returns a platform specific list of the data types currently available on the
+ * system clipboard.
+ *
+ * <p>Note: <code>getAvailableTypeNames</code> is a utility for writing a Transfer
+ * sub-class.  It should NOT be used within an application because it provides
+ * platform specific information.</p>
+ *
+ * @return a platform specific list of the data types currently available on the
+ * system clipboard
+ *
+ * @exception SWTException <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 String[] getAvailableTypeNames() {
+    checkWidget();
+    FORMATETC*[] types = _getAvailableTypes();
+    String[] names = new String[](types.length);
+    int maxSize = 128;
+    for (int i = 0; i < types.length; i++){
+        TCHAR[] buffer = NewTCHARs(0, maxSize);
+        int size = OS.GetClipboardFormatName(types[i].cfFormat, buffer.ptr, maxSize);
+        if (size !is 0) {
+            names[i] = TCHARzToStr(buffer.ptr)[0..size];
+        } else {
+            switch (types[i].cfFormat) {
+                case COM.CF_HDROP: names[i] = "CF_HDROP"; break; //$NON-NLS-1$
+                case COM.CF_TEXT: names[i] = "CF_TEXT"; break; //$NON-NLS-1$
+                case COM.CF_BITMAP: names[i] = "CF_BITMAP"; break; //$NON-NLS-1$
+                case COM.CF_METAFILEPICT: names[i] = "CF_METAFILEPICT"; break; //$NON-NLS-1$
+                case COM.CF_SYLK: names[i] = "CF_SYLK"; break; //$NON-NLS-1$
+                case COM.CF_DIF: names[i] = "CF_DIF"; break; //$NON-NLS-1$
+                case COM.CF_TIFF: names[i] = "CF_TIFF"; break; //$NON-NLS-1$
+                case COM.CF_OEMTEXT: names[i] = "CF_OEMTEXT"; break; //$NON-NLS-1$
+                case COM.CF_DIB: names[i] = "CF_DIB"; break; //$NON-NLS-1$
+                case COM.CF_PALETTE: names[i] = "CF_PALETTE"; break; //$NON-NLS-1$
+                case COM.CF_PENDATA: names[i] = "CF_PENDATA"; break; //$NON-NLS-1$
+                case COM.CF_RIFF: names[i] = "CF_RIFF"; break; //$NON-NLS-1$
+                case COM.CF_WAVE: names[i] = "CF_WAVE"; break; //$NON-NLS-1$
+                case COM.CF_UNICODETEXT: names[i] = "CF_UNICODETEXT"; break; //$NON-NLS-1$
+                case COM.CF_ENHMETAFILE: names[i] = "CF_ENHMETAFILE"; break; //$NON-NLS-1$
+                case COM.CF_LOCALE: names[i] = "CF_LOCALE"; break; //$NON-NLS-1$
+                case COM.CF_MAX: names[i] = "CF_MAX"; break; //$NON-NLS-1$
+                default: names[i] = "UNKNOWN"; //$NON-NLS-1$
+            }
+        }
+    }
+    return names;
+}
+
+private FORMATETC*[] _getAvailableTypes() {
+    FORMATETC*[] types = null;
+    IDataObject dataObject;
+    /* OleGetClipboard([out] ppDataObject).
+     * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+     */
+    if (COM.OleGetClipboard(&dataObject) !is COM.S_OK) return types;
+    IEnumFORMATETC enumFormatetc;
+    /* EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+     * AddRef has already been called on ppenumFormatetc by the callee and must be released by the caller.
+     */
+    int rc = dataObject.EnumFormatEtc(COM.DATADIR_GET, &enumFormatetc);
+    dataObject.Release();
+    if (rc !is COM.S_OK)return types;
+    // Loop over enumerator and save any types that match what we are looking for
+    //int /*long*/ rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+    uint[1] pceltFetched;
+    FORMATETC rgelt;
+    enumFormatetc.Reset();
+    while (enumFormatetc.Next(1, &rgelt, pceltFetched.ptr) is COM.S_OK && pceltFetched[0] is 1) {
+        FORMATETC* formatetc = new FORMATETC();
+        COM.MoveMemory(formatetc, &rgelt, FORMATETC.sizeof);
+        FORMATETC*[] newTypes = new FORMATETC*[types.length + 1];
+        SimpleType!(FORMATETC*).arraycopy(types, 0, newTypes, 0, types.length);
+        newTypes[types.length] = formatetc;
+        types = newTypes;
+    }
+    //OS.GlobalFree(rgelt);
+    enumFormatetc.Release();
+    return types;
+}
+}
+
+private class _IDataObjectImpl : IDataObject {
+
+    Clipboard   parent;
+    this(Clipboard  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(GUID* riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface IDataObject
+    LRESULT GetData( FORMATETC *pFormatetc, STGMEDIUM *pmedium) { return parent.GetData(pFormatetc, pmedium); }
+    LRESULT GetDataHere(FORMATETC * pFormatetc, STGMEDIUM * pmedium) { return COM.E_NOTIMPL; }
+    LRESULT QueryGetData(FORMATETC* pFormatetc) { return parent.QueryGetData(pFormatetc); }
+    LRESULT GetCanonicalFormatEtc(FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut) { return COM.E_NOTIMPL; }
+    LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) { return COM.E_NOTIMPL; }
+    LRESULT EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC * ppenumFormatetc) { return parent.EnumFormatEtc(dwDirection, ppenumFormatetc); }
+    LRESULT DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink pAdvSink, DWORD* pdwConnection) { return COM.E_NOTIMPL; }
+    LRESULT DUnadvise(DWORD dwConnection) { return COM.E_NOTIMPL; }
+    LRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise) { return COM.E_NOTIMPL; }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DND.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DND;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ *
+ * Class DND contains all the constants used in defining a
+ * DragSource or a DropTarget.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DND {
+
+    /**
+     * The transfer mechanism for data that is being cut
+     * and then pasted or copied and then pasted (value is 1).
+     *
+     * @see Clipboard
+     *
+     * @since 3.1
+     */
+    public const static int CLIPBOARD = 1 << 0;
+
+    /**
+     * The transfer mechanism for clients that use the selection
+     * mechanism (value is 2).
+     *
+     * @see Clipboard
+     *
+     * @since 3.1
+     */
+    public const static int SELECTION_CLIPBOARD = 1 << 1;
+
+    /**
+     * Drag and Drop Operation: no drag/drop operation performed
+     * (value is 0).
+     */
+    public const static int DROP_NONE = 0;
+
+    /**
+     * Drag and Drop Operation: a copy of the data in the drag source is
+     * added to the drop target (value is 1 &lt;&lt; 0).
+     */
+    public const static int DROP_COPY = 1 << 0;
+
+    /**
+     * Drag and Drop Operation: a copy of the data is added to the drop target and
+     * the original data is removed from the drag source (value is 1 &lt;&lt; 1).
+     */
+    public const static int DROP_MOVE = 1 << 1;
+
+    /**
+     * Drag and Drop Operation: the drop target makes a link to the data in
+     * the drag source (value is 1 &lt;&lt; 2).
+     */
+    public const static int DROP_LINK = 1 << 2;
+
+    /**
+     * Drag and Drop Operation: the drop target moves the data and the drag source removes
+     * any references to the data and updates its display.  This is not available on all platforms
+     * and is only used when a non-SWT application is the drop target.  In this case, the SWT
+     * drag source is informed in the dragFinished event that the drop target has moved the data.
+     * (value is 1 &lt;&lt; 3).
+     *
+     * @see DragSourceListener#dragFinished
+     */
+    public const static int DROP_TARGET_MOVE = 1 << 3;
+
+    /**
+     * Drag and Drop Operation: During a dragEnter event or a dragOperationChanged, if no modifier keys
+     * are pressed, the operation is set to DROP_DEFAULT.  The application can choose what the default
+     * operation should be by setting a new value in the operation field.  If no value is choosen, the
+     * default operation for the platform will be selected (value is 1 &lt;&lt; 4).
+     *
+     * @see DropTargetListener#dragEnter
+     * @see DropTargetListener#dragOperationChanged
+     * @since 2.0
+     */
+    public const static int DROP_DEFAULT = 1 << 4;
+
+    /**
+     * DragSource Event: the drop has successfully completed or has been terminated (such as hitting
+     * the ESC key); perform cleanup such as removing data on a move operation (value is 2000).
+     */
+    public static const int DragEnd     = 2000;
+
+    /**
+     * DragSource Event: the data to be dropped is required from the drag source (value is 2001).
+     */
+    public static const int DragSetData = 2001;
+
+    /**
+     * DropTarget Event: the cursor has entered the drop target boundaries (value is 2002).
+     */
+    public static const int DragEnter   = 2002;
+
+    /**
+     * 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 mouse button over this target) (value is 2003).
+     */
+    public static const int DragLeave   = 2003;
+
+    /**
+     * DropTarget Event: the cursor is over the drop target (value is 2004).
+     */
+    public static const int DragOver    = 2004;
+
+    /**
+     * DropTarget Event: the operation being performed has changed usually due to the user
+     * changing the selected modifier keys while dragging (value is 2005).
+     */
+    public static const int DragOperationChanged = 2005;
+
+    /**
+     * DropTarget Event: the data has been dropped (value is 2006).
+     */
+    public static const int Drop = 2006;
+
+    /**
+     * DropTarget Event: the drop target is given a last chance to modify the drop (value is 2007).
+     */
+    public static const int DropAccept  = 2007;
+
+    /**
+     * DragSource Event: a drag is about to begin (value is 2008).
+     */
+    public static const int DragStart = 2008;
+
+    /**
+     * DropTarget drag under effect: No effect is shown (value is 0).
+     */
+    public static const int FEEDBACK_NONE = 0;
+
+    /**
+     * DropTarget drag under effect: The item under the cursor is selected; applies to tables
+     * and trees (value is 1).
+     */
+    public static const int FEEDBACK_SELECT = 1;
+
+    /**
+     * DropTarget drag under effect: An insertion mark is shown before the item under the cursor; applies to
+     * trees (value is 2).
+     */
+    public static const int FEEDBACK_INSERT_BEFORE = 2;
+
+    /**
+     * DropTarget drag under effect:An insertion mark is shown after the item under the cursor; applies to
+     * trees (value is 4).
+     */
+    public static const int FEEDBACK_INSERT_AFTER = 4;
+
+    /**
+     * DropTarget drag under effect: The widget is scrolled up or down to allow the user to drop on items that
+     * are not currently visible;  applies to tables and trees (value is 8).
+     */
+    public static const int FEEDBACK_SCROLL = 8;
+
+    /**
+     * DropTarget drag under effect: The item currently under the cursor is expanded to allow the user to
+     * select a drop target from a sub item; applies to trees (value is 16).
+     */
+    public static const int FEEDBACK_EXPAND = 16;
+
+    /**
+     * Error code: drag source can not be initialized (value is 2000).
+     */
+    public static const int ERROR_CANNOT_INIT_DRAG = 2000;
+
+    /**
+     * Error code: drop target cannot be initialized (value is 2001).
+     */
+    public static const int ERROR_CANNOT_INIT_DROP = 2001;
+
+    /**
+     * Error code: Data can not be set on system clipboard (value is 2002).
+     */
+    public static const int ERROR_CANNOT_SET_CLIPBOARD = 2002;
+
+    /**
+     * Error code: Data does not have correct format for type (value is 2003).
+     * @since 3.1
+     */
+    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$
+    static const String CANNOT_SET_CLIPBOARD_MESSAGE = "Cannot set data in clipboard"; //$NON-NLS-1$
+    static const String INVALID_DATA_MESSAGE = "Data does not have correct format for type"; //$NON-NLS-1$
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ *
+ * @param code the DND error code
+ */
+public static void error (int code) {
+    error (code, 0);
+}
+
+/**
+ * Throws an appropriate exception based on the passed in error code.
+ * The <code>hresult</code> argument should be either 0, or the
+ * platform specific error code.
+ * <p>
+ * In DND, errors are reported by throwing one of three exceptions:
+ * <dl>
+ * <dd>java.lang.IllegalArgumentException</dd>
+ * <dt>thrown whenever one of the API methods is invoked with an illegal argument</dt>
+ * <dd>org.eclipse.swt.SWTException (extends java.lang.RuntimeException)</dd>
+ * <dt>thrown whenever a recoverable error happens internally in SWT</dt>
+ * <dd>org.eclipse.swt.SWTError (extends java.lang.Error)</dd>
+ * <dt>thrown whenever a <b>non-recoverable</b> error happens internally in SWT</dt>
+ * </dl>
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ * </p>
+ *
+ * @param code the DND error code.
+ * @param hresult the platform specific error code.
+ *
+ * @see SWTError
+ * @see SWTException
+ * @see IllegalArgumentException
+ */
+public static void error (int code, int hresult) {
+    switch (code) {
+        /* OS Failure/Limit (fatal, may occur only on some platforms) */
+        case DND.ERROR_CANNOT_INIT_DRAG:{
+            String msg = DND.INIT_DRAG_MESSAGE;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+            throw new SWTError (code, msg);
+        }
+        case DND.ERROR_CANNOT_INIT_DROP:{
+            String msg = DND.INIT_DROP_MESSAGE;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+            throw new SWTError (code, msg);
+        }
+        case DND.ERROR_CANNOT_SET_CLIPBOARD:{
+            String msg = DND.CANNOT_SET_CLIPBOARD_MESSAGE;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+            throw new SWTError (code, msg);
+        }
+        case DND.ERROR_INVALID_DATA:{
+            String msg = DND.INVALID_DATA_MESSAGE;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        default:
+    }
+
+    /* Unknown/Undefined Error */
+    SWT.error(code);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DNDEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DNDEvent;
+
+
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.dnd.TransferData;
+
+class DNDEvent : Event {
+    public TransferData dataType;
+    public TransferData[] dataTypes;
+    public int operations;
+    public int feedback;
+    public Image image;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DNDListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DNDListener;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DNDEvent;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceEffect;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.DropTargetEffect;
+import org.eclipse.swt.dnd.DropTarget;
+
+
+class DNDListener : TypedListener {
+    Widget dndWidget;
+/**
+ * DNDListener constructor comment.
+ * @param listener org.eclipse.swt.internal.SWTEventListener
+ */
+this(SWTEventListener listener) {
+    super(listener);
+}
+public override void handleEvent (Event e) {
+    switch (e.type) {
+        case DND.DragStart: {
+            DragSourceEvent event = new DragSourceEvent(cast(DNDEvent)e);
+            DragSourceEffect sourceEffect = (cast(DragSource) dndWidget).getDragSourceEffect();
+            if (sourceEffect !is null) {
+                sourceEffect.dragStart (event);
+            }
+            (cast(DragSourceListener) eventListener).dragStart (event);
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragEnd: {
+            DragSourceEvent event = new DragSourceEvent(cast(DNDEvent)e);
+            DragSourceEffect sourceEffect = (cast(DragSource) dndWidget).getDragSourceEffect();
+            if (sourceEffect !is null) {
+                sourceEffect.dragFinished (event);
+            }
+            (cast(DragSourceListener) eventListener).dragFinished (event);
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragSetData: {
+            DragSourceEvent event = new DragSourceEvent(cast(DNDEvent)e);
+            DragSourceEffect sourceEffect = (cast(DragSource) dndWidget).getDragSourceEffect();
+            if (sourceEffect !is null) {
+                sourceEffect.dragSetData (event);
+            }
+            (cast(DragSourceListener) eventListener).dragSetData (event);
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragEnter: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).dragEnter (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.dragEnter (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragLeave: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).dragLeave (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.dragLeave (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragOver: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).dragOver (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.dragOver (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.Drop: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).drop (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.drop (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DropAccept: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).dropAccept (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.dropAccept (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        case DND.DragOperationChanged: {
+            DropTargetEvent event = new DropTargetEvent(cast(DNDEvent)e);
+            (cast(DropTargetListener) eventListener).dragOperationChanged (event);
+            DropTargetEffect dropEffect = (cast(DropTarget) dndWidget).getDropTargetEffect();
+            if (dropEffect !is null) {
+                dropEffect.dragOperationChanged (event);
+            }
+            event.updateEvent(cast(DNDEvent)e);
+            break;
+        }
+        default:
+
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSource.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,772 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DragSource;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.ifs;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.dnd.DragSourceEffect;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DNDListener;
+import org.eclipse.swt.dnd.DNDEvent;
+import org.eclipse.swt.dnd.TreeDragSourceEffect;
+import org.eclipse.swt.dnd.TableDragSourceEffect;
+import org.eclipse.swt.dnd.OleEnumFORMATETC;
+
+import java.lang.all;
+
+/**
+ *
+ * <code>DragSource</code> defines the source object for a drag and drop transfer.
+ *
+ * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p>
+ *
+ * <p>A drag source is the object which originates a drag and drop operation. For the specified widget,
+ * it defines the type of data that is available for dragging and the set of operations that can
+ * be performed on that data.  The operations can be any bit-wise combination of DND.MOVE, DND.COPY or
+ * DND.LINK.  The type of data that can be transferred is specified by subclasses of Transfer such as
+ * TextTransfer or FileTransfer.  The type of data transferred can be a predefined system type or it
+ * can be a type defined by the application.  For instructions on how to define your own transfer type,
+ * refer to <code>ByteArrayTransfer</code>.</p>
+ *
+ * <p>You may have several DragSources in an application but you can only have one DragSource
+ * per Control.  Data dragged from this DragSource can be dropped on a site within this application
+ * or it can be dropped on another application such as an external Text editor.</p>
+ *
+ * <p>The application supplies the content of the data being transferred by implementing the
+ * <code>DragSourceListener</code> and associating it with the DragSource via DragSource#addDragListener.</p>
+ *
+ * <p>When a successful move operation occurs, the application is required to take the appropriate
+ * action to remove the data from its display and remove any associated operating system resources or
+ * internal references.  Typically in a move operation, the drop target makes a copy of the data
+ * and the drag source deletes the original.  However, sometimes copying the data can take a long
+ * time (such as copying a large file).  Therefore, on some platforms, the drop target may actually
+ * move the data in the operating system rather than make a copy.  This is usually only done in
+ * file transfers.  In this case, the drag source is informed in the DragEnd event that a
+ * DROP_TARGET_MOVE was performed.  It is the responsibility of the drag source at this point to clean
+ * up its displayed information.  No action needs to be taken on the operating system resources.</p>
+ *
+ * <p> The following example shows a Label widget that allows text to be dragged from it.</p>
+ *
+ * <code><pre>
+ *  // Enable a label as a Drag Source
+ *  Label label = new Label(shell, SWT.NONE);
+ *  // This example will allow text to be dragged
+ *  Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ *  // This example will allow the text to be copied or moved to the drop target
+ *  int operations = DND.DROP_MOVE | DND.DROP_COPY;
+ *
+ *  DragSource source = new DragSource(label, operations);
+ *  source.setTransfer(types);
+ *  source.addDragListener(new DragSourceListener() {
+ *      public void dragStart(DragSourceEvent e) {
+ *          // Only start the drag if there is actually text in the
+ *          // label - this text will be what is dropped on the target.
+ *          if (label.getText().length() is 0) {
+ *              event.doit = false;
+ *          }
+ *      };
+ *      public void dragSetData(DragSourceEvent event) {
+ *          // A drop has been performed, so provide the data of the
+ *          // requested type.
+ *          // (Checking the type of the requested data is only
+ *          // necessary if the drag source supports more than
+ *          // one data type but is shown here as an example).
+ *          if (TextTransfer.getInstance().isSupportedType(event.dataType)){
+ *              event.data = label.getText();
+ *          }
+ *      }
+ *      public void dragFinished(DragSourceEvent event) {
+ *          // A Move operation has been performed so remove the data
+ *          // from the source
+ *          if (event.detail is DND.DROP_MOVE)
+ *              label.setText("");
+ *      }
+ *  });
+ * </pre></code>
+ *
+ *
+ * <dl>
+ *  <dt><b>Styles</b></dt> <dd>DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK</dd>
+ *  <dt><b>Events</b></dt> <dd>DND.DragStart, DND.DragSetData, DND.DragEnd</dd>
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#dnd">Drag and Drop snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: DNDExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DragSource : Widget {
+
+    // info for registering as a drag source
+    Control control;
+    Listener controlListener;
+    Transfer[] transferAgents;
+    DragSourceEffect dragEffect;
+    Composite topControl;
+    HWND hwndDrag;
+
+    // ole interfaces
+    _IDropSourceImpl iDropSource;
+    _IDataObjectImpl iDataObject;
+    int refCount;
+
+    //workaround - track the operation performed by the drop target for DragEnd event
+    int dataEffect = DND.DROP_NONE;
+
+    static const String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
+    static const int CFSTR_PERFORMEDDROPEFFECT;
+    static final TCHAR[] WindowClass = "#32770\0";
+    static this(){
+        CFSTR_PERFORMEDDROPEFFECT  = Transfer.registerType("Performed DropEffect");     //$NON-NLS-1$
+    }
+/**
+ * Creates a new <code>DragSource</code> to handle dragging from the specified <code>Control</code>.
+ * Creating an instance of a DragSource may cause system resources to be allocated depending on the platform.
+ * It is therefore mandatory that the DragSource instance be disposed when no longer required.
+ *
+ * @param control the <code>Control</code> that the user clicks on to initiate the drag
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ *                  DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than one
+ *        drag source is created for a control or if the operating system will not allow the creation
+ *        of the drag source</li>
+ * </ul>
+ *
+ * <p>NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.</p>
+ *
+ * @see Widget#dispose
+ * @see DragSource#checkSubclass
+ * @see DND#DROP_NONE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ */
+public this(Control control, int style) {
+    super(control, checkStyle(style));
+    this.control = control;
+    if (control.getData(DND.DRAG_SOURCE_KEY) !is null) {
+        DND.error(DND.ERROR_CANNOT_INIT_DRAG);
+    }
+    control.setData(DND.DRAG_SOURCE_KEY, this);
+    createCOMInterfaces();
+    this.AddRef();
+
+    controlListener = new class() Listener {
+        public void handleEvent(Event event) {
+            if (event.type is SWT.Dispose) {
+                if (!this.outer.isDisposed()) {
+                    this.outer.dispose();
+                }
+            }
+            if (event.type is SWT.DragDetect) {
+                if (!this.outer.isDisposed()) {
+                    this.outer.drag(event);
+                }
+            }
+        }
+    };
+    control.addListener(SWT.Dispose, controlListener);
+    control.addListener(SWT.DragDetect, controlListener);
+
+    this.addListener(SWT.Dispose, new class() Listener {
+        public void handleEvent(Event e) {
+            this.outer.onDispose();
+        }
+    });
+
+    Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
+    if ( auto dse = cast(DragSourceEffect)effect ) {
+        dragEffect = dse;
+    } else if ( auto tree = cast(Tree)control ) {
+        dragEffect = new TreeDragSourceEffect(tree);
+    } else if ( auto table = cast(Table)control ) {
+        dragEffect = new TableDragSourceEffect(table);
+    }
+}
+
+static int checkStyle(int style) {
+    if (style is SWT.NONE) return DND.DROP_MOVE;
+    return style;
+}
+
+/**
+ * Adds the listener to the collection 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.
+ *
+ * <p><ul>
+ * <li><code>dragStart</code> is called when the user has begun the actions required to drag the widget.
+ * This event gives the application the chance to decide if a drag should be started.
+ * <li><code>dragSetData</code> is called when the data is required from the drag source.
+ * <li><code>dragFinished</code> is called when the drop has successfully completed (mouse up
+ * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup
+ * such as removing data from the source side on a successful move operation.
+ * </ul></p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 #getDragListeners
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ */
+public void addDragListener(DragSourceListener listener) {
+    if (listener is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+    DNDListener typedListener = new DNDListener(listener);
+    typedListener.dndWidget = this;
+    addListener(DND.DragStart, typedListener);
+    addListener(DND.DragSetData, typedListener);
+    addListener(DND.DragEnd, typedListener);
+}
+
+private int AddRef() {
+    refCount++;
+    return refCount;
+}
+
+private void createCOMInterfaces() {
+    // register each of the interfaces that this object implements
+    iDropSource = new _IDropSourceImpl(this);
+    iDataObject = new _IDataObjectImpl(this);
+}
+
+protected void checkSubclass() {
+    String name = this.classinfo.name;
+    String validName = DragSource.classinfo.name;
+    if (validName!=/*eq*/name) {
+        DND.error(SWT.ERROR_INVALID_SUBCLASS);
+    }
+}
+
+private void disposeCOMInterfaces() {
+    iDropSource = null;
+    iDataObject = null;
+}
+
+private void drag(Event dragEvent) {
+    DNDEvent event = new DNDEvent();
+    event.widget = this;
+    event.x = dragEvent.x;
+    event.y = dragEvent.y;
+    event.time = OS.GetMessageTime();
+    event.doit = true;
+    notifyListeners(DND.DragStart,event);
+    if (!event.doit || transferAgents is null || transferAgents.length is 0 ) return;
+
+    uint[1] pdwEffect;
+    int operations = opToOs(getStyle());
+    Display display = control.getDisplay();
+    String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+    Object oldValue = display.getData(key);
+    display.setData(key, new Boolean(true));
+    ImageList imagelist = null;
+    Image image = event.image;
+    hwndDrag = null;
+    topControl = null;
+    if (image !is null) {
+        imagelist = new ImageList(SWT.NONE);
+        imagelist.add(image);
+        topControl = control.getShell();
+        /*
+         * Bug in Windows. The image is inverted if the shell is RIGHT_TO_LEFT.
+         * The fix is to create a transparent window that covers the shell client
+         * area and use it during the drag to prevent the image from being inverted.
+         * On XP if the shell is RTL, the image is not displayed.
+         */
+        int offset = event.x - dragEvent.x;
+        hwndDrag = topControl.handle;
+        if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) !is 0) {
+            offset = image.getBounds().width - offset;
+            RECT rect;
+            OS.GetClientRect (topControl.handle, &rect);
+            hwndDrag = OS.CreateWindowEx (
+                OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT,
+                WindowClass.ptr,
+                null,
+                OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+                0, 0,
+                rect.right - rect.left, rect.bottom - rect.top,
+                topControl.handle,
+                null,
+                OS.GetModuleHandle (null),
+                null);
+            OS.ShowWindow (hwndDrag, OS.SW_SHOW);
+        }
+        OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offset, event.y - dragEvent.y);
+        /*
+        * Feature in Windows. When ImageList_DragEnter() is called,
+        * it takes a snapshot of the screen  If a drag is started
+        * when another window is in front, then the snapshot will
+        * contain part of the other window, causing pixel corruption.
+        * The fix is to force all paints to be delivered before
+        * calling ImageList_DragEnter().
+        */
+        if (OS.IsWinCE) {
+            OS.UpdateWindow (topControl.handle);
+        } else {
+            int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (topControl.handle, null, null, flags);
+        }
+        POINT pt;
+        pt.x = dragEvent.x;
+        pt.y = dragEvent.y;
+        OS.MapWindowPoints (control.handle, null, &pt, 1);
+        RECT rect;
+        OS.GetWindowRect (hwndDrag, &rect);
+        OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top);
+    }
+    int result = COM.DRAGDROP_S_CANCEL;
+    try {
+        result = COM.DoDragDrop(iDataObject, iDropSource, operations, pdwEffect.ptr);
+    } finally {
+        // ensure that we don't leave transparent window around
+        if (hwndDrag !is null) {
+            OS.ImageList_DragLeave(hwndDrag);
+            OS.ImageList_EndDrag();
+            imagelist.dispose();
+            if (hwndDrag !is topControl.handle) OS.DestroyWindow(hwndDrag);
+            hwndDrag = null;
+            topControl = null;
+        }
+        display.setData(key, oldValue);
+    }
+    int operation = osToOp(pdwEffect[0]);
+    if (dataEffect is DND.DROP_MOVE) {
+        operation = (operation is DND.DROP_NONE || operation is DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE;
+    } else {
+        if (dataEffect !is DND.DROP_NONE) {
+            operation = dataEffect;
+        }
+    }
+    event = new DNDEvent();
+    event.widget = this;
+    event.time = OS.GetMessageTime();
+    event.doit = (result is COM.DRAGDROP_S_DROP);
+    event.detail = operation;
+    notifyListeners(DND.DragEnd,event);
+    dataEffect = DND.DROP_NONE;
+}
+/*
+ * EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+ * Ownership of ppenumFormatetc transfers from callee to caller so reference count on ppenumFormatetc
+ * must be incremented before returning.  Caller is responsible for releasing ppenumFormatetc.
+ */
+private int EnumFormatEtc(int dwDirection, IEnumFORMATETC* ppenumFormatetc) {
+    // only allow getting of data - SetData is not currently supported
+    if (dwDirection is COM.DATADIR_SET) return COM.E_NOTIMPL;
+
+    // what types have been registered?
+    TransferData[] allowedDataTypes = new TransferData[0];
+    for (int i = 0; i < transferAgents.length; i++){
+        Transfer transferAgent = transferAgents[i];
+        if (transferAgent !is null) {
+            TransferData[] formats = transferAgent.getSupportedTypes();
+            TransferData[] newAllowedDataTypes = new TransferData[allowedDataTypes.length + formats.length];
+            System.arraycopy(allowedDataTypes, 0, newAllowedDataTypes, 0, allowedDataTypes.length);
+            System.arraycopy(formats, 0, newAllowedDataTypes, allowedDataTypes.length, formats.length);
+            allowedDataTypes = newAllowedDataTypes;
+        }
+    }
+
+    OleEnumFORMATETC enumFORMATETC = new OleEnumFORMATETC();
+    enumFORMATETC.AddRef();
+
+    FORMATETC*[] formats = new FORMATETC*[allowedDataTypes.length];
+    for (int i = 0; i < formats.length; i++){
+        formats[i] = allowedDataTypes[i].formatetc;
+    }
+    enumFORMATETC.setFormats(formats);
+
+    *ppenumFormatetc = enumFORMATETC.getAddress();
+    return COM.S_OK;
+}
+/**
+ * Returns the Control which is registered for this DragSource.  This is the control that the
+ * user clicks in to initiate dragging.
+ *
+ * @return the Control which is registered for this DragSource
+ */
+public Control getControl() {
+    return control;
+}
+
+.LRESULT GetData(FORMATETC *pFormatetc, STGMEDIUM *pmedium) {
+    /* Called by a data consumer to obtain data from a source data object.
+       The GetData method renders the data described in the specified FORMATETC
+       structure and transfers it through the specified STGMEDIUM structure.
+       The caller then assumes responsibility for releasing the STGMEDIUM structure.
+    */
+    if (pFormatetc is null || pmedium is null) return COM.E_INVALIDARG;
+
+    if (QueryGetData(pFormatetc) !is COM.S_OK) return COM.DV_E_FORMATETC;
+
+    TransferData transferData = new TransferData();
+    transferData.formatetc = new FORMATETC();
+    COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+    transferData.type = transferData.formatetc.cfFormat;
+    transferData.stgmedium = new STGMEDIUM();
+    transferData.result = COM.E_FAIL;
+
+    DNDEvent event = new DNDEvent();
+    event.widget = this;
+    event.time = OS.GetMessageTime();
+    event.dataType = transferData;
+    notifyListeners(DND.DragSetData,event);
+
+    // get matching transfer agent to perform conversion
+    Transfer transfer = null;
+    for (int i = 0; i < transferAgents.length; i++){
+        Transfer transferAgent = transferAgents[i];
+        if (transferAgent !is null && transferAgent.isSupportedType(transferData)){
+            transfer = transferAgent;
+            break;
+        }
+    }
+
+    if (transfer is null) return COM.DV_E_FORMATETC;
+    transfer.javaToNative(event.data, transferData);
+    if (transferData.result !is COM.S_OK) return transferData.result;
+    COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof);
+    return transferData.result;
+}
+
+/**
+ * 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.
+ *
+ * @return the listeners who will be notified when a drag and drop
+ * operation is in progress
+ *
+ * @exception SWTException <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.
+ *
+ * @return the drag effect that is registered for this DragSource
+ *
+ * @since 3.3
+ */
+public DragSourceEffect getDragSourceEffect() {
+    return dragEffect;
+}
+
+/**
+ * Returns the list of data types that can be transferred by this DragSource.
+ *
+ * @return the list of data types that can be transferred by this DragSource
+ */
+public Transfer[] getTransfer(){
+    return transferAgents;
+}
+
+package .LRESULT GiveFeedback(DWORD dwEffect) {
+    return COM.DRAGDROP_S_USEDEFAULTCURSORS;
+}
+
+package .LRESULT QueryContinueDrag(int fEscapePressed, DWORD grfKeyState) {
+    if (topControl !is null && topControl.isDisposed()) return COM.DRAGDROP_S_CANCEL;
+    if (fEscapePressed !is 0){
+        if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
+        return COM.DRAGDROP_S_CANCEL;
+    }
+    /*
+    * Bug in Windows.  On some machines that do not have XBUTTONs,
+    * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+    * causing mouse capture to become stuck.  The fix is to test
+    * for the extra buttons only when they exist.
+    */
+    int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+//  if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+    if ((grfKeyState & mask) is 0) {
+        if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
+        return COM.DRAGDROP_S_DROP;
+    }
+
+    if (hwndDrag !is null) {
+        POINT pt;
+        OS.GetCursorPos (&pt);
+        RECT rect;
+        OS.GetWindowRect (hwndDrag, &rect);
+        OS.ImageList_DragMove (pt.x - rect.left, pt.y - rect.top);
+    }
+    return COM.S_OK;
+}
+
+private void onDispose() {
+    if (control is null) return;
+    this.Release();
+    if (controlListener !is null){
+        control.removeListener(SWT.Dispose, controlListener);
+        control.removeListener(SWT.DragDetect, controlListener);
+    }
+    controlListener = null;
+    control.setData(DND.DRAG_SOURCE_KEY, null);
+    control = null;
+    transferAgents = null;
+}
+
+private int opToOs(int operation) {
+    int osOperation = 0;
+    if ((operation & DND.DROP_COPY) !is 0){
+        osOperation |= COM.DROPEFFECT_COPY;
+    }
+    if ((operation & DND.DROP_LINK) !is 0) {
+        osOperation |= COM.DROPEFFECT_LINK;
+    }
+    if ((operation & DND.DROP_MOVE) !is 0) {
+        osOperation |= COM.DROPEFFECT_MOVE;
+    }
+    return osOperation;
+}
+
+private int osToOp(int osOperation){
+    int operation = 0;
+    if ((osOperation & COM.DROPEFFECT_COPY) !is 0){
+        operation |= DND.DROP_COPY;
+    }
+    if ((osOperation & COM.DROPEFFECT_LINK) !is 0) {
+        operation |= DND.DROP_LINK;
+    }
+    if ((osOperation & COM.DROPEFFECT_MOVE) !is 0) {
+        operation |= DND.DROP_MOVE;
+    }
+    return operation;
+}
+
+private .LRESULT QueryGetData(FORMATETC* pFormatetc) {
+    if (transferAgents is null) return COM.E_FAIL;
+    TransferData transferData = new TransferData();
+    transferData.formatetc = new FORMATETC();
+    COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof);
+    transferData.type = transferData.formatetc.cfFormat;
+
+    // is this type supported by the transfer agent?
+    for (int i = 0; i < transferAgents.length; i++){
+        Transfer transfer = transferAgents[i];
+        if (transfer !is null && transfer.isSupportedType(transferData))
+            return COM.S_OK;
+    }
+
+    return COM.DV_E_FORMATETC;
+}
+
+/* QueryInterface([in] riid, [out] ppvObject)
+ * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
+ * must be incremented before returning.  Caller is responsible for releasing ppvObject.
+ */
+private HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+
+    if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDropSource)) {
+        *ppvObject = cast(void*)cast(IUnknown) iDropSource;
+        AddRef();
+        return COM.S_OK;
+    }
+
+    if (COM.IsEqualGUID(riid, &COM.IIDIDataObject) ) {
+        *ppvObject = cast(void*)cast(IDataObject) iDataObject;
+        AddRef();
+        return COM.S_OK;
+    }
+
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+
+private ULONG Release() {
+    refCount--;
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+        COM.CoFreeUnusedLibraries();
+    }
+    return refCount;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 #getDragListeners
+ */
+public void removeDragListener(DragSourceListener listener) {
+    if (listener is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+    removeListener(DND.DragStart, listener);
+    removeListener(DND.DragSetData, listener);
+    removeListener(DND.DragEnd, listener);
+}
+
+.LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM* pmedium, int fRelease) {
+    if (pFormatetc is null || pmedium is null) return COM.E_INVALIDARG;
+    FORMATETC* formatetc = new FORMATETC();
+    COM.MoveMemory(formatetc, pFormatetc, FORMATETC.sizeof);
+    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;
+        OS.MoveMemory(effect.ptr, ptrEffect[0],4);
+        dataEffect = osToOp(effect[0]);
+    }
+    if (fRelease is 1) {
+        COM.ReleaseStgMedium(pmedium);
+    }
+    return COM.S_OK;
+}
+
+/**
+ * Specifies the drag effect for this DragSource.  This drag effect will be
+ * used during a drag and drop operation.
+ *
+ * @param effect the drag effect that is registered for this DragSource
+ *
+ * @since 3.3
+ */
+public void setDragSourceEffect(DragSourceEffect effect) {
+    dragEffect = effect;
+}
+
+/**
+ * Specifies the list of data types that can be transferred by this DragSource.
+ * The application must be able to provide data to match each of these types when
+ * a successful drop has occurred.
+ *
+ * @param transferAgents a list of Transfer objects which define the types of data that can be
+ * dragged from this source
+ */
+public void setTransfer(Transfer[] transferAgents){
+    this.transferAgents = transferAgents;
+}
+
+}
+
+
+private class _IDropSourceImpl : IDropSource {
+
+    DragSource  parent;
+    this(DragSource p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IDropSource
+    HRESULT QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) { return parent.QueryContinueDrag(fEscapePressed, grfKeyState); }
+    HRESULT GiveFeedback(DWORD dwEffect) { return parent.GiveFeedback(dwEffect);}
+}
+
+private class _IDataObjectImpl : IDataObject {
+
+    DragSource  parent;
+    this(DragSource p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+
+    // interface IDataObject
+    LRESULT GetData( FORMATETC *pFormatetc, STGMEDIUM *pmedium) { return parent.GetData(pFormatetc, pmedium); }
+    LRESULT GetDataHere(FORMATETC * pFormatetc, STGMEDIUM * pmedium) { return COM.E_NOTIMPL; }
+    LRESULT QueryGetData(FORMATETC* pFormatetc) { return parent.QueryGetData(pFormatetc); }
+    LRESULT GetCanonicalFormatEtc(FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut) { return COM.E_NOTIMPL; }
+    LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) { return parent.SetData(pFormatetc, pmedium, fRelease); }
+    LRESULT EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC * ppenumFormatetc) { return parent.EnumFormatEtc(dwDirection, ppenumFormatetc); }
+    LRESULT DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink pAdvSink, DWORD* pdwConnection) { return COM.E_NOTIMPL; }
+    LRESULT DUnadvise(DWORD dwConnection) { return COM.E_NOTIMPL; }
+    LRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise) { return COM.E_NOTIMPL; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DragSourceAdapter;
+
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>DragSourceListener</code> interface.
+ *
+ * <p>Classes that wish to deal with <code>DragSourceEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.</p>
+ *
+ * @see DragSourceListener
+ * @see DragSourceEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DragSourceAdapter : DragSourceListener {
+
+/**
+ * This implementation of <code>dragStart</code> permits the drag operation to start.
+ * For additional information see <code>DragSourceListener.dragStart</code>.
+ * 
+ * @param event the information associated with the drag start event
+ */
+public void dragStart(DragSourceEvent event){}
+
+/**
+ * This implementation of <code>dragFinished</code> does nothing.
+ * For additional information see <code>DragSourceListener.dragFinished</code>.
+ * 
+ * @param event the information associated with the drag finished event
+ */
+public void dragFinished(DragSourceEvent event){}
+
+/**
+ * This implementation of <code>dragSetData</code> does nothing.
+ * For additional information see <code>DragSourceListener.dragSetData</code>.
+ * 
+ * @param event the information associated with the drag set data event
+ */
+public void dragSetData(DragSourceEvent event){}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DragSourceEffect;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.dnd.DragSourceAdapter;
+
+/**
+ * This class provides default implementations to display a drag source
+ * effect during a drag and drop operation. The current implementation
+ * does not provide any visual feedback.
+ *
+ * <p>The drag source effect has the same API as the
+ * <code>DragSourceAdapter</code> so that it can provide custom visual
+ * feedback when a <code>DragSourceEvent</code> occurs.
+ * </p>
+ *
+ * <p>Classes that wish to provide their own drag source effect such as
+ * displaying a default source image during a drag can extend the <code>DragSourceEffect</code>
+ * class, override the <code>DragSourceAdapter.dragStart</code> method and set
+ * the field <code>DragSourceEvent.image</code> with their own image.
+ * The image should be disposed when <code>DragSourceAdapter.dragFinished</code> is called.
+ * </p>
+ *
+ * @see DragSourceAdapter
+ * @see DragSourceEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class DragSourceEffect : DragSourceAdapter {
+    Control control = null;
+
+    /**
+     * Creates a new <code>DragSourceEffect</code> to handle drag effect from the specified <code>Control</code>.
+     *
+     * @param control the <code>Control</code> that the user clicks on to initiate the drag
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the control is null</li>
+     * </ul>
+     */
+    public this(Control control) {
+        if (control is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        this.control = control;
+    }
+
+    /**
+     * Returns the Control which is registered for this DragSourceEffect.  This is the control that the
+     * user clicks in to initiate dragging.
+     *
+     * @return the Control which is registered for this DragSourceEffect
+     */
+    public Control getControl() {
+        return control;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DragSourceEvent;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DNDEvent;
+
+/**
+ * The DragSourceEvent contains the event information passed in the methods of the DragSourceListener.
+ *
+ * @see DragSourceListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DragSourceEvent : TypedEvent {
+    /**
+     * The operation that was performed.
+     * @see DND#DROP_NONE
+     * @see DND#DROP_MOVE
+     * @see DND#DROP_COPY
+     * @see DND#DROP_LINK
+     * @see DND#DROP_TARGET_MOVE
+     */
+    public int detail;
+
+    /**
+     * In dragStart, the doit field determines if the drag and drop operation
+     * should proceed; in dragFinished, the doit field indicates whether
+     * the operation was performed successfully.
+     * <p></p>
+     * In dragStart:
+     * <p>Flag to determine if the drag and drop operation should proceed.
+     * The application can set this value to false to prevent the drag from starting.
+     * Set to true by default.</p>
+     *
+     * <p>In dragFinished:</p>
+     * <p>Flag to indicate if the operation was performed successfully.
+     * True if the operation was performed successfully.</p>
+     */
+    public bool doit;
+
+    /**
+     * In dragStart, the x coordinate (relative to the control) of the
+     * position the mouse went down to start the drag.
+     * @since 3.2
+     */
+    public int x;
+    /**
+     * In dragStart, the y coordinate (relative to the control) of the
+     * position the mouse went down to start the drag .
+     * @since 3.2
+     */
+    public int y;
+
+    /**
+     * The type of data requested.
+     * Data provided in the data field must be of the same type.
+     */
+    public TransferData dataType;
+
+    /**
+     * The drag source image to be displayed during the drag.
+     * <p>A value of null indicates that no drag image will be displayed.</p>
+     * <p>The default value is null.</p>
+     *
+     * @since 3.3
+     */
+    public Image image;
+
+    static const long serialVersionUID = 3257002142513770808L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(DNDEvent e) {
+    super( cast(Event) e );
+    this.data = e.data;
+    this.detail = e.detail;
+    this.doit = e.doit;
+    this.dataType = e.dataType;
+    this.x = e.x;
+    this.y = e.y;
+    this.image = e.image;
+}
+void updateEvent(DNDEvent e) {
+    e.widget = this.widget;
+    e.time = this.time;
+    e.data = this.data;
+    e.detail = this.detail;
+    e.doit = this.doit;
+    e.dataType = this.dataType;
+    e.x = this.x;
+    e.y = this.y;
+    e.image = this.image;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DragSourceListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DragSourceListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+/**
+ * The <code>DragSourceListener</code> class provides event notification to the application for DragSource events.
+ *
+ * <p>When the user drops data on a <code>DropTarget</code>, the application which defines the <code>DragSource</code>
+ * must provide the dropped data by implementing <code>dragSetData</code>.  In the dragSetData, the application
+ * must support all the data types that were specified in the DragSource#setTransfer method.</p>
+ *
+ * <p>After the drop has completed successfully or has been aborted, the application which defines the
+ * <code>DragSource</code> is required to take the appropriate cleanup action.  In the case of a successful
+ * <b>move</b> operation, the application must remove the data that was transferred.</p>
+ *
+ */
+public interface DragSourceListener : SWTEventListener {
+
+/**
+ * The user has begun the actions required to drag the widget. This event gives the application
+ * the chance to decide if a drag should be started.
+ *
+ * <p>The following fields in the DragSourceEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in,out)doit
+ * </ul></p>
+ *
+ * @param event the information associated with the drag start event
+ *
+ * @see DragSourceEvent
+ */
+public void dragStart(DragSourceEvent event);
+
+/**
+ * The data is required from the drag source.
+ *
+ * <p>The following fields in the DragSourceEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)dataType - the type of data requested.
+ * <li>(out)data    - the application inserts the actual data here (must match the dataType)
+ * </ul></p>
+ *
+ * @param event the information associated with the drag set data event
+ *
+ * @see DragSourceEvent
+ */
+public void dragSetData(DragSourceEvent event);
+
+/**
+ * The drop has successfully completed(mouse up over a valid target) or has been terminated (such as hitting
+ * the ESC key). Perform cleanup such as removing data from the source side on a successful move operation.
+ *
+ * <p>The following fields in the DragSourceEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)doit
+ * <li>(in)detail
+ * </ul></p>
+ *
+ * @param event the information associated with the drag finished event
+ *
+ * @see DragSourceEvent
+ */
+public void dragFinished(DragSourceEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTarget.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,798 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DropTarget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.C;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.ifs;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.DropTargetEffect;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.DNDListener;
+import org.eclipse.swt.dnd.DNDEvent;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TableDropTargetEffect;
+import org.eclipse.swt.dnd.TreeDropTargetEffect;
+
+import java.lang.all;
+
+/**
+ *
+ * Class <code>DropTarget</code> defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ *
+ * <p>This class identifies the <code>Control</code> over which the user must position the cursor
+ * in order to drop the data being transferred.  It also specifies what data types can be dropped on
+ * this control and what operations can be performed.  You may have several DropTragets in an
+ * application but there can only be a one to one mapping between a <code>Control</code> and a <code>DropTarget</code>.
+ * The DropTarget can receive data from within the same application or from other applications
+ * (such as text dragged from a text editor like Word).</p>
+ *
+ * <code><pre>
+ *  int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
+ *  Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ *  DropTarget target = new DropTarget(label, operations);
+ *  target.setTransfer(types);
+ * </code></pre>
+ *
+ * <p>The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface <code>DropTargetListener</code> which uses the class
+ * <code>DropTargetEvent</code>.  The application can modify the type of drag being performed
+ * on this Control at any stage of the drag by modifying the <code>event.detail</code> field or the
+ * <code>event.currentDataType</code> field.  When the data is dropped, it is the responsibility of
+ * the application to copy this data for its own purposes.
+ *
+ * <code><pre>
+ *  target.addDropListener (new DropTargetListener() {
+ *      public void dragEnter(DropTargetEvent event) {};
+ *      public void dragOver(DropTargetEvent event) {};
+ *      public void dragLeave(DropTargetEvent event) {};
+ *      public void dragOperationChanged(DropTargetEvent event) {};
+ *      public void dropAccept(DropTargetEvent event) {}
+ *      public void drop(DropTargetEvent event) {
+ *          // A drop has occurred, copy over the data
+ *          if (event.data is null) { // no data to copy, indicate failure in event.detail
+ *              event.detail = DND.DROP_NONE;
+ *              return;
+ *          }
+ *          label.setText ((String) event.data); // data copied to label text
+ *      }
+ *  });
+ * </pre></code>
+ *
+ * <dl>
+ *  <dt><b>Styles</b></dt> <dd>DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK</dd>
+ *  <dt><b>Events</b></dt> <dd>DND.DragEnter, DND.DragLeave, DND.DragOver, DND.DragOperationChanged,
+ *                             DND.DropAccept, DND.Drop </dd>
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#dnd">Drag and Drop snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: DNDExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DropTarget : Widget {
+
+    Control control;
+    Listener controlListener;
+    Transfer[] transferAgents;
+    DropTargetEffect dropEffect;
+
+    // Track application selections
+    TransferData selectedDataType;
+    int selectedOperation;
+
+    // workaround - There is no event for "operation changed" so track operation based on key state
+    int keyOperation = -1;
+
+    // workaround - The dataobject address is only passed as an argument in drag enter and drop.
+    // To allow applications to query the data values during the drag over operations,
+    // maintain a reference to it.
+    IDataObject iDataObject;
+
+    // interfaces
+    _IDropTargetImpl iDropTarget;
+    int refCount;
+
+    static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$
+
+/**
+ * Creates a new <code>DropTarget</code> to allow data to be dropped on the specified
+ * <code>Control</code>.
+ * Creating an instance of a DropTarget may cause system resources to be allocated
+ * depending on the platform.  It is therefore mandatory that the DropTarget instance
+ * be disposed when no longer required.
+ *
+ * @param control the <code>Control</code> over which the user positions the cursor to drop the data
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ *         DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_CANNOT_INIT_DROP - unable to initiate drop target; this will occur if more than one
+ *        drop target is created for a control or if the operating system will not allow the creation
+ *        of the drop target</li>
+ * </ul>
+ *
+ * <p>NOTE: ERROR_CANNOT_INIT_DROP should be an SWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility.</p>
+ *
+ * @see Widget#dispose
+ * @see DropTarget#checkSubclass
+ * @see DND#DROP_NONE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_LINK
+ */
+public this(Control control, int style) {
+    super (control, checkStyle(style));
+    this.control = control;
+    if (control.getData(DND.DROP_TARGET_KEY) !is null) {
+        DND.error(DND.ERROR_CANNOT_INIT_DROP);
+    }
+    control.setData(DND.DROP_TARGET_KEY, this);
+    createCOMInterfaces();
+    this.AddRef();
+
+    if (COM.CoLockObjectExternal(iDropTarget, true, true) !is COM.S_OK)
+        DND.error(DND.ERROR_CANNOT_INIT_DROP);
+    if (COM.RegisterDragDrop( control.handle, iDropTarget) !is COM.S_OK)
+        DND.error(DND.ERROR_CANNOT_INIT_DROP);
+
+    controlListener = new class() Listener {
+        public void handleEvent (Event event) {
+            if (!this.outer.isDisposed()){
+                this.outer.dispose();
+            }
+        }
+    };
+    control.addListener (SWT.Dispose, controlListener);
+
+    this.addListener(SWT.Dispose, new class() Listener {
+        public void handleEvent (Event event) {
+            onDispose();
+        }
+    });
+
+    Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT);
+    if ( auto dte = cast(DropTargetEffect) effect ) {
+        dropEffect = dte;
+    } else if ( auto table = cast(Table)control ) {
+        dropEffect = new TableDropTargetEffect(table);
+    } else if ( auto tree = cast(Tree)control ) {
+        dropEffect = new TreeDropTargetEffect(tree);
+    }
+}
+
+static int checkStyle (int style) {
+    if (style is SWT.NONE) return DND.DROP_MOVE;
+    return style;
+}
+
+/**
+ * Adds the listener to the collection 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.
+ *
+ * <p><ul>
+ * <li><code>dragEnter</code> is called when the cursor has entered the drop target boundaries
+ * <li><code>dragLeave</code> is called when the cursor has left the drop target boundaries and just before
+ * the drop occurs or is cancelled.
+ * <li><code>dragOperationChanged</code> is called when the operation being performed has changed
+ * (usually due to the user changing the selected modifier key(s) while dragging)
+ * <li><code>dragOver</code> is called when the cursor is moving over the drop target
+ * <li><code>dropAccept</code> is called just before the drop is performed.  The drop target is given
+ * the chance to change the nature of the drop or veto the drop by setting the <code>event.detail</code> field
+ * <li><code>drop</code> is called when the data is being dropped
+ * </ul></p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 #getDropListeners
+ * @see #removeDropListener
+ * @see DropTargetEvent
+ */
+public void addDropListener(DropTargetListener listener) {
+    if (listener is null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+    DNDListener typedListener = new DNDListener (listener);
+    typedListener.dndWidget = this;
+    addListener (DND.DragEnter, typedListener);
+    addListener (DND.DragLeave, typedListener);
+    addListener (DND.DragOver, typedListener);
+    addListener (DND.DragOperationChanged, typedListener);
+    addListener (DND.Drop, typedListener);
+    addListener (DND.DropAccept, typedListener);
+}
+
+ULONG AddRef() {
+    refCount++;
+    return refCount;
+}
+
+protected void checkSubclass () {
+    String name = this.classinfo.name;
+    String validName = DropTarget.classinfo.name;
+    if (validName!=/*eq*/name) {
+        DND.error (SWT.ERROR_INVALID_SUBCLASS);
+    }
+}
+
+void createCOMInterfaces() {
+    // register each of the interfaces that this object implements
+    iDropTarget = new _IDropTargetImpl(this);
+}
+
+void disposeCOMInterfaces() {
+    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;
+    if (iDataObject !is null) iDataObject.Release();
+    iDataObject = null;
+
+    DNDEvent event = new DNDEvent();
+    if (!setEventData(event, pDataObject, grfKeyState, pt, pdwEffect)) {
+        *pdwEffect = COM.DROPEFFECT_NONE;
+        return COM.S_FALSE;
+    }
+
+    // Remember the iDataObject because it is not passed into the DragOver callback
+    iDataObject = pDataObject;
+    iDataObject.AddRef();
+
+    int allowedOperations = event.operations;
+    TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
+    System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);
+    notifyListeners(DND.DragEnter, event);
+    refresh();
+    if (event.detail is DND.DROP_DEFAULT) {
+        event.detail = (allowedOperations & DND.DROP_MOVE) !is 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+    }
+
+    selectedDataType = null;
+    for (int i = 0; i < allowedDataTypes.length; i++) {
+        if (TransferData.sameType(allowedDataTypes[i], event.dataType)){
+            selectedDataType = allowedDataTypes[i];
+            break;
+        }
+    }
+
+    selectedOperation = DND.DROP_NONE;
+    if (selectedDataType !is null && ((allowedOperations & event.detail) !is 0)) {
+        selectedOperation = event.detail;
+    }
+
+    *pdwEffect = opToOs(selectedOperation);
+    return COM.S_OK;
+}
+
+HRESULT DragLeave() {
+    keyOperation = -1;
+
+    if (iDataObject is null) return COM.S_FALSE;
+
+    DNDEvent event = new DNDEvent();
+    event.widget = this;
+    event.time = OS.GetMessageTime();
+    event.detail = DND.DROP_NONE;
+    notifyListeners(DND.DragLeave, event);
+    refresh();
+
+    iDataObject.Release();
+    iDataObject = null;
+    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;
+
+    DNDEvent event = new DNDEvent();
+    if (!setEventData(event, iDataObject, grfKeyState, pt, pdwEffect)) {
+        keyOperation = -1;
+        *pdwEffect = COM.DROPEFFECT_NONE;
+        return COM.S_FALSE;
+    }
+
+    int allowedOperations = event.operations;
+    TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
+    System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);
+
+    if (keyOperation is oldKeyOperation) {
+        event.type = DND.DragOver;
+        event.dataType = selectedDataType;
+        event.detail = selectedOperation;
+    } else {
+        event.type = DND.DragOperationChanged;
+        event.dataType = selectedDataType;
+    }
+    notifyListeners(event.type, event);
+    refresh();
+    if (event.detail is DND.DROP_DEFAULT) {
+        event.detail = (allowedOperations & DND.DROP_MOVE) !is 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+    }
+
+    selectedDataType = null;
+    for (int i = 0; i < allowedDataTypes.length; i++) {
+        if (TransferData.sameType(allowedDataTypes[i], event.dataType)){
+            selectedDataType = allowedDataTypes[i];
+            break;
+        }
+    }
+
+    selectedOperation = DND.DROP_NONE;
+    if (selectedDataType !is null && ((allowedOperations & event.detail) is event.detail)) {
+        selectedOperation = event.detail;
+    }
+
+    *pdwEffect = opToOs(selectedOperation);
+    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;
+    event.time = OS.GetMessageTime();
+    if (dropEffect !is null) {
+        event.item = dropEffect.getItem(pt.x, pt.y);
+    }
+    event.detail = DND.DROP_NONE;
+    notifyListeners(DND.DragLeave, event);
+    refresh();
+
+    event = new DNDEvent();
+    if (!setEventData(event, pDataObject, grfKeyState, pt, pdwEffect)) {
+        keyOperation = -1;
+        *pdwEffect = COM.DROPEFFECT_NONE;
+        return COM.S_FALSE;
+    }
+    keyOperation = -1;
+    int allowedOperations = event.operations;
+    TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
+    System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);
+    event.dataType = selectedDataType;
+    event.detail = selectedOperation;
+    notifyListeners(DND.DropAccept,event);
+    refresh();
+
+    selectedDataType = null;
+    for (int i = 0; i < allowedDataTypes.length; i++) {
+        if (TransferData.sameType(allowedDataTypes[i], event.dataType)){
+            selectedDataType = allowedDataTypes[i];
+            break;
+        }
+    }
+    selectedOperation = DND.DROP_NONE;
+    if (selectedDataType !is null && (allowedOperations & event.detail) is event.detail) {
+        selectedOperation = event.detail;
+    }
+
+    if (selectedOperation is DND.DROP_NONE){
+        *pdwEffect = COM.DROPEFFECT_NONE;
+        return COM.S_OK;
+    }
+
+    // Get Data in a Java format
+    Object object = null;
+    for (int i = 0; i < transferAgents.length; i++){
+        Transfer transfer = transferAgents[i];
+        if (transfer !is null && transfer.isSupportedType(selectedDataType)){
+            object = transfer.nativeToJava(selectedDataType);
+            break;
+        }
+    }
+    if (object is null){
+        selectedOperation = DND.DROP_NONE;
+    }
+
+    event.detail = selectedOperation;
+    event.dataType = selectedDataType;
+    event.data = object;
+    OS.ImageList_DragShowNolock(false);
+    try {
+        notifyListeners(DND.Drop,event);
+    } finally {
+        OS.ImageList_DragShowNolock(true);
+    }
+    refresh();
+    selectedOperation = DND.DROP_NONE;
+    if ((allowedOperations & event.detail) is event.detail) {
+        selectedOperation = event.detail;
+    }
+    //notify source of action taken
+    *pdwEffect = opToOs(selectedOperation);
+    return COM.S_OK;
+}
+
+/**
+ * Returns the Control which is registered for this DropTarget.  This is the control over which the
+ * user positions the cursor to drop the data.
+ *
+ * @return the Control which is registered for this DropTarget
+ */
+public Control getControl () {
+    return control;
+}
+
+/**
+ * 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.
+ *
+ * @return the listeners who will be notified when a drag and drop 
+ * operation is in progress
+ *
+ * @exception SWTException <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.
+ *
+ * @return the drop effect that is registered for this DropTarget
+ *
+ * @since 3.3
+ */
+public DropTargetEffect getDropTargetEffect() {
+    return dropEffect;
+}
+
+int getOperationFromKeyState(int grfKeyState) {
+    bool ctrl = (grfKeyState & OS.MK_CONTROL) !is 0;
+    bool shift = (grfKeyState & OS.MK_SHIFT) !is 0;
+    bool alt = (grfKeyState & OS.MK_ALT) !is 0;
+    if (alt) {
+        if (ctrl || shift) return DND.DROP_DEFAULT;
+        return DND.DROP_LINK;
+    }
+    if (ctrl && shift) return DND.DROP_LINK;
+    if (ctrl)return DND.DROP_COPY;
+    if (shift)return DND.DROP_MOVE;
+    return DND.DROP_DEFAULT;
+}
+
+/**
+ * Returns a list of the data types that can be transferred to this DropTarget.
+ *
+ * @return a list of the data types that can be transferred to this DropTarget
+ */
+public Transfer[] getTransfer() {
+    return transferAgents;
+}
+
+void onDispose () {
+    if (control is null) return;
+
+    COM.RevokeDragDrop(control.handle);
+
+    if (controlListener !is null)
+        control.removeListener(SWT.Dispose, controlListener);
+    controlListener = null;
+    control.setData(DND.DROP_TARGET_KEY, null);
+    transferAgents = null;
+    control = null;
+
+    COM.CoLockObjectExternal(iDropTarget, false, true);
+
+    this.Release();
+
+    COM.CoFreeUnusedLibraries();
+}
+
+int opToOs(int operation) {
+    int osOperation = 0;
+    if ((operation & DND.DROP_COPY) !is 0){
+        osOperation |= COM.DROPEFFECT_COPY;
+    }
+    if ((operation & DND.DROP_LINK) !is 0) {
+        osOperation |= COM.DROPEFFECT_LINK;
+    }
+    if ((operation & DND.DROP_MOVE) !is 0) {
+        osOperation |= COM.DROPEFFECT_MOVE;
+    }
+    return osOperation;
+}
+
+int osToOp(int osOperation){
+    int operation = 0;
+    if ((osOperation & COM.DROPEFFECT_COPY) !is 0){
+        operation |= DND.DROP_COPY;
+    }
+    if ((osOperation & COM.DROPEFFECT_LINK) !is 0) {
+        operation |= DND.DROP_LINK;
+    }
+    if ((osOperation & COM.DROPEFFECT_MOVE) !is 0) {
+        operation |= DND.DROP_MOVE;
+    }
+    return operation;
+}
+
+/* QueryInterface([in] iid, [out] ppvObject)
+ * Ownership of ppvObject transfers from callee to caller so reference count on ppvObject
+ * must be incremented before returning.  Caller is responsible for releasing ppvObject.
+ */
+HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+    if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDropTarget)) {
+        *ppvObject = cast(void*)cast(IDropTarget) iDropTarget;
+        AddRef();
+        return COM.S_OK;
+    }
+
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+
+ULONG Release() {
+    refCount--;
+
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+        COM.CoFreeUnusedLibraries();
+    }
+
+    return refCount;
+}
+
+void refresh() {
+    if (control is null || control.isDisposed()) return;
+    auto handle = control.handle;
+    RECT lpRect;
+    if (OS.GetUpdateRect(handle, &lpRect, false)) {
+        OS.ImageList_DragShowNolock(false);
+        OS.RedrawWindow(handle, &lpRect, null, OS.RDW_UPDATENOW | OS.RDW_INVALIDATE);
+        OS.ImageList_DragShowNolock(true);
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag and drop operation is in progress.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 #getDropListeners
+ */
+public void removeDropListener(DropTargetListener listener) {
+    if (listener is null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+    removeListener (DND.DragEnter, listener);
+    removeListener (DND.DragLeave, listener);
+    removeListener (DND.DragOver, listener);
+    removeListener (DND.DragOperationChanged, listener);
+    removeListener (DND.Drop, listener);
+    removeListener (DND.DropAccept, listener);
+}
+
+/**
+ * Specifies 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.
+ *
+ * @param effect the drop effect that is registered for this DropTarget
+ *
+ * @since 3.3
+ */
+public void setDropTargetEffect(DropTargetEffect effect) {
+    dropEffect = effect;
+}
+
+bool setEventData(DNDEvent event, IDataObject pDataObject, int grfKeyState, POINTL pt, DWORD* pdwEffect) {
+    if (pDataObject is null || pdwEffect is null) return false;
+
+    // get allowed operations
+    int style = getStyle();
+    int[1] operations;
+    OS.MoveMemory(operations.ptr, pdwEffect, 4);
+    operations[0] = osToOp(operations[0]) & style;
+    if (operations[0] is DND.DROP_NONE) return false;
+
+    // get current operation
+    int operation = getOperationFromKeyState(grfKeyState);
+    keyOperation = operation;
+    if (operation is DND.DROP_DEFAULT) {
+        if ((style & DND.DROP_DEFAULT) is 0) {
+            operation = (operations[0] & DND.DROP_MOVE) !is 0 ? DND.DROP_MOVE : DND.DROP_NONE;
+        }
+    } else {
+        if ((operation & operations[0]) is 0) operation = DND.DROP_NONE;
+    }
+
+    // Get allowed transfer types
+    TransferData[] dataTypes = new TransferData[0];
+    IDataObject dataObject = pDataObject;
+    dataObject.AddRef();
+    try {
+        IEnumFORMATETC[1] address;
+        if (dataObject.EnumFormatEtc(COM.DATADIR_GET, address.ptr) !is COM.S_OK) {
+            return false;
+        }
+        IEnumFORMATETC enumFormatetc = address[0];
+        try {
+            // Loop over enumerator and save any types that match what we are looking for
+            auto rgelt = cast(FORMATETC*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+            try {
+                uint[1] pceltFetched;
+                enumFormatetc.Reset();
+                while (enumFormatetc.Next(1, rgelt, pceltFetched.ptr) is COM.S_OK && pceltFetched[0] is 1) {
+                    TransferData transferData = new TransferData();
+                    transferData.formatetc = new FORMATETC();
+                    COM.MoveMemory(transferData.formatetc, rgelt, FORMATETC.sizeof);
+                    transferData.type = transferData.formatetc.cfFormat;
+                    transferData.pIDataObject = pDataObject;
+                    for (int i = 0; i < transferAgents.length; i++){
+                        Transfer transfer = transferAgents[i];
+                        if (transfer !is null && transfer.isSupportedType(transferData)){
+                            TransferData[] newDataTypes = new TransferData[dataTypes.length + 1];
+                            System.arraycopy(dataTypes, 0, newDataTypes, 0, dataTypes.length);
+                            newDataTypes[dataTypes.length] = transferData;
+                            dataTypes = newDataTypes;
+                            break;
+                        }
+                    }
+                }
+            } finally {
+                OS.GlobalFree(rgelt);
+            }
+        } finally {
+            enumFormatetc.Release();
+        }
+    } finally {
+        dataObject.Release();
+    }
+    if (dataTypes.length is 0) return false;
+
+    event.widget = this;
+    event.x = pt.x;
+    event.y = pt.y;
+    event.time = OS.GetMessageTime();
+    event.feedback = DND.FEEDBACK_SELECT;
+    event.dataTypes = dataTypes;
+    event.dataType = dataTypes[0];
+    if (dropEffect !is null) {
+        event.item = dropEffect.getItem(pt.x, pt.y);
+    }
+    event.operations = operations[0];
+    event.detail = operation;
+    return true;
+}
+
+/**
+ * Specifies the data types that can be transferred to this DropTarget.  If data is
+ * being dragged that does not match one of these types, the drop target will be notified of
+ * the drag and drop operation but the currentDataType will be null and the operation
+ * will be DND.NONE.
+ *
+ * @param transferAgents a list of Transfer objects which define the types of data that can be
+ *                       dropped on this target
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if transferAgents is null</li>
+ * </ul>
+ */
+public void setTransfer(Transfer[] transferAgents){
+    if (transferAgents is null) DND.error(SWT.ERROR_NULL_ARGUMENT);
+    this.transferAgents = transferAgents;
+}
+}
+
+class _IDropTargetImpl : IDropTarget {
+
+    DropTarget  parent;
+    this(DropTarget p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    HRESULT DragEnter( IDataObject pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) {
+        return parent.DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
+    }
+    HRESULT DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect ) {
+        return parent.DragOver(grfKeyState, pt, pdwEffect);
+    }
+    HRESULT DragLeave(){ return parent.DragLeave(); }
+    HRESULT Drop(IDataObject pDataObj,DWORD grfKeyState,POINTL pt,DWORD *pdwEffect){
+        return parent.Drop(pDataObj, grfKeyState, pt, pdwEffect);
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DropTargetAdapter;
+
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.DropTargetEvent;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>DropTargetListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>DropTargetEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see DropTargetListener
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DropTargetAdapter : DropTargetListener {
+
+/**
+ * This implementation of <code>dragEnter</code> permits the default
+ * operation defined in <code>event.detail</code>to be performed on the current data type
+ * defined in <code>event.currentDataType</code>.
+ * For additional information see <code>DropTargetListener.dragEnter</code>.
+ * 
+ * @param event the information associated with the drag enter event
+ */
+public void dragEnter(DropTargetEvent event){}
+
+/**
+ * This implementation of <code>dragLeave</code> does nothing.
+ * For additional information see <code>DropTargetListener.dragOperationChanged</code>.
+ * 
+ * @param event the information associated with the drag leave event
+ */
+public void dragLeave(DropTargetEvent event){}
+
+/**
+ * This implementation of <code>dragOperationChanged</code> permits the default
+ * operation defined in <code>event.detail</code>to be performed on the current data type
+ * defined in <code>event.currentDataType</code>.
+ * For additional information see <code>DropTargetListener.dragOperationChanged</code>.
+ * 
+ * @param event the information associated with the drag operation changed event
+ */
+public void dragOperationChanged(DropTargetEvent event){}
+
+/**
+ * This implementation of <code>dragOver</code> permits the default
+ * operation defined in <code>event.detail</code>to be performed on the current data type
+ * defined in <code>event.currentDataType</code>.
+ * For additional information see <code>DropTargetListener.dragOver</code>.
+ * 
+ * @param event the information associated with the drag over event
+ */
+public void dragOver(DropTargetEvent event){}
+
+/**
+ * This implementation of <code>drop</code> does nothing.
+ * For additional information see <code>DropTargetListener.drop</code>.
+ * 
+ * @param event the information associated with the drop event
+ */
+public void drop(DropTargetEvent event){}
+
+/**
+ * This implementation of <code>dropAccept</code> permits the default
+ * operation defined in <code>event.detail</code>to be performed on the current data type
+ * defined in <code>event.currentDataType</code>.
+ * For additional information see <code>DropTargetListener.dropAccept</code>.
+ * 
+ * @param event the information associated with the drop accept event
+ */
+public void dropAccept(DropTargetEvent event){}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DropTargetEffect;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.dnd.DropTargetAdapter;
+
+
+/**
+ * This class provides a default drag under effect during a drag and drop.
+ * The current implementation does not provide any visual feedback.
+ *
+ * <p>The drop target effect has the same API as the
+ * <code>DropTargetAdapter</code> so that it can provide custom visual
+ * feedback when a <code>DropTargetEvent</code> occurs.
+ * </p>
+ *
+ * <p>Classes that wish to provide their own drag under effect
+ * can extend the <code>DropTargetEffect</code> and override any applicable methods
+ * in <code>DropTargetAdapter</code> to display their own drag under effect.</p>
+ *
+ * <p>The feedback value is either one of the FEEDBACK constants defined in
+ * class <code>DND</code> which is applicable to instances of this class,
+ * or it must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> effect constants.
+ * </p>
+ * <p>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_EXPAND, FEEDBACK_INSERT_AFTER, FEEDBACK_INSERT_BEFORE,
+ * FEEDBACK_NONE, FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ * </p>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class DropTargetEffect : DropTargetAdapter {
+    Control control;
+
+    /**
+     * Creates a new <code>DropTargetEffect</code> to handle the drag under effect on the specified
+     * <code>Control</code>.
+     *
+     * @param control the <code>Control</code> over which the user positions the cursor to drop the data
+     *
+     * @exception IllegalArgumentException <ul>
+     *    <li>ERROR_NULL_ARGUMENT - if the control is null</li>
+     * </ul>
+     */
+    public this(Control control) {
+        if (control is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        this.control = control;
+    }
+
+    /**
+     * Returns the Control which is registered for this DropTargetEffect.  This is the control over which the
+     * user positions the cursor to drop the data.
+     *
+     * @return the Control which is registered for this DropTargetEffect
+     */
+    public Control getControl() {
+        return control;
+    }
+
+    /**
+     * Returns the item at the given x-y coordinate in the receiver
+     * or null if no such item exists. The x-y coordinate is in the
+     * display relative coordinates.
+     *
+     * @param x the x coordinate used to locate the item
+     * @param y the y coordinate used to locate the item
+     * @return the item at the given x-y coordinate, or null if the coordinate is not in a selectable item
+     */
+    public Widget getItem(int x, int y) {
+        if ( auto table = cast(Table)control ) {
+            return getItem(table, x, y);
+        }
+        if ( auto tree = cast(Tree)control ) {
+            return getItem(tree, x, y);
+        }
+        return null;
+    }
+
+    Widget getItem(Table table, int x, int y) {
+        Point coordinates = new Point(x, y);
+        coordinates = table.toControl(coordinates);
+        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 null;
+    }
+
+    Widget getItem(Tree tree, int x, int y) {
+        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(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;
+    }
+
+    TreeItem nextItem(Tree tree, TreeItem item) {
+        if (item is null) return null;
+        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);
+        int count = parentItem is null ? tree.getItemCount() : parentItem.getItemCount();
+        while (true) {
+            if (index + 1 < count) return parentItem is null ? tree.getItem(index + 1) : parentItem.getItem(index + 1);
+            if (parentItem is null) return null;
+            childItem = parentItem;
+            parentItem = childItem.getParentItem();
+            index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+            count = parentItem is null ? tree.getItemCount() : parentItem.getItemCount();
+        }
+    }
+
+    TreeItem previousItem(Tree tree, TreeItem item) {
+        if (item is null) return null;
+        TreeItem childItem = item;
+        TreeItem parentItem = childItem.getParentItem();
+        int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
+        if (index is 0) return parentItem;
+        TreeItem nextItem = parentItem is null ? tree.getItem(index-1) : parentItem.getItem(index-1);
+        int count = nextItem.getItemCount();
+        while (count > 0 && nextItem.getExpanded()) {
+            nextItem = nextItem.getItem(count - 1);
+            count = nextItem.getItemCount();
+        }
+        return nextItem;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DropTargetEvent;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DNDEvent;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * The DropTargetEvent contains the event information passed in the methods of the DropTargetListener.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class DropTargetEvent : TypedEvent {
+    /**
+     * The x-cordinate of the cursor relative to the <code>Display</code>
+     */
+    public int x;
+
+    /**
+     * The y-cordinate of the cursor relative to the <code>Display</code>
+     */
+    public int y;
+
+    /**
+     * The operation being performed.
+     * @see DND#DROP_NONE
+     * @see DND#DROP_MOVE
+     * @see DND#DROP_COPY
+     * @see DND#DROP_LINK
+     */
+    public int detail;
+
+    /**
+     * A bitwise OR'ing of the operations that the DragSource can support
+     * (e.g. DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK).
+     * The detail value must be a member of this list or DND.DROP_NONE.
+     * @see DND#DROP_NONE
+     * @see DND#DROP_MOVE
+     * @see DND#DROP_COPY
+     * @see DND#DROP_LINK
+     */
+    public int operations;
+
+    /**
+     * A bitwise OR'ing of the drag under effect feedback to be displayed to the user
+     * (e.g. DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND).
+     * <p>A value of DND.FEEDBACK_NONE indicates that no drag under effect will be displayed.</p>
+     * <p>Feedback effects will only be applied if they are applicable.</p>
+     * <p>The default value is DND.FEEDBACK_SELECT.</p>
+     * @see DND#FEEDBACK_NONE
+     * @see DND#FEEDBACK_SELECT
+     * @see DND#FEEDBACK_INSERT_BEFORE
+     * @see DND#FEEDBACK_INSERT_AFTER
+     * @see DND#FEEDBACK_SCROLL
+     * @see DND#FEEDBACK_EXPAND
+     */
+    public int feedback;
+
+    /**
+     * If the associated control is a table or tree, this field contains the item located
+     * at the cursor coordinates.
+     */
+    public Widget item;
+
+    /**
+     * The type of data that will be dropped.
+     */
+    public TransferData currentDataType;
+
+    /**
+     * A list of the types of data that the DragSource is capable of providing.
+     * The currentDataType must be a member of this list.
+     */
+    public TransferData[] dataTypes;
+
+    static const long serialVersionUID = 3256727264573338678L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(DNDEvent e) {
+    super(cast(Event)e);
+    this.data = e.data;
+    this.x = e.x;
+    this.y = e.y;
+    this.detail = e.detail;
+    this.currentDataType = e.dataType;
+    this.dataTypes = e.dataTypes;
+    this.operations = e.operations;
+    this.feedback = e.feedback;
+    this.item = e.item;
+}
+void updateEvent(DNDEvent e) {
+    e.widget = this.widget;
+    e.time = this.time;
+    e.data = this.data;
+    e.x = this.x;
+    e.y = this.y;
+    e.detail = this.detail;
+    e.dataType = this.currentDataType;
+    e.dataTypes = this.dataTypes;
+    e.operations = this.operations;
+    e.feedback = this.feedback;
+    e.item = this.item;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/DropTargetListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.DropTargetListener;
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import java.lang.all;
+
+/**
+ * The <code>DropTargetListener</code> class provides event notification to the application
+ * for DropTarget events.
+ *
+ * <p>As the user moves the cursor into, over and out of a Control that has been designated
+ * as a DropTarget, events indicate what operation can be performed and what data can be
+ * transferred if a drop where to occur at that point.
+ * The application can respond to these events and change the type of data that will
+ * be dropped by modifying event.currentDataType, or change the operation that will be performed
+ * by modifying the event.detail field or stop any drop from happening on the current target
+ * by setting the event.detail field to DND_DROP_NONE.</p>
+ *
+ * <p>When the user causes a drop to happen by releasing the mouse over a valid drop target,
+ * the application has one last chance to change the data type of the drop through the
+ * DropAccept event.  If the drop is still allowed, the DropAccept event is immediately
+ * followed by the Drop event.  In the Drop event, the application can still change the
+ * operation that is performed but the data type is fixed.</p>
+ *
+ * @see DropTargetEvent
+ *
+ */
+public interface DropTargetListener : SWTEventListener {
+
+/**
+ * The cursor has entered the drop target boundaries.
+ *
+ * <p>The following fields in the DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in)dataTypes
+ * <li>(in,out)currentDataType
+ * <li>(in)operations
+ * <li>(in,out)detail
+ * <li>(in,out)feedback
+ * </ul></p>
+ *
+ * <p>The <code>operation</code> value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the <code>event.detail</code> field is set to DND.DROP_DEFAULT.
+ * If the application does not set the <code>event.detail</code> to something other
+ * than <code>DND.DROP_DEFAULT</code> the operation will be set to the platform defined standard
+ * default.</p>
+ *
+ * <p>The <code>currentDataType</code> is determined by the first transfer agent specified in
+ * setTransfer() that matches a data type provided by the drag source.</p>
+ *
+ * <p>It is possible to get a DragEnter event when the drag source does not provide any matching data.
+ * In this case, the default operation is DND.DROP_NONE and the currentDataType is null.</p>
+ *
+ * <p>The application can change the operation that will be performed by modifying the
+ * <code>detail</code> field but the choice must be one of the values in the <code>operations</code>
+ * field or DND.DROP_NONE.</p>
+ *
+ * <p>The application can also change the type of data being requested by
+ * modifying the <code>currentDataTypes</code> field  but the value must be one of the values
+ * in the <code>dataTypes</code> list.</p>
+ *
+ * @param event  the information associated with the drag enter event
+ *
+ * @see DropTargetEvent
+ */
+public void dragEnter(DropTargetEvent event);
+
+/**
+ * The cursor has left the drop target boundaries OR the drop has been cancelled OR the data
+ * is about to be dropped.
+ *
+ * <p>The following fields in the DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in)dataTypes
+ * <li>(in)currentDataType
+ * <li>(in)operations
+ * <li>(in)detail
+ * </ul></p>
+ *
+ * @param event  the information associated with the drag leave event
+ *
+ * @see DropTargetEvent
+ */
+public void dragLeave(DropTargetEvent event);
+
+/**
+ * The operation being performed has changed (usually due to the user changing the selected modifier key(s)
+ * while dragging).
+ *
+ * <p>The following fields in the DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in)dataTypes
+ * <li>(in,out)currentDataType
+ * <li>(in)operations
+ * <li>(in,out)detail
+ * <li>(in,out)feedback
+ * </ul></p>
+ *
+ * <p>The <code>operation</code> value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the <code>event.detail</code> field is set to DND.DROP_DEFAULT.
+ * If the application does not set the <code>event.detail</code> to something other than
+ * <code>DND.DROP_DEFAULT</code> the operation will be set to the platform defined standard default.</p>
+ *
+ * <p>The <code>currentDataType</code> value is determined by the value assigned to
+ * <code>currentDataType</code> in previous dragEnter and dragOver calls.</p>
+ *
+ * <p>The application can change the operation that will be performed by modifying the
+ * <code>detail</code> field but the choice must be one of the values in the <code>operations</code>
+ * field.</p>
+ *
+ * <p>The application can also change the type of data being requested by modifying
+ * the <code>currentDataTypes</code> field  but the value must be one of the values in the
+ * <code>dataTypes</code> list.</p>
+ *
+ * @param event  the information associated with the drag operation changed event
+ *
+ * @see DropTargetEvent
+ */
+public void dragOperationChanged(DropTargetEvent event);
+
+/**
+ * The cursor is moving over the drop target.
+ *
+ * <p>The following fields in the DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in)dataTypes
+ * <li>(in,out)currentDataType
+ * <li>(in)operations
+ * <li>(in,out)detail
+ * <li>(in,out)feedback
+ * </ul></p>
+ *
+ * <p>The <code>operation</code> value is determined by the value assigned to
+ * <code>currentDataType</code> in previous dragEnter and dragOver calls.</p>
+ *
+ * <p>The <code>currentDataType</code> value is determined by the value assigned to
+ * <code>currentDataType</code> in previous dragEnter and dragOver calls.</p>
+ *
+ * <p>The application can change the operation that will be performed by modifying the
+ * <code>detail</code> field but the choice must be one of the values in the <code>operations</code>
+ * field.</p>
+ *
+ * <p>The application can also change the type of data being requested by modifying the
+ * <code>currentDataTypes</code> field  but the value must be one of the values in the
+ * <code>dataTypes</code> list.</p>
+ *
+ * <p>NOTE: At this point the <code>data</code> field is null.  On some platforms, it is possible
+ * to obtain the data being transferred before the transfer occurs but in most platforms this is
+ * not possible.  On those platforms where the data is available, the application can access the
+ * data as follows:</p>
+ *
+ * <pre><code>
+ * public void dragOver(DropTargetEvent event) {
+ *       TextTransfer textTransfer = TextTransfer.getInstance();
+ *       String data = (String)textTransfer.nativeToJava(event.currentDataType);
+ *       if (data !is null) {
+ *           System.out.println("Data to be dropped is (Text)"+data);
+ *       }
+ * };
+ * </code></pre>
+ *
+ * @param event  the information associated with the drag over event
+ *
+ * @see DropTargetEvent
+ */
+public void dragOver(DropTargetEvent event);
+
+/**
+ * The data is being dropped.  The data field contains java format of the data being dropped.
+ * To determine the type of the data object, refer to the documentation for the Transfer subclass
+ * specified in event.currentDataType.
+ *
+ * <p>The following fields in DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in,out)detail
+ * <li>(in)currentDataType
+ * <li>(in)data
+ * </ul></p>
+ *
+ * <p>The application can refuse to perform the drop operation by setting the detail
+ * field to DND.DROP_NONE.</p>
+ *
+ * @param event the information associated with the drop event
+ *
+ * @see DropTargetEvent
+ */
+public void drop(DropTargetEvent event);
+
+/**
+ * The drop is about to be performed.
+ * The drop target is given a last chance to change the nature of the drop.
+ *
+ * <p>The following fields in the DropTargetEvent apply:
+ * <ul>
+ * <li>(in)widget
+ * <li>(in)time
+ * <li>(in)x
+ * <li>(in)y
+ * <li>(in)dataTypes
+ * <li>(in,out)currentDataType
+ * <li>(in)operations
+ * <li>(in,out)detail
+ * </ul></p>
+ *
+ * <p>The application can veto the drop by setting the <code>event.detail</code> field to
+ * <code>DND.DROP_NONE</code>.</p>
+ *
+ * <p>The application can change the operation that will be performed by modifying the
+ * <code>detail</code> field but the choice must be one of the values in the
+ * <code>operations</code> field.</p>
+ *
+ * <p>The application can also change the type of data being requested by modifying the
+ * <code>currentDataTypes</code> field  but the value must be one of the values in the <
+ * code>dataTypes</code> list.</p>
+ *
+ * @param event  the information associated with the drop accept event
+ *
+ * @see DropTargetEvent
+ */
+public void dropAccept(DropTargetEvent event);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/FileTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.FileTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * The class <code>FileTransfer</code> provides a platform specific mechanism
+ * for converting a list of files represented as a java <code>String[]</code> to a
+ * platform specific representation of the data and vice versa.
+ * Each <code>String</code> in the array contains the absolute path for a single
+ * file or directory.
+ *
+ * <p>An example of a java <code>String[]</code> containing a list of files is shown
+ * below:</p>
+ *
+ * <code><pre>
+ *     File file1 = new File("C:\temp\file1");
+ *     File file2 = new File("C:\temp\file2");
+ *     String[] fileData = new String[2];
+ *     fileData[0] = file1.getAbsolutePath();
+ *     fileData[1] = file2.getAbsolutePath();
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class FileTransfer : ByteArrayTransfer {
+
+    private static FileTransfer _instance;
+    private static final String CF_HDROP = "CF_HDROP "; //$NON-NLS-1$
+    private static final int CF_HDROPID = COM.CF_HDROP;
+    private static final String CF_HDROP_SEPARATOR = "\0"; //$NON-NLS-1$
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+    if( _instance is null ){
+        synchronized {
+            if( _instance is null ){
+                _instance = new FileTransfer();
+            }
+        }
+    }
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts a list of file names
+ * represented by a java <code>String[]</code> to a platform specific representation.
+ * Each <code>String</code> in the array contains the absolute path for a single
+ * file or directory.
+ * 
+ * @param object a java <code>String[]</code> containing the file names to be converted
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative(Object object, TransferData transferData) {
+    if (!checkFile(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    String[] fileNames;
+    if( auto strs = cast(ArrayWrapperString2) object ){
+        fileNames = strs.array;
+    }
+    StringBuffer allFiles = new StringBuffer();
+    for (int i = 0; i < fileNames.length; i++) {
+        allFiles.append(fileNames[i]);
+        allFiles.append(CF_HDROP_SEPARATOR); // each name is null terminated
+    }
+    TCHAR[] buffer = StrToTCHARs(0, allFiles.toString(), true); // there is an extra null terminator at the very end
+    DROPFILES dropfiles;
+    dropfiles.pFiles = DROPFILES.sizeof;
+    dropfiles.pt.x = dropfiles.pt.y = 0;
+    dropfiles.fNC = 0;
+    dropfiles.fWide = OS.IsUnicode ? 1 : 0;
+    // Allocate the memory because the caller (DropTarget) has not handed it in
+    // The caller of this method must release the data when it is done with it.
+    int byteCount = buffer.length * TCHAR.sizeof;
+    auto newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
+    OS.MoveMemory(newPtr, &dropfiles, DROPFILES.sizeof);
+    OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer.ptr, byteCount);
+    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 a list of file names to a java <code>String[]</code>.
+ * Each String in the array contains the absolute path for a single file or directory.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>String[]</code> containing a list of file names if the conversion
+ *      was successful; otherwise null
+ * 
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData) {
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null)  return null;
+
+    // get file names from IDataObject
+    IDataObject dataObject = transferData.pIDataObject;
+    dataObject.AddRef();
+    FORMATETC* formatetc = new FORMATETC();
+    formatetc.cfFormat = COM.CF_HDROP;
+    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 = getData(dataObject, formatetc, stgmedium);
+    dataObject.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    // How many files are there?
+    int count = OS.DragQueryFile(stgmedium.unionField, 0xFFFFFFFF, null, 0);
+    String[] fileNames = new String[](count);
+    for (int i = 0; i < count; i++) {
+        // How long is the name ?
+        int size = OS.DragQueryFile(stgmedium.unionField, i, null, 0) + 1;
+        TCHAR[] lpszFile = NewTCHARs(0, size);
+        // Get file name and append it to string
+        OS.DragQueryFile(stgmedium.unionField, i, lpszFile.ptr, size);
+        fileNames[i] = TCHARzToStr(lpszFile.ptr);
+    }
+    OS.DragFinish(stgmedium.unionField); // frees data associated with HDROP data
+    return new ArrayWrapperString2(fileNames);
+}
+
+protected int[] getTypeIds(){
+    return [CF_HDROPID];
+}
+
+protected String[] getTypeNames(){
+    return [CF_HDROP];
+}
+bool checkFile(Object object) {
+    String[] strings;
+    if( auto strs = cast(ArrayWrapperString2)object ){
+        strings = strs.array;
+    }
+    if (!strings) return false;
+    for (int i = 0; i < strings.length; i++) {
+        if (strings[i] is null || strings[i].length is 0) return false;
+    }
+    return true;
+}
+
+protected bool validate(Object object) {
+    return checkFile(object);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/HTMLTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.HTMLTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * The class <code>HTMLTransfer</code> provides a platform specific mechanism
+ * for converting text in HTML format represented as a java <code>String</code>
+ * to a platform specific representation of the data and vice versa.
+ *
+ * <p>An example of a java <code>String</code> containing HTML text is shown
+ * below:</p>
+ *
+ * <code><pre>
+ *     String htmlData = "<p>This is a paragraph of text.</p>";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class HTMLTransfer : ByteArrayTransfer {
+
+    static HTMLTransfer _instance;
+    static const String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+    static const int HTML_FORMATID;
+    static const String NUMBER = "00000000"; //$NON-NLS-1$
+    static const String HEADER = "Version:0.9\r\nStartHTML:"~NUMBER~"\r\nEndHTML:"~NUMBER~"\r\nStartFragment:"~NUMBER~"\r\nEndFragment:"~NUMBER~"\r\n";
+    static const String PREFIX = "<html><body><!--StartFragment-->"; //$NON-NLS-1$
+    static const String SUFFIX = "<!--EndFragment--></body></html>"; //$NON-NLS-1$
+    static const String StartFragment = "StartFragment:"; //$NON-NLS-1$
+    static const String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+static this(){
+    HTML_FORMATID = registerType(HTML_FORMAT);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+    if( _instance is null ){
+        synchronized {
+            if( _instance is null ){
+                _instance = new HTMLTransfer();
+            }
+        }
+    }
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts HTML-formatted text
+ * represented by a java <code>String</code> to a platform specific representation.
+ *
+ * @param object a java <code>String</code> containing HTML text
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+    if (!checkHTML(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    String string = ( cast(ArrayWrapperString)object ).array;
+    /* 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;
+        return;
+    }
+    int startHTML = HEADER.length;
+    int startFragment = startHTML + PREFIX.length;
+    int endFragment = startFragment + cchMultiByte - 1;
+    int endHTML = endFragment + SUFFIX.length;
+
+    StringBuffer buffer = new StringBuffer(HEADER);
+    int maxLength = NUMBER.length;
+    //startHTML
+    int start = buffer.toString().indexOf(NUMBER);
+    String temp = Integer.toString(startHTML);
+    buffer.select(start + maxLength-temp.length, temp.length);
+    buffer.replace(temp);
+    buffer.select();
+
+    //endHTML
+    start = buffer.toString().indexOf(NUMBER, start);
+    temp = Integer.toString(endHTML);
+    buffer.select(start + maxLength-temp.length, temp.length);
+    buffer.replace( temp);
+    buffer.select();
+
+    //startFragment
+    start = buffer.toString().indexOf(NUMBER, start);
+    temp = Integer.toString(startFragment);
+    buffer.select(start + maxLength-temp.length, temp.length);
+    buffer.replace(temp);
+    buffer.select();
+    //endFragment
+    start = buffer.toString().indexOf(NUMBER, start);
+    temp = Integer.toString(endFragment);
+    buffer.select(start + maxLength-temp.length, temp.length);
+    buffer.replace(temp);
+    buffer.select();
+
+    buffer.append(PREFIX);
+    buffer.append(string);
+    buffer.append(SUFFIX);
+
+    auto wstrz = StrToTCHARz(OS.CP_UTF8,buffer.toString);
+    cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, null, 0, null, null);
+    auto lpMultiByteStr = cast(PCHAR) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+    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;
+    transferData.stgmedium.pUnkForRelease = null;
+    transferData.result = COM.S_OK;
+    return;
+}
+
+/**
+ * This implementation of <code>nativeToJava</code> converts a platform specific
+ * representation of HTML text to a java <code>String</code>.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>String</code> containing HTML text if the conversion was successful;
+ *      otherwise null
+ * 
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+    IDataObject data = transferData.pIDataObject;
+    data.AddRef();
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    FORMATETC* formatetc = transferData.formatetc;
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = getData(data, formatetc, stgmedium);
+    data.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    auto hMem = stgmedium.unionField;
+
+    try {
+        auto lpMultiByteStr = cast(PCHAR) OS.GlobalLock(hMem);
+        if (lpMultiByteStr is null) return null;
+        try {
+            /* 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 (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;
+            int end = start + 1;
+            while (end < string.length) {
+                String s = string.substring(start, end);
+                try {
+                    fragmentStart = Integer.parseInt(s);
+                    end++;
+                } catch (NumberFormatException e) {
+                    break;
+                }
+            }
+            start = string.indexOf(EndFragment) + EndFragment.length;
+            end = start + 1;
+            while (end < string.length) {
+                String s = string.substring(start, end);
+                try {
+                    fragmentEnd = Integer.parseInt(s);
+                    end++;
+                } catch (NumberFormatException e) {
+                    break;
+                }
+            }
+            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.
+             */
+            String foxStart = "<!--StartFragment -->\r\n"; //$NON-NLS-1$
+            int prefix = s.indexOf(foxStart);
+            if (prefix !is -1) {
+                prefix += foxStart.length;
+                s = s.substring(prefix);
+            }
+            return new ArrayWrapperString(s);
+        } finally {
+            OS.GlobalUnlock(hMem);
+        }
+    } finally {
+        OS.GlobalFree(hMem);
+    }
+}
+protected int[] getTypeIds(){
+    return [HTML_FORMATID];
+}
+protected String[] getTypeNames(){
+    return [HTML_FORMAT];
+}
+bool checkHTML(Object object) {
+    if( auto ws = cast(ArrayWrapperString)object ){
+        return ws.array.length > 0;
+    }
+    return false;
+}
+protected bool validate(Object object) {
+    return checkHTML(object);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/ImageTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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 org.eclipse.swt.dnd.ImageTransfer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+
+/**
+ * The class <code>ImageTransfer</code> provides a platform specific mechanism
+ * for converting an Image represented as a java <code>ImageData</code> to a 
+ * platform specific representation of the data and vice versa.
+ *
+ * <p>An example of a java <code>ImageData</code> is shown below:</p>
+ *
+ * <code><pre>
+ *     Image image = new Image(display, "C:\temp\img1.gif");
+ *     ImageData imgData = image.getImageData();
+ * </code></pre>
+ *
+ * @see Transfer
+ * 
+ * @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.
+ *
+ * @param object a java <code>ImageData</code> containing the ImageData to be converted
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+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) SWT.error(SWT.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>.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>ImageData</code> of the image if the conversion was successful;
+ *      otherwise null
+ * 
+ * @see Transfer#javaToNative
+ */
+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 = getData(dataObject, 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) SWT.error(SWT.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.dsBmih.biHeight;
+                int scanline = dib.dsBmih.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, SWT.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);
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/OleEnumFORMATETC.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.OleEnumFORMATETC;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+
+final class OleEnumFORMATETC {
+
+    private _IEnumFORMATETCImpl iEnumFORMATETC;
+
+    private int refCount;
+    private int index;
+
+    private FORMATETC*[] formats;
+
+this() {
+
+    createCOMInterfaces();
+
+}
+int AddRef() {
+    refCount++;
+    return refCount;
+}
+private void createCOMInterfaces() {
+    // register each of the interfaces that this object implements
+    iEnumFORMATETC = new _IEnumFORMATETCImpl( this );
+}
+private void disposeCOMInterfaces() {
+    iEnumFORMATETC = null;
+}
+IEnumFORMATETC getAddress() {
+    return iEnumFORMATETC;
+}
+private FORMATETC*[] getNextItems(int numItems){
+
+    if (formats is null || numItems < 1) return null;
+
+    int endIndex = index + numItems - 1;
+    if (endIndex > (formats.length - 1)) endIndex = formats.length - 1;
+    if (index > endIndex) return null;
+
+    FORMATETC*[] items =  new FORMATETC*[endIndex - index + 1];
+    for (int i = 0; i < items.length; i++){
+        items[i] = formats[index];
+        index++;
+    }
+
+    return items;
+}
+
+package HRESULT Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
+    /* Retrieves the next celt items in the enumeration sequence.
+       If there are fewer than the requested number of elements left in the sequence,
+       it retrieves the remaining elements.
+       The number of elements actually retrieved is returned through pceltFetched
+       (unless the caller passed in NULL for that parameter).
+    */
+
+    if (rgelt is null) return COM.E_INVALIDARG;
+    if (pceltFetched is null && celt !is 1) return COM.E_INVALIDARG;
+
+    FORMATETC*[] nextItems = getNextItems(celt);
+    if (nextItems !is null) {
+        for (int i = 0; i < nextItems.length; i++) {
+            rgelt[i] = *nextItems[i];
+        }
+
+        if (pceltFetched !is null)
+            *pceltFetched = nextItems.length;
+
+        if (nextItems.length is celt) return COM.S_OK;
+
+    } else {
+        if (pceltFetched !is null)
+            *pceltFetched = 0;
+        COM.MoveMemory(rgelt, & FORMATETC.init, FORMATETC.sizeof);
+
+    }
+    return COM.S_FALSE;
+}
+private HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+
+    if (riid is null || ppvObject is null) return COM.E_NOINTERFACE;
+
+    if (COM.IsEqualGUID(riid, &COM.IIDIUnknown)) {
+        *ppvObject = cast(void*)cast(IUnknown)iEnumFORMATETC;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(riid, &COM.IIDIEnumFORMATETC)) {
+        *ppvObject = cast(void*)cast(IEnumFORMATETC)iEnumFORMATETC;
+        AddRef();
+        return COM.S_OK;
+    }
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+int Release() {
+    refCount--;
+
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+        COM.CoFreeUnusedLibraries();
+    }
+
+    return refCount;
+}
+private int Reset() {
+    //Resets the enumeration sequence to the beginning.
+    index = 0;
+    return COM.S_OK;
+}
+void setFormats(FORMATETC*[] newFormats) {
+    formats = newFormats;
+    index = 0;
+}
+private int Skip(int celt) {
+    //Skips over the next specified number of elements in the enumeration sequence.
+    if (celt < 1 ) return COM.E_INVALIDARG;
+
+    index += celt;
+    if (index > (formats.length - 1)){
+        index = formats.length - 1;
+        return COM.S_FALSE;
+    }
+    return COM.S_OK;
+}
+}
+
+class _IEnumFORMATETCImpl : IEnumFORMATETC {
+
+
+    OleEnumFORMATETC    parent;
+    this(OleEnumFORMATETC   p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IEnumFORMATETC
+    HRESULT Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
+        return parent.Next(celt, rgelt, pceltFetched);
+    }
+    HRESULT Skip(ULONG celt) { return parent.Skip(celt); }
+    HRESULT Reset() { return parent.Reset(); }
+    HRESULT Clone(IEnumFORMATETC * ppenum) { return COM.E_NOTIMPL;}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/RTFTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.RTFTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+
+/**
+ * The class <code>RTFTransfer</code> provides a platform specific mechanism
+ * for converting text in RTF format represented as a java <code>String</code>
+ * to a platform specific representation of the data and vice versa.
+ *
+ * <p>An example of a java <code>String</code> containing RTF text is shown
+ * below:</p>
+ *
+ * <code><pre>
+ *     String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class RTFTransfer : ByteArrayTransfer {
+
+    private static RTFTransfer _instance;
+    private static const String CF_RTF = "Rich Text Format"; //$NON-NLS-1$
+    private static const int CF_RTFID;
+
+static this(){
+    CF_RTFID = registerType(CF_RTF);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+    if( _instance is null ){
+        synchronized {
+            if( _instance is null ){
+                _instance = new RTFTransfer();
+            }
+        }
+    }
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts RTF-formatted text
+ * represented by a java <code>String</code> to a platform specific representation.
+ *
+ * @param object a java <code>String</code> containing RTF text
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+    if (!checkRTF(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    // CF_RTF is stored as a null terminated byte array
+    String string = (cast(ArrayWrapperString)object).array;
+    wchar* chars = StrToWCHARz(string);
+    int codePage = OS.GetACP();
+    int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+    if (cchMultiByte is 0) {
+        transferData.stgmedium = new STGMEDIUM();
+        transferData.result = COM.DV_E_STGMEDIUM;
+        return;
+    }
+    auto lpMultiByteStr = cast(PCHAR)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+    OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+    transferData.stgmedium = new STGMEDIUM();
+    transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.stgmedium.unionField = lpMultiByteStr;
+    transferData.stgmedium.pUnkForRelease = null;
+    transferData.result = COM.S_OK;
+    return;
+}
+
+/**
+ * This implementation of <code>nativeToJava</code> converts a platform specific
+ * representation of RTF text to a java <code>String</code>.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>String</code> containing RTF text if the conversion was successful;
+ *      otherwise null
+ * 
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+    IDataObject data = transferData.pIDataObject;
+    data.AddRef();
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    FORMATETC* formatetc = transferData.formatetc;
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = getData(data, formatetc, stgmedium);
+    data.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    auto hMem = stgmedium.unionField;
+    try {
+        auto lpMultiByteStr = cast(CHAR*) OS.GlobalLock(hMem);
+        if (lpMultiByteStr is null) return null;
+        try {
+            int codePage = OS.GetACP();
+            int cchWideChar  = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, 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);
+            return new ArrayWrapperString( WCHARzToStr(lpWideCharStr.ptr));
+        } finally {
+            OS.GlobalUnlock(hMem);
+        }
+    } finally {
+        OS.GlobalFree(hMem);
+    }
+}
+
+protected int[] getTypeIds(){
+    return [CF_RTFID];
+}
+
+protected String[] getTypeNames(){
+    return [CF_RTF];
+}
+
+bool checkRTF(Object object) {
+    if( auto s = cast(ArrayWrapperString)object ){
+        return s.array.length > 0 ;
+    }
+    return false;
+}
+
+protected bool validate(Object object) {
+    return checkRTF(object);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDragSourceEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TableDragSourceEffect;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+import org.eclipse.swt.dnd.DragSourceEffect;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+import java.lang.all;
+
+/**
+ * This class provides default implementations to display a source image
+ * when a drag is initiated from a <code>Table</code>.
+ *
+ * <p>Classes that wish to provide their own source image for a <code>Table</code> can
+ * extend the <code>TableDragSourceEffect</code> class, override the
+ * <code>TableDragSourceEffect.dragStart</code> method and set the field
+ * <code>DragSourceEvent.image</code> with their own image.</p>
+ *
+ * Subclasses that override any methods of this class must call the corresponding
+ * <code>super</code> method to get the default drag source effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class TableDragSourceEffect : DragSourceEffect {
+    Image dragSourceImage = null;
+
+    /**
+     * Creates a new <code>TableDragSourceEffect</code> to handle drag effect
+     * from the specified <code>Table</code>.
+     *
+     * @param table the <code>Table</code> that the user clicks on to initiate the drag
+     */
+    public this(Table table) {
+        super(table);
+    }
+
+    /**
+     * This implementation of <code>dragFinished</code> disposes the image
+     * that was created in <code>TableDragSourceEffect.dragStart</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragFinished(event)</code>
+     * to dispose the image in the default implementation.
+     *
+     * @param event the information associated with the drag finished event
+     */
+    public void dragFinished(DragSourceEvent event) {
+        if (dragSourceImage !is null) dragSourceImage.dispose();
+        dragSourceImage = null;
+    }
+
+    /**
+     * This implementation of <code>dragStart</code> will create a default
+     * image that will be used during the drag. The image should be disposed
+     * when the drag is completed in the <code>TableDragSourceEffect.dragFinished</code>
+     * method.
+     *
+     * Subclasses that override this method should call <code>super.dragStart(event)</code>
+     * to use the image from the default implementation.
+     *
+     * @param event the information associated with the drag start event
+     */
+    public void dragStart(DragSourceEvent event) {
+        event.image = getDragSourceImage(event);
+    }
+
+    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) {
+                if ((control.getStyle() & SWT.MIRRORED) !is 0) {
+                    event.x += shdi.sizeDragImage.cx - shdi.ptOffset.x;
+                } else {
+                    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) SWT.error (SWT.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 ];
+
+                    PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                    ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+                    if (shdi.crColorKey is -1) {
+                        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;
+                        }
+                        data.alphaData = alphaData;
+                    } else {
+                        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);
+                    OS.DeleteObject (hImage);
+                    return dragSourceImage;
+                }
+            }
+            return null;
+        }
+        Table table = cast(Table) control;
+        //TEMPORARY CODE
+        if (table.isListening (SWT.EraseItem) || table.isListening (SWT.PaintItem)) return null;
+        TableItem[] selection = table.getSelection();
+        if (selection.length is 0) return null;
+        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);
+            for (int i = 1; i < count; i++) {
+                bounds = bounds.makeUnion(selection[i].getBounds(0));
+            }
+            auto hDC = OS.GetDC(null);
+            auto hDC1 = OS.CreateCompatibleDC(hDC);
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+                if ((table.getStyle() & SWT.RIGHT_TO_LEFT) !is 0) {
+                    OS.SetLayout(hDC1, OS.LAYOUT_RTL | OS.LAYOUT_BITMAPORIENTATIONPRESERVED);
+                }
+            }
+            auto bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+            auto hOldBitmap = OS.SelectObject(hDC1, bitmap);
+            RECT rect;
+            rect.right = bounds.width;
+            rect.bottom = bounds.height;
+            auto hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+            OS.FillRect(hDC1, &rect, hBrush);
+            for (int i = 0; i < count; i++) {
+                TableItem selected = selection[i];
+                Rectangle cell = selected.getBounds(0);
+                POINT pt;
+                HANDLE imageList = cast(HANDLE) OS.SendMessage (table.handle, OS.LVM_CREATEDRAGIMAGE, table.indexOf(selected), &pt);
+                OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+                OS.ImageList_Destroy(imageList);
+            }
+            OS.SelectObject(hDC1, hOldBitmap);
+            OS.DeleteDC (hDC1);
+            OS.ReleaseDC (null, hDC);
+            Display display = table.getDisplay();
+            dragSourceImage = Image.win32_new(display, SWT.BITMAP, bitmap);
+            return dragSourceImage;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TableDropTargetEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TableDropTargetEffect;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableItem;
+
+import org.eclipse.swt.dnd.DropTargetEffect;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+
+/**
+ * This class provides a default drag under effect (eg. select, insert and scroll)
+ * when a drag occurs over a <code>Table</code>.
+ *
+ * <p>Classes that wish to provide their own drag under effect for a <code>Table</code>
+ * can extend the <code>TableDropTargetEffect</code> and override any applicable methods
+ * in <code>TableDropTargetEffect</code> to display their own drag under effect.</p>
+ *
+ * Subclasses that override any methods of this class must call the corresponding
+ * <code>super</code> method to get the default drag under effect implementation.
+ *
+ * <p>The feedback value is either one of the FEEDBACK constants defined in
+ * class <code>DND</code> which is applicable to instances of this class,
+ * or it must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> effect constants.
+ * </p>
+ * <p>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_SCROLL</dd>
+ * </dl>
+ * </p>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class TableDropTargetEffect : DropTargetEffect {
+    static final int SCROLL_HYSTERESIS = 200; // milli seconds
+
+    int scrollIndex = -1;
+    long scrollBeginTime;
+    TableItem dropHighlight;
+
+    /**
+     * Creates a new <code>TableDropTargetEffect</code> to handle the drag under effect on the specified
+     * <code>Table</code>.
+     *
+     * @param table the <code>Table</code> over which the user positions the cursor to drop the data
+     */
+    public this(Table table) {
+        super(table);
+    }
+
+    int checkEffect(int effect) {
+        // Some effects are mutually exclusive.  Make sure that only one of the mutually exclusive effects has been specified.
+        if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+        if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+        return effect;
+    }
+
+    /**
+     * This implementation of <code>dragEnter</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragEnter</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragEnter(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag enter event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public void dragEnter(DropTargetEvent event) {
+        scrollBeginTime = 0;
+        scrollIndex = -1;
+        dropHighlight = null;
+    }
+
+    /**
+     * This implementation of <code>dragLeave</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragLeave</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragLeave(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag leave event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public void dragLeave(DropTargetEvent event) {
+        Table table = cast(Table) control;
+        auto handle = table.handle;
+        if (dropHighlight !is null) {
+            LVITEM lvItem;
+            lvItem.stateMask = OS.LVIS_DROPHILITED;
+            OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+            dropHighlight = null;
+        }
+        scrollBeginTime = 0;
+        scrollIndex = -1;
+    }
+
+    /**
+     * This implementation of <code>dragOver</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>. The class description
+     * lists the FEEDBACK constants that are applicable to the class.
+     *
+     * For additional information see <code>DropTargetAdapter.dragOver</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragOver(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag over event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     * @see DND#FEEDBACK_SELECT
+     * @see DND#FEEDBACK_SCROLL
+     */
+    public void dragOver(DropTargetEvent event) {
+        Table table = cast(Table) getControl();
+        int effect = checkEffect(event.feedback);
+        auto handle = table.handle;
+        Point coordinates = new Point(event.x, event.y);
+        coordinates = table.toControl(coordinates);
+        LVHITTESTINFO pinfo;
+        pinfo.pt.x = coordinates.x;
+        pinfo.pt.y = coordinates.y;
+        OS.SendMessage(handle, OS.LVM_HITTEST, 0, &pinfo);
+        if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+            scrollBeginTime = 0;
+            scrollIndex = -1;
+        } else {
+            if (pinfo.iItem !is -1 && scrollIndex is pinfo.iItem && scrollBeginTime !is 0) {
+                if (System.currentTimeMillis() >= scrollBeginTime) {
+                    int top = Math.max (0, OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+                    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+                    int index = (scrollIndex - 1 < top) ? Math.max(0, scrollIndex - 1) : Math.min(count - 1, scrollIndex + 1);
+                    bool scroll = true;
+                    if (pinfo.iItem is top) {
+                        scroll = pinfo.iItem !is index;
+                    } else {
+                        RECT itemRect;
+                        itemRect.left = OS.LVIR_BOUNDS;
+                        if (OS.SendMessage (handle, OS.LVM_GETITEMRECT, pinfo.iItem, &itemRect) !is 0) {
+                            RECT rect;
+                            OS.GetClientRect (handle, &rect);
+                            POINT pt;
+                            pt.x = itemRect.left;
+                            pt.y = itemRect.top;
+                            if (OS.PtInRect (&rect, pt)) {
+                                pt.y = itemRect.bottom;
+                                if (OS.PtInRect (&rect, pt)) scroll = false;
+                            }
+                        }
+                    }
+                    if (scroll) {
+                        OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+                        table.redraw();
+                    }
+                    scrollBeginTime = 0;
+                    scrollIndex = -1;
+                }
+            } else {
+                scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+                scrollIndex = pinfo.iItem;
+            }
+        }
+
+        if (pinfo.iItem !is -1 && (effect & DND.FEEDBACK_SELECT) !is 0) {
+            TableItem item = table.getItem(pinfo.iItem);
+            if (dropHighlight !is item) {
+                LVITEM lvItem;
+                lvItem.stateMask = OS.LVIS_DROPHILITED;
+                OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+                lvItem.state = OS.LVIS_DROPHILITED;
+                OS.SendMessage(handle, OS.LVM_SETITEMSTATE, pinfo.iItem, &lvItem);
+                dropHighlight = item;
+            }
+        } else {
+            if (dropHighlight !is null) {
+                LVITEM lvItem;
+                lvItem.stateMask = OS.LVIS_DROPHILITED;
+                OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+                dropHighlight = null;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TextTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TextTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * The class <code>TextTransfer</code> provides a platform specific mechanism
+ * for converting plain text represented as a java <code>String</code>
+ * to a platform specific representation of the data and vice versa.
+ *
+ * <p>An example of a java <code>String</code> containing plain text is shown
+ * below:</p>
+ *
+ * <code><pre>
+ *     String textData = "Hello World";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class TextTransfer : ByteArrayTransfer {
+
+    private static TextTransfer _instance;
+    private static const String CF_UNICODETEXT = "CF_UNICODETEXT"; //$NON-NLS-1$
+    private static const String CF_TEXT = "CF_TEXT"; //$NON-NLS-1$
+    private static const int CF_UNICODETEXTID = COM.CF_UNICODETEXT;
+    private static const int CF_TEXTID = COM.CF_TEXT;
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+    if( _instance is null ){
+        synchronized {
+            if( _instance is null ){
+                _instance = new TextTransfer();
+            }
+        }
+    }
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts plain text
+ * represented by a java <code>String</code> to a platform specific representation.
+ *
+ * @param object a java <code>String</code> containing text
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+    if (!checkText(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    transferData.result = COM.E_FAIL;
+    String string = (cast(ArrayWrapperString)object).array;
+    switch (transferData.type) {
+        case COM.CF_UNICODETEXT: {
+            wchar[] chars = StrToWCHARs(0,string, true);
+            int charCount = chars.length;
+            int byteCount = chars.length * 2;
+            auto newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, byteCount);
+            OS.MoveMemory(newPtr, chars.ptr, byteCount);
+            transferData.stgmedium = new STGMEDIUM();
+            transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+            transferData.stgmedium.unionField = newPtr;
+            transferData.stgmedium.pUnkForRelease = null;
+            transferData.result = COM.S_OK;
+            break;
+        }
+        case COM.CF_TEXT: {
+            wchar[] chars = StrToWCHARs(0,string, true);
+            int count = chars.length;
+            int codePage = OS.GetACP();
+            int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, null, 0, null, null);
+            if (cchMultiByte is 0) {
+                transferData.stgmedium = new STGMEDIUM();
+                transferData.result = COM.DV_E_STGMEDIUM;
+                return;
+            }
+            auto lpMultiByteStr = cast(CHAR*)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+            OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, lpMultiByteStr, cchMultiByte, null, null);
+            transferData.stgmedium = new STGMEDIUM();
+            transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+            transferData.stgmedium.unionField = lpMultiByteStr;
+            transferData.stgmedium.pUnkForRelease = null;
+            transferData.result = COM.S_OK;
+            break;
+        }
+        default:
+    }
+    return;
+}
+
+/**
+ * This implementation of <code>nativeToJava</code> converts a platform specific
+ * representation of plain text to a java <code>String</code>.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>String</code> containing text if the conversion was successful; otherwise null
+ *
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+
+    IDataObject data = transferData.pIDataObject;
+    data.AddRef();
+    FORMATETC* formatetc = transferData.formatetc;
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = getData(data, formatetc, stgmedium);
+    data.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    auto hMem = stgmedium.unionField;
+    try {
+        switch (transferData.type) {
+            case CF_UNICODETEXTID: {
+                /* Ensure byteCount is a multiple of 2 bytes */
+                int size = OS.GlobalSize(hMem) / 2 * 2;
+                if (size is 0) return null;
+                wchar[] chars = new wchar[size/2];
+                auto ptr = OS.GlobalLock(hMem);
+                if (ptr is null) return null;
+                try {
+                    OS.MoveMemory(chars.ptr, ptr, size);
+                    int length_ = chars.length;
+                    for (int i=0; i<chars.length; i++) {
+                        if (chars [i] is '\0') {
+                            length_ = i;
+                            break;
+                        }
+                    }
+                    return new ArrayWrapperString (WCHARsToStr(chars[ 0 .. length_]));
+                } finally {
+                    OS.GlobalUnlock(hMem);
+                }
+            }
+            case CF_TEXTID: {
+                auto lpMultiByteStr = cast(CHAR*)OS.GlobalLock(hMem);
+                if (lpMultiByteStr is null) return null;
+                try {
+                    int codePage = OS.GetACP();
+                    int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, 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);
+                    return new ArrayWrapperString( WCHARzToStr(lpWideCharStr.ptr));
+                } finally {
+                    OS.GlobalUnlock(hMem);
+                }
+            }
+            default:
+        }
+    } finally {
+        OS.GlobalFree(hMem);
+    }
+    return null;
+}
+
+protected int[] getTypeIds(){
+    return [CF_UNICODETEXTID, CF_TEXTID];
+}
+
+protected String[] getTypeNames(){
+    return [CF_UNICODETEXT, CF_TEXT];
+}
+
+bool checkText(Object object) {
+    if( auto s = cast(ArrayWrapperString)object ){
+        return s.array.length > 0;
+    }
+    return false;
+}
+
+protected bool validate(Object object) {
+    return checkText(object);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/Transfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.Transfer;
+
+
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.ole.win32.COM;
+
+import org.eclipse.swt.dnd.TransferData;
+import java.lang.all;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+static import tango.core.Thread;
+
+/**
+ * <code>Transfer</code> provides a mechanism for converting between a java
+ * representation of data and a platform specific representation of data and
+ * vice versa.  It is used in data transfer operations such as drag and drop and
+ * clipboard copy/paste.
+ *
+ * <p>You should only need to become familiar with this class if you are
+ * implementing a Transfer subclass and you are unable to subclass the
+ * ByteArrayTransfer class.</p>
+ *
+ * @see ByteArrayTransfer
+ * @see <a href="http://www.eclipse.org/swt/snippets/#dnd">Drag and Drop snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: DNDExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class Transfer {
+
+private static final int RETRY_LIMIT = 10;
+/* 
+ * Feature in Windows. When another application has control
+ * of the clipboard, the clipboard is locked and it's not
+ * possible to retrieve data until the other application is
+ * finished. To allow other applications to get the
+ * data, use PeekMessage() to enable cross thread
+ * message sends.
+ */
+int getData(IDataObject dataObject, FORMATETC* pFormatetc, STGMEDIUM* pmedium) {
+    if (dataObject.GetData(pFormatetc, pmedium) is COM.S_OK) return COM.S_OK;
+    try {tango.core.Thread.Thread.sleep(0.050);} catch (Exception t) {}
+    int result = dataObject.GetData(pFormatetc, pmedium);
+    int retryCount = 0;
+    while (result !is COM.S_OK && retryCount++ < RETRY_LIMIT) {
+        MSG msg;
+        OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+        try {tango.core.Thread.Thread.sleep(0.050);} catch (Exception t) {}
+        result = dataObject.GetData(pFormatetc, pmedium);
+    }
+    return result;
+}
+
+/**
+ * Returns a list of the platform specific data types that can be converted using
+ * this transfer agent.
+ *
+ * <p>Only the data type fields of the <code>TransferData</code> objects are filled
+ * in.</p>
+ *
+ * @return a list of the data types that can be converted using this transfer agent
+ */
+abstract public TransferData[] getSupportedTypes();
+
+/**
+ * Returns true if the <code>TransferData</code> data type can be converted
+ * using this transfer agent, or false otherwise (including if transferData is
+ * <code>null</code>).
+ *
+ * @param transferData a platform specific description of a data type; only the data
+ *  type fields of the <code>TransferData</code> object need to be filled in
+ *
+ * @return true if the transferData data type can be converted using this transfer
+ * agent
+ */
+abstract public bool isSupportedType(TransferData transferData);
+
+/**
+ * Returns the platform specific ids of the  data types that can be converted using
+ * this transfer agent.
+ *
+ * @return the platform specific ids of the data types that can be converted using
+ * this transfer agent
+ */
+abstract protected int[] getTypeIds();
+
+/**
+ * Returns the platform specific names of the  data types that can be converted
+ * using this transfer agent.
+ *
+ * @return the platform specific names of the data types that can be converted
+ * using this transfer agent.
+ */
+abstract protected String[] getTypeNames();
+
+/**
+ * Converts a java representation of data to a platform specific representation of
+ * the data.
+ *
+ * <p>On a successful conversion, the transferData.result field will be set as follows:
+ * <ul>
+ * <li>Windows: COM.S_OK
+ * <li>Motif: 1
+ * <li>GTK: 1
+ * <li>Photon: 1
+ * </ul></p>
+ *
+ * <p>If this transfer agent is unable to perform the conversion, the transferData.result
+ * field will be set to a failure value as follows:
+ * <ul>
+ * <li>Windows: COM.DV_E_TYMED or COM.E_FAIL
+ * <li>Motif: 0
+ * <li>GTK: 0
+ * <li>Photon: 0
+ * </ul></p>
+ *
+ * @param object a java representation of the data to be converted; the type of
+ * Object that is passed in is dependent on the <code>Transfer</code> subclass.
+ *
+ * @param transferData an empty TransferData object; this object will be
+ * filled in on return with the platform specific representation of the data
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *    <li>ERROR_INVALID_DATA - if object does not contain data in a valid format or is <code>null</code></li>
+ * </ul>
+ */
+abstract public void javaToNative (Object object, TransferData transferData);
+
+/**
+ * Converts a platform specific representation of data to a java representation.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * converted
+ *
+ * @return a java representation of the converted data if the conversion was
+ * successful; otherwise null.  If transferData is <code>null</code> then
+ * <code>null</code> is returned.  The type of Object that is returned is
+ * dependent on the <code>Transfer</code> subclass.
+ */
+abstract public Object nativeToJava(TransferData transferData);
+
+/**
+ * Registers a name for a data type and returns the associated unique identifier.
+ *
+ * <p>You may register the same type more than once, the same unique identifier
+ * will be returned if the type has been previously registered.</p>
+ *
+ * <p>Note: On windows, do <b>not</b> call this method with pre-defined
+ * Clipboard Format types such as CF_TEXT or CF_BITMAP because the
+ * pre-defined identifier will not be returned</p>
+ *
+ * @param formatName the name of a data type
+ *
+ * @return the unique identifier associated with this data type
+ */
+public static int registerType(String formatName) {
+    // Look name up in the registry
+    // If name is not in registry, add it and return assigned value.
+    // If name already exists in registry, return its assigned value
+    TCHAR* chFormatName = StrToTCHARz(0, formatName);
+    return OS.RegisterClipboardFormat(chFormatName);
+}
+
+/**
+ * Test that the object is of the correct format for this Transfer class.
+ *
+ * @param object a java representation of the data to be converted
+ *
+ * @return true if object is of the correct form for this transfer type
+ *
+ * @since 3.1
+ */
+public bool validate(Object object) {
+    return true;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TransferData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TransferData;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+
+/**
+ * The <code>TransferData</code> class is a platform specific data structure for
+ * describing the type and the contents of data being converted by a transfer agent.
+ *
+ * <p>As an application writer, you do not need to know the specifics of
+ * TransferData.  TransferData instances are passed to a subclass of Transfer
+ * and the Transfer object manages the platform specific issues.
+ * You can ask a Transfer subclass if it can handle this data by calling
+ * Transfer.isSupportedType(transferData).</p>
+ *
+ * <p>You should only need to become familiar with the fields in this class if you
+ * are implementing a Transfer subclass and you are unable to subclass the
+ * ByteArrayTransfer class.</p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TransferData {
+    /**
+     * The type is a unique identifier of a system format or user defined format.
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public int type;
+
+    /**
+     * The formatetc structure is a generalized data transfer format, enhanced to
+     * encompass a target device, the aspect, or view of the data, and
+     * a storage medium.
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public FORMATETC* formatetc;
+
+    /**
+     * The stgmedium structure is a generalized global memory handle used for
+     * data transfer operations.
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public STGMEDIUM* stgmedium;
+
+    /**
+     * The result field contains the result of converting a
+     * java data type into a platform specific value.
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     * <p>The value of result is 1 if the conversion was successful.
+     * The value of result is 0 if the conversion failed.</p>
+     */
+    public int result = COM.E_FAIL;
+
+    /**
+     * The pIDataObject is the address of an IDataObject OLE Interface which
+     * provides access to the data associated with the transfer.
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public IDataObject pIDataObject;
+
+    static bool sameType(TransferData data1, TransferData data2) {
+        if (data1 is data2) return true;
+        if (data1 is null || data2 is null) return false;
+        return (data1.type is data2.type &&
+                data1.formatetc.cfFormat is data2.formatetc.cfFormat &&
+                data1.formatetc.dwAspect is data2.formatetc.dwAspect &&
+                data1.formatetc.tymed is data2.formatetc.tymed);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDragSourceEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TreeDragSourceEffect;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+import org.eclipse.swt.dnd.DragSourceEffect;
+import org.eclipse.swt.dnd.DragSourceEvent;
+
+import java.lang.all;
+
+/**
+ * This class provides default implementations to display a source image
+ * when a drag is initiated from a <code>Tree</code>.
+ *
+ * <p>Classes that wish to provide their own source image for a <code>Tree</code> can
+ * extend <code>TreeDragSourceEffect</code> class and override the <code>TreeDragSourceEffect.dragStart</code>
+ * method and set the field <code>DragSourceEvent.image</code> with their own image.</p>
+ *
+ * Subclasses that override any methods of this class must call the corresponding
+ * <code>super</code> method to get the default drag under effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class TreeDragSourceEffect : DragSourceEffect {
+    Image dragSourceImage = null;
+
+    /**
+     * Creates a new <code>TreeDragSourceEffect</code> to handle drag effect
+     * from the specified <code>Tree</code>.
+     *
+     * @param tree the <code>Tree</code> that the user clicks on to initiate the drag
+     */
+    public this(Tree tree) {
+        super(tree);
+    }
+
+    /**
+     * This implementation of <code>dragFinished</code> disposes the image
+     * that was created in <code>TreeDragSourceEffect.dragStart</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragFinished(event)</code>
+     * to dispose the image in the default implementation.
+     *
+     * @param event the information associated with the drag finished event
+     */
+    public void dragFinished(DragSourceEvent event) {
+        if (dragSourceImage !is null) dragSourceImage.dispose();
+        dragSourceImage = null;
+    }
+
+    /**
+     * This implementation of <code>dragStart</code> will create a default
+     * image that will be used during the drag. The image should be disposed
+     * when the drag is completed in the <code>TreeDragSourceEffect.dragFinished</code>
+     * method.
+     *
+     * Subclasses that override this method should call <code>super.dragStart(event)</code>
+     * to use the image from the default implementation.
+     *
+     * @param event the information associated with the drag start event
+     */
+    public void dragStart(DragSourceEvent event) {
+        event.image = getDragSourceImage(event);
+    }
+
+    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) {
+                if ((control.getStyle() & SWT.MIRRORED) !is 0) {
+                    event.x += shdi.sizeDragImage.cx - shdi.ptOffset.x;
+                } else {
+                    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) SWT.error (SWT.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);
+                    if (shdi.crColorKey is -1) {
+                        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;
+                        }
+                        data.alphaData = alphaData;
+                    } else {
+                        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);
+                    OS.DeleteObject (hImage);
+                    return dragSourceImage;
+                }
+            }
+            return null;
+        }
+
+        Tree tree = cast(Tree) control;
+        //TEMPORARY CODE
+        if (tree.isListening (SWT.EraseItem) || tree.isListening (SWT.PaintItem)) return null;
+        TreeItem[] selection = tree.getSelection();
+        if (selection.length is 0) return null;
+        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);
+            for (int i = 1; i < count; i++) {
+                bounds = bounds.makeUnion(selection[i].getBounds(0));
+            }
+            auto hDC = OS.GetDC(tree.handle);
+            auto hDC1 = OS.CreateCompatibleDC(hDC);
+            auto bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+            auto hOldBitmap = OS.SelectObject(hDC1, bitmap);
+            RECT rect;
+            rect.right = bounds.width;
+            rect.bottom = bounds.height;
+            auto hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+            OS.FillRect(hDC1, &rect, hBrush);
+            for (int i = 0; i < count; i++) {
+                TreeItem selected = selection[i];
+                Rectangle cell = selected.getBounds(0);
+                HANDLE imageList = cast(HANDLE) OS.SendMessage(tree.handle, OS.TVM_CREATEDRAGIMAGE, 0, selected.handle);
+                OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+                OS.ImageList_Destroy(imageList);
+            }
+            OS.SelectObject(hDC1, hOldBitmap);
+            OS.DeleteDC (hDC1);
+            OS.ReleaseDC (tree.handle, hDC);
+            Display display = tree.getDisplay();
+            dragSourceImage = Image.win32_new(display, SWT.BITMAP, bitmap);
+            return dragSourceImage;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/TreeDropTargetEffect.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.TreeDropTargetEffect;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+import org.eclipse.swt.dnd.DropTargetEffect;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+
+/**
+ * This class provides a default drag under effect (eg. select, insert, scroll and expand)
+ * when a drag occurs over a <code>Tree</code>.
+ *
+ * <p>Classes that wish to provide their own drag under effect for a <code>Tree</code>
+ * can extend the <code>TreeDropTargetEffect</code> class and override any applicable methods
+ * in <code>TreeDropTargetEffect</code> to display their own drag under effect.</p>
+ *
+ * Subclasses that override any methods of this class must call the corresponding
+ * <code>super</code> method to get the default drag under effect implementation.
+ *
+ * <p>The feedback value is either one of the FEEDBACK constants defined in
+ * class <code>DND</code> which is applicable to instances of this class,
+ * or it must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>DND</code> effect constants.
+ * </p>
+ * <p>
+ * <dl>
+ * <dt><b>Feedback:</b></dt>
+ * <dd>FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE, FEEDBACK_INSERT_AFTER, FEEDBACK_EXPAND, FEEDBACK_SCROLL</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE or
+ * FEEDBACK_INSERT_AFTER may be specified.
+ * </p>
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class TreeDropTargetEffect : DropTargetEffect {
+    static final int SCROLL_HYSTERESIS = 200; // milli seconds
+    static final int EXPAND_HYSTERESIS = 1000; // milli seconds
+
+    int /*long*/ dropIndex;
+    int scrollIndex;
+    long scrollBeginTime;
+    int /*long*/ expandIndex;
+    long expandBeginTime;
+    TreeItem insertItem;
+    bool insertBefore;
+
+    /**
+     * Creates a new <code>TreeDropTargetEffect</code> to handle the drag under effect on the specified
+     * <code>Tree</code>.
+     *
+     * @param tree the <code>Tree</code> over which the user positions the cursor to drop the data
+     */
+    public this(Tree tree) {
+        super(tree);
+    }
+
+    int checkEffect(int effect) {
+        // Some effects are mutually exclusive.  Make sure that only one of the mutually exclusive effects has been specified.
+        if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+        if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+        return effect;
+    }
+
+    /**
+     * This implementation of <code>dragEnter</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragEnter</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragEnter(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag enter event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public void dragEnter(DropTargetEvent event) {
+        dropIndex = -1;
+        insertItem = null;
+        expandBeginTime = 0;
+        expandIndex = -1;
+        scrollBeginTime = 0;
+        scrollIndex = -1;
+    }
+
+    /**
+     * This implementation of <code>dragLeave</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragLeave</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragLeave(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag leave event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     */
+    public void dragLeave(DropTargetEvent event) {
+        Tree tree = cast(Tree) control;
+        auto handle = tree.handle;
+        if (dropIndex !is -1) {
+            TVITEM tvItem;
+            tvItem.hItem = cast(HTREEITEM) dropIndex;
+            tvItem.mask = OS.TVIF_STATE;
+            tvItem.stateMask = OS.TVIS_DROPHILITED;
+            tvItem.state = 0;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            dropIndex = -1;
+        }
+        if (insertItem !is null) {
+            tree.setInsertMark(null, false);
+            insertItem = null;
+        }
+        expandBeginTime = 0;
+        expandIndex = -1;
+        scrollBeginTime = 0;
+        scrollIndex = -1;
+    }
+
+    /**
+     * This implementation of <code>dragOver</code> provides a default drag under effect
+     * for the feedback specified in <code>event.feedback</code>.
+     *
+     * For additional information see <code>DropTargetAdapter.dragOver</code>.
+     *
+     * Subclasses that override this method should call <code>super.dragOver(event)</code>
+     * to get the default drag under effect implementation.
+     *
+     * @param event  the information associated with the drag over event
+     *
+     * @see DropTargetAdapter
+     * @see DropTargetEvent
+     * @see DND#FEEDBACK_SELECT
+     * @see DND#FEEDBACK_INSERT_BEFORE
+     * @see DND#FEEDBACK_INSERT_AFTER
+     * @see DND#FEEDBACK_SCROLL
+     */
+    public void dragOver(DropTargetEvent event) {
+        Tree tree = cast(Tree) getControl();
+        int effect = checkEffect(event.feedback);
+        auto handle = tree.handle;
+        Point coordinates = new Point(event.x, event.y);
+        coordinates = tree.toControl(coordinates);
+        TVHITTESTINFO lpht;
+        lpht.pt.x = coordinates.x;
+        lpht.pt.y = coordinates.y;
+        OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
+        auto hItem = lpht.hItem;
+        if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+            scrollBeginTime = 0;
+            scrollIndex = -1;
+        } else {
+            if (hItem !is cast(HTREEITEM)-1 && cast(HTREEITEM)scrollIndex is hItem && scrollBeginTime !is 0) {
+                if (System.currentTimeMillis() >= scrollBeginTime) {
+                    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 null;
+                    } else {
+                        RECT itemRect;
+                        if (OS.TreeView_GetItemRect (handle, nextItem, &itemRect, true)) {
+                            RECT rect;
+                            OS.GetClientRect (handle, &rect);
+                            POINT pt;
+                            pt.x = itemRect.left;
+                            pt.y = itemRect.top;
+                            if (OS.PtInRect (&rect, pt)) {
+                                pt.y = itemRect.bottom;
+                                if (OS.PtInRect (&rect, pt)) scroll = false;
+                            }
+                        }
+                    }
+                    if (scroll) {
+                        OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, nextItem);
+                        tree.redraw();
+                    }
+                    scrollBeginTime = 0;
+                    scrollIndex = -1;
+                }
+            } else {
+                scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+                scrollIndex = cast(int)hItem;
+            }
+        }
+        if ((effect & DND.FEEDBACK_EXPAND) is 0) {
+            expandBeginTime = 0;
+            expandIndex = -1;
+        } else {
+            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) {
+                        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(SWT.Expand, expandEvent);
+                        }
+                    }
+                    expandBeginTime = 0;
+                    expandIndex = -1;
+                }
+            } else {
+                expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS;
+                expandIndex = cast(int)hItem;
+            }
+        }
+        if (dropIndex !is -1 && (dropIndex !is cast(int)hItem || (effect & DND.FEEDBACK_SELECT) is 0)) {
+            TVITEM tvItem;
+            tvItem.hItem = cast(HTREEITEM) dropIndex;
+            tvItem.mask = OS.TVIF_STATE;
+            tvItem.stateMask = OS.TVIS_DROPHILITED;
+            tvItem.state = 0;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            dropIndex = -1;
+        }
+        if (cast(int)hItem !is -1 && cast(int)hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) {
+            TVITEM tvItem;
+            tvItem.hItem = cast(HTREEITEM) 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 = 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;
+            /*
+            * Bug in Windows.  When TVM_SETINSERTMARK is used to set
+            * an insert mark for a tree and an item is expanded or
+            * collapsed near the insert mark, the tree does not redraw
+            * the insert mark properly.  The fix is to hide and show
+            * the insert mark whenever an item is expanded or collapsed.
+            * 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, cast(int)hItem);
+            if (item !is null) {
+                if (item !is insertItem || before !is insertBefore) {
+                    tree.setInsertMark(item, before);
+                }
+                insertItem = item;
+                insertBefore = before;
+            } else {
+                if (insertItem !is null) {
+                    tree.setInsertMark(null, false);
+                }
+                insertItem = null;
+            }
+        } else {
+            if (insertItem !is null) {
+                tree.setInsertMark(null, false);
+            }
+            insertItem = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/URLTransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.dnd.URLTransfer;
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.dnd.DND;
+
+import java.lang.all;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * The class <code>URLTransfer</code> provides a platform specific mechanism
+ * for converting text in URL format represented as a java <code>String</code> 
+ * to a platform specific representation of the data and vice versa. The string
+ * must contain a fully specified url.
+ *
+ * <p>An example of a java <code>String</code> containing a URL is shown below:</p>
+ *
+ * <code><pre>
+ *     String url = "http://www.eclipse.org";
+ * </code></pre>
+ *
+ * @see Transfer
+ */
+public class URLTransfer : ByteArrayTransfer {
+
+    static URLTransfer _instance;
+    static const String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$
+    static const int CFSTR_INETURLID;
+
+static this(){
+    CFSTR_INETURLID = registerType(CFSTR_INETURL);
+}
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the URLTransfer class.
+ *
+ * @return the singleton instance of the URLTransfer class
+ */
+public static URLTransfer getInstance () {
+    if( _instance is null ){
+        synchronized {
+            if( _instance is null ){
+                _instance = new URLTransfer();
+            }
+        }
+    }
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts a URL
+ * represented by a java <code>String</code> to a platform specific representation.
+ *
+ * @param object a java <code>String</code> containing a URL
+ * @param transferData an empty <code>TransferData</code> object that will
+ *      be filled in on return with the platform specific format of the data
+ * 
+ * @see Transfer#nativeToJava
+ */
+public void javaToNative (Object object, TransferData transferData){
+    if (!checkURL(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    transferData.result = COM.E_FAIL;
+    // URL is stored as a null terminated byte array
+    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);
+    if (cchMultiByte is 0) {
+        transferData.stgmedium = new STGMEDIUM();
+        transferData.result = COM.DV_E_STGMEDIUM;
+        return;
+    }
+    auto lpMultiByteStr = cast(CHAR*)OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+    OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, lpMultiByteStr, cchMultiByte, null, null);
+    transferData.stgmedium = new STGMEDIUM();
+    transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.stgmedium.unionField = lpMultiByteStr;
+    transferData.stgmedium.pUnkForRelease = null;
+    transferData.result = COM.S_OK;
+    return;
+}
+
+/**
+ * This implementation of <code>nativeToJava</code> converts a platform 
+ * specific representation of a URL to a java <code>String</code>.
+ * 
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java <code>String</code> containing a URL if the conversion was successful;
+ *      otherwise null
+ * 
+ * @see Transfer#javaToNative
+ */
+public Object nativeToJava(TransferData transferData){
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+    IDataObject data = transferData.pIDataObject;
+    data.AddRef();
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    FORMATETC* formatetc = transferData.formatetc;
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = getData(data, formatetc, stgmedium);
+    data.Release();
+    if (transferData.result !is COM.S_OK) return null;
+    auto hMem = stgmedium.unionField;
+    try {
+        auto lpMultiByteStr = cast(CHAR*)OS.GlobalLock(hMem);
+        if (lpMultiByteStr is null) return null;
+        try {
+            int codePage = OS.GetACP();
+            int cchWideChar  = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, 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);
+            return new ArrayWrapperString( WCHARzToStr( lpWideCharStr.ptr) );
+        } finally {
+            OS.GlobalUnlock(hMem);
+        }
+    } finally {
+        OS.GlobalFree(hMem);
+    }
+}
+
+protected int[] getTypeIds(){
+    return [CFSTR_INETURLID];
+}
+
+protected String[] getTypeNames(){
+    return [CFSTR_INETURL];
+}
+
+bool checkURL(Object object) {
+    return object !is null && (null !is cast(ArrayWrapperString)object) && (cast(ArrayWrapperString)object).array.length > 0;
+
+}
+
+protected bool validate(Object object) {
+    return checkURL(object);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/dnd/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+module org.eclipse.swt.dnd.all;
+
+public import org.eclipse.swt.dnd.ByteArrayTransfer;
+public import org.eclipse.swt.dnd.Clipboard;
+public import org.eclipse.swt.dnd.DND;
+public import org.eclipse.swt.dnd.DNDEvent;
+public import org.eclipse.swt.dnd.DNDListener;
+public import org.eclipse.swt.dnd.DragSource;
+public import org.eclipse.swt.dnd.DragSourceAdapter;
+public import org.eclipse.swt.dnd.DragSourceEffect;
+public import org.eclipse.swt.dnd.DragSourceEvent;
+public import org.eclipse.swt.dnd.DragSourceListener;
+public import org.eclipse.swt.dnd.DropTarget;
+public import org.eclipse.swt.dnd.DropTargetAdapter;
+public import org.eclipse.swt.dnd.DropTargetEffect;
+public import org.eclipse.swt.dnd.DropTargetEvent;
+public import org.eclipse.swt.dnd.DropTargetListener;
+public import org.eclipse.swt.dnd.FileTransfer;
+public import org.eclipse.swt.dnd.HTMLTransfer;
+public import org.eclipse.swt.dnd.ImageTransfer;
+public import org.eclipse.swt.dnd.OleEnumFORMATETC;
+public import org.eclipse.swt.dnd.RTFTransfer;
+public import org.eclipse.swt.dnd.TableDragSourceEffect;
+public import org.eclipse.swt.dnd.TableDropTargetEffect;
+public import org.eclipse.swt.dnd.TextTransfer;
+public import org.eclipse.swt.dnd.Transfer;
+public import org.eclipse.swt.dnd.TransferData;
+public import org.eclipse.swt.dnd.TreeDragSourceEffect;
+public import org.eclipse.swt.dnd.TreeDropTargetEffect;
+public import org.eclipse.swt.dnd.URLTransfer;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ArmEvent;
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * a widget such as a menu item being armed.
+ *
+ * @see ArmListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class ArmEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3258126964249212217L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ArmListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ArmListener;
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.ArmEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a widget,
+ * such as a menu item, is armed.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a widget using the
+ * <code>addArmListener</code> method and removed using
+ * the <code>removeArmListener</code> method. When the
+ * widget is armed, the widgetArmed method will be invoked.
+ * </p>
+ *
+ * @see ArmEvent
+ */
+public interface ArmListener : SWTEventListener {
+
+/**
+ * Sent when a widget is armed, or 'about to be selected'.
+ *
+ * @param e an event containing information about the arm
+ */
+public void widgetArmed(ArmEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ControlAdapter;
+
+import org.eclipse.swt.events.ControlListener;
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>ControlListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>ControlEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see ControlListener
+ * @see ControlEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class ControlAdapter : ControlListener {
+
+/**
+ * Sent when the location (x, y) of a control changes relative
+ * to its parent (or relative to the display, for <code>Shell</code>s).
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e) {
+}
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ControlEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * controls being moved or resized.
+ *
+ * @see ControlListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class ControlEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3258132436155119161L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ControlListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ControlListener;
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.ControlEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated by moving
+ * and resizing controls.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addControlListener</code> method and removed using
+ * the <code>removeControlListener</code> method. When a
+ * control is moved or resized, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see ControlAdapter
+ * @see ControlEvent
+ */
+public interface ControlListener : SWTEventListener {
+
+/**
+ * Sent when the location (x, y) of a control changes relative
+ * to its parent (or relative to the display, for <code>Shell</code>s).
+ *
+ * @param e an event containing information about the move
+ */
+public void controlMoved(ControlEvent e);
+
+/**
+ * Sent when the size (width, height) of a control changes.
+ *
+ * @param e an event containing information about the resize
+ */
+public void controlResized(ControlEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.DisposeEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets being disposed.
+ *
+ * @see DisposeListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class DisposeEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3257566187633521206L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DisposeListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.DisposeListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.DisposeEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when a widget
+ * is disposed.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a widget using the
+ * <code>addDisposeListener</code> method and removed using
+ * the <code>removeDisposeListener</code> method. When a
+ * widget is disposed, the widgetDisposed method will
+ * be invoked.
+ * </p>
+ *
+ * @see DisposeEvent
+ */
+public interface DisposeListener : SWTEventListener {
+
+/**
+ * Sent when the widget is disposed.
+ *
+ * @param e an event containing information about the dispose
+ */
+public void widgetDisposed(DisposeEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DragDetectEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.DragDetectEvent;
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * a drag gesture.
+ *
+ * @see DragDetectListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+
+public final class DragDetectEvent : MouseEvent {
+
+    //private static final long serialVersionUID = -7229172519733647232L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/DragDetectListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.DragDetectListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.DragDetectEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when a drag
+ * gesture is detected.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addDragDetectListener</code> method and removed using
+ * the <code>removeDragDetectListener</code> method. When the
+ * drag is detected, the drageDetected method will be invoked.
+ * </p>
+ *
+ * @see DragDetectEvent
+ *
+ * @since 3.3
+ */
+public interface DragDetectListener : SWTEventListener {
+
+/**
+ * Sent when a drag gesture is detected.
+ *
+ * @param e an event containing information about the drag
+ */
+public void dragDetected(DragDetectEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ExpandAdapter;
+
+import org.eclipse.swt.events.ExpandListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>ExpandListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>ExpandEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see ExpandListener
+ * @see ExpandEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public abstract class ExpandAdapter : ExpandListener {
+
+/**
+ * Sent when an item is collapsed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the operation
+ */
+public void itemCollapsed(ExpandEvent e) {
+}
+
+/**
+ * Sent when an item is expanded.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the operation
+ */
+public void itemExpanded(ExpandEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ExpandEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.SelectionEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * <code>ExpandItem</code>s being expanded or collapsed.
+ *
+ * @see ExpandListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+
+public class ExpandEvent : SelectionEvent {
+
+    //static final long serialVersionUID = 3976735856884987356L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ExpandListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ExpandListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.ExpandEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the expanding and collapsing of <code>ExpandItem</code>s.
+ *
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a <code>ExpandBar</code>
+ * control using the <code>addExpandListener</code> method and
+ * removed using the <code>removeExpandListener</code> method.
+ * When a item of the <code>ExpandBar</code> is expanded or
+ * collapsed, the appropriate method will be invoked.
+ * </p>
+ *
+ * @see ExpandAdapter
+ * @see ExpandEvent
+ *
+ * @since 3.2
+ */
+public interface ExpandListener : SWTEventListener {
+
+/**
+ * Sent when an item is collapsed.
+ *
+ * @param e an event containing information about the operation
+ */
+public void itemCollapsed(ExpandEvent e);
+
+/**
+ * Sent when an item is expanded.
+ *
+ * @param e an event containing information about the operation
+ */
+public void itemExpanded(ExpandEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.FocusAdapter;
+
+import org.eclipse.swt.events.FocusListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>FocusListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>FocusEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see FocusListener
+ * @see FocusEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class FocusAdapter : FocusListener {
+
+/**
+ * Sent when a control gets focus.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusGained(FocusEvent e) {
+}
+
+/**
+ * Sent when a control loses focus.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusLost(FocusEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.FocusEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets gaining and losing focus.
+ *
+ * @see FocusListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class FocusEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3258134643684227381L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/FocusListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.FocusListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.FocusEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as controls
+ * gain and lose focus.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addFocusListener</code> method and removed using
+ * the <code>removeFocusListener</code> method. When a
+ * control gains or loses focus, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see FocusAdapter
+ * @see FocusEvent
+ */
+public interface FocusListener : SWTEventListener {
+
+/**
+ * Sent when a control gets focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusGained(FocusEvent e);
+
+/**
+ * Sent when a control loses focus.
+ *
+ * @param e an event containing information about the focus change
+ */
+public void focusLost(FocusEvent e);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/HelpEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.HelpEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * help being requested for a widget.
+ *
+ * @see HelpListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class HelpEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3257001038606251315L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/HelpListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.HelpListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.HelpEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated when help is
+ * requested for a control, typically when the user presses F1.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addHelpListener</code> method and removed using
+ * the <code>removeHelpListener</code> method. When help
+ * is requested for a control, the helpRequested method
+ * will be invoked.
+ * </p>
+ *
+ * @see HelpEvent
+ */
+public interface HelpListener : SWTEventListener {
+
+/**
+ * Sent when help is requested for a control, typically
+ * when the user presses F1.
+ *
+ * @param e an event containing information about the help
+ */
+public void helpRequested(HelpEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.KeyAdapter;
+
+import org.eclipse.swt.events.KeyListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>KeyListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>KeyEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see KeyListener
+ * @see KeyEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class KeyAdapter : KeyListener {
+
+/**
+ * Sent when a key is pressed on the system keyboard.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the key press
+ */
+public void keyPressed(KeyEvent e) {
+}
+
+/**
+ * Sent when a key is released on the system keyboard.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the key release
+ */
+public void keyReleased(KeyEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.KeyEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * keys being pressed and released on the keyboard.
+ * <p>
+ * When a key listener is added to a control, the control
+ * will take part in widget traversal.  By default, all
+ * traversal keys (such as the tab key and so on) are
+ * delivered to the control.  In order for a control to take
+ * part in traversal, it should listen for traversal events.
+ * Otherwise, the user can traverse into a control but not
+ * out.  Note that native controls such as table and tree
+ * implement key traversal in the operating system.  It is
+ * not necessary to add traversal listeners for these controls,
+ * unless you want to override the default traversal.
+ * </p>
+ *
+ * @see KeyListener
+ * @see TraverseListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class KeyEvent : TypedEvent {
+
+    /**
+     * the character represented by the key that was typed.
+     * This is the final character that results after all modifiers have been
+     * applied.  For example, when the user types Ctrl+A, the character value
+     * is 0x01.  It is important that applications do not attempt to modify the
+     * character value based on a stateMask (such as SWT.CTRL) or the resulting
+     * character will not be correct.
+     */
+    public wchar character = '\0';
+
+    /**
+     * the key code of the key that was typed,
+     * as defined by the key code constants in class <code>SWT</code>.
+     * When the character field of the event is ambiguous, this field
+     * contains the unicode value of the original character.  For example,
+     * typing Ctrl+M or Return both result in the character '\r' but the
+     * keyCode field will also contain '\r' when Return was typed.
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int keyCode;
+
+    /**
+     * the state of the keyboard modifier keys at the time
+     * the event was generated, as defined by the key code
+     * constants in class <code>SWT</code>.
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int stateMask;
+
+    /**
+     * A flag indicating whether the operation should be allowed.
+     * Setting this field to <code>false</code> will cancel the operation.
+     */
+    public bool doit;
+
+    static final long serialVersionUID = 3256442491011412789L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.character = e.character;
+    this.keyCode = e.keyCode;
+    this.stateMask = e.stateMask;
+    this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} character={} keyCode={} stateMask={} doit={}}",
+        super.toString[ 0 .. $-2 ],
+        character, keyCode, stateMask, doit );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/KeyListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.KeyListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.KeyEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as keys
+ * are pressed on the system keyboard.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addKeyListener</code> method and removed using
+ * the <code>removeKeyListener</code> method. When a
+ * key is pressed or released, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see KeyAdapter
+ * @see KeyEvent
+ */
+public interface KeyListener : SWTEventListener {
+
+/**
+ * Sent when a key is pressed on the system keyboard.
+ *
+ * @param e an event containing information about the key press
+ */
+public void keyPressed(KeyEvent e);
+
+/**
+ * Sent when a key is released on the system keyboard.
+ *
+ * @param e an event containing information about the key release
+ */
+public void keyReleased(KeyEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MenuAdapter;
+
+import org.eclipse.swt.events.MenuListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MenuListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MenuEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MenuListener
+ * @see MenuEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class MenuAdapter : MenuListener {
+
+/**
+ * Sent when a menu is hidden.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuHidden(MenuEvent e) {
+}
+
+/**
+ * Sent when a menu is shown.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuShown(MenuEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MenuDetectEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent whenever the platform-
+ * specific trigger for showing a context menu is detected.
+ *
+ * @see MenuDetectListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+
+public final class MenuDetectEvent : TypedEvent {
+
+    /**
+     * the display-relative x coordinate of the pointer
+     * at the time the context menu trigger occurred
+     */
+    public int x;
+
+    /**
+     * the display-relative y coordinate of the pointer
+     * at the time the context menu trigger occurred
+     */
+    public int y;
+
+    /**
+     * A flag indicating whether the operation should be allowed.
+     * Setting this field to <code>false</code> will cancel the operation.
+     */
+    public bool doit;
+
+    //private static final long serialVersionUID = -3061660596590828941L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.x = e.x;
+    this.y = e.y;
+    this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} x={} y={} doit={}}", super.toString[ 0 .. $-2 ], x, y, doit );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuDetectListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MenuDetectListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MenuDetectEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when the
+ * platform-specific trigger for showing a context menu is
+ * detected.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control or TrayItem
+ * using the <code>addMenuDetectListener</code> method and
+ * removed using the <code>removeMenuDetectListener</code> method.
+ * When the context menu trigger occurs, the
+ * <code>menuDetected</code> method will be invoked.
+ * </p>
+ *
+ * @see MenuDetectEvent
+ *
+ * @since 3.3
+ */
+public interface MenuDetectListener : SWTEventListener {
+
+/**
+ * Sent when the platform-dependent trigger for showing a menu item is detected.
+ *
+ * @param e an event containing information about the menu detect
+ */
+public void menuDetected (MenuDetectEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MenuEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * menus being shown and hidden.
+ *
+ * @see MenuListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class MenuEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3258132440332383025L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MenuListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MenuListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MenuEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the hiding and showing of menus.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a menu using the
+ * <code>addMenuListener</code> method and removed using
+ * the <code>removeMenuListener</code> method. When the
+ * menu is hidden or shown, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see MenuAdapter
+ * @see MenuEvent
+ */
+public interface MenuListener : SWTEventListener {
+
+/**
+ * Sent when a menu is hidden.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuHidden(MenuEvent e);
+
+/**
+ * Sent when a menu is shown.
+ *
+ * @param e an event containing information about the menu operation
+ */
+public void menuShown(MenuEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ModifyEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ModifyEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * text being modified.
+ *
+ * @see ModifyListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class ModifyEvent : TypedEvent {
+
+    //static final long serialVersionUID = 3258129146227011891L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ModifyListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ModifyListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.ModifyEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when text
+ * is modified.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a text widget using the
+ * <code>addModifyListener</code> method and removed using
+ * the <code>removeModifyListener</code> method. When the
+ * text is modified, the modifyText method will be invoked.
+ * </p>
+ *
+ * @see ModifyEvent
+ */
+public interface ModifyListener : SWTEventListener {
+
+/**
+ * Sent when the text is modified.
+ *
+ * @param e an event containing information about the modify
+ */
+public void modifyText(ModifyEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseAdapter;
+
+import org.eclipse.swt.events.MouseListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MouseListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MouseEvent</code>s
+ * which occur as mouse buttons are pressed and released can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MouseListener
+ * @see MouseEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class MouseAdapter : MouseListener {
+
+/**
+ * Sent when a mouse button is pressed twice within the
+ * (operating system specified) double click period.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse double click
+ *
+ * @see org.eclipse.swt.widgets.Display#getDoubleClickTime()
+ */
+public void mouseDoubleClick(MouseEvent e) {
+}
+
+/**
+ * Sent when a mouse button is pressed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse button press
+ */
+public void mouseDown(MouseEvent e) {
+}
+
+/**
+ * Sent when a mouse button is released.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse button release
+ */
+public void mouseUp(MouseEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent whenever mouse
+ * related actions occur. This includes mouse buttons
+ * being pressed and released, the mouse pointer being
+ * moved and the mouse pointer crossing widget boundaries.
+ * <p>
+ * Note: The <code>button</code> field is an integer that
+ * represents the mouse button number.  This is not the same
+ * as the <code>SWT</code> mask constants <code>BUTTONx</code>.
+ * </p>
+ *
+ * @see MouseListener
+ * @see MouseMoveListener
+ * @see MouseTrackListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class MouseEvent : TypedEvent {
+
+    /**
+     * the button that was pressed or released; 1 for the
+     * first button, 2 for the second button, and 3 for the
+     * third button, etc.
+     */
+    public int button;
+
+    /**
+     * the state of the keyboard modifier keys at the time
+     * the event was generated
+     */
+    public int stateMask;
+
+    /**
+     * the widget-relative, x coordinate of the pointer
+     * at the time the mouse button was pressed or released
+     */
+    public int x;
+
+    /**
+     * the widget-relative, y coordinate of the pointer
+     * at the time the mouse button was pressed or released
+     */
+    public int y;
+
+    /**
+     * the number times the mouse has been clicked, as defined
+     * by the operating system; 1 for the first click, 2 for the
+     * second click and so on.
+     *
+     * @since 3.3
+     */
+    public int count;
+
+    //static final long serialVersionUID = 3257288037011566898L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.x = e.x;
+    this.y = e.y;
+    this.button = e.button;
+    this.stateMask = e.stateMask;
+    this.count = e.count;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} button={} stateMask={} x={} y={} count={}}",
+        super.toString[ 0 .. $-1 ],
+        button, stateMask, x, y, count );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as mouse buttons
+ * are pressed.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addMouseListener</code> method and removed using
+ * the <code>removeMouseListener</code> method. When a
+ * mouse button is pressed or released, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see MouseAdapter
+ * @see MouseEvent
+ */
+public interface MouseListener : SWTEventListener {
+
+/**
+ * Sent when a mouse button is pressed twice within the
+ * (operating system specified) double click period.
+ *
+ * @param e an event containing information about the mouse double click
+ *
+ * @see org.eclipse.swt.widgets.Display#getDoubleClickTime()
+ */
+public void mouseDoubleClick(MouseEvent e);
+
+/**
+ * Sent when a mouse button is pressed.
+ *
+ * @param e an event containing information about the mouse button press
+ */
+public void mouseDown(MouseEvent e);
+
+/**
+ * Sent when a mouse button is released.
+ *
+ * @param e an event containing information about the mouse button release
+ */
+public void mouseUp(MouseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseMoveListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseMoveListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated as the mouse
+ * pointer moves.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addMouseMoveListener</code> method and removed using
+ * the <code>removeMouseMoveListener</code> method. As the
+ * mouse moves, the mouseMove method will be invoked.
+ * </p>
+ *
+ * @see MouseEvent
+ */
+public interface MouseMoveListener : SWTEventListener {
+
+/**
+ * Sent when the mouse moves.
+ *
+ * @param e an event containing information about the mouse move
+ */
+public void mouseMove(MouseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseTrackAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseTrackAdapter;
+
+import org.eclipse.swt.events.MouseTrackListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>MouseTrackListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>MouseEvent</code>s which
+ * occur as the mouse pointer passes (or hovers) over controls can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see MouseTrackListener
+ * @see MouseEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class MouseTrackAdapter : MouseTrackListener {
+
+/**
+ * Sent when the mouse pointer passes into the area of
+ * the screen covered by a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse enter
+ */
+public void mouseEnter(MouseEvent e) {
+}
+
+/**
+ * Sent when the mouse pointer passes out of the area of
+ * the screen covered by a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the mouse exit
+ */
+public void mouseExit(MouseEvent e) {
+}
+
+/**
+ * Sent when the mouse pointer hovers (that is, stops moving
+ * for an (operating system specified) period of time) over
+ * a control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the hover
+ */
+public void mouseHover(MouseEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseTrackListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseTrackListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated as the mouse
+ * pointer passes (or hovers) over controls.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addMouseTrackListener</code> method and removed using
+ * the <code>removeMouseTrackListener</code> method. When the
+ * mouse pointer passes into or out of the area of the screen
+ * covered by a control or pauses while over a control, the
+ * appropriate method will be invoked.
+ * </p>
+ *
+ * @see MouseTrackAdapter
+ * @see MouseEvent
+ */
+public interface MouseTrackListener : SWTEventListener {
+
+/**
+ * Sent when the mouse pointer passes into the area of
+ * the screen covered by a control.
+ *
+ * @param e an event containing information about the mouse enter
+ */
+public void mouseEnter(MouseEvent e);
+
+/**
+ * Sent when the mouse pointer passes out of the area of
+ * the screen covered by a control.
+ *
+ * @param e an event containing information about the mouse exit
+ */
+public void mouseExit(MouseEvent e);
+
+/**
+ * Sent when the mouse pointer hovers (that is, stops moving
+ * for an (operating system specified) period of time) over
+ * a control.
+ *
+ * @param e an event containing information about the hover
+ */
+public void mouseHover(MouseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/MouseWheelListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.MouseWheelListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the event that is generated as the mouse
+ * wheel is scrolled.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addMouseWheelListener</code> method and removed using
+ * the <code>removeMouseWheelListener</code> method. When the
+ * mouse wheel is scrolled the <code>mouseScrolled</code> method
+ * will be invoked.
+ * </p>
+ *
+ * @see MouseEvent
+ *
+ * @since 3.3
+ */
+public interface MouseWheelListener : SWTEventListener {
+
+/**
+ * Sent when the mouse wheel is scrolled.
+ *
+ * @param e an event containing information about the mouse wheel action
+ */
+public void mouseScrolled (MouseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/PaintEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.PaintEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.graphics.GC;
+
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * visible areas of controls requiring re-painting.
+ *
+ * @see PaintListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class PaintEvent : TypedEvent {
+
+    /**
+     * the graphics context to use when painting
+     * that is configured to use the colors, font and
+     * damaged region of the control.  It is valid
+     * only during the paint and must not be disposed
+     */
+    public GC gc;
+
+    /**
+     * the x offset of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int x;
+
+    /**
+     * the y offset of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int y;
+
+    /**
+     * the width of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int width;
+
+    /**
+     * the height of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int height;
+
+    /**
+     * the number of following paint events which
+     * are pending which may always be zero on
+     * some platforms
+     */
+    public int count;
+
+    //static final long serialVersionUID = 3256446919205992497L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.gc = e.gc;
+    this.x = e.x;
+    this.y = e.y;
+    this.width = e.width;
+    this.height = e.height;
+    this.count = e.count;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} gc={} x={} y={} width={} height={} count={}}",
+        super.toString[ 0 .. $-1 ],
+        gc is null ? "null" : gc.toString,
+        x,
+        y,
+        width,
+        height,
+        count );
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/PaintListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.PaintListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.PaintEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when the
+ * control needs to be painted.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addPaintListener</code> method and removed using
+ * the <code>removePaintListener</code> method. When a
+ * paint event occurs, the paintControl method will be
+ * invoked.
+ * </p>
+ *
+ * @see PaintEvent
+ */
+public interface PaintListener : SWTEventListener {
+
+/**
+ * Sent when a paint event occurs for the control.
+ *
+ * @param e an event containing information about the paint
+ */
+public void paintControl(PaintEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.SelectionAdapter;
+
+import org.eclipse.swt.events.SelectionListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>SelectionListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>SelectionEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see SelectionListener
+ * @see SelectionEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class SelectionAdapter : SelectionListener {
+
+/**
+ * Sent when selection occurs in the control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the selection
+ */
+public void widgetSelected(SelectionEvent e) {
+}
+
+/**
+ * Sent when default selection occurs in the control.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the default selection
+ */
+public void widgetDefaultSelected(SelectionEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.SelectionEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets being selected.
+ * <p>
+ * Note: The fields that are filled in depend on the widget.
+ * </p>
+ *
+ * @see SelectionListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class SelectionEvent : TypedEvent {
+
+    /**
+     * The item that was selected.
+     */
+    public Widget item;
+
+    /**
+     * Extra detail information about the selection, depending on the widget.
+     *
+     * <p><b>Sash</b><ul>
+     * <li>{@link org.eclipse.swt.SWT#DRAG}</li>
+     * </ul></p><p><b>ScrollBar and Slider</b><ul>
+     * <li>{@link org.eclipse.swt.SWT#DRAG}</li>
+     * <li>{@link org.eclipse.swt.SWT#HOME}</li>
+     * <li>{@link org.eclipse.swt.SWT#END}</li>
+     * <li>{@link org.eclipse.swt.SWT#ARROW_DOWN}</li>
+     * <li>{@link org.eclipse.swt.SWT#ARROW_UP}</li>
+     * <li>{@link org.eclipse.swt.SWT#PAGE_DOWN}</li>
+     * <li>{@link org.eclipse.swt.SWT#PAGE_UP}</li>
+     * </ul></p><p><b>Table and Tree</b><ul>
+     * <li>{@link org.eclipse.swt.SWT#CHECK}</li>
+     * </ul></p><p><b>Text</b><ul>
+     * <li>{@link org.eclipse.swt.SWT#CANCEL}</li>
+     * </ul></p><p><b>CoolItem and ToolItem</b><ul>
+     * <li>{@link org.eclipse.swt.SWT#ARROW}</li>
+     * </ul></p>
+     */
+    public int detail;
+
+    /**
+     * The x location of the selected area.
+     */
+    public int x;
+
+    /**
+     * The y location of selected area.
+     */
+    public int y;
+
+    /**
+     * The width of selected area.
+     */
+    public int width;
+
+    /**
+     * The height of selected area.
+     */
+    public int height;
+
+    /**
+     * The state of the keyboard modifier keys at the time
+     * the event was generated.
+     */
+    public int stateMask;
+
+    /**
+     * The text of the hyperlink that was selected.
+     * This will be either the text of the hyperlink or the value of its HREF,
+     * if one was specified.
+     *
+     * @see org.eclipse.swt.widgets.Link#setText(String)
+     * @since 3.1
+     */
+    public String text;
+
+    /**
+     * A flag indicating whether the operation should be allowed.
+     * Setting this field to <code>false</code> will cancel the
+     * operation, depending on the widget.
+     */
+    public bool doit;
+
+    //static final long serialVersionUID = 3976735856884987953L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.item = e.item;
+    this.x = e.x;
+    this.y = e.y;
+    this.width = e.width;
+    this.height = e.height;
+    this.detail = e.detail;
+    this.stateMask = e.stateMask;
+    this.text = e.text;
+    this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} item={} detail={} x={} y={} width={} height={} stateMask={} text={} doit={}}",
+        super.toString[ 0 .. $-2 ],
+        item,
+        detail,
+        x,
+        y,
+        width,
+        height,
+        stateMask,
+        text,
+        doit );
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/SelectionListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.SelectionListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.SelectionEvent;
+
+import tango.core.Traits;
+import tango.core.Tuple;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when selection
+ * occurs in a control.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addSelectionListener</code> method and removed using
+ * the <code>removeSelectionListener</code> method. When
+ * selection occurs in a control the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see SelectionAdapter
+ * @see SelectionEvent
+ */
+public interface SelectionListener : SWTEventListener {
+
+    public enum {
+        SELECTION,
+        DEFAULTSELECTION
+    }
+/**
+ * Sent when selection occurs in the control.
+ * <p>
+ * For example, selection occurs in a List when the user selects
+ * an item or items with the keyboard or mouse.  On some platforms,
+ * the event occurs when a mouse button or key is pressed.  On others,
+ * it happens when the mouse or key is released.  The exact key or
+ * mouse gesture that causes this event is platform specific.
+ * </p>
+ *
+ * @param e an event containing information about the selection
+ */
+public void widgetSelected(SelectionEvent e);
+
+/**
+ * Sent when default selection occurs in the control.
+ * <p>
+ * For example, on some platforms default selection occurs in a List
+ * when the user double-clicks an item or types return in a Text.
+ * On some platforms, the event occurs when a mouse button or key is
+ * pressed.  On others, it happens when the mouse or key is released.
+ * The exact key or mouse gesture that causes this event is platform
+ * specific.
+ * </p>
+ *
+ * @param e an event containing information about the default selection
+ */
+public void widgetDefaultSelected(SelectionEvent e);
+}
+
+
+/// SWT extension
+private class _DgSelectionListenerT(Dg,T...) : SelectionListener {
+
+    alias ParameterTupleOf!(Dg) DgArgs;
+    static assert( is(DgArgs == Tuple!(SelectionEvent,T)),
+                "Delegate args not correct: "~DgArgs.stringof~" vs. (Event,"~T.stringof~")" );
+
+    Dg dg;
+    T  t;
+    int type;
+
+    private this( int type, Dg dg, T t ){
+        this.type = type;
+        this.dg = dg;
+        static if( T.length > 0 ){
+            this.t = t;
+        }
+    }
+
+    public void widgetSelected(SelectionEvent e){
+        if( type is SelectionListener.SELECTION ){
+            dg(e,t);
+        }
+    }
+    public void widgetDefaultSelected(SelectionEvent e){
+        if( type is SelectionListener.DEFAULTSELECTION ){
+            dg(e,t);
+        }
+    }
+}
+
+SelectionListener dgSelectionListener( Dg, T... )( int type, Dg dg, T args ){
+    return new _DgSelectionListenerT!( Dg, T )( type, dg, args );
+}
+
+SelectionListener dgSelectionListenerWidgetSelected( Dg, T... )( Dg dg, T args ){
+    return dgSelectionListener( SelectionListener.SELECTION, dg, args );
+}
+SelectionListener dgSelectionListenerWidgetDefaultSelected( Dg, T... )( Dg dg, T args ){
+    return dgSelectionListener( SelectionListener.DEFAULTSELECTION, dg, args );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ShellAdapter;
+
+import org.eclipse.swt.events.ShellListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>ShellListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>ShellEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see ShellListener
+ * @see ShellEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class ShellAdapter : ShellListener {
+
+/**
+ * Sent when a shell becomes the active window.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the activation
+ */
+public void shellActivated(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is closed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the close
+ */
+public void shellClosed(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell stops being the active window.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the deactivation
+ */
+public void shellDeactivated(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is un-minimized.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the un-minimization
+ */
+public void shellDeiconified(ShellEvent e) {
+}
+
+/**
+ * Sent when a shell is minimized.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the minimization
+ */
+public void shellIconified(ShellEvent e) {
+}
+}
+
+class ShellDelegator : ShellAdapter {
+    alias void delegate(ShellEvent) DFunc;
+    DFunc delShellActivated;
+    DFunc delShellClosed;
+    DFunc delShellDeactivated;
+    DFunc delShellDeiconified;
+    DFunc delShellIconified;
+
+private this(
+    DFunc delShellActivated,
+    DFunc delShellClosed,
+    DFunc delShellDeactivated,
+    DFunc delShellDeiconified,
+    DFunc delShellIconified )
+{
+    this.delShellActivated = delShellActivated;
+    this.delShellClosed = delShellClosed;
+    this.delShellDeactivated = delShellDeactivated;
+    this.delShellDeiconified = delShellDeiconified;
+    this.delShellIconified = delShellIconified;
+}
+
+static ShellDelegator createShellActivated( DFunc del ){
+    return new ShellDelegator( del, null, null, null, null );
+}
+static ShellDelegator createShellClosed( DFunc del ){
+    return new ShellDelegator( null, del, null, null, null );
+}
+
+public void shellActivated(ShellEvent e) {
+    if( delShellActivated !is null ) delShellActivated(e);
+}
+public void shellClosed(ShellEvent e) {
+    if( delShellClosed !is null ) delShellClosed(e);
+}
+public void shellDeactivated(ShellEvent e) {
+    if( delShellDeactivated !is null ) delShellDeactivated(e);
+}
+public void shellDeiconified(ShellEvent e) {
+    if( delShellDeiconified !is null ) delShellDeiconified(e);
+}
+public void shellIconified(ShellEvent e) {
+    if( delShellIconified !is null ) delShellIconified(e);
+}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ShellEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.TypedEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * operations being performed on shells.
+ *
+ * @see ShellListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class ShellEvent : TypedEvent {
+
+    /**
+     * A flag indicating whether the operation should be allowed.
+     * Setting this field to <code>false</code> will cancel the operation.
+     */
+    public bool doit;
+
+    //static final long serialVersionUID = 3257569490479888441L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} doit={}}", super.toString[ 0 .. $-2 ], doit );
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/ShellListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.ShellListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.ShellEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with changes in state of <code>Shell</code>s.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a shell using the
+ * <code>addShellListener</code> method and removed using
+ * the <code>removeShellListener</code> method. When the
+ * state of the shell changes, the appropriate method will
+ * be invoked.
+ * </p>
+ *
+ * @see ShellAdapter
+ * @see ShellEvent
+ */
+public interface ShellListener : SWTEventListener {
+
+/**
+ * Sent when a shell becomes the active window.
+ *
+ * @param e an event containing information about the activation
+ */
+public void shellActivated(ShellEvent e);
+
+/**
+ * Sent when a shell is closed.
+ *
+ * @param e an event containing information about the close
+ */
+public void shellClosed(ShellEvent e);
+
+/**
+ * Sent when a shell stops being the active window.
+ *
+ * @param e an event containing information about the deactivation
+ */
+public void shellDeactivated(ShellEvent e);
+
+/**
+ * Sent when a shell is un-minimized.
+ *
+ * @param e an event containing information about the un-minimization
+ */
+public void shellDeiconified(ShellEvent e);
+
+/**
+ * Sent when a shell is minimized.
+ *
+ * @param e an event containing information about the minimization
+ */
+public void shellIconified(ShellEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TraverseEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.KeyEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * widget traversal actions.
+ * <p>
+ * The traversal event allows fine control over keyboard traversal
+ * in a control both to implement traversal and override the default
+ * traversal behavior defined by the system.  This is achieved using
+ * two fields, <code>detail</code> and <code>doit</code>.
+ * </p><p>
+ * When a control is traversed, a traverse event is sent.  The detail
+ * describes the type of traversal and the doit field indicates the default
+ * behavior of the system.  For example, when a right arrow key is pressed
+ * in a text control, the detail field is <code>TRAVERSE_ARROW_NEXT</code>
+ * and the doit field is <code>false</code>, indicating that the system
+ * will not traverse to the next tab item and the arrow key will be
+ * delivered to the text control.  If the same key is pressed in a radio
+ * button, the doit field will be <code>true</code>, indicating that
+ * traversal is to proceed to the next tab item, possibly another radio
+ * button in the group and that the arrow key is not to be delivered
+ * to the radio button.
+ * </p><p>
+ * How can the traversal event be used to implement traversal?
+ * When a tab key is pressed in a canvas, the detail field will be
+ * <code>TRAVERSE_TAB_NEXT</code> and the doit field will be
+ * <code>false</code>.  The default behavior of the system is to
+ * provide no traversal for canvas controls.  This means that by
+ * default in a canvas, a key listener will see every key that the
+ * user types, including traversal keys.  To understand why this
+ * is so, it is important to understand that only the widget implementor
+ * can decide which traversal is appropriate for the widget.  Returning
+ * to the <code>TRAVERSE_TAB_NEXT</code> example, a text widget implemented
+ * by a canvas would typically want to use the tab key to insert a
+ * tab character into the widget.  A list widget implementation, on the
+ * other hand, would like the system default traversal behavior.  Using
+ * only the doit flag, both implementations are possible.  The text widget
+ * implementor sets doit to <code>false</code>, ensuring that the system
+ * will not traverse and that the tab key will be delivered to key listeners.
+ * The list widget implementor sets doit to <code>true</code>, indicating
+ * that the system should perform tab traversal and that the key should not
+ * be delivered to the list widget.
+ * </p><p>
+ * How can the traversal event be used to override system traversal?
+ * When the return key is pressed in a single line text control, the
+ * detail field is <code>TRAVERSE_RETURN</code> and the doit field
+ * is <code>true</code>.  This means that the return key will be processed
+ * by the default button, not the text widget.  If the text widget has
+ * a default selection listener, it will not run because the return key
+ * will be processed by the default button.  Imagine that the text control
+ * is being used as an in-place editor and return is used to dispose the
+ * widget.  Setting doit to <code>false</code> will stop the system from
+ * activating the default button but the key will be delivered to the text
+ * control, running the key and selection listeners for the text.  How
+ * can <code>TRAVERSE_RETURN</code> be implemented so that the default button
+ * will not be activated and the text widget will not see the return key?
+ * This is achieved by setting doit to <code>true</code>, and the detail
+ * to <code>TRAVERSE_NONE</code>.
+ * </p><p>
+ * Note: A widget implementor will typically implement traversal using
+ * only the doit flag to either enable or disable system traversal.
+ * </p>
+ *
+ * @see TraverseListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class TraverseEvent : KeyEvent {
+
+    /**
+     * The traversal type.
+     * <p><ul>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_NONE}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_ESCAPE}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_RETURN}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_TAB_NEXT}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_TAB_PREVIOUS}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_ARROW_NEXT}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_ARROW_PREVIOUS}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_MNEMONIC}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_PAGE_NEXT}</li>
+     * <li>{@link org.eclipse.swt.SWT#TRAVERSE_PAGE_PREVIOUS}</li>
+     * </ul></p>
+     *
+     * Setting this field will change the type of traversal.
+     * For example, setting the detail to <code>TRAVERSE_NONE</code>
+     * causes no traversal action to be taken.
+     *
+     * When used in conjunction with the <code>doit</code> field, the
+     * traversal detail field can be useful when overriding the default
+     * traversal mechanism for a control. For example, setting the doit
+     * field to <code>false</code> will cancel the operation and allow
+     * the traversal key stroke to be delivered to the control. Setting
+     * the doit field to <code>true</code> indicates that the traversal
+     * described by the detail field is to be performed.
+     */
+    public int detail;
+
+    //static final long serialVersionUID = 3257565105301239349L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.detail = e.detail;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} detail={}}", super.toString[ 0 .. $-2 ], detail );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TraverseListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TraverseListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.TraverseEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when a
+ * traverse event occurs in a control.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a control using the
+ * <code>addTraverseListener</code> method and removed using
+ * the <code>removeTraverseListener</code> method. When a
+ * traverse event occurs in a control, the keyTraversed method
+ * will be invoked.
+ * </p>
+ *
+ * @see TraverseEvent
+ */
+public interface TraverseListener : SWTEventListener {
+
+/**
+ * Sent when a traverse event occurs in a control.
+ * <p>
+ * A traverse event occurs when the user presses a traversal
+ * key. Traversal keys are typically tab and arrow keys, along
+ * with certain other keys on some platforms. Traversal key
+ * constants beginning with <code>TRAVERSE_</code> are defined
+ * in the <code>SWT</code> class.
+ * </p>
+ *
+ * @param e an event containing information about the traverse
+ */
+public void keyTraversed(TraverseEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeAdapter.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TreeAdapter;
+
+import org.eclipse.swt.events.TreeListener;
+
+/**
+ * This adapter class provides default implementations for the
+ * methods described by the <code>TreeListener</code> interface.
+ * <p>
+ * Classes that wish to deal with <code>TreeEvent</code>s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ * </p>
+ *
+ * @see TreeListener
+ * @see TreeEvent
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class TreeAdapter : TreeListener {
+
+/**
+ * Sent when a tree branch is collapsed.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeCollapsed(TreeEvent e) {
+}
+
+/**
+ * Sent when a tree branch is expanded.
+ * The default behavior is to do nothing.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeExpanded(TreeEvent e) {
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TreeEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.SelectionEvent;
+
+/**
+ * Instances of this class are sent as a result of
+ * trees being expanded and collapsed.
+ *
+ * @see TreeListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class TreeEvent : SelectionEvent {
+
+    //static final long serialVersionUID = 3257282548009677109L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TreeListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TreeListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.TreeEvent;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the expanding and collapsing of tree
+ * branches.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a tree control using the
+ * <code>addTreeListener</code> method and removed using
+ * the <code>removeTreeListener</code> method. When a branch
+ * of the tree is expanded or collapsed, the appropriate method
+ * will be invoked.
+ * </p>
+ *
+ * @see TreeAdapter
+ * @see TreeEvent
+ */
+public interface TreeListener : SWTEventListener {
+
+/**
+ * Sent when a tree branch is collapsed.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeCollapsed(TreeEvent e);
+
+/**
+ * Sent when a tree branch is expanded.
+ *
+ * @param e an event containing information about the tree operation
+ */
+public void treeExpanded(TreeEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/TypedEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.TypedEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.internal.SWTEventObject;
+
+import tango.text.convert.Format;
+import tango.text.Util : split;
+import java.lang.all;
+
+/**
+ * This is the super class for all typed event classes provided
+ * by SWT. Typed events contain particular information which is
+ * applicable to the event occurrence.
+ *
+ * @see org.eclipse.swt.widgets.Event
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TypedEvent : SWTEventObject {
+
+    /**
+     * the display where the event occurred
+     *
+     * @since 2.0
+     */
+    public Display display;
+
+    /**
+     * the widget that issued the event
+     */
+    public Widget widget;
+
+    /**
+     * the time that the event occurred.
+     *
+     * NOTE: This field is an unsigned integer and should
+     * be AND'ed with 0xFFFFFFFFL so that it can be treated
+     * as a signed long.
+     */
+    public int time;
+
+    /**
+     * a field for application use
+     */
+    public Object data;
+
+    //static final long serialVersionUID = 3257285846578377524L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param object the object that fired the event
+ */
+public this(Object object) {
+    super(object);
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the argument.
+ *
+ * @param e the low level event to initialize the receiver with
+ */
+public this(Event e) {
+    super(e.widget);
+    this.display = e.display;
+    this.widget = e.widget;
+    this.time = e.time;
+    this.data = e.data;
+}
+
+/**
+ * Returns the name of the event. This is the name of
+ * the class without the module name.
+ *
+ * @return the name of the event
+ */
+String getName () {
+    String str = this.classinfo.name;
+    return split( str, "." )[$-1];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    String str_widget = widget is null ? "null" : widget.toString;
+    String str_data   = data is null ? "null" : data.toString;
+    return Format( "{}{{time={} data={}}", str_widget, time, str_data );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/VerifyEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.VerifyEvent;
+
+
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.KeyEvent;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are sent as a result of
+ * widgets handling keyboard events
+ *
+ * @see VerifyListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class VerifyEvent : KeyEvent {
+
+    /**
+     * the range of text being modified.
+     * Setting these fields has no effect.
+     */
+    public int start, end;
+
+    /**
+     * the new text that will be inserted.
+     * Setting this field will change the text that is about to
+     * be inserted or deleted.
+     */
+    public String text;
+
+    //static final long serialVersionUID = 3257003246269577014L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public this(Event e) {
+    super(e);
+    this.start = e.start;
+    this.end = e.end;
+    this.text = e.text;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    return Format( "{} start={} end={} text={}}", super.toString[ 0 .. $-2 ], start, end, text );
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/VerifyListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.events.VerifyListener;
+
+
+public import org.eclipse.swt.internal.SWTEventListener;
+public import org.eclipse.swt.events.VerifyEvent;
+
+/**
+ * Classes which implement this interface provide a method
+ * that deals with the events that are generated when text
+ * is about to be modified.
+ * <p>
+ * After creating an instance of a class that :
+ * this interface it can be added to a text control using the
+ * <code>addVerifyListener</code> method and removed using
+ * the <code>removeVerifyListener</code> method. When the
+ * text is about to be modified, the verifyText method
+ * will be invoked.
+ * </p>
+ *
+ * @see VerifyEvent
+ */
+public interface VerifyListener : SWTEventListener {
+
+/**
+ * Sent when the text is about to be modified.
+ * <p>
+ * A verify event occurs after the user has done something
+ * to modify the text (typically typed a key), but before
+ * the text is modified. The doit field in the verify event
+ * indicates whether or not to modify the text.
+ * </p>
+ *
+ * @param e an event containing information about the verify
+ */
+public void verifyText(VerifyEvent e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/events/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,54 @@
+module org.eclipse.swt.events.all;
+
+public import org.eclipse.swt.events.ArmEvent;
+public import org.eclipse.swt.events.ArmListener;
+public import org.eclipse.swt.events.ControlAdapter;
+public import org.eclipse.swt.events.ControlEvent;
+public import org.eclipse.swt.events.ControlListener;
+public import org.eclipse.swt.events.DisposeEvent;
+public import org.eclipse.swt.events.DisposeListener;
+public import org.eclipse.swt.events.DragDetectEvent;
+public import org.eclipse.swt.events.DragDetectListener;
+public import org.eclipse.swt.events.ExpandAdapter;
+public import org.eclipse.swt.events.ExpandEvent;
+public import org.eclipse.swt.events.ExpandListener;
+public import org.eclipse.swt.events.FocusAdapter;
+public import org.eclipse.swt.events.FocusEvent;
+public import org.eclipse.swt.events.FocusListener;
+public import org.eclipse.swt.events.HelpEvent;
+public import org.eclipse.swt.events.HelpListener;
+public import org.eclipse.swt.events.KeyAdapter;
+public import org.eclipse.swt.events.KeyEvent;
+public import org.eclipse.swt.events.KeyListener;
+public import org.eclipse.swt.events.MenuAdapter;
+public import org.eclipse.swt.events.MenuDetectEvent;
+public import org.eclipse.swt.events.MenuDetectListener;
+public import org.eclipse.swt.events.MenuEvent;
+public import org.eclipse.swt.events.MenuListener;
+public import org.eclipse.swt.events.ModifyEvent;
+public import org.eclipse.swt.events.ModifyListener;
+public import org.eclipse.swt.events.MouseAdapter;
+public import org.eclipse.swt.events.MouseEvent;
+public import org.eclipse.swt.events.MouseListener;
+public import org.eclipse.swt.events.MouseMoveListener;
+public import org.eclipse.swt.events.MouseTrackAdapter;
+public import org.eclipse.swt.events.MouseTrackListener;
+public import org.eclipse.swt.events.MouseWheelListener;
+public import org.eclipse.swt.events.PaintEvent;
+public import org.eclipse.swt.events.PaintListener;
+public import org.eclipse.swt.events.SelectionAdapter;
+public import org.eclipse.swt.events.SelectionEvent;
+public import org.eclipse.swt.events.SelectionListener;
+public import org.eclipse.swt.events.ShellAdapter;
+public import org.eclipse.swt.events.ShellEvent;
+public import org.eclipse.swt.events.ShellListener;
+public import org.eclipse.swt.events.TraverseEvent;
+public import org.eclipse.swt.events.TraverseListener;
+public import org.eclipse.swt.events.TreeAdapter;
+public import org.eclipse.swt.events.TreeEvent;
+public import org.eclipse.swt.events.TreeListener;
+public import org.eclipse.swt.events.TypedEvent;
+public import org.eclipse.swt.events.VerifyEvent;
+public import org.eclipse.swt.events.VerifyListener;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Color.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Color;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Device;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class manage the operating system resources that
+ * implement SWT's RGB color model. To create a color you can either
+ * specify the individual color components as integers in the range
+ * 0 to 255 or provide an instance of an <code>RGB</code>.
+ * <p>
+ * Application code must explicitly invoke the <code>Color.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see RGB
+ * @see Device#getSystemColor
+ * @see <a href="http://www.eclipse.org/swt/snippets/#color">Color and RGB snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Color : Resource {
+
+    alias Resource.init_ init_;
+
+    /**
+     * the handle to the OS color resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public COLORREF handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this(Device device) {
+    super(device);
+}
+
+/**
+ * Constructs a new instance of this class given a device and the
+ * desired red, green and blue values expressed as ints in the range
+ * 0 to 255 (where 0 is black and 255 is full brightness). On limited
+ * color devices, the color instance created by this call may not have
+ * the same RGB values as the ones specified by the arguments. The
+ * RGB values on the returned instance will be the color values of
+ * the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public this (Device device, int red, int green, int blue) {
+    super(device);
+    init_(red, green, blue);
+    init_();
+}
+
+/**
+ * Constructs a new instance of this class given a device and an
+ * <code>RGB</code> describing the desired red, green and blue values.
+ * On limited color devices, the color instance created by this call
+ * may not have the same RGB values as the ones specified by the
+ * argument. The RGB values on the returned instance will be the color
+ * values of the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param rgb the RGB values of the desired color
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the rgb argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public this (Device device, RGB rgb) {
+    super(device);
+    if (rgb is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(rgb.red, rgb.green, rgb.blue);
+    init_();
+}
+
+void destroy() {
+    /*
+     * If this is a palette-based device,
+     * Decrease the reference count for this color.
+     * If the reference count reaches 0, the slot may
+     * be reused when another color is allocated.
+     */
+    auto hPal = device.hPalette;
+    if (hPal !is null) {
+        int index = OS.GetNearestPaletteIndex(hPal, handle);
+        int[] colorRefCount = device.colorRefCount;
+        if (colorRefCount[index] > 0) {
+            colorRefCount[index]--;
+        }
+    }
+    handle = -1;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals (Object object) {
+    if (object is this) return true;
+    if (!(cast(Color)object)) return false;
+    Color color = cast(Color) object;
+    return device is color.device && (handle & 0xFFFFFF) is (color.handle & 0xFFFFFF);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getBlue () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return (handle & 0xFF0000) >> 16;
+}
+
+/**
+ * Returns the amount of green in the color, from 0 to 255.
+ *
+ * @return the green component of the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getGreen () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return (handle & 0xFF00) >> 8 ;
+}
+
+/**
+ * Returns the amount of red in the color, from 0 to 255.
+ *
+ * @return the red component of the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getRed () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return handle & 0xFF;
+}
+
+/**
+ * Returns an <code>RGB</code> representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public RGB getRGB () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return new RGB(cast(int)handle & 0xFF,cast(int) (handle & 0xFF00) >> 8,cast(int) (handle & 0xFF0000) >> 16);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public int hashCode () {
+    return handle;
+}
+
+/**
+ * Allocates the operating system resources associated
+ * with the receiver.
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+void init_(int red, int green, int blue) {
+    if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    handle = (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+
+    /* If this is not a palette-based device, return */
+    auto hPal = device.hPalette;
+    if (hPal is null) return;
+
+    int[] colorRefCount = device.colorRefCount;
+    /* Add this color to the default palette now */
+    /* First find out if the color already exists */
+    int index = OS.GetNearestPaletteIndex(hPal, handle);
+    /* See if the nearest color actually is the color */
+    PALETTEENTRY entry;
+    OS.GetPaletteEntries(hPal, index, 1, &entry);
+    if ((entry.peRed is cast(byte)red) && (entry.peGreen is cast(byte)green) &&
+        (entry.peBlue is cast(byte)blue)) {
+            /* Found the color. Increment the ref count and return */
+            colorRefCount[index]++;
+            return;
+    }
+    /* Didn't find the color, allocate it now. Find the first free entry */
+    int i = 0;
+    while (i < colorRefCount.length) {
+        if (colorRefCount[i] is 0) {
+            index = i;
+            break;
+        }
+        i++;
+    }
+    if (i is colorRefCount.length) {
+        /* No free entries, use the closest one */
+        /* Remake the handle from the actual rgbs */
+        handle = (entry.peRed & 0xFF) | ((entry.peGreen & 0xFF) << 8) |
+                 ((entry.peBlue & 0xFF) << 16);
+    } else {
+        /* Found a free entry */
+        entry.peRed = cast(BYTE)(red & 0xFF);
+        entry.peGreen = cast(BYTE)(green & 0xFF);
+        entry.peBlue = cast(BYTE)(blue & 0xFF);
+        entry.peFlags = 0;
+        OS.SetPaletteEntries(hPal, index, 1, &entry);
+    }
+    colorRefCount[index]++;
+}
+
+/**
+ * Returns <code>true</code> if the color has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the color.
+ * When a color has been disposed, it is an error to
+ * invoke any other method using the color.
+ *
+ * @return <code>true</code> when the color is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is -1;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$
+    return Format( "Color {{{}, {}, {}}", getRed(), getGreen(), getBlue()); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new color.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Color</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the color
+ * @return a new color object containing the specified device and handle
+ */
+public static Color win32_new(Device device, int handle) {
+    Color color = new Color(device);
+    color.disposeChecking = false;
+    color.handle = handle;
+    return color;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Cursor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Cursor;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Image;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class manage operating system resources that
+ * specify the appearance of the on-screen pointer. To create a
+ * cursor you specify the device and either a simple cursor style
+ * describing one of the standard operating system provided cursors
+ * or the image and mask data for the desired appearance.
+ * <p>
+ * Application code must explicitly invoke the <code>Cursor.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>
+ *   CURSOR_ARROW, CURSOR_WAIT, CURSOR_CROSS, CURSOR_APPSTARTING, CURSOR_HELP,
+ *   CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE,
+ *   CURSOR_SIZEN, CURSOR_SIZES, CURSOR_SIZEE, CURSOR_SIZEW, CURSOR_SIZENE, CURSOR_SIZESE,
+ *   CURSOR_SIZESW, CURSOR_SIZENW, CURSOR_UPARROW, CURSOR_IBEAM, CURSOR_NO, CURSOR_HAND
+ * </dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the above styles may be specified.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#cursor">Cursor snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Cursor : Resource {
+
+    alias Resource.init_ init_;
+
+    /**
+     * the handle to the OS cursor resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HCURSOR handle;
+
+    bool isIcon;
+
+    /**
+     * data used to create a HAND cursor.
+     */
+    static const byte[] HAND_SOURCE = [
+        cast(byte)0xf9,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0x3f,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0x07,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0x03,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff,
+
+        cast(byte)0x10,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0x80,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0xc0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0xe0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0xf0,cast(byte)0x00,cast(byte)0x7f,cast(byte)0xff,
+        cast(byte)0xf8,cast(byte)0x00,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xfc,cast(byte)0x01,cast(byte)0xff,cast(byte)0xff,
+
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,
+        cast(byte)0xff,cast(byte)0xff,cast(byte)0xff,cast(byte)0xff
+    ];
+    static const byte[] HAND_MASK = [
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0xc0,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x06,cast(byte)0xd8,cast(byte)0x00,cast(byte)0x00,
+
+        cast(byte)0x07,cast(byte)0xdb,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x67,cast(byte)0xfb,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x3f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x1f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x0f,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x07,cast(byte)0xff,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x03,cast(byte)0xfe,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,
+        cast(byte)0x00,cast(byte)0x00,cast(byte)0x00,cast(byte)0x00
+    ];
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this(Device device) {
+    super(device);
+}
+
+/**
+ * Constructs a new cursor given a device and a style
+ * constant describing the desired cursor appearance.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param style the style of cursor to allocate
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_INVALID_ARGUMENT - when an unknown style is specified</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ */
+public this(Device device, int style) {
+    super(device);
+    int /*long*/ lpCursorName = 0;
+    switch (style) {
+        case SWT.CURSOR_HAND:       lpCursorName = OS.IDC_HAND; break;
+        case SWT.CURSOR_ARROW:      lpCursorName = OS.IDC_ARROW; break;
+        case SWT.CURSOR_WAIT:       lpCursorName = OS.IDC_WAIT; break;
+        case SWT.CURSOR_CROSS:      lpCursorName = OS.IDC_CROSS; break;
+        case SWT.CURSOR_APPSTARTING:    lpCursorName = OS.IDC_APPSTARTING; break;
+        case SWT.CURSOR_HELP:       lpCursorName = OS.IDC_HELP; break;
+        case SWT.CURSOR_SIZEALL:    lpCursorName = OS.IDC_SIZEALL; break;
+        case SWT.CURSOR_SIZENESW:   lpCursorName = OS.IDC_SIZENESW; break;
+        case SWT.CURSOR_SIZENS:     lpCursorName = OS.IDC_SIZENS; break;
+        case SWT.CURSOR_SIZENWSE:   lpCursorName = OS.IDC_SIZENWSE; break;
+        case SWT.CURSOR_SIZEWE:     lpCursorName = OS.IDC_SIZEWE; break;
+        case SWT.CURSOR_SIZEN:      lpCursorName = OS.IDC_SIZENS; break;
+        case SWT.CURSOR_SIZES:      lpCursorName = OS.IDC_SIZENS; break;
+        case SWT.CURSOR_SIZEE:      lpCursorName = OS.IDC_SIZEWE; break;
+        case SWT.CURSOR_SIZEW:      lpCursorName = OS.IDC_SIZEWE; break;
+        case SWT.CURSOR_SIZENE:     lpCursorName = OS.IDC_SIZENESW; break;
+        case SWT.CURSOR_SIZESE:     lpCursorName = OS.IDC_SIZENWSE; break;
+        case SWT.CURSOR_SIZESW:     lpCursorName = OS.IDC_SIZENESW; break;
+        case SWT.CURSOR_SIZENW:     lpCursorName = OS.IDC_SIZENWSE; break;
+        case SWT.CURSOR_UPARROW:    lpCursorName = OS.IDC_UPARROW; break;
+        case SWT.CURSOR_IBEAM:      lpCursorName = OS.IDC_IBEAM; break;
+        case SWT.CURSOR_NO:         lpCursorName = OS.IDC_NO; break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    handle = OS.LoadCursor(null, cast(wchar*)lpCursorName);
+    /*
+    * IDC_HAND is supported only on Windows 2000 and Windows 98.
+    * Create a hand cursor if running in other Windows platforms.
+    */
+    if (handle is null && style is SWT.CURSOR_HAND) {
+        int width = OS.GetSystemMetrics(OS.SM_CXCURSOR);
+        int height = OS.GetSystemMetrics(OS.SM_CYCURSOR);
+        if (width is 32 && height is 32) {
+            auto hInst = OS.GetModuleHandle(null);
+            static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+            handle = OS.CreateCursor(hInst, 5, 0, 32, 32, HAND_SOURCE.ptr, HAND_MASK.ptr);
+
+        }
+    }
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new cursor given a device, image and mask
+ * data describing the desired cursor appearance, and the x
+ * and y coordinates of the <em>hotspot</em> (that is, the point
+ * within the area covered by the cursor which is considered
+ * to be where the on-screen pointer is "pointing").
+ * <p>
+ * The mask data is allowed to be null, but in this case the source
+ * must be an ImageData representing an icon that specifies both
+ * color data and mask data.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the color data for the cursor
+ * @param mask the mask data for the cursor (or null)
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the source is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the mask is null and the source does not have a mask</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the source and the mask are not the same
+ *          size, or if the hotspot is outside the bounds of the image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ */
+public this(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
+    super(device);
+    if (source is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (mask is null) {
+        if (source.getTransparencyType() !is SWT.TRANSPARENCY_MASK) {
+            SWT.error(SWT.ERROR_NULL_ARGUMENT);
+        }
+        mask = source.getTransparencyMask();
+    }
+    /* Check the bounds. Mask must be the same size as source */
+    if (mask.width !is source.width || mask.height !is source.height) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    /* Check the hotspots */
+    if (hotspotX >= source.width || hotspotX < 0 ||
+        hotspotY >= source.height || hotspotY < 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    /* Convert depth to 1 */
+    mask = ImageData.convertMask(mask);
+    source = ImageData.convertMask(source);
+
+    /* Make sure source and mask scanline pad is 2 */
+    byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2);
+    byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2);
+
+    /* Create the cursor */
+    auto hInst = OS.GetModuleHandle(null);
+    static if (OS.IsWinCE) SWT.error (SWT.ERROR_NOT_IMPLEMENTED);
+    handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData.ptr, maskData.ptr);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new cursor given a device, image data describing
+ * the desired cursor appearance, and the x and y coordinates of
+ * the <em>hotspot</em> (that is, the point within the area
+ * covered by the cursor which is considered to be where the
+ * on-screen pointer is "pointing").
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the image data for the cursor
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ *       image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public this(Device device, ImageData source, int hotspotX, int hotspotY) {
+    super(device);
+    if (source is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    /* Check the hotspots */
+    if (hotspotX >= source.width || hotspotX < 0 ||
+        hotspotY >= source.height || hotspotY < 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    ImageData mask = source.getTransparencyMask();
+    int[] result = Image.init_(this.device, null, source, mask);
+    auto hBitmap = cast(HBITMAP)result[0];
+    auto hMask = cast(HBITMAP)result[1];
+    /* Create the icon */
+    ICONINFO info;
+    info.fIcon = false;
+    info.hbmColor = hBitmap;
+    info.hbmMask = hMask;
+    info.xHotspot = hotspotX;
+    info.yHotspot = hotspotY;
+    handle = OS.CreateIconIndirect(&info);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    OS.DeleteObject(hBitmap);
+    OS.DeleteObject(hMask);
+    isIcon = true;
+    init_();
+}
+
+void destroy () {
+    /*
+    * It is an error in Windows to destroy the current
+    * cursor.  Check that the cursor that is about to
+    * be destroyed is the current cursor.  If so, set
+    * the current cursor to be IDC_ARROW.  Note that
+    * Windows shares predefined cursors so the call to
+    * LoadCursor() does not leak.
+    */
+    // TEMPORARY CODE
+//  if (OS.GetCursor() is handle) {
+//      OS.SetCursor(OS.LoadCursor(0, OS.IDC_ARROW));
+//  }
+
+    if (isIcon) {
+        OS.DestroyIcon(handle);
+    } else {
+        /*
+        * The MSDN states that one should not destroy a shared
+        * cursor, that is, one obtained from LoadCursor.
+        * However, it does not appear to do any harm, so rather
+        * than keep track of how a cursor was created, we just
+        * destroy them all. If this causes problems in the future,
+        * put the flag back in.
+        */
+        static if (!OS.IsWinCE) OS.DestroyCursor(handle);
+    }
+    handle = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public override int opEquals (Object object) {
+    if (object is this) return true;
+    if (!(cast(Cursor)object)) return false;
+    Cursor cursor = cast(Cursor) object;
+    return device is cursor.device && handle is cursor.handle;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+public override hash_t toHash () {
+    return cast(hash_t)handle;
+}
+
+/**
+ * Returns <code>true</code> if the cursor has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the cursor.
+ * When a cursor has been disposed, it is an error to
+ * invoke any other method using the cursor.
+ *
+ * @return <code>true</code> when the cursor is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "Cursor {*DISPOSED*}";
+    return Format( "Cursor {{{}}", handle );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new cursor.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Cursor</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the cursor
+ * @return a new cursor object containing the specified device and handle
+ */
+public static Cursor win32_new(Device device, HCURSOR handle) {
+    Cursor cursor = new Cursor(device);
+    cursor.disposeChecking = false;
+    cursor.handle = handle;
+    return cursor;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Device.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,957 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Device;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Path;
+import org.eclipse.swt.graphics.Pattern;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.graphics.Transform;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.graphics.DeviceData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Color;
+
+import java.lang.Runnable;
+import java.lang.System;
+
+import java.lang.all;
+import tango.core.Exception;
+import tango.util.Convert;
+import tango.io.Stdout;
+
+/**
+ * This class is the abstract superclass of all device objects,
+ * such as the Display device and the Printer device. Devices
+ * can have a graphics context (GC) created for them, and they
+ * can be drawn on by sending messages to the associated GC.
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class Device : Drawable {
+
+    private struct CallbackData {
+        Device device;
+        bool scalable;
+    }
+
+    /* Debugging */
+    public static bool DEBUG = true;
+    bool debug_;
+    bool tracking;
+    Exception [] errors;
+    Object [] objects;
+    Object trackingLock;
+
+    /**
+     * Palette
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HPALETTE hPalette;
+    int [] colorRefCount;
+
+    /* System Font */
+    Font systemFont;
+
+    /* Font Enumeration */
+    int nFonts = 256;
+    LOGFONT* [] logFonts;
+    TEXTMETRIC metrics;
+    int[] pixels;
+
+    /* Scripts */
+    SCRIPT_PROPERTIES*[] scripts;
+
+    /* Advanced Graphics */
+    ULONG_PTR gdipToken;
+
+    bool disposed;
+
+    /*
+    * TEMPORARY CODE. When a graphics object is
+    * created and the device parameter is null,
+    * the current Display is used. This presents
+    * a problem because SWT graphics does not
+    * reference classes in SWT widgets. The correct
+    * fix is to remove this feature. Unfortunately,
+    * too many application programs rely on this
+    * feature.
+    *
+    * This code will be removed in the future.
+    */
+    protected static Device CurrentDevice;
+    protected static Runnable DeviceFinder;
+
+
+/*
+* TEMPORARY CODE.
+*/
+static synchronized Device getDevice () {
+    if (DeviceFinder !is null) DeviceFinder.run();
+    Device device = CurrentDevice;
+    CurrentDevice = null;
+    return device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @see #create
+ * @see #init
+ *
+ * @since 3.1
+ */
+public this() {
+    this(null);
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #create
+ * @see #init
+ * @see DeviceData
+ */
+public this(DeviceData data) {
+    synchronized (Device.classinfo) {
+        debug_ = DEBUG;
+        tracking = DEBUG;
+        if (data !is null) {
+            debug_ = data.debug_;
+            tracking = data.tracking;
+        }
+        if (tracking) {
+            errors = new Exception [128];
+            objects = new Object [128];
+            trackingLock = new Object ();
+        }
+        create (data);
+        init_ ();
+        gdipToken = 0;
+    }
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * device implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code> and <code>dispose()</code>) on a
+ * device that has had its <code>dispose()</code> method called.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * <p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+protected void checkDevice () {
+    if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+void checkGDIP() {
+    if (gdipToken) return;
+    int oldErrorMode = 0;
+    static if (!OS.IsWinCE) oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
+    try {
+        ULONG_PTR token;
+        GdiplusStartupInput input;
+        input.GdiplusVersion = 1;
+        if (Gdip.GdiplusStartup ( &token, &input, null ) is 0) {
+            gdipToken = token;
+        }
+    } catch (Exception t) {
+        SWT.error (SWT.ERROR_NO_GRAPHICS_LIBRARY, t, " [GDI+ is required]"); //$NON-NLS-1$
+    } finally {
+        if (!OS.IsWinCE) OS.SetErrorMode (oldErrorMode);
+    }
+}
+
+/**
+ * Creates the device in the operating system.  If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ * <p>
+ * This method is called before <code>init</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+protected void create (DeviceData data) {
+}
+
+int computePixels(float height) {
+    auto hDC = internal_new_GC (null);
+    int pixels = -cast(int)(0.5f + (height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY) / 72f));
+    internal_dispose_GC (hDC, null);
+    return pixels;
+}
+
+float computePoints(LOGFONT* logFont, HFONT hFont) {
+    auto hDC = internal_new_GC (null);
+    int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
+    int pixels = 0;
+    if (logFont.lfHeight > 0) {
+        /*
+         * Feature in Windows. If the lfHeight of the LOGFONT structure
+         * is positive, the lfHeight measures the height of the entire
+         * cell, including internal leading, in logical units. Since the
+         * height of a font in points does not include the internal leading,
+         * we must subtract the internal leading, which requires a TEXTMETRIC.
+         */
+        auto oldFont = OS.SelectObject(hDC, hFont);
+        TEXTMETRIC* lptm = new TEXTMETRIC();
+        OS.GetTextMetrics(hDC, lptm);
+        OS.SelectObject(hDC, oldFont);
+        pixels = logFont.lfHeight - lptm.tmInternalLeading;
+    } else {
+        pixels = -logFont.lfHeight;
+    }
+    internal_dispose_GC (hDC, null);
+    return pixels * 72f / logPixelsY;
+}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle.  If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ * <p>
+ * This method is called after <code>release</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #release
+ */
+protected void destroy () {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver. After this method has been invoked, the receiver
+ * will answer <code>true</code> when sent the message
+ * <code>isDisposed()</code>.
+ *
+ * @see #release
+ * @see #destroy
+ * @see #checkDevice
+ */
+public void dispose () {
+    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) {
+    synchronized (trackingLock) {
+        for (int i=0; i<objects.length; i++) {
+            if (objects [i] is object) {
+                objects [i] = null;
+                errors [i] = null;
+                return;
+            }
+        }
+    }
+}
+
+static extern(Windows) int EnumFontFamFunc (ENUMLOGFONT* lpelfe, NEWTEXTMETRIC* lpntme, int FontType, int lParam) {
+    auto cbdata = cast(CallbackData*)lParam;
+    return cbdata.device.EnumFontFamProc( lpelfe, lpntme, FontType, cbdata.scalable );
+}
+
+int EnumFontFamProc (ENUMLOGFONT* lpelfe, NEWTEXTMETRIC* lpntme, DWORD FontType, bool scalable) {
+    bool isScalable = (FontType & OS.RASTER_FONTTYPE) is 0;
+    if (isScalable is scalable) {
+        /* Add the log font to the list of log fonts */
+        if (nFonts is logFonts.length) {
+            LOGFONT* [] newLogFonts = new LOGFONT* [logFonts.length + 128];
+            SimpleType!(LOGFONT*).arraycopy (logFonts, 0, newLogFonts, 0, nFonts);
+            logFonts = newLogFonts;
+            int[] newPixels = new int[newLogFonts.length];
+            System.arraycopy (pixels, 0, newPixels, 0, nFonts);
+            pixels = newPixels;
+        }
+        LOGFONT* logFont = logFonts [nFonts];
+        if (logFont is null) logFont = new LOGFONT ();
+        *logFont = *cast(LOGFONT*)lpelfe;
+        logFonts [nFonts] = logFont;
+        if (logFont.lfHeight > 0) {
+            /*
+             * Feature in Windows. If the lfHeight of the LOGFONT structure
+             * is positive, the lfHeight measures the height of the entire
+             * cell, including internal leading, in logical units. Since the
+             * height of a font in points does not include the internal leading,
+             * we must subtract the internal leading, which requires a TEXTMETRIC,
+             * which in turn requires font creation.
+             */
+            metrics = *cast(TEXTMETRIC*)lpntme;
+            pixels[nFonts] = logFont.lfHeight - metrics.tmInternalLeading;
+        } else {
+            pixels[nFonts] = -logFont.lfHeight;
+        }
+        nFonts++;
+    }
+    return 1;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location.
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds () {
+    checkDevice ();
+    auto hDC = internal_new_GC (null);
+    int width = OS.GetDeviceCaps (hDC, OS.HORZRES);
+    int height = OS.GetDeviceCaps (hDC, OS.VERTRES);
+    internal_dispose_GC (hDC, null);
+    return new Rectangle (0, 0, width, height);
+}
+
+/**
+ * Returns a <code>DeviceData</code> based on the receiver.
+ * Modifications made to this <code>DeviceData</code> will not
+ * affect the receiver.
+ *
+ * @return a <code>DeviceData</code> containing the device's data and attributes
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see DeviceData
+ */
+public DeviceData getDeviceData () {
+    checkDevice();
+    DeviceData data = new DeviceData ();
+    data.debug_ = debug_;
+    data.tracking = tracking;
+    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;
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ */
+public Rectangle getClientArea () {
+    return getBounds ();
+}
+
+/**
+ * Returns the bit depth of the screen, which is the number of
+ * bits it takes to represent the number of unique colors that
+ * the screen is currently capable of displaying. This number
+ * will typically be one of 1, 8, 15, 16, 24 or 32.
+ *
+ * @return the depth of the screen
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getDepth () {
+    checkDevice ();
+    auto hDC = internal_new_GC (null);
+    int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+    int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+    internal_dispose_GC (hDC, null);
+    return bits * planes;
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the display, and whose y coordinate
+ * is the vertical dots per inch of the display.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point getDPI () {
+    checkDevice ();
+    auto hDC = internal_new_GC (null);
+    int dpiX = OS.GetDeviceCaps (hDC, OS.LOGPIXELSX);
+    int dpiY = OS.GetDeviceCaps (hDC, OS.LOGPIXELSY);
+    internal_dispose_GC (hDC, null);
+    return new Point (dpiX, dpiY);
+}
+
+/**
+ * Returns <code>FontData</code> objects which describe
+ * the fonts that match the given arguments. If the
+ * <code>faceName</code> is null, all fonts will be returned.
+ *
+ * @param faceName the name of the font to look for, or null
+ * @param scalable if true only scalable fonts are returned, otherwise only non-scalable fonts are returned.
+ * @return the matching font data
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData [] getFontList (String faceName, bool scalable) {
+    checkDevice ();
+
+    /* Create the callback */
+    CallbackData cbdata;
+    cbdata.device = this;
+
+    /* Initialize the instance variables */
+    metrics = TEXTMETRIC.init;
+    pixels = new int[nFonts];
+    logFonts = new LOGFONT* [nFonts];
+    for (int i=0; i<logFonts.length; i++) {
+        logFonts [i] = new LOGFONT();
+    }
+    nFonts = 0;
+
+    /* Enumerate */
+    int offset = 0;
+    auto hDC = internal_new_GC (null);
+    if (faceName is null) {
+        /* The user did not specify a face name, so they want all versions of all available face names */
+        cbdata.scalable = scalable;
+        OS.EnumFontFamilies (hDC, null, &EnumFontFamFunc, cast(int)&cbdata );
+
+        /**
+         * For bitmapped fonts, EnumFontFamilies only enumerates once for each font, regardless
+         * of how many styles are available. If the user wants bitmapped fonts, enumerate on
+         * each face name now.
+         */
+        offset = nFonts;
+        for (int i=0; i<offset; i++) {
+            LOGFONT* lf = logFonts [i];
+            /**
+             * Bug in Windows 98. When EnumFontFamiliesEx is called with a specified face name, it
+             * should enumerate for each available style of that font. Instead, it only enumerates
+             * once. The fix is to call EnumFontFamilies, which works as expected.
+             */
+            cbdata.scalable = scalable;
+            static if (OS.IsUnicode) {
+                OS.EnumFontFamiliesW (hDC, (cast(LOGFONTW*)lf).lfFaceName.ptr, &EnumFontFamFunc, cast(int)&cbdata);
+            } else {
+                OS.EnumFontFamiliesA (hDC, (cast(LOGFONTA*)lf).lfFaceName.ptr, &EnumFontFamFunc, cast(int)&cbdata);
+            }
+        }
+    } else {
+        /* Use the character encoding for the default locale */
+        /**
+         * Bug in Windows 98. When EnumFontFamiliesEx is called with a specified face name, it
+         * should enumerate for each available style of that font. Instead, it only enumerates
+         * once. The fix is to call EnumFontFamilies, which works as expected.
+         */
+        cbdata.scalable = scalable;
+        OS.EnumFontFamilies (hDC, .StrToTCHARz(faceName), &EnumFontFamFunc, cast(int)&cbdata);
+    }
+    int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
+    internal_dispose_GC (hDC, null);
+
+    /* Create the fontData from the logfonts */
+    int count = 0;
+    FontData [] result = new FontData [nFonts - offset];
+    for (int i=offset; i<nFonts; i++) {
+        FontData fd = FontData.win32_new (logFonts [i], pixels [i] * 72f / logPixelsY);
+        int j;
+        for (j = 0; j < count; j++) {
+            if (fd == result [j]) break;
+        }
+        if (j is count) result [count++] = fd;
+    }
+    if (count !is result.length) {
+        FontData [] newResult = new FontData [count];
+        System.arraycopy (result, 0, newResult, 0, count);
+        result = newResult;
+    }
+
+    /* Clean up */
+    logFonts = null;
+    pixels = null;
+    metrics = TEXTMETRIC.init;
+    return result;
+}
+
+String getLastError () {
+    int error = OS.GetLastError();
+    if (error is 0) return ""; //$NON-NLS-1$
+    return " [GetLastError=0x" ~ .toHex(error) ~ "]"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+String getLastErrorText () {
+    int error = OS.GetLastError();
+    if (error is 0) return ""; //$NON-NLS-1$
+    TCHAR* buffer = null;
+    int dwFlags = OS.FORMAT_MESSAGE_ALLOCATE_BUFFER | OS.FORMAT_MESSAGE_FROM_SYSTEM | OS.FORMAT_MESSAGE_IGNORE_INSERTS;
+    int length = OS.FormatMessage(dwFlags, null, error, OS.LANG_USER_DEFAULT, cast(TCHAR*)&buffer, 0, null);
+    String errorNum = ("[GetLastError=") ~ .toHex(error) ~ "] ";
+    if (length == 0) return errorNum;
+    String buffer1 = .TCHARzToStr(buffer, length);
+    if ( *buffer != 0)
+        OS.LocalFree(cast(HLOCAL)buffer);
+    return errorNum ~ buffer1;
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class <code>SWT</code>. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be freed because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT
+ */
+public Color getSystemColor (int id) {
+    checkDevice ();
+    int pixel = 0x00000000;
+    switch (id) {
+        case SWT.COLOR_WHITE:               pixel = 0x00FFFFFF;  break;
+        case SWT.COLOR_BLACK:               pixel = 0x00000000;  break;
+        case SWT.COLOR_RED:                 pixel = 0x000000FF;  break;
+        case SWT.COLOR_DARK_RED:            pixel = 0x00000080;  break;
+        case SWT.COLOR_GREEN:               pixel = 0x0000FF00;  break;
+        case SWT.COLOR_DARK_GREEN:          pixel = 0x00008000;  break;
+        case SWT.COLOR_YELLOW:              pixel = 0x0000FFFF;  break;
+        case SWT.COLOR_DARK_YELLOW:         pixel = 0x00008080;  break;
+        case SWT.COLOR_BLUE:                pixel = 0x00FF0000;  break;
+        case SWT.COLOR_DARK_BLUE:           pixel = 0x00800000;  break;
+        case SWT.COLOR_MAGENTA:             pixel = 0x00FF00FF;  break;
+        case SWT.COLOR_DARK_MAGENTA:        pixel = 0x00800080;  break;
+        case SWT.COLOR_CYAN:                pixel = 0x00FFFF00;  break;
+        case SWT.COLOR_DARK_CYAN:           pixel = 0x00808000;  break;
+        case SWT.COLOR_GRAY:                pixel = 0x00C0C0C0;  break;
+        case SWT.COLOR_DARK_GRAY:           pixel = 0x00808080;  break;
+        default:
+    }
+    return Color.win32_new (this, pixel);
+}
+
+/**
+ * Returns a reasonable font for applications to use.
+ * On some platforms, this will match the "default font"
+ * or "system font" if such can be found.  This font
+ * should not be freed because it was allocated by the
+ * system, not the application.
+ * <p>
+ * Typically, applications which want the default look
+ * should simply not set the font on the widgets they
+ * create. Widgets are always created with the correct
+ * default font for the class of user-interface component
+ * they represent.
+ * </p>
+ *
+ * @return a font
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getSystemFont () {
+    checkDevice ();
+    auto hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    return Font.win32_new (this, hFont);
+}
+
+/**
+ * Returns <code>true</code> if the underlying window system prints out
+ * warning messages on the console, and <code>setWarnings</code>
+ * had previously been called with <code>true</code>.
+ *
+ * @return <code>true</code>if warnings are being handled, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool getWarnings () {
+    checkDevice ();
+    return false;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ * <p>
+ * This method is called after <code>create</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #create
+ */
+protected void init_ () {
+    if (debug_) {
+        static if (!OS.IsWinCE) OS.GdiSetBatchLimit(1);
+    }
+
+    /* Initialize the system font slot */
+    systemFont = getSystemFont();
+
+    /* Initialize scripts list */
+    static if (!OS.IsWinCE) {
+        SCRIPT_PROPERTIES** ppSp;
+        int piNumScripts;
+        OS.ScriptGetProperties (&ppSp, &piNumScripts);
+        scripts = ppSp[ 0 .. piNumScripts ].dup;
+    }
+
+    /*
+     * If we're not on a device which supports palettes,
+     * don't create one.
+     */
+    auto hDC = internal_new_GC (null);
+    int rc = OS.GetDeviceCaps (hDC, OS.RASTERCAPS);
+    int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+    int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+
+    bits *= planes;
+    if ((rc & OS.RC_PALETTE) is 0 || bits !is 8) {
+        internal_dispose_GC (hDC, null);
+        return;
+    }
+
+    int numReserved = OS.GetDeviceCaps (hDC, OS.NUMRESERVED);
+    int numEntries = OS.GetDeviceCaps (hDC, OS.SIZEPALETTE);
+
+    static if (OS.IsWinCE) {
+        /*
+        * Feature on WinCE.  For some reason, certain 8 bit WinCE
+        * devices return 0 for the number of reserved entries in
+        * the system palette.  Their system palette correctly contains
+        * the usual 20 system colors.  The workaround is to assume
+        * there are 20 reserved system colors instead of 0.
+        */
+        if (numReserved is 0 && numEntries >= 20) numReserved = 20;
+    }
+
+    /* Create the palette and reference counter */
+    colorRefCount = new int [numEntries];
+
+    /* 4 bytes header + 4 bytes per entry * numEntries entries */
+    byte [] logPalette = new byte [4 + 4 * numEntries];
+
+    /* 2 bytes = special header */
+    logPalette [0] = 0x00;
+    logPalette [1] = 0x03;
+
+    /* 2 bytes = number of colors, LSB first */
+    logPalette [2] = 0;
+    logPalette [3] = 1;
+
+    /*
+    * Create a palette which contains the system entries
+    * as they are located in the system palette.  The
+    * MSDN article 'Memory Device Contexts' describes
+    * where system entries are located.  On an 8 bit
+    * display with 20 reserved colors, the system colors
+    * will be the first 10 entries and the last 10 ones.
+    */
+    byte[] lppe = new byte [4 * numEntries];
+    OS.GetSystemPaletteEntries (hDC, 0, numEntries, cast(PALETTEENTRY*)lppe.ptr);
+    /* Copy all entries from the system palette */
+    System.arraycopy (lppe, 0, logPalette, 4, 4 * numEntries);
+    /* Lock the indices corresponding to the system entries */
+    for (int i = 0; i < numReserved / 2; i++) {
+        colorRefCount [i] = 1;
+        colorRefCount [numEntries - 1 - i] = 1;
+    }
+    internal_dispose_GC (hDC, null);
+    hPalette = OS.CreatePalette (cast(LOGPALETTE*)logPalette.ptr);
+}
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public abstract HDC internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public abstract void internal_dispose_GC (HDC hDC, GCData data);
+
+/**
+ * Returns <code>true</code> if the device has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the device.
+ * When a device has been disposed, it is an error to
+ * invoke any other method using the device.
+ *
+ * @return <code>true</code> when the device is disposed and <code>false</code> otherwise
+ */
+public bool isDisposed () {
+    synchronized (Device.classinfo) {
+        return disposed;
+    }
+}
+
+/**
+ * Loads the font specified by a file.  The font will be
+ * present in the list of fonts available to the application.
+ *
+ * @param path the font file path
+ * @return whether the font was successfully loaded
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if path is null</li>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Font
+ *
+ * @since 3.3
+ */
+public bool loadFont (String path) {
+    checkDevice();
+    if (path is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (OS.IsWinNT && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        //TCHAR lpszFilename = new TCHAR (0, path, true);
+        return OS.AddFontResourceEx ( .StrToTCHARz(path), OS.FR_PRIVATE, null) !is 0;
+    }
+    return false;
+}
+
+void new_Object (Object object) {
+    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);
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the device handle.
+ * <p>
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system.  For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in <code>release</code>.  Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by <code>destroy</code>.
+ * </p>
+ * This method is called before <code>destroy</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #destroy
+ */
+protected void release () {
+    if (gdipToken) {
+        Gdip.GdiplusShutdown ( gdipToken );
+    }
+    gdipToken = 0; // TODO: assignment of 0 might not be valid for token
+    scripts = null;
+    if (hPalette !is null) OS.DeleteObject (hPalette);
+    hPalette = null;
+    colorRefCount = null;
+    logFonts = null;
+    nFonts = 0;
+}
+
+/**
+ * If the underlying window system supports printing warning messages
+ * to the console, setting warnings to <code>false</code> prevents these
+ * messages from being printed. If the argument is <code>true</code> then
+ * message printing is not blocked.
+ *
+ * @param warnings <code>true</code>if warnings should be printed, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setWarnings (bool warnings) {
+    checkDevice ();
+}
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/DeviceData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.DeviceData;
+
+import tango.core.Exception;
+
+public class DeviceData {
+    /*
+    * Debug fields - may not be honoured
+    * on some SWT platforms.
+    */
+    public bool debug_;
+    public bool tracking;
+    public Exception [] errors;
+    public Object [] objects;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Drawable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Drawable;
+
+
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.internal.win32.WINTYPES;
+
+/**
+ * Implementers of <code>Drawable</code> can have a graphics context (GC)
+ * created for them, and then they can be drawn on by sending messages to
+ * their associated GC. SWT images, and device objects such as the Display
+ * device and the Printer device, are drawables.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @see Device
+ * @see Image
+ * @see GC
+ */
+public interface Drawable {
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Drawable</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+
+public HDC internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Drawable</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param handle the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC ( HDC handle, GCData data);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Font.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Font;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Device;
+
+import tango.text.convert.Format;
+import java.lang.all;
+//import tango.stdc.stringz;
+
+/**
+ * Instances of this class manage operating system resources that
+ * define how text looks when it is displayed. Fonts may be constructed
+ * by providing a device and either name, size and style information
+ * or a <code>FontData</code> object which encapsulates this data.
+ * <p>
+ * Application code must explicitly invoke the <code>Font.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see FontData
+ * @see <a href="http://www.eclipse.org/swt/snippets/#font">Font snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Font : Resource {
+
+    alias Resource.init_ init_;
+    /**
+     * the handle to the OS font resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HFONT handle;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this(Device device) {
+    super(device);
+}
+
+/**
+ * Constructs a new font given a device and font data
+ * which describes the desired font's appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fd the FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the fd argument is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ */
+public this(Device device, FontData fd) {
+    super(device);
+    init_(fd);
+    init_();
+}
+
+/**
+ * Constructs a new font given a device and an array
+ * of font data which describes the desired font's
+ * appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fds the array of FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the fds argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the length of fds is zero</li>
+ *    <li>ERROR_NULL_ARGUMENT - if any fd in the array is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public this(Device device, FontData[] fds) {
+    super(device);
+    if (fds is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (fds.length is 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<fds.length; i++) {
+        if (fds[i] is null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    init_(fds[0]);
+    init_();
+}
+
+/**
+ * Constructs a new font given a device, a font name,
+ * the height of the desired font in points, and a font
+ * style.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the name argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if a font could not be created from the given arguments</li>
+ * </ul>
+ */
+public this(Device device, String name, int height, int style) {
+    super(device);
+    if (name is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(new FontData (name, height, style));
+    init_();
+}
+
+/*public*/ this(Device device, String name, float height, int style) {
+    super(device);
+    if (name is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(new FontData (name, height, style));
+    init_();
+}
+void destroy() {
+    OS.DeleteObject(handle);
+    handle = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public int opEquals(Object object) {
+    if (object is this) return true;
+    if ( auto font = cast(Font)object ){
+        return device is font.device && handle is font.handle;
+    }
+    return false;
+}
+
+/**
+ * Returns an array of <code>FontData</code>s representing the receiver.
+ * On Windows, only one FontData will be returned per font. On X however,
+ * a <code>Font</code> object <em>may</em> be composed of multiple X
+ * fonts. To support this case, we return an array of font data objects.
+ *
+ * @return an array of font data objects describing the receiver
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData[] getFontData() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    LOGFONT logFont;
+    OS.GetObject(handle, LOGFONT.sizeof, &logFont);
+    return [ cast(FontData) FontData.win32_new(&logFont, device.computePoints(&logFont, handle))];
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+    return cast(hash_t)handle;
+}
+
+void init_ (FontData fd) {
+    if (fd is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    LOGFONT* logFont = &fd.data;
+    int lfHeight = logFont.lfHeight;
+    logFont.lfHeight = device.computePixels(fd.height);
+    handle = OS.CreateFontIndirect(logFont);
+    logFont.lfHeight = lfHeight;
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Returns <code>true</code> if the font has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the font.
+ * When a font has been disposed, it is an error to
+ * invoke any other method using the font.
+ *
+ * @return <code>true</code> when the font is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "Font {*DISPOSED*}";
+    return Format( "Font {{{}}", handle );
+//
+//    LOGFONT logFont;
+//    OS.GetObject(handle, LOGFONT.sizeof, &logFont);
+//    char[] name = .TCHARzToStr( logFont.lfFaceName.ptr, -1 );
+//
+//    return Format( "Font {{{}, {}}", handle, name );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Font</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param handle the handle for the font
+ * @return a new font object containing the specified device and handle
+ */
+public static Font win32_new(Device device, HFONT handle) {
+    Font font = new Font(device);
+    font.disposeChecking = false;
+    font.handle = handle;
+    return font;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,651 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.FontData;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+static import tango.text.Text;
+import tango.util.Convert;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * Instances of this class describe operating system fonts.
+ * <p>
+ * For platform-independent behaviour, use the get and set methods
+ * corresponding to the following properties:
+ * <dl>
+ * <dt>height</dt><dd>the height of the font in points</dd>
+ * <dt>name</dt><dd>the face name of the font, which may include the foundry</dd>
+ * <dt>style</dt><dd>A bitwise combination of NORMAL, ITALIC and BOLD</dd>
+ * </dl>
+ * If extra, platform-dependent functionality is required:
+ * <ul>
+ * <li>On <em>Windows</em>, the data member of the <code>FontData</code>
+ * corresponds to a Windows <code>LOGFONT</code> structure whose fields
+ * may be retrieved and modified.</li>
+ * <li>On <em>X</em>, the fields of the <code>FontData</code> correspond
+ * to the entries in the font's XLFD name and may be retrieved and modified.
+ * </ul>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ *
+ * @see Font
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class FontData {
+
+    /**
+     * A Win32 LOGFONT struct
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public LOGFONT data;
+
+    /**
+     * The height of the font data in points
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public float height;
+
+    /**
+     * The locales of the font
+     */
+    String lang, country, variant;
+
+    private static FontData s_this;
+
+/**
+ * Constructs a new uninitialized font data.
+ */
+public this() {
+    // We set the charset field so that
+    // wildcard searching will work properly
+    // out of the box
+    data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+    height = 12;
+}
+
+/**
+ * Constructs a new font data given the Windows <code>LOGFONT</code>
+ * that it should represent.
+ *
+ * @param data the <code>LOGFONT</code> for the result
+ */
+this(LOGFONT* data, float height) {
+    this.data = *data;
+    this.height = height;
+}
+
+/**
+ * Constructs a new FontData given a string representation
+ * in the form generated by the <code>FontData.toString</code>
+ * method.
+ * <p>
+ * Note that the representation varies between platforms,
+ * and a FontData can only be created from a string that was
+ * generated on the same platform.
+ * </p>
+ *
+ * @param string the string representation of a <code>FontData</code> (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument does not represent a valid description</li>
+ * </ul>
+ *
+ * @see #toString
+ */
+public this(String string) {
+    if (string is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    int start = 0;
+    int end = string.indexOf('|');
+    if (end is -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    String version1 = string.substring(start, end);
+    try {
+        if (Integer.parseInt(version1) !is 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    } catch (NumberFormatException e) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    start = end + 1;
+    end = string.indexOf('|', start);
+    if (end is -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    String name = string.substring(start, end);
+
+    start = end + 1;
+    end = string.indexOf('|', start);
+    if (end is -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    float height = 0;
+    try {
+        height = Float.parseFloat(string.substring(start, end));
+    } catch (NumberFormatException e) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    start = end + 1;
+    end = string.indexOf('|', start);
+    if (end is -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int style = 0;
+    try {
+        style = Integer.parseInt(string.substring(start, end));
+    } catch (NumberFormatException e) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    start = end + 1;
+    end = string.indexOf('|', start);
+    //data = OS.IsUnicode ? cast(LOGFONT)new LOGFONTW() : new LOGFONTA();
+    data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+    setName(name);
+    setHeight(height);
+    setStyle(style);
+    if (end is -1) return;
+    String platform = string.substring(start, end);
+
+    start = end + 1;
+    end = string.indexOf('|', start);
+    if (end is -1) return;
+    String version2 = string.substring(start, end);
+
+    if (platform ==/*eq*/ "WINDOWS" && version2 ==/*eq*/ "1") {  //$NON-NLS-1$//$NON-NLS-2$
+        LOGFONT newData;// = OS.IsUnicode ? cast(LOGFONT)new LOGFONTW() : new LOGFONTA();
+        try {
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfHeight = Integer.parseInt(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfWidth = Integer.parseInt(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfEscapement = Integer.parseInt(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfOrientation = Integer.parseInt(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfWeight = Integer.parseInt(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfItalic = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfUnderline = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfStrikeOut = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfCharSet = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfOutPrecision = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfClipPrecision = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfQuality = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+            end = string.indexOf('|', start);
+            if (end is -1) return;
+            newData.lfPitchAndFamily = Byte.parseByte(string.substring(start, end));
+            start = end + 1;
+        } catch (NumberFormatException e) {
+            setName(name);
+            setHeight(height);
+            setStyle(style);
+            return;
+        }
+        String buffer = string.substring(start);
+        auto wname = StrToTCHARs(buffer);
+        int len = Math.min(OS.LF_FACESIZE - 1, wname.length);
+        newData.lfFaceName[ 0 .. len ] = wname[ 0 .. len ];
+        newData.lfFaceName[ len .. $ ] = 0;
+        data = newData;
+    }
+}
+
+/**
+ * Constructs a new font data given a font name,
+ * the height of the desired font in points,
+ * and a font style.
+ *
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ */
+public this(String name, int height, int style) {
+    if (name is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    setName(name);
+    setHeight(height);
+    setStyle(style);
+    // We set the charset field so that
+    // wildcard searching will work properly
+    // out of the box
+    data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+}
+
+/*public*/ this(String name, float height, int style) {
+    if (name is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    setName(name);
+    setHeight(height);
+    setStyle(style);
+    // We set the charset field so that
+    // wildcard searching will work properly
+    // out of the box
+    data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+    if (object is this) return true;
+    if( auto fd = cast(FontData)object ){
+        LOGFONT* lf = &fd.data;
+        return data.lfCharSet is lf.lfCharSet &&
+            /*
+            * This code is intentionally commented.  When creating
+            * a FontData, lfHeight is not necessarily set.  Instead
+            * we check the height field which is always set.
+            */
+    //      data.lfHeight is lf.lfHeight &&
+            height is fd.height &&
+            data.lfWidth is lf.lfWidth &&
+            data.lfEscapement is lf.lfEscapement &&
+            data.lfOrientation is lf.lfOrientation &&
+            data.lfWeight is lf.lfWeight &&
+            data.lfItalic is lf.lfItalic &&
+            data.lfUnderline is lf.lfUnderline &&
+            data.lfStrikeOut is lf.lfStrikeOut &&
+            data.lfCharSet is lf.lfCharSet &&
+            data.lfOutPrecision is lf.lfOutPrecision &&
+            data.lfClipPrecision is lf.lfClipPrecision &&
+            data.lfQuality is lf.lfQuality &&
+            data.lfPitchAndFamily is lf.lfPitchAndFamily &&
+            getName() ==/*eq*/ fd.getName();
+    }
+    return false;
+}
+
+extern (Windows) static int EnumLocalesProc(TCHAR* lpLocaleString) {
+
+    /* Get the locale ID */
+    int length_ = 8;
+    String str = .TCHARzToStr( cast(TCHAR*)lpLocaleString, length_);
+    int lcid = Integer.parseInt(str, 16);
+
+    TCHAR[] buffer = new TCHAR[length_];
+
+    /* Check the language */
+    int size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO639LANGNAME, buffer.ptr, length_);
+    if (size <= 0 || s_this.lang !=/*eq*/ .TCHARzToStr( buffer.ptr ).substring(0, size - 1)) return 1;
+
+    /* Check the country */
+    if (s_this.country !is null) {
+        size = OS.GetLocaleInfo(lcid, OS.LOCALE_SISO3166CTRYNAME, buffer.ptr, length_);
+        if (size <= 0 || s_this.country !=/*eq*/ .TCHARzToStr( buffer.ptr ).substring(0, size - 1)) return 1;
+    }
+
+    /* Get the charset */
+    size = OS.GetLocaleInfo(lcid, OS.LOCALE_IDEFAULTANSICODEPAGE, buffer.ptr, length_);
+    if (size <= 0) return 1;
+    int cp = Integer.parseInt(.TCHARzToStr(buffer.ptr).substring(0, size - 1));
+    CHARSETINFO lpCs;
+    OS.TranslateCharsetInfo(cast(DWORD*)cp, &lpCs, OS.TCI_SRCCODEPAGE);
+    s_this.data.lfCharSet = cast(BYTE)lpCs.ciCharset;
+
+    return 0;
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight(int)
+ */
+public int getHeight() {
+    return cast(int)(0.5f + height);
+}
+
+/*public*/ float getHeightF() {
+    return height;
+}
+
+/**
+ * Returns the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @return the <code>String</code> representing a Locale object
+ * @since 3.0
+ */
+public String getLocale () {
+    StringBuffer buffer = new StringBuffer ();
+    char sep = '_';
+    if (lang !is null) {
+        buffer.append (lang);
+        buffer.append (sep);
+    }
+    if (country !is null) {
+        buffer.append (country);
+        buffer.append (sep);
+    }
+    if (variant !is null) {
+        buffer.append (variant);
+    }
+
+    String result = buffer.toString ();
+    int length_ = result.length;
+    if (length_ > 0) {
+        if (result.charAt (length_ - 1) is sep) {
+            result = result.substring (0, length_ - 1);
+        }
+    }
+    return result;
+}
+
+/**
+ * Returns the name of the receiver.
+ * On platforms that support font foundries, the return value will
+ * be the foundry followed by a dash ("-") followed by the face name.
+ *
+ * @return the name of this <code>FontData</code>
+ *
+ * @see #setName
+ */
+public String getName() {
+    return .TCHARzToStr( data.lfFaceName.ptr, -1 );
+}
+
+/**
+ * Returns the style of the receiver which is a bitwise OR of
+ * one or more of the <code>SWT</code> constants NORMAL, BOLD
+ * and ITALIC.
+ *
+ * @return the style of this <code>FontData</code>
+ *
+ * @see #setStyle
+ */
+public int getStyle() {
+    int style = SWT.NORMAL;
+    if (data.lfWeight is 700) style |= SWT.BOLD;
+    if (data.lfItalic !is 0) style |= SWT.ITALIC;
+    return style;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+    String name = getName();
+    return data.lfCharSet ^ getHeight() ^ data.lfWidth ^ data.lfEscapement ^
+        data.lfOrientation ^ data.lfWeight ^ data.lfItalic ^data.lfUnderline ^
+        data.lfStrikeOut ^ data.lfCharSet ^ data.lfOutPrecision ^
+        data.lfClipPrecision ^ data.lfQuality ^ data.lfPitchAndFamily ^
+        typeid(String).getHash(&name);
+}
+
+/**
+ * Sets the height of the receiver. The parameter is
+ * specified in terms of points, where a point is one
+ * seventy-second of an inch.
+ *
+ * @param height the height of the <code>FontData</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ *
+ * @see #getHeight
+ */
+public void setHeight(int height) {
+    if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    this.height = height;
+}
+
+/*public*/ void setHeight(float height) {
+    if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    this.height = height;
+}
+
+/**
+ * Sets the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @param locale the <code>String</code> representing a Locale object
+ * @see java.util.Locale#toString
+ */
+public void setLocale(String locale) {
+    lang = country = variant = null;
+    if (locale !is null) {
+        char sep = '_';
+        int length_ = locale.length;
+        int firstSep, secondSep;
+
+        firstSep = locale.indexOf(sep);
+        if (firstSep is -1) {
+            firstSep = secondSep = length_;
+        } else {
+            secondSep = locale.indexOf(sep, firstSep + 1);
+            if (secondSep is -1) secondSep = length_;
+        }
+        if (firstSep > 0) lang = locale.substring(0, firstSep);
+        if (secondSep > firstSep + 1) country = locale.substring(firstSep + 1, secondSep);
+        if (length_ > secondSep + 1) variant = locale.substring(secondSep + 1);
+    }
+    if (lang is null) {
+        data.lfCharSet = cast(byte)OS.DEFAULT_CHARSET;
+    } else {
+        synchronized(this.classinfo){
+            s_this = this;
+            OS.EnumSystemLocales(&EnumLocalesProc, OS.LCID_SUPPORTED);
+            s_this = null;
+        }
+    }
+}
+
+/**
+ * Sets the name of the receiver.
+ * <p>
+ * Some platforms support font foundries. On these platforms, the name
+ * of the font specified in setName() may have one of the following forms:
+ * <ol>
+ * <li>a face name (for example, "courier")</li>
+ * <li>a foundry followed by a dash ("-") followed by a face name (for example, "adobe-courier")</li>
+ * </ol>
+ * In either case, the name returned from getName() will include the
+ * foundry.
+ * </p>
+ * <p>
+ * On platforms that do not support font foundries, only the face name
+ * (for example, "courier") is used in <code>setName()</code> and
+ * <code>getName()</code>.
+ * </p>
+ *
+ * @param name the name of the font data (must not be null)
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ * </ul>
+ *
+ * @see #getName
+ */
+public void setName(String name) {
+    if (name is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+
+    /* The field lfFaceName must be NULL terminated */
+    auto wname = StrToTCHARs(name);
+    int len = Math.min(OS.LF_FACESIZE - 1, wname.length);
+    data.lfFaceName[0 .. len] = wname[ 0 .. len ];
+    data.lfFaceName[len .. $] = 0;
+}
+
+/**
+ * Sets the style of the receiver to the argument which must
+ * be a bitwise OR of one or more of the <code>SWT</code>
+ * constants NORMAL, BOLD and ITALIC.  All other style bits are
+ * ignored.
+ *
+ * @param style the new style for this <code>FontData</code>
+ *
+ * @see #getStyle
+ */
+public void setStyle(int style) {
+    if ((style & SWT.BOLD) is SWT.BOLD) {
+        data.lfWeight = 700;
+    } else {
+        data.lfWeight = 0;
+    }
+    if ((style & SWT.ITALIC) is SWT.ITALIC) {
+        data.lfItalic = 1;
+    } else {
+        data.lfItalic = 0;
+    }
+}
+
+/**
+ * Returns a string representation of the receiver which is suitable
+ * for constructing an equivalent instance using the
+ * <code>FontData(String)</code> constructor.
+ *
+ * @return a string representation of the FontData
+ *
+ * @see FontData
+ */
+override public String toString() {
+    StringBuffer buffer = new StringBuffer();
+    buffer.append("1|"); //$NON-NLS-1$
+    buffer.append(getName());
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(getHeightF()));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(getStyle()));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append("WINDOWS|1|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfHeight));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfWidth));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfEscapement));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfOrientation));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfWeight));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfItalic));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfUnderline));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfStrikeOut));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfCharSet));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfOutPrecision));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfClipPrecision));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfQuality));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(to!(String)(data.lfPitchAndFamily));
+    buffer.append("|"); //$NON-NLS-1$
+    buffer.append(getName());
+    return buffer.toString();
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font data.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>FontData</code>. It is marked public only so that
+ * it can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the <code>LOGFONT</code> for the font data
+ * @param height the height of the font data
+ * @return a new font data object containing the specified <code>LOGFONT</code> and height
+ */
+public static FontData win32_new(LOGFONT* data, float height) {
+    return new FontData(data, height);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/FontMetrics.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.FontMetrics;
+
+
+import org.eclipse.swt.internal.win32.WINTYPES;
+
+/**
+ * Instances of this class provide measurement information
+ * about fonts including ascent, descent, height, leading
+ * space between rows, and average character width.
+ * <code>FontMetrics</code> are obtained from <code>GC</code>s
+ * using the <code>getFontMetrics()</code> method.
+ *
+ * @see GC#getFontMetrics
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class FontMetrics {
+
+    /**
+     * On Windows, handle is a Win32 TEXTMETRIC struct
+     * On Photon, handle is a Photon FontQueryInfo struct
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public TEXTMETRIC handle;
+
+/**
+ * Prevents instances from being created outside the package.
+ */
+this() {
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+    if (object is this) return true;
+    if( auto metricObj = cast(FontMetrics)object ){
+        auto metric = metricObj.handle;
+        return handle.tmHeight is metric.tmHeight &&
+            handle.tmAscent is metric.tmAscent &&
+            handle.tmDescent is metric.tmDescent &&
+            handle.tmInternalLeading is metric.tmInternalLeading &&
+            handle.tmExternalLeading is metric.tmExternalLeading &&
+            handle.tmAveCharWidth is metric.tmAveCharWidth &&
+            handle.tmMaxCharWidth is metric.tmMaxCharWidth &&
+            handle.tmWeight is metric.tmWeight &&
+            handle.tmOverhang is metric.tmOverhang &&
+            handle.tmDigitizedAspectX is metric.tmDigitizedAspectX &&
+            handle.tmDigitizedAspectY is metric.tmDigitizedAspectY &&
+    //      handle.tmFirstChar is metric.tmFirstChar &&
+    //      handle.tmLastChar is metric.tmLastChar &&
+    //      handle.tmDefaultChar is metric.tmDefaultChar &&
+    //      handle.tmBreakChar is metric.tmBreakChar &&
+            handle.tmItalic is metric.tmItalic &&
+            handle.tmUnderlined is metric.tmUnderlined &&
+            handle.tmStruckOut is metric.tmStruckOut &&
+            handle.tmPitchAndFamily is metric.tmPitchAndFamily &&
+            handle.tmCharSet is metric.tmCharSet;
+    }
+    return false;
+}
+
+/**
+ * Returns the ascent of the font described by the receiver. A
+ * font's <em>ascent</em> is the distance from the baseline to the
+ * top of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the ascent of the font
+ */
+public int getAscent() {
+    return handle.tmAscent - handle.tmInternalLeading;
+}
+
+/**
+ * Returns the average character width, measured in pixels,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ */
+public int getAverageCharWidth() {
+    return handle.tmAveCharWidth;
+}
+
+/**
+ * Returns the descent of the font described by the receiver. A
+ * font's <em>descent</em> is the distance from the baseline to the
+ * bottom of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the descent of the font
+ */
+public int getDescent() {
+    return handle.tmDescent;
+}
+
+/**
+ * Returns the height of the font described by the receiver,
+ * measured in pixels. A font's <em>height</em> is the sum of
+ * its ascent, descent and leading area.
+ *
+ * @return the height of the font
+ *
+ * @see #getAscent
+ * @see #getDescent
+ * @see #getLeading
+ */
+public int getHeight() {
+    return handle.tmHeight;
+}
+
+/**
+ * Returns the leading area of the font described by the
+ * receiver. A font's <em>leading area</em> is the space
+ * above its ascent which may include accents or other marks.
+ *
+ * @return the leading space of the font
+ */
+public int getLeading() {
+    return handle.tmInternalLeading;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash() {
+    return handle.tmHeight ^ handle.tmAscent ^ handle.tmDescent ^
+        handle.tmInternalLeading ^ handle.tmExternalLeading ^
+        handle.tmAveCharWidth ^ handle.tmMaxCharWidth ^ handle.tmWeight ^
+        handle.tmOverhang ^ handle.tmDigitizedAspectX ^ handle.tmDigitizedAspectY ^
+//      handle.tmFirstChar ^ handle.tmLastChar ^ handle.tmDefaultChar ^ handle.tmBreakChar ^
+        handle.tmItalic ^ handle.tmUnderlined ^ handle.tmStruckOut ^
+        handle.tmPitchAndFamily ^ handle.tmCharSet;
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font metrics.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>FontMetrics</code>. It is marked public only so that
+ * it can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param handle the <code>TEXTMETRIC</code> containing information about a font
+ * @return a new font metrics object containing the specified <code>TEXTMETRIC</code>
+ */
+public static FontMetrics win32_new(TEXTMETRIC* handle) {
+    FontMetrics fontMetrics = new FontMetrics();
+    fontMetrics.handle = *handle;
+    return fontMetrics;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GC.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,4932 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.GC;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Path;
+import org.eclipse.swt.graphics.Pattern;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Transform;
+import org.eclipse.swt.graphics.LineAttributes;
+
+import java.lang.all;
+import tango.text.convert.Format;
+
+/**
+ * Class <code>GC</code> is where all of the drawing capabilities that are
+ * supported by SWT are located. Instances are used to draw on either an
+ * <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * </dl>
+ *
+ * <p>
+ * The SWT drawing coordinate system is the two-dimensional space with the origin
+ * (0,0) at the top left corner of the drawing area and with (x,y) values increasing
+ * to the right and downward respectively.
+ * </p>
+ *
+ * <p>
+ * Application code must explicitly invoke the <code>GC.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required. This is <em>particularly</em>
+ * important on Windows95 and Windows98 where the operating system has a limited
+ * number of device contexts available.
+ * </p>
+ *
+ * <p>
+ * Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified.
+ * </p>
+ *
+ * @see org.eclipse.swt.events.PaintEvent
+ * @see <a href="http://www.eclipse.org/swt/snippets/#gc">GC snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, PaintExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class GC : Resource {
+
+    alias Resource.init_ init_;
+
+    /**
+     * the handle to the OS device context
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HDC handle;
+
+    Drawable drawable;
+    GCData data;
+
+    static const int FOREGROUND = 1 << 0;
+    static const int BACKGROUND = 1 << 1;
+    static const int FONT = 1 << 2;
+    static const int LINE_STYLE = 1 << 3;
+    static const int LINE_WIDTH = 1 << 4;
+    static const int LINE_CAP = 1 << 5;
+    static const int LINE_JOIN = 1 << 6;
+    static const int LINE_MITERLIMIT = 1 << 7;
+    static const int FOREGROUND_TEXT = 1 << 8;
+    static const int BACKGROUND_TEXT = 1 << 9;
+    static const int BRUSH = 1 << 10;
+    static const int PEN = 1 << 11;
+    static const int NULL_BRUSH = 1 << 12;
+    static const int NULL_PEN = 1 << 13;
+    static const int DRAW_OFFSET = 1 << 14;
+
+    static const int DRAW = FOREGROUND | LINE_STYLE | LINE_WIDTH | LINE_CAP | LINE_JOIN | LINE_MITERLIMIT | PEN | NULL_BRUSH | DRAW_OFFSET;
+    static const int FILL = BACKGROUND | BRUSH | NULL_PEN;
+
+    static const float[] LINE_DOT_ZERO = [3, 3];
+    static const float[] LINE_DASH_ZERO = [18, 6];
+    static const float[] LINE_DASHDOT_ZERO = [9, 6, 3, 6];
+    static const float[] LINE_DASHDOTDOT_ZERO = [9, 3, 3, 3, 3, 3];
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this() {
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground color, background color and font in the GC
+ * to match those in the drawable.
+ * <p>
+ * You must dispose the graphics context when it is no longer required.
+ * </p>
+ * @param drawable the drawable to draw on
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
+ *    <li>ERROR_INVALID_ARGUMENT
+ *          - if the drawable is an image that is not a bitmap or an icon
+ *          - if the drawable is an image or printer that is already selected
+ *            into another graphics context</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
+ * </ul>
+ */
+public this(Drawable drawable) {
+    this(drawable, SWT.NONE);
+}
+
+/**
+ * Constructs a new instance of this class which has been
+ * configured to draw on the specified drawable. Sets the
+ * foreground color, background color and font in the GC
+ * to match those in the drawable.
+ * <p>
+ * You must dispose the graphics context when it is no longer required.
+ * </p>
+ *
+ * @param drawable the drawable to draw on
+ * @param style the style of GC to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
+ *    <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
+ *    <li>ERROR_INVALID_ARGUMENT
+ *          - if the drawable is an image that is not a bitmap or an icon
+ *          - if the drawable is an image or printer that is already selected
+ *            into another graphics context</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for GC creation</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public this(Drawable drawable, int style) {
+    if (drawable is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    GCData data = new GCData ();
+    data.style = checkStyle(style);
+    auto hDC = drawable.internal_new_GC(data);
+    Device device = data.device;
+    if (device is null) device = Device.getDevice();
+    if (device is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    this.device = data.device = device;
+    init_ (drawable, data, hDC);
+    init_();
+}
+
+static int checkStyle(int style) {
+    if ((style & SWT.LEFT_TO_RIGHT) !is 0) style &= ~SWT.RIGHT_TO_LEFT;
+    return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+void checkGC(int mask) {
+    int state = data.state;
+    if ((state & mask) is mask) return;
+    state = (state ^ mask) & mask;
+    data.state |= mask;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        auto pen = data.gdipPen;
+        float width = data.lineWidth;
+        if ((state & FOREGROUND) !is 0 || (pen is null && (state & (LINE_WIDTH | LINE_STYLE | LINE_MITERLIMIT | LINE_JOIN | LINE_CAP)) !is 0)) {
+            if (data.gdipFgBrush !is null) Gdip.SolidBrush_delete(data.gdipFgBrush);
+            data.gdipFgBrush = null;
+            Gdip.Brush brush;
+            Pattern pattern = data.foregroundPattern;
+            if (pattern !is null) {
+                brush = pattern.handle;
+                if ((data.style & SWT.MIRRORED) !is 0) {
+                    switch (Gdip.Brush_GetType(brush)) {
+                        case Gdip.BrushTypeTextureFill:
+                            brush = Gdip.Brush_Clone(brush);
+                            if (brush is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                            Gdip.TextureBrush_ScaleTransform( cast(Gdip.TextureBrush) brush, -1, 1, Gdip.MatrixOrderPrepend);
+                            data.gdipFgBrush = cast(Gdip.SolidBrush)brush;
+                        default:
+                    }
+                }
+            } else {
+                auto foreground = data.foreground;
+                int rgb = ((foreground >> 16) & 0xFF) | (foreground & 0xFF00) | ((foreground & 0xFF) << 16);
+                auto color = Gdip.Color_new(data.alpha << 24 | rgb);
+                if (color is 0) SWT.error(SWT.ERROR_NO_HANDLES);
+                brush = cast(Gdip.Brush) Gdip.SolidBrush_new(color);
+                if (brush is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                Gdip.Color_delete(color);
+                data.gdipFgBrush = cast(Gdip.SolidBrush)brush;
+            }
+            if (pen !is null) {
+                Gdip.Pen_SetBrush(pen, brush);
+            } else {
+                pen = data.gdipPen = Gdip.Pen_new(brush, width);
+            }
+        }
+        if ((state & LINE_WIDTH) !is 0) {
+            Gdip.Pen_SetWidth(pen, width);
+            switch (data.lineStyle) {
+                case SWT.LINE_CUSTOM:
+                    state |= LINE_STYLE;
+                default:
+            }
+        }
+        if ((state & LINE_STYLE) !is 0) {
+            float[] dashes = null;
+            float dashOffset = 0;
+            int dashStyle = Gdip.DashStyleSolid;
+            switch (data.lineStyle) {
+                case SWT.LINE_SOLID: break;
+                case SWT.LINE_DOT: dashStyle = Gdip.DashStyleDot; if (width is 0) dashes = LINE_DOT_ZERO; break;
+                case SWT.LINE_DASH: dashStyle = Gdip.DashStyleDash; if (width is 0) dashes = LINE_DASH_ZERO; break;
+                case SWT.LINE_DASHDOT: dashStyle = Gdip.DashStyleDashDot; if (width is 0) dashes = LINE_DASHDOT_ZERO; break;
+                case SWT.LINE_DASHDOTDOT: dashStyle = Gdip.DashStyleDashDotDot; if (width is 0) dashes = LINE_DASHDOTDOT_ZERO; break;
+                case SWT.LINE_CUSTOM: {
+                    if (data.lineDashes !is null) {
+                        dashOffset = data.lineDashesOffset / Math.max (1, width);
+                        dashes = new float[data.lineDashes.length * 2];
+                        for (int i = 0; i < data.lineDashes.length; i++) {
+                            float dash = data.lineDashes[i] / Math.max (1, width);
+                            dashes[i] = dash;
+                            dashes[i + data.lineDashes.length] = dash;
+                        }
+                    }
+                }
+                default:
+            }
+            if (dashes !is null) {
+                Gdip.Pen_SetDashPattern(pen, dashes.ptr, dashes.length);
+                Gdip.Pen_SetDashStyle(pen, Gdip.DashStyleCustom);
+                Gdip.Pen_SetDashOffset(pen, dashOffset);
+            } else {
+                Gdip.Pen_SetDashStyle(pen, dashStyle);
+            }
+        }
+        if ((state & LINE_MITERLIMIT) !is 0) {
+            Gdip.Pen_SetMiterLimit(pen, data.lineMiterLimit);
+        }
+        if ((state & LINE_JOIN) !is 0) {
+            int joinStyle = 0;
+            switch (data.lineJoin) {
+                case SWT.JOIN_MITER: joinStyle = Gdip.LineJoinMiter; break;
+                case SWT.JOIN_BEVEL: joinStyle = Gdip.LineJoinBevel; break;
+                case SWT.JOIN_ROUND: joinStyle = Gdip.LineJoinRound; break;
+                default:
+            }
+            Gdip.Pen_SetLineJoin(pen, joinStyle);
+        }
+        if ((state & LINE_CAP) !is 0) {
+            int dashCap = Gdip.DashCapFlat, capStyle = 0;
+            switch (data.lineCap) {
+                case SWT.CAP_FLAT: capStyle = Gdip.LineCapFlat; break;
+                case SWT.CAP_ROUND: capStyle = Gdip.LineCapRound; dashCap = Gdip.DashCapRound; break;
+                case SWT.CAP_SQUARE: capStyle = Gdip.LineCapSquare; break;
+                default:
+            }
+            Gdip.Pen_SetLineCap(pen, capStyle, capStyle, dashCap);
+        }
+        if ((state & BACKGROUND) !is 0) {
+            if (data.gdipBgBrush !is null) Gdip.SolidBrush_delete(data.gdipBgBrush);
+            data.gdipBgBrush = null;
+            Pattern pattern = data.backgroundPattern;
+            if (pattern !is null) {
+                data.gdipBrush = pattern.handle;
+                if ((data.style & SWT.MIRRORED) !is 0) {
+                    switch (Gdip.Brush_GetType(data.gdipBrush)) {
+                        case Gdip.BrushTypeTextureFill:
+                            auto brush = Gdip.Brush_Clone(data.gdipBrush);
+                            if (brush is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                            Gdip.TextureBrush_ScaleTransform( cast(Gdip.TextureBrush)brush, -1, 1, Gdip.MatrixOrderPrepend);
+                            data.gdipBrush = brush;
+                            data.gdipBgBrush = cast(Gdip.SolidBrush) brush;
+                        default:
+                    }
+                }
+            } else {
+                auto background = data.background;
+                int rgb = ((background >> 16) & 0xFF) | (background & 0xFF00) | ((background & 0xFF) << 16);
+                auto color = Gdip.Color_new(data.alpha << 24 | rgb);
+                // if (color is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                auto brush = Gdip.SolidBrush_new(color);
+                if (brush is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                Gdip.Color_delete(color);
+                data.gdipBrush = cast(Gdip.Brush)brush;
+                data.gdipBgBrush = brush;
+            }
+        }
+        if ((state & FONT) !is 0) {
+            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 = gdipFont;
+        }
+        if ((state & DRAW_OFFSET) !is 0) {
+            data.gdipXOffset = data.gdipYOffset = 0;
+            auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+            float[2] point; point[0]=1.0; point[1]=1.0;
+            Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+            Gdip.Matrix_TransformPoints(matrix, cast(Gdip.PointF*)point.ptr, 1);
+            Gdip.Matrix_delete(matrix);
+            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 = point[1];
+            if (scaling < 0) scaling = -scaling;
+            penWidth = data.lineWidth * scaling;
+            if (penWidth is 0 || (cast(int)penWidth % 2) is 1) {
+                data.gdipYOffset = 0.5f / scaling;
+            }
+        }
+        return;
+    }
+    if ((state & (FOREGROUND | LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) !is 0) {
+        int color = data.foreground;
+        int width = cast(int)data.lineWidth;
+        uint[] dashes = null;
+        int lineStyle = OS.PS_SOLID;
+        switch (data.lineStyle) {
+            case SWT.LINE_SOLID: break;
+            case SWT.LINE_DASH: lineStyle = OS.PS_DASH; break;
+            case SWT.LINE_DOT: lineStyle = OS.PS_DOT; break;
+            case SWT.LINE_DASHDOT: lineStyle = OS.PS_DASHDOT; break;
+            case SWT.LINE_DASHDOTDOT: lineStyle = OS.PS_DASHDOTDOT; break;
+            case SWT.LINE_CUSTOM: {
+                if (data.lineDashes !is null) {
+                    lineStyle = OS.PS_USERSTYLE;
+                    dashes = new uint[data.lineDashes.length];
+                    for (int i = 0; i < dashes.length; i++) {
+                        dashes[i] = cast(int)data.lineDashes[i];
+                    }
+                }
+                break;
+            }
+            default:
+        }
+        if ((state & LINE_STYLE) !is 0) {
+            OS.SetBkMode(handle, data.lineStyle is SWT.LINE_SOLID ? OS.OPAQUE : OS.TRANSPARENT);
+        }
+        int joinStyle = 0;
+        switch (data.lineJoin) {
+            case SWT.JOIN_MITER: joinStyle = OS.PS_JOIN_MITER; break;
+            case SWT.JOIN_ROUND: joinStyle = OS.PS_JOIN_ROUND; break;
+            case SWT.JOIN_BEVEL: joinStyle = OS.PS_JOIN_BEVEL; break;
+            default:
+        }
+        int capStyle = 0;
+        switch (data.lineCap) {
+            case SWT.CAP_ROUND: capStyle = OS.PS_ENDCAP_ROUND; break;
+            case SWT.CAP_FLAT: capStyle = OS.PS_ENDCAP_FLAT; break;
+            case SWT.CAP_SQUARE: capStyle = OS.PS_ENDCAP_SQUARE;break;
+            default:
+        }
+        int style = lineStyle | joinStyle | capStyle;
+        /*
+        * Feature in Windows.  Windows does not honour line styles other then
+        * PS_SOLID for pens wider than 1 pixel created with CreatePen().  The fix
+        * is to use ExtCreatePen() instead.
+        */
+        HPEN newPen;
+        if (OS.IsWinCE || (width is 0 && lineStyle !is OS.PS_USERSTYLE) || style is 0) {
+            newPen = OS.CreatePen(style & OS.PS_STYLE_MASK, width, color);
+        } else {
+            LOGBRUSH logBrush;
+            logBrush.lbStyle = OS.BS_SOLID;
+            logBrush.lbColor = color;
+            /* Feature in Windows. PS_GEOMETRIC pens cannot have zero width. */
+            newPen = OS.ExtCreatePen (style | OS.PS_GEOMETRIC, Math.max(1, width), &logBrush, dashes !is null ? dashes.length : 0, dashes.ptr);
+        }
+        OS.SelectObject(handle, newPen);
+        data.state |= PEN;
+        data.state &= ~NULL_PEN;
+        if (data.hPen !is null) OS.DeleteObject(data.hPen);
+        data.hPen = data.hOldPen = newPen;
+    } else if ((state & PEN) !is 0) {
+        OS.SelectObject(handle, data.hOldPen);
+        data.state &= ~NULL_PEN;
+    } else if ((state & NULL_PEN) !is 0) {
+        data.hOldPen = OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+        data.state &= ~PEN;
+    }
+    if ((state & BACKGROUND) !is 0) {
+        auto newBrush = OS.CreateSolidBrush(data.background);
+        OS.SelectObject(handle, newBrush);
+        data.state |= BRUSH;
+        data.state &= ~NULL_BRUSH;
+        if (data.hBrush !is null) OS.DeleteObject(data.hBrush);
+        data.hOldBrush = data.hBrush = newBrush;
+    } else if ((state & BRUSH) !is 0) {
+        OS.SelectObject(handle, data.hOldBrush);
+        data.state &= ~NULL_BRUSH;
+    } else if ((state & NULL_BRUSH) !is 0) {
+        data.hOldBrush = OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+        data.state &= ~BRUSH;
+    }
+    if ((state & BACKGROUND_TEXT) !is 0) {
+        OS.SetBkColor(handle, data.background);
+    }
+    if ((state & FOREGROUND_TEXT) !is 0) {
+        OS.SetTextColor(handle, data.foreground);
+    }
+    if ((state & FONT) !is 0) {
+        Font font = data.font;
+        OS.SelectObject(handle, font.handle);
+    }
+}
+
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position into the image, which must be of type <code>SWT.BITMAP</code>.
+ *
+ * @param image the image to copy into
+ * @param x the x coordinate in the receiver of the area to be copied
+ * @param y the y coordinate in the receiver of the area to be copied
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void copyArea(Image image, int x, int y) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (image is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (image.type !is SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    /* Copy the bitmap area */
+    Rectangle rect = image.getBounds();
+    auto memHdc = OS.CreateCompatibleDC(handle);
+    auto hOldBitmap = OS.SelectObject(memHdc, image.handle);
+    OS.BitBlt(memHdc, 0, 0, rect.width, rect.height, handle, x, y, OS.SRCCOPY);
+    OS.SelectObject(memHdc, hOldBitmap);
+    OS.DeleteDC(memHdc);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) {
+    copyArea(srcX, srcY, width, height, destX, destY, true);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the source
+ * position onto the receiver at the destination position.
+ *
+ * @param srcX the x coordinate in the receiver of the area to be copied
+ * @param srcY the y coordinate in the receiver of the area to be copied
+ * @param width the width of the area to copy
+ * @param height the height of the area to copy
+ * @param destX the x coordinate in the receiver of the area to copy to
+ * @param destY the y coordinate in the receiver of the area to copy to
+ * @param paint if <code>true</code> paint events will be generated for old and obscured areas
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, bool paint) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+
+    /*
+    * Feature in WinCE.  The function WindowFromDC is not part of the
+    * WinCE SDK.  The fix is to remember the HWND.
+    */
+    auto hwnd = data.hwnd;
+    if (hwnd is null) {
+        OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+    } else {
+        RECT lprcClip;
+        auto hrgn = OS.CreateRectRgn(0, 0, 0, 0);
+        if (OS.GetClipRgn(handle, hrgn) is 1) {
+            OS.GetRgnBox(hrgn, &lprcClip);
+        }
+        OS.DeleteObject(hrgn);
+        RECT lprcScroll;
+        OS.SetRect(&lprcScroll, srcX, srcY, srcX + width, srcY + height);
+        int flags = paint ? OS.SW_INVALIDATE | OS.SW_ERASE : 0;
+        int res = OS.ScrollWindowEx(hwnd, destX - srcX, destY - srcY, &lprcScroll, &lprcClip, null, null, flags);
+
+        /*
+        * Feature in WinCE.  ScrollWindowEx does not accept combined
+        * vertical and horizontal scrolling.  The fix is to do a
+        * BitBlt and invalidate the appropriate source area.
+        */
+        static if (OS.IsWinCE) {
+            if (res is 0) {
+                OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+                if (paint) {
+                    int deltaX = destX - srcX, deltaY = destY - srcY;
+                    bool disjoint = (destX + width < srcX) || (srcX + width < destX) || (destY + height < srcY) || (srcY + height < destY);
+                    if (disjoint) {
+                        OS.InvalidateRect(hwnd, &lprcScroll, true);
+                    } else {
+                        if (deltaX !is 0) {
+                            int newX = destX - deltaX;
+                            if (deltaX < 0) newX = destX + width;
+                            OS.SetRect(&lprcScroll, newX, srcY, newX + Math.abs(deltaX), srcY + height);
+                            OS.InvalidateRect(hwnd, &lprcScroll, true);
+                        }
+                        if (deltaY !is 0) {
+                            int newY = destY - deltaY;
+                            if (deltaY < 0) newY = destY + height;
+                            OS.SetRect(&lprcScroll, srcX, newY, srcX + width, newY + Math.abs(deltaY));
+                            OS.InvalidateRect(hwnd, &lprcScroll, true);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static Gdip.Font createGdipFont(HDC hDC, HFONT hFont) {
+    auto font = Gdip.Font_new(hDC, hFont);
+    if (font is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    if (!Gdip.Font_IsAvailable(font)) {
+        Gdip.Font_delete(font);
+        LOGFONT logFont;
+        OS.GetObject(hFont, LOGFONT.sizeof, &logFont);
+        int size = Math.abs(logFont.lfHeight);
+        int style = Gdip.FontStyleRegular;
+        if (logFont.lfWeight is 700) style |= Gdip.FontStyleBold;
+        if (logFont.lfItalic !is 0) style |= Gdip.FontStyleItalic;
+        wchar[] chars;
+        static if (OS.IsUnicode) {
+            chars = logFont.lfFaceName;
+        } else {
+            chars = new wchar[OS.LF_FACESIZE];
+            String bytes = logFont.lfFaceName;
+            OS.MultiByteToWideChar (OS.CP_ACP, OS.MB_PRECOMPOSED, bytes.ptr, bytes.length, chars, chars.length);
+        }
+        int index = 0;
+        while (index < chars.length) {
+            if (chars [index] is 0) break;
+            index++;
+        }
+        String name = WCHARsToStr( chars[ 0 .. index ] );
+        if (Compatibility.equalsIgnoreCase(name, "Courier")) { //$NON-NLS-1$
+            name = "Courier New"; //$NON-NLS-1$
+        }
+        font = Gdip.Font_new( StrToWCHARz(name), size, style, Gdip.UnitPixel, null);
+    }
+    if (font is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    return font;
+}
+
+static void destroyGdipBrush(Gdip.Brush brush) {
+    int type = Gdip.Brush_GetType(brush);
+    switch (type) {
+        case Gdip.BrushTypeSolidColor:
+            Gdip.SolidBrush_delete( cast(Gdip.SolidBrush)brush);
+            break;
+        case Gdip.BrushTypeHatchFill:
+            Gdip.HatchBrush_delete(cast(Gdip.HatchBrush)brush);
+            break;
+        case Gdip.BrushTypeLinearGradient:
+            Gdip.LinearGradientBrush_delete(cast(Gdip.LinearGradientBrush)brush);
+            break;
+        case Gdip.BrushTypeTextureFill:
+            Gdip.TextureBrush_delete(cast(Gdip.TextureBrush)brush);
+            break;
+        default:
+    }
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the graphics context. Applications must dispose of all GCs
+ * which they allocate.
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
+ * </ul>
+ */
+void destroy() {
+    bool gdip = data.gdipGraphics !is null;
+    disposeGdip();
+    if (gdip && (data.style & SWT.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) {
+        OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+        OS.DeleteObject(data.hPen);
+        data.hPen = null;
+    }
+    if (data.hBrush !is null) {
+        OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+        OS.DeleteObject(data.hBrush);
+        data.hBrush = null;
+    }
+
+    /*
+    * Put back the original bitmap into the device context.
+    * This will ensure that we have not left a bitmap
+    * selected in it when we delete the HDC.
+    */
+    auto hNullBitmap = data.hNullBitmap;
+    if (hNullBitmap !is null) {
+        OS.SelectObject(handle, hNullBitmap);
+        data.hNullBitmap = null;
+    }
+    Image image = data.image;
+    if (image !is null) image.memGC = null;
+
+    /*
+    * Dispose the HDC.
+    */
+    if (drawable !is null) drawable.internal_dispose_GC(handle, data);
+    drawable = null;
+    handle = null;
+    data.image = null;
+    data.ps = null;
+    data = null;
+}
+
+void disposeGdip() {
+    if (data.gdipPen !is null) Gdip.Pen_delete(data.gdipPen);
+    if (data.gdipBgBrush !is null) destroyGdipBrush(cast(Gdip.Brush)data.gdipBgBrush);
+    if (data.gdipFgBrush !is null) destroyGdipBrush(cast(Gdip.Brush)data.gdipFgBrush);
+    if (data.gdipFont !is null) Gdip.Font_delete(data.gdipFont);
+    if (data.gdipGraphics !is null) Gdip.Graphics_delete(data.gdipGraphics);
+    data.gdipGraphics = null;
+    data.gdipBrush = null;
+    data.gdipBgBrush = null;
+    data.gdipFgBrush = null;
+    data.gdipFont = null;
+    data.gdipPen = null;
+}
+
+/**
+ * Draws the outline of a circular or elliptical arc
+ * within the specified rectangular area.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be drawn
+ * @param y the y coordinate of the upper-left corner of the arc to be drawn
+ * @param width the width of the arc to be drawn
+ * @param height the height of the arc to be drawn
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(DRAW);
+    if (width < 0) {
+        x = x + width;
+        width = -width;
+    }
+    if (height < 0) {
+        y = y + height;
+        height = -height;
+    }
+    if (width is 0 || height is 0 || arcAngle is 0) return;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        if (width is height) {
+            Gdip.Graphics_DrawArc(gdipGraphics, data.gdipPen, x, y, width, height, -startAngle, -arcAngle);
+        } else {
+            auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+            if (path is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            auto matrix = Gdip.Matrix_new(width, 0, 0, height, x, y);
+            if (matrix is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            Gdip.GraphicsPath_AddArc(path, 0, 0, 1, 1, -startAngle, -arcAngle);
+            Gdip.GraphicsPath_Transform(path, matrix);
+            Gdip.Graphics_DrawPath(gdipGraphics, data.gdipPen, path);
+            Gdip.Matrix_delete(matrix);
+            Gdip.GraphicsPath_delete(path);
+        }
+        Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) x--;
+    }
+    /*
+    * Feature in WinCE.  The function Arc is not present in the
+    * WinCE SDK.  The fix is to emulate arc drawing by using
+    * Polyline.
+    */
+    static if (OS.IsWinCE) {
+        /* compute arc with a simple linear interpolation */
+        if (arcAngle < 0) {
+            startAngle += arcAngle;
+            arcAngle = -arcAngle;
+        }
+        if (arcAngle > 360) arcAngle = 360;
+        int[] points = new int[(arcAngle + 1) * 2];
+        int cteX = 2 * x + width;
+        int cteY = 2 * y + height;
+        int index = 0;
+        for (int i = 0; i <= arcAngle; i++) {
+            points[index++] = (Compatibility.cos(startAngle + i, width) + cteX) >> 1;
+            points[index++] = (cteY - Compatibility.sin(startAngle + i, height)) >> 1;
+        }
+        OS.Polyline(handle, cast(POINT*)points.ptr, points.length / 2);
+    } else {
+        int x1, y1, x2, y2,tmp;
+        bool isNegative;
+        if (arcAngle >= 360 || arcAngle <= -360) {
+            x1 = x2 = x + width;
+            y1 = y2 = y + height / 2;
+        } else {
+            isNegative = arcAngle < 0;
+
+            arcAngle = arcAngle + startAngle;
+            if (isNegative) {
+                // swap angles
+                tmp = startAngle;
+                startAngle = arcAngle;
+                arcAngle = tmp;
+            }
+            x1 = Compatibility.cos(startAngle, width) + x + width/2;
+            y1 = -1 * Compatibility.sin(startAngle, height) + y + height/2;
+
+            x2 = Compatibility.cos(arcAngle, width) + x + width/2;
+            y2 = -1 * Compatibility.sin(arcAngle, height) + y + height/2;
+        }
+        OS.Arc(handle, x, y, x + width + 1, y + height + 1, x1, y1, x2, y2);
+    }
+}
+
+/**
+ * Draws a rectangle, based on the specified arguments, which has
+ * the appearance of the platform's <em>focus rectangle</em> if the
+ * platform supports such a notion, and otherwise draws a simple
+ * rectangle in the receiver's foreground color.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void drawFocus (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.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;
+    if (gdipGraphics !is null) {
+        HRGN clipRgn;
+        Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+        auto rgn = Gdip.Region_new();
+        if (rgn is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        Gdip.Graphics_GetClip(gdipGraphics, rgn);
+        if (!Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
+            clipRgn = Gdip.Region_GetHRGN(rgn, gdipGraphics);
+        }
+        Gdip.Region_delete(rgn);
+        Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+        float[6] lpXform;
+        bool gotElements = false;
+        auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+        if (matrix is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+        if (!Gdip.Matrix_IsIdentity(matrix)) {
+            gotElements = true;
+            Gdip.Matrix_GetElements(matrix, lpXform.ptr);
+        }
+        Gdip.Matrix_delete(matrix);
+        hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+        state = OS.SaveDC(hdc);
+        if (gotElements) {
+            OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+            OS.SetWorldTransform(hdc, cast(XFORM*)lpXform.ptr);
+        }
+        if (clipRgn !is null) {
+            OS.SelectClipRgn(hdc, clipRgn);
+            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);
+    }
+}
+
+/**
+ * Draws the given image in the receiver at the specified
+ * coordinates.
+ *
+ * @param image the image to draw
+ * @param x the x coordinate of where to draw
+ * @param y the y coordinate of where to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
+ * </ul>
+ */
+public void drawImage(Image image, int x, int y) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (image is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
+}
+
+/**
+ * Copies a rectangular area from the source image into a (potentially
+ * different sized) rectangular area in the receiver. If the source
+ * and destination areas are of differing sizes, then the source
+ * area will be stretched or shrunk to fit the destination area
+ * as it is copied. The copy fails if any part of the source rectangle
+ * lies outside the bounds of the source image, or if any of the width
+ * or height arguments are negative.
+ *
+ * @param image the source image
+ * @param srcX the x coordinate in the source image to copy from
+ * @param srcY the y coordinate in the source image to copy from
+ * @param srcWidth the width in pixels to copy from the source
+ * @param srcHeight the height in pixels to copy from the source
+ * @param destX the x coordinate in the destination to copy to
+ * @param destY the y coordinate in the destination to copy to
+ * @param destWidth the width in pixels of the destination rectangle
+ * @param destHeight the height in pixels of the destination rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
+ *    <li>ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
+ * </ul>
+ */
+public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (srcWidth is 0 || srcHeight is 0 || destWidth is 0 || destHeight is 0) return;
+    if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (image is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false);
+}
+
+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 /*long*/ [] gdipImage = srcImage.createGdipImage();
+        auto img = cast(Gdip.Image) gdipImage[0];
+        int imgWidth = Gdip.Image_GetWidth(img);
+        int imgHeight = Gdip.Image_GetHeight(img);
+        if (simple) {
+            srcWidth = destWidth = imgWidth;
+            srcHeight = destHeight = imgHeight;
+        } else {
+            if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) {
+                SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+            }
+            simple = srcX is 0 && srcY is 0 &&
+                srcWidth is destWidth && destWidth is imgWidth &&
+                srcHeight is destHeight && destHeight is imgHeight;
+        }
+        Gdip.Rect rect;
+        rect.X = destX;
+        rect.Y = destY;
+        rect.Width = destWidth;
+        rect.Height = destHeight;
+        /*
+        * Note that if the wrap mode is not WrapModeTileFlipXY, the scaled image
+        * is translucent around the borders.
+        */
+        auto attrib = Gdip.ImageAttributes_new();
+        Gdip.ImageAttributes_SetWrapMode(attrib, Gdip.WrapModeTileFlipXY);
+        if (data.alpha != 0xFF) {
+
+            Gdip.ColorMatrix matrix =
+            { [ [1,0,0,0,0],
+                [0,1,0,0,0],
+                [0,0,1,0,0],
+                [0,0,0,data.alpha / cast(float)0xFF,0,],
+                [0,0,0,0,1] ] };
+            /*
+            float[] matrix = [ cast(float)
+                1,0,0,0,0,
+                0,1,0,0,0,
+                0,0,1,0,0,
+                0,0,0,data.alpha / cast(float)0xFF,0,
+                0,0,0,0,1,
+            ];*/
+            Gdip.ImageAttributes_SetColorMatrix(attrib, matrix, Gdip.ColorMatrixFlagsDefault, Gdip.ColorAdjustTypeBitmap);
+        }
+        int gstate = 0;
+        if ((data.style & SWT.MIRRORED) != 0) {
+            gstate = Gdip.Graphics_Save(data.gdipGraphics);
+            Gdip.Graphics_ScaleTransform(data.gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
+            Gdip.Graphics_TranslateTransform(data.gdipGraphics, - 2 * destX - destWidth, 0, Gdip.MatrixOrderPrepend);
+        }
+        Gdip.Graphics_DrawImage(data.gdipGraphics, img, rect, srcX, srcY, srcWidth, srcHeight, Gdip.UnitPixel, attrib, null, null);
+        if ((data.style & SWT.MIRRORED) != 0) {
+            Gdip.Graphics_Restore(data.gdipGraphics, gstate);
+        }
+        Gdip.ImageAttributes_delete(attrib);
+        Gdip.Bitmap_delete( cast(Gdip.Bitmap) img);
+        if (gdipImage[1] != 0) {
+            auto hHeap = OS.GetProcessHeap ();
+            OS.HeapFree(hHeap, 0, cast(void*)gdipImage[1]);
+        }
+        return;
+    }
+    switch (srcImage.type) {
+        case SWT.BITMAP:
+            drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+            break;
+        case SWT.ICON:
+            drawIcon(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple);
+            break;
+        default:
+    }
+}
+
+void drawIcon(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple) {
+    int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY);
+
+    bool drawIcon = true;
+    int flags = OS.DI_NORMAL;
+    int offsetX = 0, offsetY = 0;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(5, 1)) {
+        if ((OS.GetLayout(handle) & OS.LAYOUT_RTL) !is 0) {
+            flags |= OS.DI_NOMIRROR;
+            /*
+            * Bug in Windows.  For some reason, DrawIconEx() does not take
+            * into account the window origin when the DI_NOMIRROR and
+            * LAYOUT_RTL are set.  The fix is to set the window origin to
+            * (0, 0) and offset the drawing ourselves.
+            */
+            POINT pt;
+            OS.GetWindowOrgEx(handle, &pt);
+            offsetX = pt.x;
+            offsetY = pt.y;
+        }
+    } else {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+            drawIcon = (OS.GetLayout(handle) & OS.LAYOUT_RTL) is 0;
+        }
+    }
+
+    /* Simple case: no stretching, entire icon */
+    if (simple && technology !is OS.DT_RASPRINTER && drawIcon) {
+        if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+        OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, srcImage.handle, 0, 0, 0, null, flags);
+        if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null);
+        return;
+    }
+
+    /* Get the icon info */
+    ICONINFO srcIconInfo;
+    static if (OS.IsWinCE) {
+        Image.GetIconInfo(srcImage, &srcIconInfo);
+    } else {
+        OS.GetIconInfo(srcImage.handle, &srcIconInfo);
+    }
+
+    /* Get the icon width and height */
+    auto hBitmap = srcIconInfo.hbmColor;
+    if (hBitmap is null) hBitmap = srcIconInfo.hbmMask;
+    BITMAP bm;
+    OS.GetObject(hBitmap, BITMAP.sizeof, &bm);
+    int iconWidth = bm.bmWidth, iconHeight = bm.bmHeight;
+    if (hBitmap is srcIconInfo.hbmMask) iconHeight /= 2;
+
+    if (simple) {
+        srcWidth = destWidth = iconWidth;
+        srcHeight = destHeight = iconHeight;
+    }
+
+    /* Draw the icon */
+    bool failed = srcX + srcWidth > iconWidth || srcY + srcHeight > iconHeight;
+    if (!failed) {
+        simple = srcX is 0 && srcY is 0 &&
+            srcWidth is destWidth && srcHeight is destHeight &&
+            srcWidth is iconWidth && srcHeight is iconHeight;
+        if (!drawIcon) {
+            drawBitmapMask(srcImage, srcIconInfo.hbmColor, srcIconInfo.hbmMask, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, iconWidth, iconHeight, false);
+        } else if (simple && technology !is OS.DT_RASPRINTER) {
+            /* Simple case: no stretching, entire icon */
+            if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+            OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, srcImage.handle, 0, 0, 0, null, flags);
+            if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null);
+        } else {
+            /* Create the icon info and HDC's */
+            ICONINFO newIconInfo;
+            newIconInfo.fIcon = true;
+            auto srcHdc = OS.CreateCompatibleDC(handle);
+            auto dstHdc = OS.CreateCompatibleDC(handle);
+
+            /* Blt the color bitmap */
+            int srcColorY = srcY;
+            auto srcColor = srcIconInfo.hbmColor;
+            if (srcColor is null) {
+                srcColor = srcIconInfo.hbmMask;
+                srcColorY += iconHeight;
+            }
+            auto oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
+            newIconInfo.hbmColor = OS.CreateCompatibleBitmap(srcHdc, destWidth, destHeight);
+            if (newIconInfo.hbmColor is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            auto oldDestBitmap = OS.SelectObject(dstHdc, newIconInfo.hbmColor);
+            bool stretch = !simple && (srcWidth !is destWidth || srcHeight !is destHeight);
+            if (stretch) {
+                static if (!OS.IsWinCE) OS.SetStretchBltMode(dstHdc, OS.COLORONCOLOR);
+                OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, srcWidth, srcHeight, OS.SRCCOPY);
+            } else {
+                OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcColorY, OS.SRCCOPY);
+            }
+
+            /* Blt the mask bitmap */
+            OS.SelectObject(srcHdc, srcIconInfo.hbmMask);
+            newIconInfo.hbmMask = OS.CreateBitmap(destWidth, destHeight, 1, 1, null);
+            if (newIconInfo.hbmMask is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            OS.SelectObject(dstHdc, newIconInfo.hbmMask);
+            if (stretch) {
+                OS.StretchBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCCOPY);
+            } else {
+                OS.BitBlt(dstHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+            }
+
+            if (technology is OS.DT_RASPRINTER) {
+                OS.SelectObject(srcHdc, newIconInfo.hbmColor);
+                OS.SelectObject(dstHdc, newIconInfo.hbmMask);
+                drawBitmapTransparentByClipping(srcHdc, dstHdc, 0, 0, destWidth, destHeight, destX, destY, destWidth, destHeight, true, destWidth, destHeight);
+                OS.SelectObject(srcHdc, oldSrcBitmap);
+                OS.SelectObject(dstHdc, oldDestBitmap);
+            } else {
+                OS.SelectObject(srcHdc, oldSrcBitmap);
+                OS.SelectObject(dstHdc, oldDestBitmap);
+                auto hIcon = OS.CreateIconIndirect(&newIconInfo);
+                if (hIcon is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, 0, 0, null);
+                OS.DrawIconEx(handle, destX - offsetX, destY - offsetY, hIcon, destWidth, destHeight, 0, null, flags);
+                if (offsetX !is 0 || offsetY !is 0) OS.SetWindowOrgEx(handle, offsetX, offsetY, null);
+                OS.DestroyIcon(hIcon);
+            }
+
+            /* Destroy the new icon src and mask and hdc's*/
+            OS.DeleteObject(newIconInfo.hbmMask);
+            OS.DeleteObject(newIconInfo.hbmColor);
+            OS.DeleteDC(dstHdc);
+            OS.DeleteDC(srcHdc);
+        }
+    }
+
+    /* Free icon info */
+    OS.DeleteObject(srcIconInfo.hbmMask);
+    if (srcIconInfo.hbmColor !is null) {
+        OS.DeleteObject(srcIconInfo.hbmColor);
+    }
+
+    if (failed) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+}
+
+void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple) {
+    BITMAP bm;
+    OS.GetObject(srcImage.handle, BITMAP.sizeof, &bm);
+    int imgWidth = bm.bmWidth;
+    int imgHeight = bm.bmHeight;
+    if (simple) {
+        srcWidth = destWidth = imgWidth;
+        srcHeight = destHeight = imgHeight;
+    } else {
+        if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) {
+            SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+        }
+        simple = srcX is 0 && srcY is 0 &&
+            srcWidth is destWidth && destWidth is imgWidth &&
+            srcHeight is destHeight && destHeight is imgHeight;
+    }
+    bool mustRestore = false;
+    GC memGC = srcImage.memGC;
+    if (memGC !is null && !memGC.isDisposed()) {
+        memGC.flush();
+        mustRestore = true;
+        GCData data = memGC.data;
+        if (data.hNullBitmap !is null) {
+            OS.SelectObject(memGC.handle, data.hNullBitmap);
+            data.hNullBitmap = null;
+        }
+    }
+    if (srcImage.alpha !is -1 || srcImage.alphaData !is null) {
+        drawBitmapAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+    } else if (srcImage.transparentPixel !is -1) {
+        drawBitmapTransparent(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+    } else {
+        drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+    }
+    if (mustRestore) {
+        auto hOldBitmap = OS.SelectObject(memGC.handle, srcImage.handle);
+        memGC.data.hNullBitmap = hOldBitmap;
+    }
+}
+
+void drawBitmapAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, BITMAP bm, int imgWidth, int imgHeight) {
+    /* Simple cases */
+    if (srcImage.alpha is 0) return;
+    if (srcImage.alpha is 255) {
+        drawBitmap(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, bm, imgWidth, imgHeight);
+        return;
+    }
+
+    if (OS.IsWinNT && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        BLENDFUNCTION blend;
+        blend.BlendOp = OS.AC_SRC_OVER;
+        auto srcHdc = OS.CreateCompatibleDC(handle);
+        auto oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+        if (srcImage.alpha !is -1) {
+            blend.SourceConstantAlpha = cast(byte)srcImage.alpha;
+            OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, blend);
+        } else {
+            auto memDib = Image.createDIB(srcWidth, srcHeight, 32);
+            if (memDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            auto memHdc = OS.CreateCompatibleDC(handle);
+            auto oldMemBitmap = OS.SelectObject(memHdc, memDib);
+            BITMAP dibBM;
+            OS.GetObject(memDib, BITMAP.sizeof, &dibBM);
+            OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+            byte[] srcData = new byte[dibBM.bmWidthBytes * dibBM.bmHeight];
+            srcData[] = (cast(byte*)dibBM.bmBits)[ 0 .. srcData.length ];
+            final int apinc = imgWidth - srcWidth;
+            int ap = srcY * imgWidth + srcX, sp = 0;
+            byte[] alphaData = srcImage.alphaData;
+            for (int y = 0; y < srcHeight; ++y) {
+                for (int x = 0; x < srcWidth; ++x) {
+                    int alpha = alphaData[ap++] & 0xff;
+                    int r = ((srcData[sp + 0] & 0xFF) * alpha) + 128;
+                    r = (r + (r >> 8)) >> 8;
+                    int g = ((srcData[sp + 1] & 0xFF) * alpha) + 128;
+                    g = (g + (g >> 8)) >> 8;
+                    int b = ((srcData[sp + 2] & 0xFF) * alpha) + 128;
+                    b = (b + (b >> 8)) >> 8;
+                    srcData[sp+0] = cast(byte)r;
+                    srcData[sp+1] = cast(byte)g;
+                    srcData[sp+2] = cast(byte)b;
+                    srcData[sp+3] = cast(byte)alpha;
+                    sp += 4;
+                }
+                ap += apinc;
+            }
+            (cast(byte*)dibBM.bmBits)[ 0 .. srcData.length ] = srcData[];
+            blend.SourceConstantAlpha = 0xff;
+            blend.AlphaFormat = OS.AC_SRC_ALPHA;
+            OS.AlphaBlend(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, blend);
+            OS.SelectObject(memHdc, oldMemBitmap);
+            OS.DeleteDC(memHdc);
+            OS.DeleteObject(memDib);
+        }
+        OS.SelectObject(srcHdc, oldSrcBitmap);
+        OS.DeleteDC(srcHdc);
+        return;
+    }
+
+    /* Check clipping */
+    Rectangle rect = getClipping();
+    rect = rect.intersection(new Rectangle(destX, destY, destWidth, destHeight));
+    if (rect.isEmpty()) return;
+
+    /*
+    * Optimization.  Recalculate src and dest rectangles so that
+    * only the clipping area is drawn.
+    */
+    int sx1 = srcX + (((rect.x - destX) * srcWidth) / destWidth);
+    int sx2 = srcX + ((((rect.x + rect.width) - destX) * srcWidth) / destWidth);
+    int sy1 = srcY + (((rect.y - destY) * srcHeight) / destHeight);
+    int sy2 = srcY + ((((rect.y + rect.height) - destY) * srcHeight) / destHeight);
+    destX = rect.x;
+    destY = rect.y;
+    destWidth = rect.width;
+    destHeight = rect.height;
+    srcX = sx1;
+    srcY = sy1;
+    srcWidth = Math.max(1, sx2 - sx1);
+    srcHeight = Math.max(1, sy2 - sy1);
+
+    /* Create resources */
+    auto srcHdc = OS.CreateCompatibleDC(handle);
+    auto oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+    auto memHdc = OS.CreateCompatibleDC(handle);
+    auto memDib = Image.createDIB(Math.max(srcWidth, destWidth), Math.max(srcHeight, destHeight), 32);
+    if (memDib is null) SWT.error(SWT.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 background pixels */
+    OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+    byte[] destData = new byte[sizeInBytes];
+    destData[] = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ];
+
+    /* Get the foreground pixels */
+    OS.BitBlt(memHdc, 0, 0, srcWidth, srcHeight, srcHdc, srcX, srcY, OS.SRCCOPY);
+    byte[] srcData = new byte[sizeInBytes];
+    srcData[] = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ];
+
+    /* Merge the alpha channel in place */
+    int alpha = srcImage.alpha;
+    final bool hasAlphaChannel = (srcImage.alpha is -1);
+    if (hasAlphaChannel) {
+        final int apinc = imgWidth - srcWidth;
+        final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+        int ap = srcY * imgWidth + srcX, sp = 3;
+        byte[] alphaData = srcImage.alphaData;
+        for (int y = 0; y < srcHeight; ++y) {
+            for (int x = 0; x < srcWidth; ++x) {
+                srcData[sp] = alphaData[ap++];
+                sp += 4;
+            }
+            ap += apinc;
+            sp += spinc;
+        }
+    }
+
+    /* Scale the foreground pixels with alpha */
+     (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ] = srcData[];
+    /*
+    * Bug in WinCE and Win98.  StretchBlt does not correctly stretch when
+    * the source and destination HDCs are the same.  The workaround is to
+    * stretch to a temporary HDC and blit back into the original HDC.
+    * Note that on WinCE StretchBlt correctly compresses the image when the
+    * source and destination HDCs are the same.
+    */
+    if ((OS.IsWinCE && (destWidth > srcWidth || destHeight > srcHeight)) || (!OS.IsWinNT && !OS.IsWinCE)) {
+        auto tempHdc = OS.CreateCompatibleDC(handle);
+        auto tempDib = Image.createDIB(destWidth, destHeight, 32);
+        if (tempDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        auto oldTempBitmap = OS.SelectObject(tempHdc, tempDib);
+        if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+            static if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR);
+            OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        } else {
+            OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+        }
+        OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY);
+        OS.SelectObject(tempHdc, oldTempBitmap);
+        OS.DeleteObject(tempDib);
+        OS.DeleteDC(tempHdc);
+    } else {
+        if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+            static if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc, OS.COLORONCOLOR);
+            OS.StretchBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        } else {
+            OS.BitBlt(memHdc, 0, 0, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+        }
+    }
+    srcData[] = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ];
+
+    /* Compose the pixels */
+    final int dpinc = dibBM.bmWidthBytes - destWidth * 4;
+    int dp = 0;
+    for (int y = 0; y < destHeight; ++y) {
+        for (int x = 0; x < destWidth; ++x) {
+            if (hasAlphaChannel) alpha = srcData[dp + 3] & 0xff;
+            destData[dp] += ((srcData[dp] & 0xff) - (destData[dp] & 0xff)) * alpha / 255;
+            destData[dp + 1] += ((srcData[dp + 1] & 0xff) - (destData[dp + 1] & 0xff)) * alpha / 255;
+            destData[dp + 2] += ((srcData[dp + 2] & 0xff) - (destData[dp + 2] & 0xff)) * alpha / 255;
+            dp += 4;
+        }
+        dp += dpinc;
+    }
+
+    /* Draw the composed pixels */
+    (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ] = destData[];
+    OS.BitBlt(handle, destX, destY, destWidth, destHeight, memHdc, 0, 0, OS.SRCCOPY);
+
+    /* Free resources */
+    OS.SelectObject(memHdc, oldMemBitmap);
+    OS.DeleteDC(memHdc);
+    OS.DeleteObject(memDib);
+    OS.SelectObject(srcHdc, oldSrcBitmap);
+    OS.DeleteDC(srcHdc);
+}
+
+void drawBitmapTransparentByClipping(HDC srcHdc, HDC maskHdc, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, int imgWidth, int imgHeight) {
+    /* Create a clipping region from the mask */
+    auto rgn = OS.CreateRectRgn(0, 0, 0, 0);
+    for (int y=0; y<imgHeight; y++) {
+        for (int x=0; x<imgWidth; x++) {
+            if (OS.GetPixel(maskHdc, x, y) is 0) {
+                auto tempRgn = OS.CreateRectRgn(x, y, x+1, y+1);
+                OS.CombineRgn(rgn, rgn, tempRgn, OS.RGN_OR);
+                OS.DeleteObject(tempRgn);
+            }
+        }
+    }
+    /* Stretch the clipping mask if needed */
+    if (destWidth !is srcWidth || destHeight !is srcHeight) {
+        int nBytes = OS.GetRegionData (rgn, 0, null);
+        int[] lpRgnData = new int[nBytes / 4];
+        OS.GetRegionData (rgn, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+        float[6] lpXform;
+        lpXform[] = 0.0f;
+        lpXform[0] = cast(float)destWidth/srcWidth;
+        lpXform[3] = cast(float)destHeight/srcHeight;
+        auto tmpRgn = OS.ExtCreateRegion(cast(XFORM*)lpXform.ptr, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+        OS.DeleteObject(rgn);
+        rgn = tmpRgn;
+    }
+    OS.OffsetRgn(rgn, destX, destY);
+    auto clip = OS.CreateRectRgn(0, 0, 0, 0);
+    int result = OS.GetClipRgn(handle, clip);
+    if (result is 1) OS.CombineRgn(rgn, rgn, clip, OS.RGN_AND);
+    OS.SelectClipRgn(handle, rgn);
+    int rop2 = 0;
+    static if (!OS.IsWinCE) {
+        rop2 = OS.GetROP2(handle);
+    } else {
+        rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN);
+        OS.SetROP2 (handle, rop2);
+    }
+    int dwRop = rop2 is OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY;
+    if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+        int mode = 0;
+        static if (!OS.IsWinCE) mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+        OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop);
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(handle, mode);
+    } else {
+        OS.BitBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, dwRop);
+    }
+    OS.SelectClipRgn(handle, result is 1 ? clip : null);
+    OS.DeleteObject(clip);
+    OS.DeleteObject(rgn);
+}
+
+void drawBitmapMask(Image srcImage, HBITMAP srcColor, HBITMAP srcMask, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, int imgWidth, int imgHeight, bool offscreen) {
+    int srcColorY = srcY;
+    if (srcColor is null) {
+        srcColor = srcMask;
+        srcColorY += imgHeight;
+    }
+    auto srcHdc = OS.CreateCompatibleDC(handle);
+    auto oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
+    auto destHdc = handle;
+    int x = destX, y = destY;
+    HDC tempHdc;
+    HBITMAP tempBitmap;
+    HBITMAP oldTempBitmap;
+    int oldBkColor = 0, oldTextColor = 0;
+    if (offscreen) {
+        tempHdc = OS.CreateCompatibleDC(handle);
+        tempBitmap = OS.CreateCompatibleBitmap(handle, destWidth, destHeight);
+        oldTempBitmap = OS.SelectObject(tempHdc, tempBitmap);
+        OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+        destHdc = tempHdc;
+        x = y = 0;
+    } else {
+        oldBkColor = OS.SetBkColor(handle, 0xFFFFFF);
+        oldTextColor = OS.SetTextColor(handle, 0);
+    }
+    if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+        int mode = 0;
+        static if (!OS.IsWinCE) mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+        OS.StretchBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcColorY, srcWidth, srcHeight, OS.SRCINVERT);
+        OS.SelectObject(srcHdc, srcMask);
+        OS.StretchBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCAND);
+        OS.SelectObject(srcHdc, srcColor);
+        OS.StretchBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcColorY, srcWidth, srcHeight, OS.SRCINVERT);
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(handle, mode);
+    } else {
+        OS.BitBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcColorY, OS.SRCINVERT);
+        OS.SetTextColor(destHdc, 0);
+        OS.SelectObject(srcHdc, srcMask);
+        OS.BitBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCAND);
+        OS.SelectObject(srcHdc, srcColor);
+        OS.BitBlt(destHdc, x, y, destWidth, destHeight, srcHdc, srcX, srcColorY, OS.SRCINVERT);
+    }
+    if (offscreen) {
+        OS.BitBlt(handle, destX, destY, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY);
+        OS.SelectObject(tempHdc, oldTempBitmap);
+        OS.DeleteDC(tempHdc);
+        OS.DeleteObject(tempBitmap);
+    } else {
+        OS.SetBkColor(handle, oldBkColor);
+        OS.SetTextColor(handle, oldTextColor);
+    }
+    OS.SelectObject(srcHdc, oldSrcBitmap);
+    OS.DeleteDC(srcHdc);
+}
+
+void drawBitmapTransparent(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, BITMAP bm, int imgWidth, int imgHeight) {
+
+    /* Find the RGB values for the transparent pixel. */
+    bool isDib = bm.bmBits !is null;
+    auto hBitmap = srcImage.handle;
+    auto srcHdc = OS.CreateCompatibleDC(handle);
+    auto oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
+    byte[] originalColors = null;
+    int transparentColor = srcImage.transparentColor;
+    if (transparentColor is -1) {
+        int transBlue = 0, transGreen = 0, transRed = 0;        
+        bool fixPalette = false;
+        if (bm.bmBitsPixel <= 8) {
+            if (isDib) {
+                /* Palette-based DIBSECTION */
+                static if (OS.IsWinCE) {
+                    byte* pBits = cast(byte*)bm.bmBits;
+                    //OS.MoveMemory(pBits, bm.bmBits, 1);
+                    byte oldValue = pBits[0];
+                    int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
+                    pBits[0] = cast(byte)((srcImage.transparentPixel << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
+                    //OS.MoveMemory(bm.bmBits, pBits, 1);
+                    int color = OS.GetPixel(srcHdc, 0, 0);
+                    pBits[0] = oldValue;
+                    //OS.MoveMemory(bm.bmBits, pBits, 1);
+                    transBlue = (color & 0xFF0000) >> 16;
+                    transGreen = (color & 0xFF00) >> 8;
+                    transRed = color & 0xFF;
+                } else {
+                    int maxColors = 1 << bm.bmBitsPixel;
+                    byte[] oldColors = new byte[maxColors * 4];
+                    OS.GetDIBColorTable(srcHdc, 0, maxColors, cast(RGBQUAD*)oldColors.ptr);
+                    int offset = srcImage.transparentPixel * 4;
+                    for (int i = 0; i < oldColors.length; i += 4) {
+                        if (i !is offset) {
+                            if (oldColors[offset] is oldColors[i] && oldColors[offset+1] is oldColors[i+1] && oldColors[offset+2] is oldColors[i+2]) {
+                                fixPalette = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (fixPalette) {
+                        byte[] newColors = new byte[oldColors.length];
+                        transRed = transGreen = transBlue = 0xff;
+                        newColors[offset] = cast(byte)transBlue;
+                        newColors[offset+1] = cast(byte)transGreen;
+                        newColors[offset+2] = cast(byte)transRed;
+                        OS.SetDIBColorTable(srcHdc, 0, maxColors, cast(RGBQUAD*)newColors.ptr);
+                        originalColors = oldColors;
+                    } else {
+                        transBlue = oldColors[offset] & 0xFF;
+                        transGreen = oldColors[offset+1] & 0xFF;
+                        transRed = oldColors[offset+2] & 0xFF;
+                    }
+                }
+            } else {
+                /* Palette-based bitmap */
+                int numColors = 1 << bm.bmBitsPixel;
+                /* Set the few fields necessary to get the RGB data out */
+                BITMAPINFOHEADER bmiHeader;
+                bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                bmiHeader.biPlanes = bm.bmPlanes;
+                bmiHeader.biBitCount = bm.bmBitsPixel;
+                byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+                bmi[] = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof ];
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(srcHdc, srcImage.handle, 0, 0, null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                int offset = BITMAPINFOHEADER.sizeof + 4 * srcImage.transparentPixel;
+                transRed = bmi[offset + 2] & 0xFF;
+                transGreen = bmi[offset + 1] & 0xFF;
+                transBlue = bmi[offset] & 0xFF;
+            }
+        } else {
+            /* Direct color image */
+            int pixel = srcImage.transparentPixel;
+            switch (bm.bmBitsPixel) {
+                case 16:
+                    transBlue = (pixel & 0x1F) << 3;
+                    transGreen = (pixel & 0x3E0) >> 2;
+                    transRed = (pixel & 0x7C00) >> 7;
+                    break;
+                case 24:
+                    transBlue = (pixel & 0xFF0000) >> 16;
+                    transGreen = (pixel & 0xFF00) >> 8;
+                    transRed = pixel & 0xFF;
+                    break;
+                case 32:
+                    transBlue = (pixel & 0xFF000000) >>> 24;
+                    transGreen = (pixel & 0xFF0000) >> 16;
+                    transRed = (pixel & 0xFF00) >> 8;
+                    break;
+            default:
+            }
+        }
+        transparentColor = transBlue << 16 | transGreen << 8 | transRed;
+        if (!fixPalette) srcImage.transparentColor = transparentColor;
+    }
+
+    static if (OS.IsWinCE) {
+        /*
+        * Note in WinCE. TransparentImage uses the first entry of a palette
+        * based image when there are multiple entries that have the same
+        * transparent color.
+        */
+        OS.TransparentImage(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, transparentColor);
+    } else if (originalColors is null && OS.IsWinNT && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        int mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+        OS.TransparentBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, transparentColor);
+        OS.SetStretchBltMode(handle, mode);
+    } else {
+        /* Create the mask for the source image */
+        auto maskHdc = OS.CreateCompatibleDC(handle);
+        auto maskBitmap = OS.CreateBitmap(imgWidth, imgHeight, 1, 1, null);
+        auto oldMaskBitmap = OS.SelectObject(maskHdc, maskBitmap);
+        OS.SetBkColor(srcHdc, transparentColor);
+        OS.BitBlt(maskHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+        if (originalColors !is null) OS.SetDIBColorTable(srcHdc, 0, 1 << bm.bmBitsPixel, cast(RGBQUAD*)originalColors.ptr);
+
+        if (OS.GetDeviceCaps(handle, OS.TECHNOLOGY) is OS.DT_RASPRINTER) {
+            /* Most printers do not support BitBlt(), draw the source bitmap transparently using clipping */
+            drawBitmapTransparentByClipping(srcHdc, maskHdc, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight);
+        } else {
+            /* Draw the source bitmap transparently using invert/and mask/invert */
+            auto tempHdc = OS.CreateCompatibleDC(handle);
+            auto tempBitmap = OS.CreateCompatibleBitmap(handle, destWidth, destHeight);
+            auto oldTempBitmap = OS.SelectObject(tempHdc, tempBitmap);
+            OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, handle, destX, destY, OS.SRCCOPY);
+            if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+                static if (!OS.IsWinCE) OS.SetStretchBltMode(tempHdc, OS.COLORONCOLOR);
+                OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT);
+                OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCAND);
+                OS.StretchBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, OS.SRCINVERT);
+            } else {
+                OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT);
+                OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, maskHdc, srcX, srcY, OS.SRCAND);
+                OS.BitBlt(tempHdc, 0, 0, destWidth, destHeight, srcHdc, srcX, srcY, OS.SRCINVERT);
+            }
+            OS.BitBlt(handle, destX, destY, destWidth, destHeight, tempHdc, 0, 0, OS.SRCCOPY);
+            OS.SelectObject(tempHdc, oldTempBitmap);
+            OS.DeleteDC(tempHdc);
+            OS.DeleteObject(tempBitmap);
+        }
+        OS.SelectObject(maskHdc, oldMaskBitmap);
+        OS.DeleteDC(maskHdc);
+        OS.DeleteObject(maskBitmap);
+    }
+    OS.SelectObject(srcHdc, oldSrcBitmap);
+    if (hBitmap !is srcImage.handle) OS.DeleteObject(hBitmap);
+    OS.DeleteDC(srcHdc);
+}
+
+void drawBitmap(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, BITMAP bm, int imgWidth, int imgHeight) {
+    auto srcHdc = OS.CreateCompatibleDC(handle);
+    auto oldSrcBitmap = OS.SelectObject(srcHdc, srcImage.handle);
+    int rop2 = 0;
+    static if (!OS.IsWinCE) {
+        rop2 = OS.GetROP2(handle);
+    } else {
+        rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN);
+        OS.SetROP2 (handle, rop2);
+    }
+    int dwRop = rop2 is OS.R2_XORPEN ? OS.SRCINVERT : OS.SRCCOPY;
+    if (!simple && (srcWidth !is destWidth || srcHeight !is destHeight)) {
+        int mode = 0;
+        static if (!OS.IsWinCE) mode = OS.SetStretchBltMode(handle, OS.COLORONCOLOR);
+        OS.StretchBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, srcWidth, srcHeight, dwRop);
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(handle, mode);
+    } else {
+        OS.BitBlt(handle, destX, destY, destWidth, destHeight, srcHdc, srcX, srcY, dwRop);
+    }
+    OS.SelectObject(srcHdc, oldSrcBitmap);
+    OS.DeleteDC(srcHdc);
+}
+
+/**
+ * Draws a line, using the foreground color, between the points
+ * (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
+ *
+ * @param x1 the first point's x coordinate
+ * @param y1 the first point's y coordinate
+ * @param x2 the second point's x coordinate
+ * @param y2 the second point's y coordinate
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawLine (int x1, int y1, int x2, int y2) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(DRAW);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        Gdip.Graphics_DrawLine(gdipGraphics, data.gdipPen, x1, y1, x2, y2);
+        Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) {
+            x1--;
+            x2--;
+        }
+    }
+    static if (OS.IsWinCE) {
+        int [4] points; points[0] = x1; points[1] = y1; points[2] = x2; points[3] = y2;
+        OS.Polyline (handle, cast(POINT*)points.ptr, points.length / 2);
+    } else {
+        OS.MoveToEx (handle, x1, y1, null);
+        OS.LineTo (handle, x2, y2);
+    }
+    if (data.lineWidth <= 1) {
+        OS.SetPixel (handle, x2, y2, data.foreground);
+    }
+}
+
+/**
+ * Draws the outline of an oval, using the foreground color,
+ * within the specified rectangular area.
+ * <p>
+ * The result is a circle or ellipse that fits within the
+ * rectangle specified by the <code>x</code>, <code>y</code>,
+ * <code>width</code>, and <code>height</code> arguments.
+ * </p><p>
+ * The oval covers an area that is <code>width + 1</code>
+ * pixels wide and <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be drawn
+ * @param y the y coordinate of the upper left corner of the oval to be drawn
+ * @param width the width of the oval to be drawn
+ * @param height the height of the oval to be drawn
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawOval (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(DRAW);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        Gdip.Graphics_DrawEllipse(gdipGraphics, data.gdipPen, x, y, width, height);
+        Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) x--;
+    }
+    OS.Ellipse(handle, x, y, x + width + 1, y + height + 1);
+}
+
+/**
+ * Draws the path described by the parameter.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the path to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void drawPath (Path path) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (path is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (path.handle is null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    initGdip();
+    checkGC(DRAW);
+    auto gdipGraphics = data.gdipGraphics;
+    Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+    Gdip.Graphics_DrawPath(gdipGraphics, data.gdipPen, path.handle);
+    Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Draws a pixel, using the foreground color, at the specified
+ * point (<code>x</code>, <code>y</code>).
+ * <p>
+ * Note that the receiver's line attributes do not affect this
+ * operation.
+ * </p>
+ *
+ * @param x the point's x coordinate
+ * @param y the point's y coordinate
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void drawPoint (int x, int y) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics !is null) {
+        checkGC(DRAW);
+        Gdip.Graphics_FillRectangle(data.gdipGraphics, getFgBrush(), x, y, 1, 1);
+        return;
+    }
+    OS.SetPixel (handle, x, y, data.foreground);
+}
+
+/**
+ * Draws the closed polygon which is defined by the specified array
+ * of integer coordinates, using the receiver's foreground color. The array
+ * contains alternating x and y values which are considered to represent
+ * points which are the vertices of the polygon. Lines are drawn between
+ * each consecutive pair, and between the first pair and last pair in the
+ * array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawPolygon( int[] pointArray) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT extension: allow null array
+    //if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    checkGC(DRAW);
+    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.ptr, pointArray.length/2);
+        Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) {
+            for (int i = 0; i < pointArray.length; i+=2) {
+                pointArray[i]--;
+            }
+        }
+    }
+    OS.Polygon(handle, cast(POINT*)pointArray.ptr, pointArray.length/2);
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) {
+            for (int i = 0; i < pointArray.length; i+=2) {
+                pointArray[i]++;
+            }
+        }
+    }
+}
+
+/**
+ * Draws the polyline which is defined by the specified array
+ * of integer coordinates, using the receiver's foreground color. The array
+ * contains alternating x and y values which are considered to represent
+ * points which are the corners of the polyline. Lines are drawn between
+ * each consecutive pair, but not between the first pair and last pair in
+ * the array.
+ *
+ * @param pointArray an array of alternating x and y values which are the corners of the polyline
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawPolyline(int[] pointArray) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT externsion: allow null array
+    //if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    checkGC(DRAW);
+    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.ptr, pointArray.length / 2);
+        Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) {
+            for (int i = 0; i < pointArray.length; i+=2) {
+                pointArray[i]--;
+            }
+        }
+    }
+    OS.Polyline(handle, cast(POINT*)pointArray.ptr, pointArray.length / 2);
+    int length_ = pointArray.length;
+    if (length_ >= 2) {
+        if (data.lineWidth <= 1) {
+            OS.SetPixel (handle, pointArray[length_ - 2], pointArray[length_ - 1], data.foreground);
+        }
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) {
+            for (int i = 0; i < pointArray.length; i+=2) {
+                pointArray[i]++;
+            }
+        }
+    }
+}
+
+/**
+ * Draws the outline of the rectangle specified by the arguments,
+ * using the receiver's foreground color. The left and right edges
+ * of the rectangle are at <code>x</code> and <code>x + width</code>.
+ * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRectangle (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    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);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        /*
+        * Note that Rectangle() subtracts one pixel in MIRRORED mode when
+        * the pen was created with CreatePen() and its width is 0 or 1.
+        */
+        if (data.lineWidth > 1) {
+            if ((data.lineWidth % 2) is 1) x++;
+        } else {
+            if (data.hPen !is null && OS.GetObject(data.hPen, 0, null) !is LOGPEN.sizeof) {
+                x++;
+            }
+        }
+    }
+    OS.Rectangle (handle, x, y, x + width + 1, y + height + 1);
+}
+
+/**
+ * Draws the outline of the specified rectangle, using the receiver's
+ * foreground color. The left and right edges of the rectangle are at
+ * <code>rect.x</code> and <code>rect.x + rect.width</code>. The top
+ * and bottom edges are at <code>rect.y</code> and
+ * <code>rect.y + rect.height</code>.
+ *
+ * @param rect the rectangle to draw
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRectangle (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    drawRectangle (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Draws the outline of the round-cornered rectangle specified by
+ * the arguments, using the receiver's foreground color. The left and
+ * right edges of the rectangle are at <code>x</code> and <code>x + width</code>.
+ * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
+ * The <em>roundness</em> of the corners is specified by the
+ * <code>arcWidth</code> and <code>arcHeight</code> arguments, which
+ * are respectively the width and height of the ellipse used to draw
+ * the corners.
+ *
+ * @param x the x coordinate of the rectangle to be drawn
+ * @param y the y coordinate of the rectangle to be drawn
+ * @param width the width of the rectangle to be drawn
+ * @param height the height of the rectangle to be drawn
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(DRAW);
+    if (data.gdipGraphics !is null) {
+        drawRoundRectangleGdip(data.gdipGraphics, data.gdipPen, x, y, width, height, arcWidth, arcHeight);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (data.lineWidth !is 0 && data.lineWidth % 2 is 0) x--;
+    }
+    static if (OS.IsWinCE) {
+        /*
+        * Bug in WinCE PPC.  On certain devices, RoundRect does not draw
+        * all the pixels.  The workaround is to draw a round rectangle
+        * using lines and arcs.
+        */
+        if (width is 0 || height is 0) return;
+        if (arcWidth is 0 || arcHeight is 0) {
+            drawRectangle(x, y, width, height);
+            return;
+        }
+        if (width < 0) {
+            x += width;
+            width = -width;
+        }
+        if (height < 0) {
+            y += height;
+            height = -height;
+        }
+        if (arcWidth < 0) arcWidth = -arcWidth;
+        if (arcHeight < 0) arcHeight = -arcHeight;
+        if (arcWidth > width) arcWidth = width;
+        if (arcHeight > height) arcHeight = height;
+
+        if (arcWidth < width) {
+            drawLine(x+arcWidth/2, y, x+width-arcWidth/2, y);
+            drawLine(x+arcWidth/2, y+height, x+width-arcWidth/2, y+height);
+        }
+        if (arcHeight < height) {
+            drawLine(x, y+arcHeight/2, x, y+height-arcHeight/2);
+            drawLine(x+width, y+arcHeight/2, x+width, y+height-arcHeight/2);
+        }
+        if (arcWidth !is 0 && arcHeight !is 0) {
+            drawArc(x, y, arcWidth, arcHeight, 90, 90);
+            drawArc(x+width-arcWidth, y, arcWidth, arcHeight, 0, 90);
+            drawArc(x+width-arcWidth, y+height-arcHeight, arcWidth, arcHeight, 0, -90);
+            drawArc(x, y+height-arcHeight, arcWidth, arcHeight, 180, 90);
+        }
+    } else {
+        OS.RoundRect(handle, x,y,x+width+1,y+height+1, arcWidth, arcHeight);
+    }
+}
+
+void drawRoundRectangleGdip (Gdip.Graphics gdipGraphics, Gdip.Pen pen, int x, int y, int width, int height, int arcWidth, int arcHeight) {
+    int nx = x;
+    int ny = y;
+    int nw = width;
+    int nh = height;
+    int naw = arcWidth;
+    int nah = arcHeight;
+
+    if (nw < 0) {
+        nw = 0 - nw;
+        nx = nx - nw;
+    }
+    if (nh < 0) {
+        nh = 0 - nh;
+        ny = ny - nh;
+    }
+    if (naw < 0)
+        naw = 0 - naw;
+    if (nah < 0)
+        nah = 0 - nah;
+
+    Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
+    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) SWT.error(SWT.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 {
+            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.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. The background of the rectangular area where
+ * the string is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y) {
+    drawString(string, x, y, false);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. No tab expansion or carriage return processing
+ * will be performed. If <code>isTransparent</code> is <code>true</code>,
+ * then the background of the rectangular area where the string is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
+ * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawString (String string, int x, int y, bool isTransparent) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT extension: allow null string
+    //if (string is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+//  TCHAR buffer = new TCHAR (getCodePage(), string, false);
+    wchar[] wstr = StrToWCHARs( string );
+    int length_ = wstr.length;
+    if (length_ is 0) return;
+    wchar* buffer = wstr.ptr;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        checkGC(FONT | FOREGROUND | (isTransparent ? 0 : BACKGROUND));
+        Gdip.PointF pt;
+        auto format = Gdip.StringFormat_Clone(Gdip.StringFormat_GenericTypographic());
+        int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces;
+        if ((data.style & SWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
+        Gdip.StringFormat_SetFormatFlags(format, formatFlags);
+        if (!isTransparent) {
+            Gdip.RectF bounds;
+            Gdip.Graphics_MeasureString(gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds);
+            Gdip.Graphics_FillRectangle(gdipGraphics, data.gdipBrush, x, y, Math.rndint(bounds.Width), Math.rndint(bounds.Height));
+        }
+        int gstate = 0;
+        auto brush = getFgBrush();
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            switch (Gdip.Brush_GetType(brush)) {
+                case Gdip.BrushTypeLinearGradient:
+                    Gdip.LinearGradientBrush_ScaleTransform(cast(Gdip.LinearGradientBrush)brush, -1, 1, Gdip.MatrixOrderPrepend);
+                    Gdip.LinearGradientBrush_TranslateTransform(cast(Gdip.LinearGradientBrush)brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                    break;
+                case Gdip.BrushTypeTextureFill:
+                    Gdip.TextureBrush_ScaleTransform(cast(Gdip.TextureBrush)brush, -1, 1, Gdip.MatrixOrderPrepend);
+                    Gdip.TextureBrush_TranslateTransform(cast(Gdip.TextureBrush)brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                    break;
+                default:
+            }
+            gstate = Gdip.Graphics_Save(gdipGraphics);
+            Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
+            Gdip.Graphics_TranslateTransform(gdipGraphics, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+        }
+        pt.X = x;
+        pt.Y = y;
+        Gdip.Graphics_DrawString(gdipGraphics, buffer, length_, data.gdipFont, pt, format, brush);
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            switch (Gdip.Brush_GetType(brush)) {
+                case Gdip.BrushTypeLinearGradient:
+                    Gdip.LinearGradientBrush_ResetTransform(cast(Gdip.LinearGradientBrush)brush);
+                    break;
+                case Gdip.BrushTypeTextureFill:
+                    Gdip.TextureBrush_ResetTransform(cast(Gdip.TextureBrush)brush);
+                    break;
+                default:
+            }
+            Gdip.Graphics_Restore(gdipGraphics, gstate);
+        }
+        Gdip.StringFormat_delete(format);
+        return;
+    }
+    int rop2 = 0;
+    static if (OS.IsWinCE) {
+        rop2 = OS.SetROP2(handle, OS.R2_COPYPEN);
+        OS.SetROP2(handle, rop2);
+    } else {
+        rop2 = OS.GetROP2(handle);
+    }
+    checkGC(FONT | FOREGROUND_TEXT | BACKGROUND_TEXT);
+    int oldBkMode = OS.SetBkMode(handle, isTransparent ? OS.TRANSPARENT : OS.OPAQUE);
+    RECT rect;
+    SIZE size;
+    bool sizeValid = false;
+    int flags = 0;
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        if (!isTransparent) {
+            sizeValid = true;
+            OS.GetTextExtentPoint32W(handle, buffer, length_, &size);
+            rect.left = x;
+            rect.right = x + size.cx;
+            rect.top = y;
+            rect.bottom = y + size.cy;
+            flags = OS.ETO_CLIPPED;
+        }
+        x--;
+    }
+    if (rop2 !is OS.R2_XORPEN) {
+        OS.ExtTextOutW(handle, x, y, flags, &rect, buffer, length_, null);
+    } else {
+        int foreground = OS.GetTextColor(handle);
+        if (isTransparent) {
+            if (!sizeValid) {
+                OS.GetTextExtentPoint32W(handle, buffer, length_, &size);
+            }
+            int width = size.cx, height = size.cy;
+            auto hBitmap = OS.CreateCompatibleBitmap(handle, width, height);
+            if (hBitmap is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            auto memDC = OS.CreateCompatibleDC(handle);
+            auto hOldBitmap = OS.SelectObject(memDC, hBitmap);
+            OS.PatBlt(memDC, 0, 0, width, height, OS.BLACKNESS);
+            OS.SetBkMode(memDC, OS.TRANSPARENT);
+            OS.SetTextColor(memDC, foreground);
+            OS.SelectObject(memDC, OS.GetCurrentObject(handle, OS.OBJ_FONT));
+            OS.ExtTextOutW(memDC, 0, 0, 0, null, buffer, length_, null);
+            OS.BitBlt(handle, x, y, width, height, memDC, 0, 0, OS.SRCINVERT);
+            OS.SelectObject(memDC, hOldBitmap);
+            OS.DeleteDC(memDC);
+            OS.DeleteObject(hBitmap);
+        } else {
+            auto background = OS.GetBkColor(handle);
+            OS.SetTextColor(handle, foreground ^ background);
+            OS.ExtTextOutW(handle, x, y, flags, &rect, buffer, length_, null);
+            OS.SetTextColor(handle, foreground);
+        }
+    }
+    OS.SetBkMode(handle, oldBkMode);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. The background of the rectangular area where
+ * the text is being drawn will be filled with the receiver's
+ * background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y) {
+    drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion and carriage return processing
+ * are performed. If <code>isTransparent</code> is <code>true</code>,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y, bool isTransparent) {
+    int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
+    if (isTransparent) flags |= SWT.DRAW_TRANSPARENT;
+    drawText(string, x, y, flags);
+}
+
+/**
+ * Draws the given string, using the receiver's current font and
+ * foreground color. Tab expansion, line delimiter and mnemonic
+ * processing are performed according to the specified flags. If
+ * <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
+ * then the background of the rectangular area where the text is being
+ * drawn will not be modified, otherwise it will be filled with the
+ * receiver's background color.
+ * <p>
+ * The parameter <code>flags</code> may be a combination of:
+ * <dl>
+ * <dt><b>DRAW_DELIMITER</b></dt>
+ * <dd>draw multiple lines</dd>
+ * <dt><b>DRAW_TAB</b></dt>
+ * <dd>expand tabs</dd>
+ * <dt><b>DRAW_MNEMONIC</b></dt>
+ * <dd>underline the mnemonic character</dd>
+ * <dt><b>DRAW_TRANSPARENT</b></dt>
+ * <dd>transparent background</dd>
+ * </dl>
+ * </p>
+ *
+ * @param string the string to be drawn
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param flags the flags specifying how to process the text
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void drawText (String string, int x, int y, int flags) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT extension: allow null string
+    //if (string is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (string.length is 0) return;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        checkGC(FONT | FOREGROUND | ((flags & SWT.DRAW_TRANSPARENT) !is 0 ? 0 : BACKGROUND));
+        wchar[] wstr = StrToWCHARs( string );
+        int length_ = wstr.length;
+        wchar* buffer = wstr.ptr;
+        Gdip.PointF pt;
+        auto format = Gdip.StringFormat_Clone(Gdip.StringFormat_GenericTypographic());
+        int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces;
+        if ((data.style & SWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
+        Gdip.StringFormat_SetFormatFlags(format, formatFlags);
+        float[] tabs = (flags & SWT.DRAW_TAB) !is 0 ? [ cast(float) measureSpace(data.gdipFont, format) * 8] : new float[1];
+        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr);
+        int hotkeyPrefix = (flags & SWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone;
+        if ((flags & SWT.DRAW_MNEMONIC) !is 0 && (data.uiState & OS.UISF_HIDEACCEL) !is 0) hotkeyPrefix = Gdip.HotkeyPrefixHide;
+        Gdip.StringFormat_SetHotkeyPrefix(format, hotkeyPrefix);
+        if ((flags & SWT.DRAW_TRANSPARENT) is 0) {
+            Gdip.RectF bounds;
+            Gdip.Graphics_MeasureString(gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds);
+            Gdip.Graphics_FillRectangle(gdipGraphics, data.gdipBrush, x, y, Math.rndint(bounds.Width), Math.rndint(bounds.Height));
+        }
+        int gstate = 0;
+        auto brush = getFgBrush();
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            switch (Gdip.Brush_GetType(brush)) {
+                case Gdip.BrushTypeLinearGradient:
+                    Gdip.LinearGradientBrush_ScaleTransform(cast(Gdip.LinearGradientBrush)brush, -1, 1, Gdip.MatrixOrderPrepend);
+                    Gdip.LinearGradientBrush_TranslateTransform(cast(Gdip.LinearGradientBrush)brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                    break;
+                case Gdip.BrushTypeTextureFill:
+                    Gdip.TextureBrush_ScaleTransform(cast(Gdip.TextureBrush)brush, -1, 1, Gdip.MatrixOrderPrepend);
+                    Gdip.TextureBrush_TranslateTransform(cast(Gdip.TextureBrush)brush, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+                    break;
+                default:
+            }
+            gstate = Gdip.Graphics_Save(gdipGraphics);
+            Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
+            Gdip.Graphics_TranslateTransform(gdipGraphics, - 2 * x, 0, Gdip.MatrixOrderPrepend);
+        }
+        pt.X = x;
+        pt.Y = y;
+        Gdip.Graphics_DrawString(gdipGraphics, buffer, length_, data.gdipFont, pt, format, brush);
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            switch (Gdip.Brush_GetType(brush)) {
+                case Gdip.BrushTypeLinearGradient:
+                    Gdip.LinearGradientBrush_ResetTransform(cast(Gdip.LinearGradientBrush)brush);
+                    break;
+                case Gdip.BrushTypeTextureFill:
+                    Gdip.TextureBrush_ResetTransform(cast(Gdip.TextureBrush)brush);
+                    break;
+                default:
+            }
+            Gdip.Graphics_Restore(gdipGraphics, gstate);
+        }
+        Gdip.StringFormat_delete(format);
+        return;
+    }
+    TCHAR[] wstr = StrToTCHARs( string );
+    TCHAR* buffer = wstr.ptr;
+    int length_ = wstr.length;
+    if (length_ is 0) return;
+    RECT rect;
+    /*
+    * Feature in Windows.  For some reason DrawText(), the maximum
+    * value for the bottom and right coordinates for the RECT that
+    * is used to position the text is different on between Windows
+    * versions.  If this value is larger than the maximum, nothing
+    * is drawn.  On Windows 98, the limit is 0x7FFF.  On Windows CE,
+    * NT, and 2000 it is 0x6FFFFFF. And on XP, it is 0x7FFFFFFF.
+    * The fix is to use the the smaller limit for Windows 98 and the
+    * larger limit on the other Windows platforms.
+    */
+    int limit = OS.IsWin95 ? 0x7FFF : 0x6FFFFFF;
+    OS.SetRect(&rect, x, y, limit, limit);
+    int uFormat = OS.DT_LEFT;
+    if ((flags & SWT.DRAW_DELIMITER) is 0) uFormat |= OS.DT_SINGLELINE;
+    if ((flags & SWT.DRAW_TAB) !is 0) uFormat |= OS.DT_EXPANDTABS;
+    if ((flags & SWT.DRAW_MNEMONIC) is 0) uFormat |= OS.DT_NOPREFIX;
+    if ((flags & SWT.DRAW_MNEMONIC) !is 0 && (data.uiState & OS.UISF_HIDEACCEL) !is 0) {
+        uFormat |= OS.DT_HIDEPREFIX;
+    }
+    int rop2 = 0;
+    static if (OS.IsWinCE) {
+        rop2 = OS.SetROP2(handle, OS.R2_COPYPEN);
+        OS.SetROP2(handle, rop2);
+    } else {
+        rop2 = OS.GetROP2(handle);
+    }
+    checkGC(FONT | FOREGROUND_TEXT | BACKGROUND_TEXT);
+    int oldBkMode = OS.SetBkMode(handle, (flags & SWT.DRAW_TRANSPARENT) !is 0 ? OS.TRANSPARENT : OS.OPAQUE);
+    if (rop2 !is OS.R2_XORPEN) {
+        OS.DrawText(handle, buffer, length_, &rect, uFormat);
+    } else {
+        int foreground = OS.GetTextColor(handle);
+        if ((flags & SWT.DRAW_TRANSPARENT) !is 0) {
+            OS.DrawText(handle, buffer, length_, &rect, uFormat | OS.DT_CALCRECT);
+            int width = rect.right - rect.left;
+            int height = rect.bottom - rect.top;
+            auto hBitmap = OS.CreateCompatibleBitmap(handle, width, height);
+            if (hBitmap is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            auto memDC = OS.CreateCompatibleDC(handle);
+            auto hOldBitmap = OS.SelectObject(memDC, hBitmap);
+            OS.PatBlt(memDC, 0, 0, width, height, OS.BLACKNESS);
+            OS.SetBkMode(memDC, OS.TRANSPARENT);
+            OS.SetTextColor(memDC, foreground);
+            OS.SelectObject(memDC, OS.GetCurrentObject(handle, OS.OBJ_FONT));
+            OS.SetRect(&rect, 0, 0, 0x7FFF, 0x7FFF);
+            OS.DrawText(memDC, buffer, length_, &rect, uFormat);
+            OS.BitBlt(handle, x, y, width, height, memDC, 0, 0, OS.SRCINVERT);
+            OS.SelectObject(memDC, hOldBitmap);
+            OS.DeleteDC(memDC);
+            OS.DeleteObject(hBitmap);
+        } else {
+            int background = OS.GetBkColor(handle);
+            OS.SetTextColor(handle, foreground ^ background);
+            OS.DrawText(handle, buffer, length_, &rect, uFormat);
+            OS.SetTextColor(handle, foreground);
+        }
+    }
+    OS.SetBkMode(handle, oldBkMode);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+public bool equals (Object object) {
+    return (object is this) || (null !is (cast(GC)object) && (handle is (cast(GC)object).handle));
+}
+
+/**
+ * Fills the interior of a circular or elliptical arc within
+ * the specified rectangular area, with the receiver's background
+ * color.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees, using the current color.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc to be filled
+ * @param y the y coordinate of the upper-left corner of the arc to be filled
+ * @param width the width of the arc to be filled
+ * @param height the height of the arc to be filled
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawArc
+ */
+public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FILL);
+    if (width < 0) {
+        x = x + width;
+        width = -width;
+    }
+    if (height < 0) {
+        y = y + height;
+        height = -height;
+    }
+    if (width is 0 || height is 0 || arcAngle is 0) return;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        if (width is height) {
+            Gdip.Graphics_FillPie(gdipGraphics, data.gdipBrush, x, y, width, height, -startAngle, -arcAngle);
+        } else {
+            int state = Gdip.Graphics_Save(gdipGraphics);
+            Gdip.Graphics_TranslateTransform(gdipGraphics, x, y, Gdip.MatrixOrderPrepend);
+            Gdip.Graphics_ScaleTransform(gdipGraphics, width, height, Gdip.MatrixOrderPrepend);
+            Gdip.Graphics_FillPie(gdipGraphics, data.gdipBrush, 0, 0, 1, 1, -startAngle, -arcAngle);
+            Gdip.Graphics_Restore(gdipGraphics, state);
+        }
+        return;
+    }
+
+    if ((data.style & SWT.MIRRORED) !is 0) x--;
+    /*
+    * Feature in WinCE.  The function Pie is not present in the
+    * WinCE SDK.  The fix is to emulate it by using Polygon.
+    */
+    static if (OS.IsWinCE) {
+        /* compute arc with a simple linear interpolation */
+        if (arcAngle < 0) {
+            startAngle += arcAngle;
+            arcAngle = -arcAngle;
+        }
+        bool drawSegments = true;
+        if (arcAngle >= 360) {
+            arcAngle = 360;
+            drawSegments = false;
+        }
+        int[] points = new int[(arcAngle + 1) * 2 + (drawSegments ? 4 : 0)];
+        int cteX = 2 * x + width;
+        int cteY = 2 * y + height;
+        int index = (drawSegments ? 2 : 0);
+        for (int i = 0; i <= arcAngle; i++) {
+            points[index++] = (Compatibility.cos(startAngle + i, width) + cteX) >> 1;
+            points[index++] = (cteY - Compatibility.sin(startAngle + i, height)) >> 1;
+        }
+        if (drawSegments) {
+            points[0] = points[points.length - 2] = cteX >> 1;
+            points[1] = points[points.length - 1] = cteY >> 1;
+        }
+        OS.Polygon(handle, cast(POINT*)points.ptr, points.length / 2);
+    } else {
+        int x1, y1, x2, y2,tmp;
+        bool isNegative;
+        if (arcAngle >= 360 || arcAngle <= -360) {
+            x1 = x2 = x + width;
+            y1 = y2 = y + height / 2;
+        } else {
+            isNegative = arcAngle < 0;
+
+            arcAngle = arcAngle + startAngle;
+            if (isNegative) {
+                // swap angles
+                tmp = startAngle;
+                startAngle = arcAngle;
+                arcAngle = tmp;
+            }
+            x1 = Compatibility.cos(startAngle, width) + x + width/2;
+            y1 = -1 * Compatibility.sin(startAngle, height) + y + height/2;
+
+            x2 = Compatibility.cos(arcAngle, width) + x + width/2;
+            y2 = -1 * Compatibility.sin(arcAngle, height) + y + height/2;
+        }
+        OS.Pie(handle, x, y, x + width + 1, y + height + 1, x1, y1, x2, y2);
+    }
+}
+
+/**
+ * Fills the interior of the specified rectangle with a gradient
+ * sweeping from left to right or top to bottom progressing
+ * from the receiver's foreground color to its background color.
+ *
+ * @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, may be negative
+ *        (inverts direction of gradient if horizontal)
+ * @param height the height of the rectangle to be filled, may be negative
+ *        (inverts direction of gradient if vertical)
+ * @param vertical if true sweeps from top to bottom, else
+ *        sweeps from left to right
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillGradientRectangle(int x, int y, int width, int height, bool vertical) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width is 0 || height is 0) return;
+
+    RGB backgroundRGB, foregroundRGB;
+    backgroundRGB = getBackground().getRGB();
+    foregroundRGB = getForeground().getRGB();
+
+    RGB fromRGB, toRGB;
+    fromRGB = foregroundRGB;
+    toRGB   = backgroundRGB;
+
+    bool swapColors = false;
+    if (width < 0) {
+        x += width; width = -width;
+        if (! vertical) swapColors = true;
+    }
+    if (height < 0) {
+        y += height; height = -height;
+        if (vertical) swapColors = true;
+    }
+    if (swapColors) {
+        fromRGB = backgroundRGB;
+        toRGB   = foregroundRGB;
+    }
+    if (fromRGB ==/*eq*/ toRGB) {
+        fillRectangle(x, y, width, height);
+        return;
+    }
+    if (data.gdipGraphics !is null) {
+        initGdip();
+        Gdip.PointF p1, p2;
+        p1.X = x;
+        p1.Y = y;
+        if (vertical) {
+            p2.X = p1.X;
+            p2.Y = p1.Y + height;
+        } else {
+            p2.X = p1.X + width;
+            p2.Y = p1.Y;
+        }
+        int rgb = ((fromRGB.red & 0xFF) << 16) | ((fromRGB.green & 0xFF) << 8) | (fromRGB.blue & 0xFF);
+        auto fromGpColor = Gdip.Color_new(data.alpha << 24 | rgb);
+        //if (fromGpColor is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        rgb = ((toRGB.red & 0xFF) << 16) | ((toRGB.green & 0xFF) << 8) | (toRGB.blue & 0xFF);
+        auto toGpColor = Gdip.Color_new(data.alpha << 24 | rgb);
+        //if (toGpColor is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        auto brush = Gdip.LinearGradientBrush_new(p1, p2, fromGpColor, toGpColor);
+        Gdip.Graphics_FillRectangle(data.gdipGraphics, cast(Gdip.Brush)brush, x, y, width, height);
+        Gdip.LinearGradientBrush_delete(brush);
+        Gdip.Color_delete(fromGpColor);
+        Gdip.Color_delete(toGpColor);
+        return;
+    }
+    /* Use GradientFill if supported, only on Windows 98, 2000 and newer. */
+    /*
+    * Bug in Windows: On Windows 2000 when the device is a printer,
+    * GradientFill swaps red and blue color components, causing the
+    * gradient to be printed in the wrong color. On Windows 98 when
+    * the device is a printer, GradientFill does not fill completely
+    * to the right edge of the rectangle. The fix is not to use
+    * GradientFill for printer devices.
+    */
+    int rop2 = 0;
+    static if (OS.IsWinCE) {
+        rop2 = OS.SetROP2(handle, OS.R2_COPYPEN);
+        OS.SetROP2(handle, rop2);
+    } else {
+        rop2 = OS.GetROP2(handle);
+    }
+    if (OS.IsWinNT && rop2 !is OS.R2_XORPEN && OS.GetDeviceCaps(handle, OS.TECHNOLOGY) !is OS.DT_RASPRINTER) {
+        final auto hHeap = OS.GetProcessHeap();
+        final auto pMesh = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, GRADIENT_RECT.sizeof + TRIVERTEX.sizeof * 2);
+        if (pMesh is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        auto pVertex = cast(TRIVERTEX*)( pMesh + GRADIENT_RECT.sizeof );
+
+        GRADIENT_RECT gradientRect;
+        gradientRect.UpperLeft = 0;
+        gradientRect.LowerRight = 1;
+        *cast(GRADIENT_RECT*)pMesh = gradientRect;
+
+        TRIVERTEX* trivertex = pVertex;
+        trivertex.x = x;
+        trivertex.y = y;
+        trivertex.Red = cast(short)((fromRGB.red << 8) | fromRGB.red);
+        trivertex.Green = cast(short)((fromRGB.green << 8) | fromRGB.green);
+        trivertex.Blue = cast(short)((fromRGB.blue << 8) | fromRGB.blue);
+        trivertex.Alpha = ushort.max;
+
+        trivertex = pVertex+1;
+        trivertex.x = x + width;
+        trivertex.y = y + height;
+        trivertex.Red = cast(short)((toRGB.red << 8) | toRGB.red);
+        trivertex.Green = cast(short)((toRGB.green << 8) | toRGB.green);
+        trivertex.Blue = cast(short)((toRGB.blue << 8) | toRGB.blue);
+        trivertex.Alpha = ushort.max;
+
+        bool success = cast(bool)OS.GradientFill(handle, pVertex, 2, pMesh, 1, vertical ? OS.GRADIENT_FILL_RECT_V : OS.GRADIENT_FILL_RECT_H);
+        OS.HeapFree(hHeap, 0, pMesh);
+        if (success) return;
+    }
+
+    final int depth = OS.GetDeviceCaps(handle, OS.BITSPIXEL);
+    final int bitResolution = (depth >= 24) ? 8 : (depth >= 15) ? 5 : 0;
+    ImageData.fillGradientRectangle(this, data.device,
+        x, y, width, height, vertical, fromRGB, toRGB,
+        bitResolution, bitResolution, bitResolution);
+}
+
+/**
+ * Fills the interior of an oval, within the specified
+ * rectangular area, with the receiver's background
+ * color.
+ *
+ * @param x the x coordinate of the upper left corner of the oval to be filled
+ * @param y the y coordinate of the upper left corner of the oval to be filled
+ * @param width the width of the oval to be filled
+ * @param height the height of the oval to be filled
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawOval
+ */
+public void fillOval (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FILL);
+    if (data.gdipGraphics !is null) {
+        Gdip.Graphics_FillEllipse(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) x--;
+    OS.Ellipse(handle, x, y, x + width + 1, y + height + 1);
+}
+
+/**
+ * Fills the path described by the parameter.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the path to fill
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ *
+ * @since 3.1
+ */
+public void fillPath (Path path) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (path is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (path.handle is null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    initGdip();
+    checkGC(FILL);
+    int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
+    Gdip.GraphicsPath_SetFillMode(path.handle, mode);
+    Gdip.Graphics_FillPath(data.gdipGraphics, data.gdipBrush, path.handle);
+}
+
+/**
+ * Fills the interior of the closed polygon which is defined by the
+ * specified array of integer coordinates, using the receiver's
+ * background color. The array contains alternating x and y values
+ * which are considered to represent points which are the vertices of
+ * the polygon. Lines are drawn between each consecutive pair, and
+ * between the first pair and last pair in the array.
+ *
+ * @param pointArray an array of alternating x and y values which are the vertices of the polygon
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawPolygon
+ */
+public void fillPolygon(int[] pointArray) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT externsion: allow null array
+    //if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    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.ptr, pointArray.length / 2, mode);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        for (int i = 0; i < pointArray.length; i+=2) {
+            pointArray[i]--;
+        }
+    }
+    OS.Polygon(handle, cast(POINT*)pointArray.ptr, pointArray.length / 2);
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        for (int i = 0; i < pointArray.length; i+=2) {
+            pointArray[i]++;
+        }
+    }
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * using the receiver's background color.
+ *
+ * @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 SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.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;
+    }
+    int rop2 = 0;
+    static if (OS.IsWinCE) {
+        rop2 = OS.SetROP2(handle, OS.R2_COPYPEN);
+        OS.SetROP2(handle, rop2);
+    } else {
+        rop2 = OS.GetROP2(handle);
+    }
+    int dwRop = rop2 is OS.R2_XORPEN ? OS.PATINVERT : OS.PATCOPY;
+    OS.PatBlt(handle, x, y, width, height, dwRop);
+}
+
+/**
+ * Fills the interior of the specified rectangle, using the receiver's
+ * background color.
+ *
+ * @param rect the rectangle to be filled
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRectangle(int, int, int, int)
+ */
+public void fillRectangle (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    fillRectangle (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Fills the interior of the round-cornered rectangle specified by
+ * the arguments, using the receiver's background color.
+ *
+ * @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
+ * @param arcWidth the width of the arc
+ * @param arcHeight the height of the arc
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #drawRoundRectangle
+ */
+public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FILL);
+    if (data.gdipGraphics !is null) {
+        fillRoundRectangleGdip(data.gdipGraphics, data.gdipBrush, x, y, width, height, arcWidth, arcHeight);
+        return;
+    }
+    if ((data.style & SWT.MIRRORED) !is 0) x--;
+    OS.RoundRect(handle, x,y,x+width+1,y+height+1,arcWidth, arcHeight);
+}
+
+void fillRoundRectangleGdip (Gdip.Graphics gdipGraphics, Gdip.Brush brush, int x, int y, int width, int height, int arcWidth, int arcHeight) {
+    int nx = x;
+    int ny = y;
+    int nw = width;
+    int nh = height;
+    int naw = arcWidth;
+    int nah = arcHeight;
+
+    if (nw < 0) {
+        nw = 0 - nw;
+        nx = nx - nw;
+    }
+    if (nh < 0) {
+        nh = 0 - nh;
+        ny = ny -nh;
+    }
+    if (naw < 0)
+        naw = 0 - naw;
+    if (nah < 0)
+        nah = 0 - nah;
+
+    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) SWT.error(SWT.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 {
+            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);
+    }
+}
+
+void flush () {
+    if (data.gdipGraphics !is null) {
+        Gdip.Graphics_Flush(data.gdipGraphics, 0);
+        /*
+        * Note Flush() does not flush the output to the
+        * underline HDC. This is done by calling GetHDC()
+        * followed by ReleaseHDC().
+        */
+        auto hdc = Gdip.Graphics_GetHDC(data.gdipGraphics);
+        Gdip.Graphics_ReleaseHDC(data.gdipGraphics, hdc);
+    }
+}
+
+/**
+ * Returns the <em>advance width</em> of the specified character in
+ * the font which is currently selected into the receiver.
+ * <p>
+ * The advance width is defined as the horizontal distance the cursor
+ * should move after printing the character in the selected font.
+ * </p>
+ *
+ * @param ch the character to measure
+ * @return the distance in the x direction to move past the character before painting the next
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getAdvanceWidth(char ch) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FONT);
+    static if (OS.IsWinCE) {
+        SIZE size;
+        OS.GetTextExtentPoint32W(handle, [ch], 1, &size);
+        return size.cx;
+    }
+    int tch = ch;
+    if (ch > 0x7F) {
+        char[1] str;
+        str[0] = ch;
+        TCHAR[] buffer = StrToTCHARs( str );
+        tch = buffer[0];
+    }
+    int width;
+    OS.GetCharWidth(handle, tch, tch, &width);
+    return width;
+}
+
+/**
+ * Returns <code>true</code> if receiver is using the operating system's
+ * advanced graphics subsystem.  Otherwise, <code>false</code> is returned
+ * to indicate that normal graphics are in use.
+ * <p>
+ * Advanced graphics may not be installed for the operating system.  In this
+ * case, <code>false</code> is always returned.  Some operating system have
+ * only one graphics subsystem.  If this subsystem supports advanced graphics,
+ * then <code>true</code> is always returned.  If any graphics operation such
+ * as alpha, antialias, patterns, interpolation, paths, clipping or transformation
+ * has caused the receiver to switch from regular to advanced graphics mode,
+ * <code>true</code> is returned.  If the receiver has been explicitly switched
+ * to advanced mode and this mode is supported, <code>true</code> is returned.
+ * </p>
+ *
+ * @return the advanced value
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public bool getAdvanced() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.gdipGraphics !is null;
+}
+
+/**
+ * Returns the receiver's alpha value. The alpha value
+ * is between 0 (transparent) and 255 (opaque).
+ *
+ * @return the alpha value
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getAlpha() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.alpha;
+}
+
+/**
+ * Returns the receiver's anti-aliasing setting value, which will be
+ * one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
+ * <code>SWT.ON</code>. Note that this controls anti-aliasing for all
+ * <em>non-text drawing</em> operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getTextAntialias
+ *
+ * @since 3.1
+ */
+public int getAntialias() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null) return SWT.DEFAULT;
+    int mode = Gdip.Graphics_GetSmoothingMode(data.gdipGraphics);
+    switch (mode) {
+        case Gdip.SmoothingModeDefault: return SWT.DEFAULT;
+        case Gdip.SmoothingModeHighSpeed:
+        case Gdip.SmoothingModeNone: return SWT.OFF;
+        case Gdip.SmoothingModeAntiAlias:
+        case Gdip.SmoothingModeAntiAlias8x8:
+        case Gdip.SmoothingModeHighQuality: return SWT.ON;
+        default:
+    }
+    return SWT.DEFAULT;
+}
+
+/**
+ * Returns the background color.
+ *
+ * @return the receiver's background color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getBackground() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return Color.win32_new(data.device, data.background);
+}
+
+/**
+ * Returns the background pattern. The default value is
+ * <code>null</code>.
+ *
+ * @return the receiver's background pattern
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public Pattern getBackgroundPattern() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.backgroundPattern;
+}
+
+/**
+ * Returns the width of the specified character in the font
+ * selected into the receiver.
+ * <p>
+ * The width is defined as the space taken up by the actual
+ * character, not including the leading and tailing whitespace
+ * or overhang.
+ * </p>
+ *
+ * @param ch the character to measure
+ * @return the width of the character
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getCharWidth(char ch) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FONT);
+
+    /* GetCharABCWidths only succeeds on truetype fonts */
+    static if (!OS.IsWinCE) {
+        int tch = ch;
+        if (ch > 0x7F) {
+            char[1] str;
+            str[0] = ch;
+            TCHAR[] buffer = StrToTCHARs( str );
+            tch = buffer[0];
+        }
+        ABC abc;
+        if (OS.GetCharABCWidths(handle, tch, tch, &abc)) {
+            return abc.abcA;
+        }
+    }
+
+    /* It wasn't a truetype font */
+    TEXTMETRIC lptm;
+    OS.GetTextMetrics(handle, &lptm);
+    SIZE size;
+    char[1] str;
+    str[0] = ch;
+    OS.GetTextExtentPoint32W(handle, StrToWCHARz( str ), 1, &size);
+    return size.cx - lptm.tmOverhang;
+}
+
+/**
+ * Returns the bounding rectangle of the receiver's clipping
+ * region. If no clipping region is set, the return value
+ * will be a rectangle which covers the entire bounds of the
+ * object the receiver is drawing on.
+ *
+ * @return the bounding rectangle of the clipping region
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getClipping() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        Gdip.Rect rect;
+        Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+        Gdip.Graphics_GetVisibleClipBounds(gdipGraphics, rect);
+        Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+        return new Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
+    }
+    RECT rect;
+    OS.GetClipBox(handle, &rect);
+    return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/**
+ * Sets the region managed by the argument to the current
+ * clipping region of the receiver.
+ *
+ * @param region the region to fill with the clipping region
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the region is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the region is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getClipping (Region region) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (region is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        auto rgn = Gdip.Region_new();
+        Gdip.Graphics_GetClip(data.gdipGraphics, rgn);
+        if (Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
+            Gdip.Rect rect;
+            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+            Gdip.Graphics_GetVisibleClipBounds(gdipGraphics, rect);
+            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+            OS.SetRectRgn(region.handle, rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
+        } else {
+            auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+            auto identity_ = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+            Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+            Gdip.Graphics_SetTransform(gdipGraphics, identity_);
+            auto hRgn = Gdip.Region_GetHRGN(rgn, data.gdipGraphics);
+            Gdip.Graphics_SetTransform(gdipGraphics, matrix);
+            Gdip.Matrix_delete(identity_);
+            Gdip.Matrix_delete(matrix);
+            OS.CombineRgn(region.handle, hRgn, null, OS.RGN_COPY);
+            OS.DeleteObject(hRgn);
+        }
+        Gdip.Region_delete(rgn);
+        return;
+    }
+    POINT pt;
+    static if (!OS.IsWinCE) OS.GetWindowOrgEx (handle, &pt);
+    int result = OS.GetClipRgn (handle, region.handle);
+    if (result !is 1) {
+        RECT rect;
+        OS.GetClipBox(handle, &rect);
+        OS.SetRectRgn(region.handle, rect.left, rect.top, rect.right, rect.bottom);
+    } else {
+        OS.OffsetRgn (region.handle, pt.x, pt.y);
+    }
+    static if (!OS.IsWinCE) {
+        auto metaRgn = OS.CreateRectRgn (0, 0, 0, 0);
+        if (OS.GetMetaRgn (handle, metaRgn) !is 0) {
+            OS.OffsetRgn (metaRgn, pt.x, pt.y);
+            OS.CombineRgn (region.handle, metaRgn, region.handle, OS.RGN_AND);
+        }
+        OS.DeleteObject(metaRgn);
+        auto hwnd = data.hwnd;
+        if (hwnd !is null && data.ps !is null) {
+            auto sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+            if (OS.GetRandomRgn (handle, sysRgn, OS.SYSRGN) is 1) {
+                if (OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+                    if ((OS.GetLayout(handle) & OS.LAYOUT_RTL) !is 0) {
+                        int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                        int [] lpRgnData = new int [nBytes / 4];
+                        OS.GetRegionData (sysRgn, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+                        auto newSysRgn = OS.ExtCreateRegion( cast(XFORM*) [-1, 0, 0, 1, 0, 0].ptr, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+                        OS.DeleteObject(sysRgn);
+                        sysRgn = newSysRgn;
+                    }
+                }
+                if (OS.IsWinNT) {
+                    OS.MapWindowPoints(null, hwnd, &pt, 1);
+                    OS.OffsetRgn(sysRgn, pt.x, pt.y);
+                }
+                OS.CombineRgn (region.handle, sysRgn, region.handle, OS.RGN_AND);
+            }
+            OS.DeleteObject(sysRgn);
+        }
+    }
+}
+
+int getCodePage () {
+    if (OS.IsUnicode) return OS.CP_ACP;
+    CHARSETINFO csi;
+    auto cs = OS.GetTextCharset(handle);
+    OS.TranslateCharsetInfo( cast(DWORD*)cs, &csi, OS.TCI_SRCCHARSET);
+    return csi.ciACP;
+}
+
+Gdip.Brush getFgBrush() {
+    return data.foregroundPattern !is null ? data.foregroundPattern.handle : cast(Gdip.Brush)data.gdipFgBrush;
+}
+
+/**
+ * Returns the receiver's fill rule, which will be one of
+ * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
+ *
+ * @return the receiver's fill rule
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getFillRule() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    static if (OS.IsWinCE) return SWT.FILL_EVEN_ODD;
+    return OS.GetPolyFillMode(handle) is OS.WINDING ? SWT.FILL_WINDING : SWT.FILL_EVEN_ODD;
+}
+
+/**
+ * Returns the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getFont () {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.font;
+}
+
+/**
+ * Returns a FontMetrics which contains information
+ * about the font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return font metrics for the receiver's font
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontMetrics getFontMetrics() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    checkGC(FONT);
+    TEXTMETRIC lptm;
+    OS.GetTextMetrics(handle, &lptm);
+    return FontMetrics.win32_new(&lptm);
+}
+
+/**
+ * Returns the receiver's foreground color.
+ *
+ * @return the color used for drawing foreground things
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getForeground() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return Color.win32_new(data.device, data.foreground);
+}
+
+/**
+ * Returns the foreground pattern. The default value is
+ * <code>null</code>.
+ *
+ * @return the receiver's foreground pattern
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Pattern
+ *
+ * @since 3.1
+ */
+public Pattern getForegroundPattern() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.foregroundPattern;
+}
+
+/**
+ * Returns the GCData.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @return the receiver's GCData
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see GCData
+ *
+ * @since 3.2
+ */
+public GCData getGCData() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data;
+}
+
+/**
+ * Returns the receiver's interpolation setting, which will be one of
+ * <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>,
+ * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
+ *
+ * @return the receiver's interpolation setting
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getInterpolation() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null) return SWT.DEFAULT;
+    int mode = Gdip.Graphics_GetInterpolationMode(data.gdipGraphics);
+    switch (mode) {
+        case Gdip.InterpolationModeDefault: return SWT.DEFAULT;
+        case Gdip.InterpolationModeNearestNeighbor: return SWT.NONE;
+        case Gdip.InterpolationModeBilinear:
+        case Gdip.InterpolationModeLowQuality: return SWT.LOW;
+        case Gdip.InterpolationModeBicubic:
+        case Gdip.InterpolationModeHighQualityBilinear:
+        case Gdip.InterpolationModeHighQualityBicubic:
+        case Gdip.InterpolationModeHighQuality: return SWT.HIGH;
+        default:
+    }
+    return SWT.DEFAULT;
+}
+
+/**
+ * Returns the receiver's line attributes.
+ *
+ * @return the line attributes used for drawing lines
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public LineAttributes getLineAttributes() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    float[] dashes = null;
+    if (data.lineDashes !is null) {
+        dashes = new float[data.lineDashes.length];
+        System.arraycopy(data.lineDashes, 0, dashes, 0, dashes.length);
+    }
+    return new LineAttributes(data.lineWidth, data.lineCap, data.lineJoin, data.lineStyle, dashes, data.lineDashesOffset, data.lineMiterLimit);
+}
+
+/**
+ * Returns the receiver's line cap style, which will be one
+ * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
+ * or <code>SWT.CAP_SQUARE</code>.
+ *
+ * @return the cap style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getLineCap() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.lineCap;
+}
+
+/**
+ * Returns the receiver's line dash style. The default value is
+ * <code>null</code>.
+ *
+ * @return the line dash style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int[] getLineDash() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.lineDashes is null) return null;
+    int[] lineDashes = new int[data.lineDashes.length];
+    for (int i = 0; i < lineDashes.length; i++) {
+        lineDashes[i] = cast(int)data.lineDashes[i];
+    }
+    return lineDashes;
+}
+
+/**
+ * Returns the receiver's line join style, which will be one
+ * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
+ * or <code>SWT.JOIN_BEVEL</code>.
+ *
+ * @return the join style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public int getLineJoin() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.lineJoin;
+}
+
+/**
+ * Returns the receiver's line style, which will be one
+ * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
+ * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
+ * <code>SWT.LINE_DASHDOTDOT</code>.
+ *
+ * @return the style used for drawing lines
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineStyle() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.lineStyle;
+}
+
+/**
+ * Returns the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * <code>drawLine</code>, <code>drawRectangle</code>,
+ * <code>drawPolyline</code>, and so forth.
+ *
+ * @return the receiver's line width
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineWidth() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return cast(int)data.lineWidth;
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.1.2
+ */
+public int getStyle () {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return data.style;
+}
+
+/**
+ * Returns the receiver's text drawing anti-aliasing setting value,
+ * which will be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
+ * <code>SWT.ON</code>. Note that this controls anti-aliasing
+ * <em>only</em> for text drawing operations.
+ *
+ * @return the anti-aliasing setting
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getAntialias
+ *
+ * @since 3.1
+ */
+public int getTextAntialias() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null) return SWT.DEFAULT;
+    int mode = Gdip.Graphics_GetTextRenderingHint(data.gdipGraphics);
+    switch (mode) {
+        case Gdip.TextRenderingHintSystemDefault: return SWT.DEFAULT;
+        case Gdip.TextRenderingHintSingleBitPerPixel:
+        case Gdip.TextRenderingHintSingleBitPerPixelGridFit: return SWT.OFF;
+        case Gdip.TextRenderingHintAntiAlias:
+        case Gdip.TextRenderingHintAntiAliasGridFit:
+        case Gdip.TextRenderingHintClearTypeGridFit: return SWT.ON;
+        default:
+    }
+    return SWT.DEFAULT;
+}
+
+/**
+ * Sets the parameter to the transform that is currently being
+ * used by the receiver.
+ *
+ * @param transform the destination to copy the transform into
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Transform
+ *
+ * @since 3.1
+ */
+public void getTransform(Transform transform) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (transform is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        Gdip.Graphics_GetTransform(gdipGraphics, transform.handle);
+        auto identity_ = identity();
+        Gdip.Matrix_Invert(identity_);
+        Gdip.Matrix_Multiply(transform.handle, identity_, Gdip.MatrixOrderAppend);
+        Gdip.Matrix_delete(identity_);
+    } else {
+        transform.setElements(1, 0, 0, 1, 0, 0);
+    }
+}
+
+/**
+ * Returns <code>true</code> if this GC is drawing in the mode
+ * where the resulting color in the destination is the
+ * <em>exclusive or</em> of the color values in the source
+ * and the destination, and <code>false</code> if it is
+ * drawing in the mode where the destination color is being
+ * replaced with the source color value.
+ *
+ * @return <code>true</code> true if the receiver is in XOR mode, and false otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool getXORMode() {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    int rop2 = 0;
+    static if (OS.IsWinCE) {
+        rop2 = OS.SetROP2 (handle, OS.R2_COPYPEN);
+        OS.SetROP2 (handle, rop2);
+    } else {
+        rop2 = OS.GetROP2(handle);
+    }
+    return rop2 is OS.R2_XORPEN;
+}
+
+void initGdip() {
+    data.device.checkGDIP();
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) return;
+    /*
+    * Feature in GDI+. The GDI+ clipping set with Graphics->SetClip()
+    * is always intersected with the GDI clipping at the time the
+    * GDI+ graphics is created.  This means that the clipping
+    * cannot be reset.  The fix is to clear the clipping before
+    * the GDI+ graphics is created and reset it afterwards.
+    */
+    auto hRgn = OS.CreateRectRgn(0, 0, 0, 0);
+    auto result = OS.GetClipRgn(handle, hRgn);
+    static if (!OS.IsWinCE) {
+        POINT pt;
+        OS.GetWindowOrgEx (handle, &pt);
+        OS.OffsetRgn (hRgn, pt.x, pt.y);
+    }
+    OS.SelectClipRgn(handle, null);
+
+    /*
+    * Bug in GDI+.  GDI+ does not work when the HDC layout is RTL.  There
+    * are many issues like pixel corruption, but the most visible problem
+    * is that it does not have an effect when drawing to an bitmap.  The
+    * fix is to clear the bit before creating the GDI+ graphics and install
+    * a mirroring matrix ourselves.
+    */
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        OS.SetLayout(handle, OS.GetLayout(handle) & ~OS.LAYOUT_RTL);
+    }
+
+    gdipGraphics = data.gdipGraphics = Gdip.Graphics_new(handle);
+    if (gdipGraphics is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    Gdip.Graphics_SetPageUnit(gdipGraphics, Gdip.UnitPixel);
+    Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        auto matrix = identity();
+        Gdip.Graphics_SetTransform(gdipGraphics, matrix);
+        Gdip.Matrix_delete(matrix);
+    }
+    if (result is 1) setClipping(hRgn);
+    OS.DeleteObject(hRgn);
+    data.state = 0;
+    if (data.hPen !is null) {
+        OS.SelectObject(handle, OS.GetStockObject(OS.NULL_PEN));
+        OS.DeleteObject(data.hPen);
+        data.hPen = null;
+    }
+    if (data.hBrush !is null) {
+        OS.SelectObject(handle, OS.GetStockObject(OS.NULL_BRUSH));
+        OS.DeleteObject(data.hBrush);
+        data.hBrush = null;
+    }
+}
+
+Gdip.Matrix identity() {
+    if ((data.style & SWT.MIRRORED) !is 0) {
+        int width = 0;
+        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 {
+                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);
+        return Gdip.Matrix_new(-1, 0, 0, 1, width + 2 * pt.x, 0);
+    }
+    return Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+}
+
+void init_(Drawable drawable, GCData data, HDC hDC) {
+    auto foreground = data.foreground;
+    if (foreground !is -1) {
+        data.state &= ~(FOREGROUND | FOREGROUND_TEXT | PEN);
+    } else {
+        data.foreground = OS.GetTextColor(hDC);
+    }
+    auto background = data.background;
+    if (background !is -1) {
+        data.state &= ~(BACKGROUND | BACKGROUND_TEXT | BRUSH);
+    } else {
+        data.background = OS.GetBkColor(hDC);
+    }
+    data.state &= ~(NULL_BRUSH | NULL_PEN);
+    Font font = data.font;
+    if (font !is null) {
+        data.state &= ~FONT;
+    } else {
+        data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT));
+    }
+    auto hPalette = data.device.hPalette;
+    if (hPalette !is null) {
+        OS.SelectPalette(hDC, hPalette, true);
+        OS.RealizePalette(hDC);
+    }
+    Image image = data.image;
+    if (image !is null) {
+        data.hNullBitmap = OS.SelectObject(hDC, image.handle);
+        image.memGC = this;
+    }
+    auto layout = data.layout;
+    if (layout !is -1) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+            int flags = OS.GetLayout(hDC);
+            if ((flags & OS.LAYOUT_RTL) !is (layout & OS.LAYOUT_RTL)) {
+                flags &= ~OS.LAYOUT_RTL;
+                OS.SetLayout(hDC, flags | layout);
+            }
+            if ((data.style & SWT.RIGHT_TO_LEFT) !is 0) data.style |= SWT.MIRRORED;
+        }
+    }
+    this.drawable = drawable;
+    this.data = data;
+    handle = hDC;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #equals
+ */
+public override hash_t toHash () {
+    return cast(hash_t)handle;
+}
+
+/**
+ * Returns <code>true</code> if the receiver has a clipping
+ * region set into it, and <code>false</code> otherwise.
+ * If this method returns false, the receiver will draw on all
+ * available space in the destination. If it returns true,
+ * it will draw only in the area that is covered by the region
+ * that can be accessed with <code>getClipping(region)</code>.
+ *
+ * @return <code>true</code> if the GC has a clipping region, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool isClipped() {
+    if (handle is null) SWT.error(SWT.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);
+    int result = OS.GetClipRgn(handle, region);
+    OS.DeleteObject(region);
+    return result > 0;
+}
+
+/**
+ * Returns <code>true</code> if the GC has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the GC.
+ * When a GC has been disposed, it is an error to
+ * invoke any other method using the GC.
+ *
+ * @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+float measureSpace(Gdip.Font font, Gdip.StringFormat format) {
+    Gdip.PointF pt;
+    Gdip.RectF bounds;
+    Gdip.Graphics_MeasureString(data.gdipGraphics, (" "w).ptr, 1, font, pt, format, bounds);
+    return bounds.Width;
+}
+
+/**
+ * Sets the receiver to always use the operating system's advanced graphics
+ * subsystem for all graphics operations if the argument is <code>true</code>.
+ * If the argument is <code>false</code>, the advanced graphics subsystem is
+ * no longer used, advanced graphics state is cleared and the normal graphics
+ * subsystem is used from now on.
+ * <p>
+ * Normally, the advanced graphics subsystem is invoked automatically when
+ * any one of the alpha, antialias, patterns, interpolation, paths, clipping
+ * or transformation operations in the receiver is requested.  When the receiver
+ * is switched into advanced mode, the advanced graphics subsystem performs both
+ * advanced and normal graphics operations.  Because the two subsystems are
+ * different, their output may differ.  Switching to advanced graphics before
+ * any graphics operations are performed ensures that the output is consistent.
+ * </p><p>
+ * Advanced graphics may not be installed for the operating system.  In this
+ * case, this operation does nothing.  Some operating system have only one
+ * graphics subsystem, so switching from normal to advanced graphics does
+ * nothing.  However, switching from advanced to normal graphics will always
+ * clear the advanced graphics state, even for operating systems that have
+ * only one graphics subsystem.
+ * </p>
+ *
+ * @param advanced the new advanced graphics state
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAlpha
+ * @see #setAntialias
+ * @see #setBackgroundPattern
+ * @see #setClipping(Path)
+ * @see #setForegroundPattern
+ * @see #setLineAttributes
+ * @see #setInterpolation
+ * @see #setTextAntialias
+ * @see #setTransform
+ * @see #getAdvanced
+ *
+ * @since 3.1
+ */
+public void setAdvanced(bool advanced) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (advanced && data.gdipGraphics !is null) return;
+    if (advanced) {
+        try {
+            initGdip();
+        } catch (SWTException e) {}
+    } else {
+        disposeGdip();
+        data.alpha = 0xFF;
+        data.backgroundPattern = data.foregroundPattern = null;
+        data.state = 0;
+        setClipping( cast(HRGN) null);
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            OS.SetLayout(handle, OS.GetLayout(handle) | OS.LAYOUT_RTL);
+        }
+    }
+}
+
+/**
+ * Sets the receiver's anti-aliasing value to the parameter,
+ * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
+ * or <code>SWT.ON</code>. Note that this controls anti-aliasing for all
+ * <em>non-text drawing</em> operations.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
+ *                                 <code>SWT.OFF</code> or <code>SWT.ON</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ * @see #setTextAntialias
+ *
+ * @since 3.1
+ */
+public void setAntialias(int antialias) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null && antialias is SWT.DEFAULT) return;
+    int mode = 0;
+    switch (antialias) {
+        case SWT.DEFAULT:
+            mode = Gdip.SmoothingModeDefault;
+            break;
+        case SWT.OFF:
+            mode = Gdip.SmoothingModeNone;
+            break;
+        case SWT.ON:
+            mode = Gdip.SmoothingModeAntiAlias;
+            break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    initGdip();
+    Gdip.Graphics_SetSmoothingMode(data.gdipGraphics, mode);
+}
+
+/**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param alpha the alpha value
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setAlpha(int alpha) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null && (alpha & 0xFF) is 0xFF) return;
+    initGdip();
+    data.alpha = alpha & 0xFF;
+    data.state &= ~(BACKGROUND | FOREGROUND);
+}
+
+/**
+ * Sets the background color. The background color is used
+ * for fill operations and as the background color when text
+ * is drawn.
+ *
+ * @param color the new background color for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setBackground (Color color) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (color is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (data.backgroundPattern is null && data.background is color.handle) return;
+    data.backgroundPattern = null;
+    data.background = color.handle;
+    data.state &= ~(BACKGROUND | BACKGROUND_TEXT);
+}
+
+/**
+ * Sets the background pattern. The default value is <code>null</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param pattern the new background pattern
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Pattern
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setBackgroundPattern (Pattern pattern) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pattern !is null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (data.gdipGraphics is null && pattern is null) return;
+    initGdip();
+    if (data.backgroundPattern is pattern) return;
+    data.backgroundPattern = pattern;
+    data.state &= ~BACKGROUND;
+}
+
+void setClipping(HRGN clipRgn) {
+    auto hRgn = clipRgn;
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        if (hRgn !is null) {
+            auto region = Gdip.Region_new(hRgn);
+            Gdip.Graphics_SetClip(gdipGraphics, region, Gdip.CombineModeReplace);
+            Gdip.Region_delete(region);
+        } else {
+            Gdip.Graphics_ResetClip(gdipGraphics);
+        }
+    } else {
+        POINT pt;
+        if (hRgn !is null && !OS.IsWinCE) {
+            OS.GetWindowOrgEx(handle, &pt);
+            OS.OffsetRgn(hRgn, -pt.x, -pt.y);
+        }
+        OS.SelectClipRgn(handle, hRgn);
+        if (hRgn !is null && !OS.IsWinCE) {
+            OS.OffsetRgn(hRgn, pt.x, pt.y);
+        }
+    }
+    if (hRgn !is null && hRgn !is clipRgn) {
+        OS.DeleteObject(hRgn);
+    }
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the arguments.
+ *
+ * @param x the x coordinate of the clipping rectangle
+ * @param y the y coordinate of the clipping rectangle
+ * @param width the width of the clipping rectangle
+ * @param height the height of the clipping rectangle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (int x, int y, int width, int height) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    auto hRgn = OS.CreateRectRgn(x, y, x + width, y + height);
+    setClipping(hRgn);
+    OS.DeleteObject(hRgn);
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the path specified
+ * by the argument.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param path the clipping path.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Path
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setClipping (Path path) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (path !is null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    setClipping(cast(HRGN)null);
+    if (path !is null) {
+        initGdip();
+        int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
+        Gdip.GraphicsPath_SetFillMode(path.handle, mode);
+        Gdip.Graphics_SetClipPath(data.gdipGraphics, path.handle);
+    }
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the rectangular area specified
+ * by the argument.  Specifying <code>null</code> for the
+ * rectangle reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param rect the clipping rectangle or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (Rectangle rect) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (rect is null) {
+        setClipping(cast(HRGN)null);
+    } else {
+        setClipping(rect.x, rect.y, rect.width, rect.height);
+    }
+}
+
+/**
+ * Sets the area of the receiver which can be changed
+ * by drawing operations to the region specified
+ * by the argument.  Specifying <code>null</code> for the
+ * region reverts the receiver's clipping area to its
+ * original value.
+ *
+ * @param region the clipping region or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setClipping (Region region) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (region !is null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    setClipping(region !is null ? region.handle : cast(HRGN)null);
+}
+
+/**
+ * Sets the receiver's fill rule to the parameter, which must be one of
+ * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
+ *
+ * @param rule the new fill rule
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.FILL_EVEN_ODD</code>
+ *                                 or <code>SWT.FILL_WINDING</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setFillRule(int rule) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    static if (OS.IsWinCE) return;
+    int mode = OS.ALTERNATE;
+    switch (rule) {
+        case SWT.FILL_WINDING: mode = OS.WINDING; break;
+        case SWT.FILL_EVEN_ODD: mode = OS.ALTERNATE; break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    OS.SetPolyFillMode(handle, mode);
+}
+
+/**
+ * Sets the font which will be used by the receiver
+ * to draw and measure text to the argument. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setFont (Font font) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (font !is null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    data.font = font !is null ? font : data.device.systemFont;
+    data.state &= ~FONT;
+}
+
+/**
+ * Sets the foreground color. The foreground color is used
+ * for drawing operations including when text is drawn.
+ *
+ * @param color the new foreground color for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setForeground (Color color) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (color is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (data.foregroundPattern is null && color.handle is data.foreground) return;
+    data.foregroundPattern = null;
+    data.foreground = color.handle;
+    data.state &= ~(FOREGROUND | FOREGROUND_TEXT);
+}
+
+/**
+ * Sets the foreground pattern. The default value is <code>null</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param pattern the new foreground pattern
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Pattern
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setForegroundPattern (Pattern pattern) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pattern !is null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (data.gdipGraphics is null && pattern is null) return;
+    initGdip();
+    if (data.foregroundPattern is pattern) return;
+    data.foregroundPattern = pattern;
+    data.state &= ~FOREGROUND;
+}
+
+/**
+ * Sets the receiver's interpolation setting to the parameter, which
+ * must be one of <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>,
+ * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param interpolation the new interpolation setting
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.DEFAULT</code>,
+ *                                 <code>SWT.NONE</code>, <code>SWT.LOW</code> or <code>SWT.HIGH</code>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setInterpolation(int interpolation) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null && interpolation is SWT.DEFAULT) return;
+    int mode = 0;
+    switch (interpolation) {
+        case SWT.DEFAULT: mode = Gdip.InterpolationModeDefault; break;
+        case SWT.NONE: mode = Gdip.InterpolationModeNearestNeighbor; break;
+        case SWT.LOW: mode = Gdip.InterpolationModeLowQuality; break;
+        case SWT.HIGH: mode = Gdip.InterpolationModeHighQuality; break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    initGdip();
+    Gdip.Graphics_SetInterpolationMode(data.gdipGraphics, mode);
+}
+
+/**
+ * Sets the receiver's line attributes.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param attributes the line attributes
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the attributes is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if any of the line attributes is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see LineAttributes
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.3
+ */
+public void setLineAttributes(LineAttributes attributes) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (attributes is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    int mask = 0;
+    float lineWidth = attributes.width;
+    if (lineWidth !is data.lineWidth) {
+        mask |= LINE_WIDTH | DRAW_OFFSET;
+    }
+    int lineStyle = attributes.style;
+    if (lineStyle !is data.lineStyle) {
+        mask |= LINE_STYLE;
+        switch (lineStyle) {
+            case SWT.LINE_SOLID:
+            case SWT.LINE_DASH:
+            case SWT.LINE_DOT:
+            case SWT.LINE_DASHDOT:
+            case SWT.LINE_DASHDOTDOT:
+                break;
+            case SWT.LINE_CUSTOM:
+                if (attributes.dash is null) lineStyle = SWT.LINE_SOLID;
+                break;
+            default:
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+    int join = attributes.join;
+    if (join !is data.lineJoin) {
+        mask |= LINE_JOIN;
+        switch (join) {
+            case SWT.CAP_ROUND:
+            case SWT.CAP_FLAT:
+            case SWT.CAP_SQUARE:
+                break;
+            default:
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+    int cap = attributes.cap;
+    if (cap !is data.lineCap) {
+        mask |= LINE_CAP;
+        switch (cap) {
+            case SWT.JOIN_MITER:
+            case SWT.JOIN_ROUND:
+            case SWT.JOIN_BEVEL:
+                break;
+            default:
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+    float[] dashes = attributes.dash;
+    float[] lineDashes = data.lineDashes;
+    if (dashes !is null && dashes.length > 0) {
+        bool changed = lineDashes is null || lineDashes.length !is dashes.length;
+        for (int i = 0; i < dashes.length; i++) {
+            float dash = dashes[i];
+            if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            if (!changed && lineDashes[i] !is dash) changed = true;
+        }
+        if (changed) {
+            float[] newDashes = new float[dashes.length];
+            System.arraycopy(dashes, 0, newDashes, 0, dashes.length);
+            dashes = newDashes;
+            mask |= LINE_STYLE;
+        } else {
+            dashes = lineDashes;
+        }
+    } else {
+        if (lineDashes !is null && lineDashes.length > 0) {
+            mask |= LINE_STYLE;
+        } else {
+            dashes = lineDashes;
+        }
+    }
+    float dashOffset = attributes.dashOffset;
+    if (dashOffset !is data.lineDashesOffset) {
+        mask |= LINE_STYLE;
+    }
+    float miterLimit = attributes.miterLimit;
+    if (miterLimit !is data.lineMiterLimit) {
+        mask |= LINE_MITERLIMIT;
+    }
+    initGdip();
+    if (mask is 0) return;
+    data.lineWidth = lineWidth;
+    data.lineStyle = lineStyle;
+    data.lineCap = cap;
+    data.lineJoin = join;
+    data.lineDashes = dashes;
+    data.lineDashesOffset = dashOffset;
+    data.lineMiterLimit = miterLimit;
+    data.state &= ~mask;
+}
+
+/**
+ * Sets the receiver's line cap style to the argument, which must be one
+ * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
+ * or <code>SWT.CAP_SQUARE</code>.
+ *
+ * @param cap the cap style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineCap(int cap) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.lineCap is cap) return;
+    switch (cap) {
+        case SWT.CAP_ROUND:
+        case SWT.CAP_FLAT:
+        case SWT.CAP_SQUARE:
+            break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    data.lineCap = cap;
+    data.state &= ~LINE_CAP;
+}
+
+/**
+ * Sets the receiver's line dash style to the argument. The default
+ * value is <code>null</code>. If the argument is not <code>null</code>,
+ * the receiver's line style is set to <code>SWT.LINE_CUSTOM</code>, otherwise
+ * it is set to <code>SWT.LINE_SOLID</code>.
+ *
+ * @param dashes the dash style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if any of the values in the array is less than or equal 0</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineDash(int[] dashes) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    float[] lineDashes = data.lineDashes;
+    if (dashes !is null && dashes.length > 0) {
+        bool changed = data.lineStyle !is SWT.LINE_CUSTOM || lineDashes is null || lineDashes.length !is dashes.length;
+        for (int i = 0; i < dashes.length; i++) {
+            int dash = dashes[i];
+            if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+            if (!changed && lineDashes[i] !is dash) changed = true;
+        }
+        if (!changed) return;
+        data.lineDashes = new float[dashes.length];
+        for (int i = 0; i < dashes.length; i++) {
+            data.lineDashes[i] = dashes[i];
+        }
+        data.lineStyle = SWT.LINE_CUSTOM;
+    } else {
+        if (data.lineStyle is SWT.LINE_SOLID && (lineDashes is null || lineDashes.length is 0)) return;
+        data.lineDashes = null;
+        data.lineStyle = SWT.LINE_SOLID;
+    }
+    data.state &= ~LINE_STYLE;
+}
+
+/**
+ * Sets the receiver's line join style to the argument, which must be one
+ * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
+ * or <code>SWT.JOIN_BEVEL</code>.
+ *
+ * @param join the join style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void setLineJoin(int join) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.lineJoin is join) return;
+    switch (join) {
+        case SWT.JOIN_MITER:
+        case SWT.JOIN_ROUND:
+        case SWT.JOIN_BEVEL:
+            break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    data.lineJoin = join;
+    data.state &= ~LINE_JOIN;
+}
+
+/**
+ * Sets the receiver's line style to the argument, which must be one
+ * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
+ * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
+ * <code>SWT.LINE_DASHDOTDOT</code>.
+ *
+ * @param lineStyle the style to be used for drawing lines
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setLineStyle(int lineStyle) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.lineStyle is lineStyle) return;
+    switch (lineStyle) {
+        case SWT.LINE_SOLID:
+        case SWT.LINE_DASH:
+        case SWT.LINE_DOT:
+        case SWT.LINE_DASHDOT:
+        case SWT.LINE_DASHDOTDOT:
+            break;
+        case SWT.LINE_CUSTOM:
+            if (data.lineDashes is null) lineStyle = SWT.LINE_SOLID;
+            break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    data.lineStyle = lineStyle;
+    data.state &= ~LINE_STYLE;
+}
+
+/**
+ * Sets the width that will be used when drawing lines
+ * for all of the figure drawing operations (that is,
+ * <code>drawLine</code>, <code>drawRectangle</code>,
+ * <code>drawPolyline</code>, and so forth.
+ * <p>
+ * Note that line width of zero is used as a hint to
+ * indicate that the fastest possible line drawing
+ * algorithms should be used. This means that the
+ * output may be different from line width one.
+ * </p>
+ *
+ * @param lineWidth the width of a line
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setLineWidth(int lineWidth) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.lineWidth is lineWidth) return;
+    data.lineWidth = lineWidth;
+    data.state &= ~(LINE_WIDTH | DRAW_OFFSET);
+}
+
+/**
+ * If the argument is <code>true</code>, puts the receiver
+ * in a drawing mode where the resulting color in the destination
+ * is the <em>exclusive or</em> of the color values in the source
+ * and the destination, and if the argument is <code>false</code>,
+ * puts the receiver in a drawing mode where the destination color
+ * is replaced with the source color value.
+ * <p>
+ * Note that this mode in fundamentally unsupportable on certain
+ * platforms, notably Carbon (Mac OS X). Clients that want their
+ * code to run on all platforms need to avoid this method.
+ * </p>
+ *
+ * @param xor if <code>true</code>, then <em>xor</em> mode is used, otherwise <em>source copy</em> mode is used
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @deprecated this functionality is not supported on some platforms
+ */
+public void setXORMode(bool xor) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    OS.SetROP2(handle, xor ? OS.R2_XORPEN : OS.R2_COPYPEN);
+}
+
+/**
+ * Sets the receiver's text anti-aliasing value to the parameter,
+ * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
+ * or <code>SWT.ON</code>. Note that this controls anti-aliasing only
+ * for all <em>text drawing</em> operations.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param antialias the anti-aliasing setting
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
+ *                                 <code>SWT.OFF</code> or <code>SWT.ON</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see #getAdvanced
+ * @see #setAdvanced
+ * @see #setAntialias
+ *
+ * @since 3.1
+ */
+public void setTextAntialias(int antialias) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (data.gdipGraphics is null && antialias is SWT.DEFAULT) return;
+    int textMode = 0;
+    switch (antialias) {
+        case SWT.DEFAULT:
+            textMode = Gdip.TextRenderingHintSystemDefault;
+            break;
+        case SWT.OFF:
+            textMode = Gdip.TextRenderingHintSingleBitPerPixelGridFit;
+            break;
+        case SWT.ON:
+            int type;
+            OS.SystemParametersInfo(OS.SPI_GETFONTSMOOTHINGTYPE, 0, &type, 0);
+            if (type is OS.FE_FONTSMOOTHINGCLEARTYPE) {
+                textMode = Gdip.TextRenderingHintClearTypeGridFit;
+            } else {
+                textMode = Gdip.TextRenderingHintAntiAliasGridFit;
+            }
+            break;
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    initGdip();
+    Gdip.Graphics_SetTextRenderingHint(data.gdipGraphics, textMode);
+}
+
+/**
+ * Sets the transform that is currently being used by the receiver. If
+ * the argument is <code>null</code>, the current transform is set to
+ * the identity transform.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param transform the transform to set
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ *
+ * @see Transform
+ * @see #getAdvanced
+ * @see #setAdvanced
+ *
+ * @since 3.1
+ */
+public void setTransform(Transform transform) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (transform !is null && transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (data.gdipGraphics is null && transform is null) return;
+    initGdip();
+    auto identity_ = identity();
+    if (transform !is null) {
+         Gdip.Matrix_Multiply(identity_, transform.handle, Gdip.MatrixOrderPrepend);
+    }
+    Gdip.Graphics_SetTransform(data.gdipGraphics, identity_);
+    Gdip.Matrix_delete(identity_);
+    data.state &= ~DRAW_OFFSET;
+}
+
+/**
+ * Returns the extent of the given string. No tab
+ * expansion or carriage return processing will be performed.
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point stringExtent(String string) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    // SWT externsion: allow null string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    checkGC(FONT);
+    int length_ = string.length;
+    if (data.gdipGraphics !is null) {
+        Gdip.PointF pt;
+        Gdip.RectF bounds;
+        wchar* buffer;
+        if (length_ !is 0) {
+            wchar[] wstr = StrToWCHARs( string );
+            buffer = wstr.ptr;
+            length_ = wstr.length;
+        } else {
+            buffer = (" "w).ptr;
+        }
+        auto format = Gdip.StringFormat_Clone(Gdip.StringFormat_GenericTypographic());
+        int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces;
+        if ((data.style & SWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
+        Gdip.StringFormat_SetFormatFlags(format, formatFlags);
+        Gdip.Graphics_MeasureString(data.gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds);
+        Gdip.StringFormat_delete(format);
+        return new Point(length_ is 0 ? 0 : Math.rndint(bounds.Width), Math.rndint(bounds.Height));
+    }
+    SIZE size;
+    if (length_ is 0) {
+//      OS.GetTextExtentPoint32(handle, SPACE, SPACE.length(), size);
+        OS.GetTextExtentPoint32W(handle, (" "w).ptr, 1, &size);
+        return new Point(0, size.cy);
+    } else {
+//      TCHAR buffer = new TCHAR (getCodePage(), string, false);
+        wchar[] wstr = StrToWCHARs( string );
+        wchar* buffer = wstr.ptr;
+        length_ = wstr.length;
+        OS.GetTextExtentPoint32W(handle, buffer, length_, &size);
+        return new Point(size.cx, size.cy);
+    }
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion and
+ * carriage return processing are performed.
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @return a point containing the extent of the string
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent(String string) {
+    return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
+}
+
+/**
+ * Returns the extent of the given string. Tab expansion, line
+ * delimiter and mnemonic processing are performed according to
+ * the specified flags, which can be a combination of:
+ * <dl>
+ * <dt><b>DRAW_DELIMITER</b></dt>
+ * <dd>draw multiple lines</dd>
+ * <dt><b>DRAW_TAB</b></dt>
+ * <dd>expand tabs</dd>
+ * <dt><b>DRAW_MNEMONIC</b></dt>
+ * <dd>underline the mnemonic character</dd>
+ * <dt><b>DRAW_TRANSPARENT</b></dt>
+ * <dd>transparent background</dd>
+ * </dl>
+ * <p>
+ * The <em>extent</em> of a string is the width and height of
+ * the rectangular area it would cover if drawn in a particular
+ * font (in this case, the current font in the receiver).
+ * </p>
+ *
+ * @param string the string to measure
+ * @param flags the flags specifying how to process the text
+ * @return a point containing the extent of the string
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point textExtent(String string, int flags) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    //DWT_CHANGE: allow null string
+    //if (string is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    checkGC(FONT);
+    if (data.gdipGraphics !is null) {
+        Gdip.PointF pt;
+        Gdip.RectF bounds;
+        wchar* buffer;
+        int length_ = string.length;
+        if (length_ !is 0) {
+            wchar[] wstr = StrToWCHARs( string );
+            buffer = wstr.ptr;
+            length_ = wstr.length;
+        } else {
+            buffer = (" "w).ptr;
+        }
+        auto format = Gdip.StringFormat_Clone(Gdip.StringFormat_GenericTypographic());
+        int formatFlags = Gdip.StringFormat_GetFormatFlags(format) | Gdip.StringFormatFlagsMeasureTrailingSpaces;
+        if ((data.style & SWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
+        Gdip.StringFormat_SetFormatFlags(format, formatFlags);
+        float[] tabs = (flags & SWT.DRAW_TAB) !is 0 ? [measureSpace(data.gdipFont, format) * 8] : new float[1];
+        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr);
+        Gdip.StringFormat_SetHotkeyPrefix(format, (flags & SWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone);
+        Gdip.Graphics_MeasureString(data.gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds);
+        Gdip.StringFormat_delete(format);
+        return new Point(length_ is 0 ? 0 : Math.rndint(bounds.Width), Math.rndint(bounds.Height));
+    }
+    if (string.length is 0) {
+        SIZE size;
+//      OS.GetTextExtentPoint32(handle, SPACE, SPACE.length(), size);
+        OS.GetTextExtentPoint32W(handle, (" "w).ptr, 1, &size);
+        return new Point(0, size.cy);
+    }
+    RECT rect;
+    auto wstr = StrToTCHARs( string );
+    TCHAR* buffer = wstr.ptr;
+    int length_ = wstr.length;
+    int uFormat = OS.DT_LEFT | OS.DT_CALCRECT;
+    if ((flags & SWT.DRAW_DELIMITER) is 0) uFormat |= OS.DT_SINGLELINE;
+    if ((flags & SWT.DRAW_TAB) !is 0) uFormat |= OS.DT_EXPANDTABS;
+    if ((flags & SWT.DRAW_MNEMONIC) is 0) uFormat |= OS.DT_NOPREFIX;
+    OS.DrawText(handle, buffer, length_, &rect, uFormat);
+    return new Point(rect.right, rect.bottom);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "GC {*DISPOSED*}";
+    return Format( "GC {{{}}", handle );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new graphics context.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param drawable the Drawable for the receiver.
+ * @param data the data for the receiver.
+ *
+ * @return a new <code>GC</code>
+ */
+public static GC win32_new(Drawable drawable, GCData data) {
+    GC gc = new GC();
+    auto hDC = drawable.internal_new_GC(data);
+    gc.disposeChecking = false;
+    gc.device = data.device;
+    gc.init_(drawable, data, hDC);
+    return gc;
+}
+
+/**
+ * Invokes platform specific functionality to wrap a graphics context.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>GC</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the Windows HDC.
+ * @param data the data for the receiver.
+ *
+ * @return a new <code>GC</code>
+ */
+public static GC win32_new(HDC hDC, GCData data) {
+    GC gc = new GC();
+    gc.disposeChecking = false;
+    gc.device = data.device;
+    data.style |= SWT.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 |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+        }
+    }
+    gc.init_(null, data, hDC);
+    return gc;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GCData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.GCData;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.win32.WINTYPES;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Pattern;
+import org.eclipse.swt.graphics.Font;
+
+/**
+ * Instances of this class are descriptions of GCs in terms
+ * of unallocated platform-specific data fields.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the public
+ * API for SWT. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It is not available on all
+ * platforms, and should never be called from application code.
+ * </p>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class GCData {
+    public Device device;
+    public int style, state = -1;
+    public int foreground = -1;
+    public int background = -1;
+    public Font font;
+    public Pattern foregroundPattern;
+    public Pattern backgroundPattern;
+    public int lineStyle = SWT.LINE_SOLID;
+    public float lineWidth;
+    public int lineCap = SWT.CAP_FLAT;
+    public int lineJoin = SWT.JOIN_MITER;
+    public float lineDashesOffset;
+    public float[] lineDashes;
+    public float lineMiterLimit = 10;
+    public int alpha = 0xFF;
+
+    public Image image;
+    public HPEN hPen, hOldPen;
+    public HBRUSH hBrush, hOldBrush;
+    public HBITMAP hNullBitmap;
+    public HWND hwnd;
+    public PAINTSTRUCT* ps;
+    public int layout = -1;
+    public Gdip.Graphics gdipGraphics;
+    public Gdip.Pen gdipPen;
+    public Gdip.Brush gdipBrush;
+    public Gdip.SolidBrush gdipFgBrush;
+    public Gdip.SolidBrush gdipBgBrush;
+    public Gdip.Font gdipFont;
+    public float gdipXOffset, gdipYOffset;
+    public int uiState = 0;
+    public bool focusDrawn;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/GlyphMetrics.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.GlyphMetrics;
+
+import org.eclipse.swt.SWT;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent glyph metrics.
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see TextStyle
+ * @see TextLayout
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public final class GlyphMetrics {
+
+    /**
+     * the ascent of the GlyphMetrics
+     */
+    public int ascent;
+
+    /**
+     * the descent of the GlyphMetrics
+     */
+    public int descent;
+
+    /**
+     * the width of the GlyphMetrics
+     */
+    public int width;
+
+/**
+ * Constructs an instance of this class with the given
+ * ascent, descent and width values.
+ *
+ * @param ascent the GlyphMetrics ascent
+ * @param descent the GlyphMetrics descent
+ * @param width the GlyphMetrics width
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the ascent, descent or width argument is negative</li>
+ * </ul>
+ */
+public this(int ascent, int descent, int width) {
+    if (ascent < 0 || descent < 0 || width < 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.ascent = ascent;
+    this.descent = descent;
+    this.width = width;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+    if (object is this) return true;
+    if (auto metrics = cast(GlyphMetrics)object ){
+       return metrics.ascent == ascent && metrics.descent == descent && metrics.width == width;
+    }
+    return false;
+}
+
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash () {
+    return ascent ^ descent ^ width;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the <code>GlyphMetrics</code>
+ */
+public override String toString () {
+    return Format( "GlyphMetrics {{{}, {}, {}}", ascent, descent, width ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Image.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2161 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Image;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Resource;
+
+
+import java.io.InputStream;
+import java.lang.all;
+
+import tango.text.convert.Format;
+//import tango.stdc.string;
+//import tango.stdc.stringz;
+
+/**
+ * Instances of this class are graphics which have been prepared
+ * for display on a specific device. That is, they are ready
+ * to paint using methods such as <code>GC.drawImage()</code>
+ * and display on widgets with, for example, <code>Button.setImage()</code>.
+ * <p>
+ * If loaded from a file format that supports it, an
+ * <code>Image</code> may have transparency, meaning that certain
+ * pixels are specified as being transparent when drawn. Examples
+ * of file formats that support transparency are GIF and PNG.
+ * </p><p>
+ * There are two primary ways to use <code>Images</code>.
+ * The first is to load a graphic file from disk and create an
+ * <code>Image</code> from it. This is done using an <code>Image</code>
+ * constructor, for example:
+ * <pre>
+ *    Image i = new Image(device, "C:\\graphic.bmp");
+ * </pre>
+ * A graphic file may contain a color table specifying which
+ * colors the image was intended to possess. In the above example,
+ * these colors will be mapped to the closest available color in
+ * SWT. It is possible to get more control over the mapping of
+ * colors as the image is being created, using code of the form:
+ * <pre>
+ *    ImageData data = new ImageData("C:\\graphic.bmp");
+ *    RGB[] rgbs = data.getRGBs();
+ *    // At this point, rgbs contains specifications of all
+ *    // the colors contained within this image. You may
+ *    // allocate as many of these colors as you wish by
+ *    // using the Color constructor Color(RGB), then
+ *    // create the image:
+ *    Image i = new Image(device, data);
+ * </pre>
+ * <p>
+ * Applications which require even greater control over the image
+ * loading process should use the support provided in class
+ * <code>ImageLoader</code>.
+ * </p><p>
+ * Application code must explicitly invoke the <code>Image.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see Color
+ * @see ImageData
+ * @see ImageLoader
+ * @see <a href="http://www.eclipse.org/swt/snippets/#image">Image snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: GraphicsExample, ImageAnalyzer</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Image : Resource, Drawable {
+
+    alias Resource.init_ init_;
+
+    /**
+     * specifies whether the receiver is a bitmap or an icon
+     * (one of <code>SWT.BITMAP</code>, <code>SWT.ICON</code>)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public int type;
+
+    /**
+     * the handle to the OS image resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HGDIOBJ handle;
+
+    /**
+     * specifies the transparent pixel
+     */
+    int transparentPixel = -1, transparentColor = -1;
+
+    /**
+     * the GC which is drawing on the image
+     */
+    GC memGC;
+
+    /**
+     * the alpha data for the image
+     */
+    byte[] alphaData;
+
+    /**
+     * the global alpha value to be used for every pixel
+     */
+    int alpha = -1;
+
+    /**
+     * the image data used to create this image if it is a
+     * icon. Used only in WinCE
+     */
+    ImageData data;
+
+    /**
+     * width of the image
+     */
+    int width = -1;
+
+    /**
+     * height of the image
+     */
+    int height = -1;
+
+    /**
+     * specifies the default scanline padding
+     */
+    static const int DEFAULT_SCANLINE_PAD = 4;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this (Device device) {
+    super(device);
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * specified width and height. The result may be drawn upon
+ * by creating a GC and using any of its drawing operations,
+ * as shown in the following example:
+ * <pre>
+ *    Image i = new Image(device, width, height);
+ *    GC gc = new GC(i);
+ *    gc.drawRectangle(0, 0, 50, 50);
+ *    gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param width the width of the new image
+ * @param height the height of the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this(Device device, int width, int height) {
+    super(device);
+    init_(width, height);
+    init_();
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * provided image, with an appearance that varies depending
+ * on the value of the flag. The possible flag values are:
+ * <dl>
+ * <dt><b>{@link SWT#IMAGE_COPY}</b></dt>
+ * <dd>the result is an identical copy of srcImage</dd>
+ * <dt><b>{@link SWT#IMAGE_DISABLE}</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd>
+ * <dt><b>{@link SWT#IMAGE_GRAY}</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd>
+ * </dl>
+ *
+ * @param device the device on which to create the image
+ * @param srcImage the image to use as the source
+ * @param flag the style, either <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if srcImage is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the flag is not one of <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code></li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state</li>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this(Device device, Image srcImage, int flag) {
+    super(device);
+    device = this.device;
+    if (srcImage is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    Rectangle rect = srcImage.getBounds();
+    this.type = srcImage.type;
+    switch (flag) {
+        case SWT.IMAGE_COPY: {
+            switch (type) {
+                case SWT.BITMAP:
+                    /* Get the HDC for the device */
+                    auto hDC = device.internal_new_GC(null);
+
+                    /* Copy the bitmap */
+                    auto hdcSource = OS.CreateCompatibleDC(hDC);
+                    auto hdcDest = OS.CreateCompatibleDC(hDC);
+                    auto hOldSrc = OS.SelectObject(hdcSource, srcImage.handle);
+                    BITMAP bm;
+                    OS.GetObject(srcImage.handle, BITMAP.sizeof, &bm);
+                    handle = OS.CreateCompatibleBitmap(hdcSource, rect.width, bm.bmBits !is null ? -rect.height : rect.height);
+                    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                    auto hOldDest = OS.SelectObject(hdcDest, handle);
+                    OS.BitBlt(hdcDest, 0, 0, rect.width, rect.height, hdcSource, 0, 0, OS.SRCCOPY);
+                    OS.SelectObject(hdcSource, hOldSrc);
+                    OS.SelectObject(hdcDest, hOldDest);
+                    OS.DeleteDC(hdcSource);
+                    OS.DeleteDC(hdcDest);
+
+                    /* Release the HDC for the device */
+                    device.internal_dispose_GC(hDC, null);
+
+                    transparentPixel = srcImage.transparentPixel;
+                    alpha = srcImage.alpha;
+                    if (srcImage.alphaData !is null) {
+                        alphaData = new byte[srcImage.alphaData.length];
+                        System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+                    }
+                    break;
+                case SWT.ICON:
+                    static if (OS.IsWinCE) {
+                        init_(srcImage.data);
+                    } else {
+                        handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0);
+                        if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                    }
+                    break;
+                default:
+                    SWT.error(SWT.ERROR_INVALID_IMAGE);
+            }
+            break;
+        }
+        case SWT.IMAGE_DISABLE: {
+            ImageData data = srcImage.getImageData();
+            PaletteData palette = data.palette;
+            RGB[] rgbs = new RGB[3];
+            rgbs[0] = device.getSystemColor(SWT.COLOR_BLACK).getRGB();
+            rgbs[1] = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW).getRGB();
+            rgbs[2] = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
+            ImageData newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+            newData.alpha = data.alpha;
+            newData.alphaData = data.alphaData;
+            newData.maskData = data.maskData;
+            newData.maskPad = data.maskPad;
+            if (data.transparentPixel !is -1) newData.transparentPixel = 0;
+
+            /* Convert the pixels. */
+            int[] scanline = new int[rect.width];
+            int[] maskScanline = null;
+            ImageData mask = null;
+            if (data.maskData !is null) mask = data.getTransparencyMask();
+            if (mask !is null) maskScanline = new int[rect.width];
+            int redMask = palette.redMask;
+            int greenMask = palette.greenMask;
+            int blueMask = palette.blueMask;
+            int redShift = palette.redShift;
+            int greenShift = palette.greenShift;
+            int blueShift = palette.blueShift;
+            for (int y=0; y<rect.height; y++) {
+                int offset = y * newData.bytesPerLine;
+                data.getPixels(0, y, rect.width, scanline, 0);
+                if (mask !is null) mask.getPixels(0, y, rect.width, maskScanline, 0);
+                for (int x=0; x<rect.width; x++) {
+                    int pixel = scanline[x];
+                    if (!((data.transparentPixel !is -1 && pixel is data.transparentPixel) || (mask !is null && maskScanline[x] is 0))) {
+                        int red, green, blue;
+                        if (palette.isDirect) {
+                            red = pixel & redMask;
+                            red = (redShift < 0) ? red >>> -redShift : red << redShift;
+                            green = pixel & greenMask;
+                            green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+                            blue = pixel & blueMask;
+                            blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+                        } else {
+                            red = palette.colors[pixel].red;
+                            green = palette.colors[pixel].green;
+                            blue = palette.colors[pixel].blue;
+                        }
+                        int intensity = red * red + green * green + blue * blue;
+                        if (intensity < 98304) {
+                            newData.data[offset] = cast(byte)1;
+                        } else {
+                            newData.data[offset] = cast(byte)2;
+                        }
+                    }
+                    offset++;
+                }
+            }
+            init_ (newData);
+            break;
+        }
+        case SWT.IMAGE_GRAY: {
+            ImageData data = srcImage.getImageData();
+            PaletteData palette = data.palette;
+            ImageData newData = data;
+            if (!palette.isDirect) {
+                /* Convert the palette entries to gray. */
+                RGB [] rgbs = palette.getRGBs();
+                for (int i=0; i<rgbs.length; i++) {
+                    if (data.transparentPixel !is i) {
+                        RGB color = rgbs [i];
+                        int red = color.red;
+                        int green = color.green;
+                        int blue = color.blue;
+                        int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+                        color.red = color.green = color.blue = intensity;
+                    }
+                }
+                newData.palette = new PaletteData(rgbs);
+            } else {
+                /* Create a 8 bit depth image data with a gray palette. */
+                RGB[] rgbs = new RGB[256];
+                for (int i=0; i<rgbs.length; i++) {
+                    rgbs[i] = new RGB(i, i, i);
+                }
+                newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+                newData.alpha = data.alpha;
+                newData.alphaData = data.alphaData;
+                newData.maskData = data.maskData;
+                newData.maskPad = data.maskPad;
+                if (data.transparentPixel !is -1) newData.transparentPixel = 254;
+
+                /* Convert the pixels. */
+                int[] scanline = new int[rect.width];
+                int redMask = palette.redMask;
+                int greenMask = palette.greenMask;
+                int blueMask = palette.blueMask;
+                int redShift = palette.redShift;
+                int greenShift = palette.greenShift;
+                int blueShift = palette.blueShift;
+                for (int y=0; y<rect.height; y++) {
+                    int offset = y * newData.bytesPerLine;
+                    data.getPixels(0, y, rect.width, scanline, 0);
+                    for (int x=0; x<rect.width; x++) {
+                        int pixel = scanline[x];
+                        if (pixel !is data.transparentPixel) {
+                            int red = pixel & redMask;
+                            red = (redShift < 0) ? red >>> -redShift : red << redShift;
+                            int green = pixel & greenMask;
+                            green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+                            int blue = pixel & blueMask;
+                            blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+                            int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+                            if (newData.transparentPixel is intensity) intensity = 255;
+                            newData.data[offset] = cast(byte)intensity;
+                        } else {
+                            newData.data[offset] = cast(byte)254;
+                        }
+                        offset++;
+                    }
+                }
+            }
+            init_ (newData);
+            break;
+        }
+        default:
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    init_();
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * width and height of the specified rectangle. The result
+ * may be drawn upon by creating a GC and using any of its
+ * drawing operations, as shown in the following example:
+ * <pre>
+ *    Image i = new Image(device, boundsRectangle);
+ *    GC gc = new GC(i);
+ *    gc.drawRectangle(0, 0, 50, 50);
+ *    gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param bounds a rectangle specifying the image's width and height (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the bounds rectangle is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this(Device device, Rectangle bounds) {
+    super(device);
+    if (bounds is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(bounds.width, bounds.height);
+    init_();
+}
+
+/**
+ * Constructs an instance of this class from the given
+ * <code>ImageData</code>.
+ *
+ * @param device the device on which to create the image
+ * @param data the image data to create the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the image data is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this(Device device, ImageData data) {
+    super(device);
+    init_(data);
+    init_();
+}
+
+/**
+ * Constructs an instance of this class, whose type is
+ * <code>SWT.ICON</code>, from the two given <code>ImageData</code>
+ * objects. The two images must be the same size. Pixel transparency
+ * in either image will be ignored.
+ * <p>
+ * The mask image should contain white wherever the icon is to be visible,
+ * and black wherever the icon is to be transparent. In addition,
+ * the source image should contain black wherever the icon is to be
+ * transparent.
+ * </p>
+ *
+ * @param device the device on which to create the icon
+ * @param source the color data for the icon
+ * @param mask the mask data for the icon
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if either the source or mask is null </li>
+ *    <li>ERROR_INVALID_ARGUMENT - if source and mask are different sizes</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this(Device device, ImageData source, ImageData mask) {
+    super(device);
+    if (source is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (mask is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (source.width !is mask.width || source.height !is mask.height) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    mask = ImageData.convertMask(mask);
+    init_(this.device, this, source, mask);
+    init_();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the specified input stream. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type.  Application code is still responsible
+ * for closing the input stream.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p><p>
+ * This constructor may be used to load a resource as follows:
+ * </p>
+ * <pre>
+ *     static Image loadImage (Display display, Class clazz, String string) {
+ *          InputStream stream = clazz.getResourceAsStream (string);
+ *          if (stream is null) return null;
+ *          Image image = null;
+ *          try {
+ *               image = new Image (display, stream);
+ *          } catch (SWTException ex) {
+ *          } finally {
+ *               try {
+ *                    stream.close ();
+ *               } catch (IOException ex) {}
+ *          }
+ *          return image;
+ *     }
+ * </pre>
+ *
+ * @param device the device on which to create the image
+ * @param stream the input stream to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data </li>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this (Device device, InputStream stream) {
+    super(device);
+    init_(new ImageData(stream));
+    init_();
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the file with the specified name. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading
+ * a single image only. If the specified file contains
+ * multiple images, only the first one will be used.
+ *
+ * @param device the device on which to create the image
+ * @param filename the name of the file to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the file</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public this (Device device, String filename) {
+    super(device);
+    device = this.device;
+    if (filename is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    bool gdip = true;
+    try {
+        device.checkGDIP();
+    } catch (SWTException 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);
+        auto bitmap = Gdip.Bitmap_new( .StrToWCHARz( filename ), false);
+        if (bitmap !is null) {
+            int error = SWT.ERROR_NO_HANDLES;
+            int status = Gdip.Image_GetLastStatus(cast(Gdip.Image)bitmap);
+            if (status is 0) {
+                if (filename.toLowerCase().endsWith(".ico")) {
+                    this.type = SWT.ICON;
+                    HICON hicon;
+                    Gdip.Bitmap_GetHICON(bitmap, hicon);
+                    this.handle = hicon;
+                } else {
+                    this.type = SWT.BITMAP;
+                    int width = Gdip.Image_GetWidth(cast(Gdip.Image)bitmap);
+                    int height = Gdip.Image_GetHeight(cast(Gdip.Image)bitmap);
+                    int pixelFormat = Gdip.Image_GetPixelFormat(cast(Gdip.Image)bitmap);
+                    switch (pixelFormat) {
+                        case Gdip.PixelFormat16bppRGB555:
+                        case Gdip.PixelFormat16bppRGB565:
+                            this.handle = createDIB(width, height, 16);
+                            break;
+                        case Gdip.PixelFormat24bppRGB:
+                            this.handle = createDIB(width, height, 24);
+                            break;
+                        case Gdip.PixelFormat32bppRGB:
+                        // These will loose either precision or transparency
+                        case Gdip.PixelFormat16bppGrayScale:
+                        case Gdip.PixelFormat48bppRGB:
+                        case Gdip.PixelFormat32bppPARGB:
+                        case Gdip.PixelFormat64bppARGB:
+                        case Gdip.PixelFormat64bppPARGB:
+                            this.handle = createDIB(width, height, 32);
+                            break;
+                        default:
+                    }
+                    if (this.handle !is null) {
+                        /*
+                        * This performs better than getting the bits with Bitmap.LockBits(),
+                        * but it cannot be used when there is transparency.
+                        */
+                        auto hDC = device.internal_new_GC(null);
+                        auto srcHDC = OS.CreateCompatibleDC(hDC);
+                        auto oldSrcBitmap = OS.SelectObject(srcHDC, this.handle);
+                        auto graphics = Gdip.Graphics_new(srcHDC);
+                        if (graphics !is null) {
+                            Gdip.Rect rect;
+                            rect.Width = width;
+                            rect.Height = height;
+                            status = Gdip.Graphics_DrawImage(graphics, cast(Gdip.Image)bitmap, rect, 0, 0, width, height, Gdip.UnitPixel, null, null, null);
+                            if (status !is 0) {
+                                error = SWT.ERROR_INVALID_IMAGE;
+                                OS.DeleteObject(handle);
+                                this.handle = null;
+                            }
+                            Gdip.Graphics_delete(graphics);
+                        }
+                        OS.SelectObject(srcHDC, oldSrcBitmap);
+                        OS.DeleteDC(srcHDC);
+                        device.internal_dispose_GC(hDC, null);
+                    } else {
+                        auto lockedBitmapData = Gdip.BitmapData_new();
+                        if (lockedBitmapData !is null) {
+                            Gdip.Bitmap_LockBits(bitmap, null, 0, pixelFormat, lockedBitmapData);
+                            //BitmapData bitmapData = new BitmapData();
+                            //Gdip.MoveMemory(bitmapData, lockedBitmapData);
+                            auto stride = lockedBitmapData.Stride;
+                            auto pixels = lockedBitmapData.Scan0;
+                            int depth = 0, scanlinePad = 4, transparentPixel = -1;
+                            switch (lockedBitmapData.PixelFormat) {
+                                case Gdip.PixelFormat1bppIndexed: depth = 1; break;
+                                case Gdip.PixelFormat4bppIndexed: depth = 4; break;
+                                case Gdip.PixelFormat8bppIndexed: depth = 8; break;
+                                case Gdip.PixelFormat16bppARGB1555:
+                                case Gdip.PixelFormat16bppRGB555:
+                                case Gdip.PixelFormat16bppRGB565: depth = 16; break;
+                                case Gdip.PixelFormat24bppRGB: depth = 24; break;
+                                case Gdip.PixelFormat32bppRGB:
+                                case Gdip.PixelFormat32bppARGB: depth = 32; break;
+                                default:
+                            }
+                            if (depth !is 0) {
+                                PaletteData paletteData = null;
+                                switch (lockedBitmapData.PixelFormat) {
+                                    case Gdip.PixelFormat1bppIndexed:
+                                    case Gdip.PixelFormat4bppIndexed:
+                                    case Gdip.PixelFormat8bppIndexed:
+                                        int paletteSize = Gdip.Image_GetPaletteSize(cast(Gdip.Image)bitmap);
+                                        auto hHeap = OS.GetProcessHeap();
+                                        auto palette = cast(Gdip.ColorPalette*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, paletteSize);
+                                        if (palette is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                                        Gdip.Image_GetPalette(cast(Gdip.Image)bitmap, palette, paletteSize);
+                                        Gdip.ColorPalette* colorPalette = palette;
+                                        //Gdip.MoveMemory(colorPalette, palette, ColorPalette.sizeof);
+                                        //int[] entries = new int[colorPalette.Count];
+                                        //OS.MoveMemory(entries, palette + 8, entries.length * 4);
+
+                                        //PORTING_COMMENT: moved down
+                                        //OS.HeapFree(hHeap, 0, palette);
+                                        RGB[] rgbs = new RGB[colorPalette.Count];
+                                        paletteData = new PaletteData(rgbs);
+                                        for (int i = 0; i < colorPalette.Count; i++) {
+                                            // SWT: access palette.Entries without array bounds checking
+                                            if (((*(palette.Entries.ptr + i) >> 24) & 0xFF) is 0 && (colorPalette.Flags & Gdip.PaletteFlagsHasAlpha) !is 0) {
+                                                transparentPixel = i;
+                                            }
+                                            rgbs[i] = new RGB(((*(palette.Entries.ptr + i) & 0xFF0000) >> 16), ((*(palette.Entries.ptr + i) & 0xFF00) >> 8), ((*(palette.Entries.ptr + i) & 0xFF) >> 0));
+                                        }
+                                        OS.HeapFree(hHeap, 0, palette);
+                                        break;
+                                    case Gdip.PixelFormat16bppARGB1555:
+                                    case Gdip.PixelFormat16bppRGB555: paletteData = new PaletteData(0x7C00, 0x3E0, 0x1F); break;
+                                    case Gdip.PixelFormat16bppRGB565: paletteData = new PaletteData(0xF800, 0x7E0, 0x1F); break;
+                                    case Gdip.PixelFormat24bppRGB: paletteData = new PaletteData(0xFF, 0xFF00, 0xFF0000); break;
+                                    case Gdip.PixelFormat32bppRGB:
+                                    case Gdip.PixelFormat32bppARGB: paletteData = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); break;
+                                    default:
+                                }
+                                byte[] data = new byte[ stride * height ], alphaData = null;
+                                OS.MoveMemory(data.ptr, pixels, data.length);
+                                switch (lockedBitmapData.PixelFormat) {
+                                    case Gdip.PixelFormat16bppARGB1555:
+                                        alphaData = new byte[width * height];
+                                        for (int i = 1, j = 0; i < data.length; i += 2, j++) {
+                                            alphaData[j] = cast(byte)((data[i] & 0x80) !is 0 ? 255 : 0);
+                                        }
+                                        break;
+                                    case Gdip.PixelFormat32bppARGB:
+                                        alphaData = new byte[width * height];
+                                        for (int i = 3, j = 0; i < data.length; i += 4, j++) {
+                                            alphaData[j] = data[i];
+                                        }
+                                        break;
+                                    default:
+                                }
+                                Gdip.Bitmap_UnlockBits(bitmap, lockedBitmapData);
+                                Gdip.BitmapData_delete(lockedBitmapData);
+                                ImageData img = new ImageData(width, height, depth, paletteData, scanlinePad, data);
+                                img.transparentPixel = transparentPixel;
+                                img.alphaData = alphaData;
+                                init_(img);
+                            }
+                        }
+                    }
+                }
+            }
+            Gdip.Bitmap_delete(bitmap);
+            if (status is 0) {
+                if (this.handle is null) SWT.error(error);
+                return;
+            }
+        }
+    }
+    init_(new ImageData(filename));
+    init_();
+}
+
+/**
+ * Create a DIB from a DDB without using GetDIBits. Note that
+ * the DDB should not be selected into a HDC.
+ */
+HBITMAP createDIBFromDDB(HDC hDC, HBITMAP hBitmap, int width, int height) {
+
+    /* Determine the DDB depth */
+    int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+    int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+    int depth = bits * planes;
+
+    /* Determine the DIB palette */
+    bool isDirect = depth > 8;
+    RGB[] rgbs = null;
+    if (!isDirect) {
+        int numColors = 1 << depth;
+        byte[] logPalette = new byte[4 * numColors];
+        OS.GetPaletteEntries(device.hPalette, 0, numColors, cast(PALETTEENTRY*)logPalette.ptr);
+        rgbs = new RGB[numColors];
+        for (int i = 0; i < numColors; i++) {
+            rgbs[i] = new RGB(logPalette[i] & 0xFF, logPalette[i + 1] & 0xFF, logPalette[i + 2] & 0xFF);
+        }
+    }
+
+    bool useBitfields = OS.IsWinCE && (depth is 16 || depth is 32);
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biWidth = width;
+    bmiHeader.biHeight = -height;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)depth;
+    if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
+    else bmiHeader.biCompression = OS.BI_RGB;
+    byte[] bmi;
+    if (isDirect) bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
+    else  bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
+    OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+
+    /* Set the rgb colors into the bitmap info */
+    int offset = BITMAPINFOHEADER.sizeof;
+    if (isDirect) {
+        if (useBitfields) {
+            int redMask = 0;
+            int greenMask = 0;
+            int blueMask = 0;
+            switch (depth) {
+                case 16:
+                    redMask = 0x7C00;
+                    greenMask = 0x3E0;
+                    blueMask = 0x1F;
+                    /* little endian */
+                    bmi[offset] = cast(byte)((redMask & 0xFF) >> 0);
+                    bmi[offset + 1] = cast(byte)((redMask & 0xFF00) >> 8);
+                    bmi[offset + 2] = cast(byte)((redMask & 0xFF0000) >> 16);
+                    bmi[offset + 3] = cast(byte)((redMask & 0xFF000000) >> 24);
+                    bmi[offset + 4] = cast(byte)((greenMask & 0xFF) >> 0);
+                    bmi[offset + 5] = cast(byte)((greenMask & 0xFF00) >> 8);
+                    bmi[offset + 6] = cast(byte)((greenMask & 0xFF0000) >> 16);
+                    bmi[offset + 7] = cast(byte)((greenMask & 0xFF000000) >> 24);
+                    bmi[offset + 8] = cast(byte)((blueMask & 0xFF) >> 0);
+                    bmi[offset + 9] = cast(byte)((blueMask & 0xFF00) >> 8);
+                    bmi[offset + 10] = cast(byte)((blueMask & 0xFF0000) >> 16);
+                    bmi[offset + 11] = cast(byte)((blueMask & 0xFF000000) >> 24);
+                    break;
+                case 32:
+                    redMask = 0xFF00;
+                    greenMask = 0xFF0000;
+                    blueMask = 0xFF000000;
+                    /* big endian */
+                    bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+                    bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+                    bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+                    bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+                    bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+                    bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+                    bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+                    bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+                    bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+                    bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+                    bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+                    bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
+                    break;
+                default:
+                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+            }
+        }
+    } else {
+        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;
+        }
+    }
+    void* pBits;
+    HBITMAP hDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+    if (hDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+
+    /* Bitblt DDB into DIB */
+    auto hdcSource = OS.CreateCompatibleDC(hDC);
+    auto hdcDest = OS.CreateCompatibleDC(hDC);
+    auto hOldSrc = OS.SelectObject(hdcSource, hBitmap);
+    auto hOldDest = OS.SelectObject(hdcDest, hDib);
+    OS.BitBlt(hdcDest, 0, 0, width, height, hdcSource, 0, 0, OS.SRCCOPY);
+    OS.SelectObject(hdcSource, hOldSrc);
+    OS.SelectObject(hdcDest, hOldDest);
+    OS.DeleteDC(hdcSource);
+    OS.DeleteDC(hdcDest);
+
+    return hDib;
+}
+
+// FIXME: Potential crash site in D:  createGdipImage casts pointers to int before
+// returning them in an int[].  Since the D GC does not and cannot scan int's for
+// pointers, there is potential that the pointer's object could be collected while still
+// active, even though it might be unlikely given the short span of time that the
+// function has them stored in the int array.
+
+int /*long*/ [] createGdipImage() {
+    switch (type) {
+        case SWT.BITMAP: {
+            if (alpha !is -1 || alphaData !is null || transparentPixel !is -1) {
+                BITMAP bm;
+                OS.GetObject(handle, BITMAP.sizeof, &bm);
+                int imgWidth = bm.bmWidth;
+                int imgHeight = bm.bmHeight;
+                auto hDC = device.internal_new_GC(null);
+                auto srcHdc = OS.CreateCompatibleDC(hDC);
+                auto oldSrcBitmap = OS.SelectObject(srcHdc, handle);
+                auto memHdc = OS.CreateCompatibleDC(hDC);
+                auto memDib = createDIB(imgWidth, imgHeight, 32);
+                if (memDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                auto oldMemBitmap = OS.SelectObject(memHdc, memDib);
+                BITMAP dibBM;
+                OS.GetObject(memDib, BITMAP.sizeof, &dibBM);
+                int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+                OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+                ubyte red = 0, green = 0, blue = 0;
+                if (transparentPixel !is -1) {
+                    if (bm.bmBitsPixel <= 8)  {
+                        ubyte[] color = new ubyte[4];
+                        OS.GetDIBColorTable(srcHdc, transparentPixel, 1, cast(RGBQUAD*)color.ptr);
+                        blue = color[0];
+                        green = color[1];
+                        red = color[2];
+                    } else {
+                        switch (bm.bmBitsPixel) {
+                            case 16:
+                                int blueMask = 0x1F;
+                                int blueShift = ImageData.getChannelShift(blueMask);
+                                byte[] blues = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(blueMask, blueShift)];
+                                blue = blues[(transparentPixel & blueMask) >> blueShift];
+                                int greenMask = 0x3E0;
+                                int greenShift = ImageData.getChannelShift(greenMask);
+                                byte[] greens = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(greenMask, greenShift)];
+                                green = greens[(transparentPixel & greenMask) >> greenShift];
+                                int redMask = 0x7C00;
+                                int redShift = ImageData.getChannelShift(redMask);
+                                byte[] reds = ImageData.ANY_TO_EIGHT[ImageData.getChannelWidth(redMask, redShift)];
+                                red = reds[(transparentPixel & redMask) >> redShift];
+                                break;
+                            case 24:
+                                blue = cast(ubyte)((transparentPixel & 0xFF0000) >> 16);
+                                green = cast(ubyte)((transparentPixel & 0xFF00) >> 8);
+                                red = cast(ubyte)(transparentPixel & 0xFF);
+                                break;
+                            case 32:
+                                blue = cast(ubyte)((transparentPixel & 0xFF000000) >>> 24);
+                                green = cast(ubyte)((transparentPixel & 0xFF0000) >> 16);
+                                red = cast(ubyte)((transparentPixel & 0xFF00) >> 8);
+                                break;
+                            default:
+                        }
+                    }
+                }
+                OS.SelectObject(srcHdc, oldSrcBitmap);
+                OS.SelectObject(memHdc, oldMemBitmap);
+                OS.DeleteObject(srcHdc);
+                OS.DeleteObject(memHdc);
+                ubyte[] srcData = new ubyte[sizeInBytes];
+                OS.MoveMemory(srcData.ptr, dibBM.bmBits, sizeInBytes);
+                OS.DeleteObject(memDib);
+                device.internal_dispose_GC(hDC, null);
+                if (alpha !is -1) {
+                    for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                        for (int x = 0; x < imgWidth; ++x) {
+                            srcData[dp + 3] = cast(ubyte)alpha;
+                            dp += 4;
+                        }
+                    }
+                } else if (alphaData !is null) {
+                    for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
+                        for (int x = 0; x < imgWidth; ++x) {
+                            srcData[dp + 3] = alphaData[ap++];
+                            dp += 4;
+                        }
+                    }
+                } else if (transparentPixel !is -1) {
+                    for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                        for (int x = 0; x < imgWidth; ++x) {
+                            if (srcData[dp] is blue && srcData[dp + 1] is green && srcData[dp + 2] is red) {
+                                srcData[dp + 3] = cast(ubyte)0;
+                            } else {
+                                srcData[dp + 3] = cast(ubyte)0xFF;
+                            }
+                            dp += 4;
+                        }
+                    }
+                }
+                auto hHeap = OS.GetProcessHeap();
+                auto pixels = cast(ubyte*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
+                if (pixels is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                OS.MoveMemory(pixels, srcData.ptr, sizeInBytes);
+                return [ cast(int)(Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels)), cast(int) pixels];
+            }
+            return [cast(int)Gdip.Bitmap_new(handle, null), 0];
+        }
+        case SWT.ICON: {
+            /*
+            * Bug in GDI+. Creating a new GDI+ Bitmap from a HICON segment faults
+            * when the icon width is bigger than the icon height.  The fix is to
+            * detect this and create a PixelFormat32bppARGB image instead.
+            */
+            ICONINFO iconInfo;
+            static if (OS.IsWinCE) {
+                GetIconInfo(this, &iconInfo);
+            } else {
+                OS.GetIconInfo(handle, &iconInfo);
+            }
+            auto hBitmap = iconInfo.hbmColor;
+            if (hBitmap is null) hBitmap = iconInfo.hbmMask;
+            BITMAP bm;
+            OS.GetObject(hBitmap, BITMAP.sizeof, &bm);
+            int imgWidth = bm.bmWidth;
+            int imgHeight = hBitmap is iconInfo.hbmMask ? bm.bmHeight / 2 : bm.bmHeight;
+            Gdip.Bitmap img;
+            ubyte* pixels;
+            /*
+            * 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);
+                auto memHdc = OS.CreateCompatibleDC(hDC);
+                auto memDib = createDIB(imgWidth, imgHeight, 32);
+                if (memDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                auto oldMemBitmap = OS.SelectObject(memHdc, memDib);
+                BITMAP dibBM;
+                OS.GetObject(memDib, BITMAP.sizeof, &dibBM);
+                OS.BitBlt(memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, hBitmap is iconInfo.hbmMask ? imgHeight : 0, OS.SRCCOPY);
+                OS.SelectObject(memHdc, oldMemBitmap);
+                OS.DeleteObject(memHdc);
+                ubyte[] srcData = new ubyte[dibBM.bmWidthBytes * dibBM.bmHeight];
+                OS.MoveMemory(srcData.ptr, dibBM.bmBits, srcData.length);
+                OS.DeleteObject(memDib);
+                OS.SelectObject(srcHdc, iconInfo.hbmMask);
+                for (int y = 0, dp = 3; y < imgHeight; ++y) {
+                    for (int x = 0; x < imgWidth; ++x) {
+                        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;
+                    }
+                }
+                OS.SelectObject(srcHdc, oldSrcBitmap);
+                OS.DeleteObject(srcHdc);
+                device.internal_dispose_GC(hDC, null);
+                auto hHeap = OS.GetProcessHeap();
+                pixels = cast(ubyte*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, srcData.length);
+                if (pixels is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                OS.MoveMemory(pixels, srcData.ptr, srcData.length);
+                img = Gdip.Bitmap_new(imgWidth, imgHeight, dibBM.bmWidthBytes, Gdip.PixelFormat32bppARGB, pixels);
+            } else {
+                img = Gdip.Bitmap_new(handle);
+            }
+            if (iconInfo.hbmColor !is null) OS.DeleteObject(iconInfo.hbmColor);
+            if (iconInfo.hbmMask !is null) OS.DeleteObject(iconInfo.hbmMask);
+            return [ cast(int)img, cast(int) pixels ];
+        }
+        default: SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    return null;
+}
+
+void destroy () {
+    if (memGC !is null) memGC.dispose();
+    if (type is SWT.ICON) {
+        static if (OS.IsWinCE) data = null;
+        OS.DestroyIcon (handle);
+    } else {
+        OS.DeleteObject (handle);
+    }
+    handle = null;
+    memGC = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+    if (object is this) return true;
+    if (!(cast(Image)object)) return false;
+    Image image = cast(Image) object;
+    return device is image.device && handle is image.handle;
+}
+
+/**
+ * Returns the color to which to map the transparent pixel, or null if
+ * the receiver has no transparent pixel.
+ * <p>
+ * There are certain uses of Images that do not support transparency
+ * (for example, setting an image into a button or label). In these cases,
+ * it may be desired to simulate transparency by using the background
+ * color of the widget to paint the transparent pixels of the image.
+ * Use this method to check which color will be used in these cases
+ * in place of transparency. This value may be set with setBackground().
+ * <p>
+ *
+ * @return the background color of the image, or null if there is no transparency in the image
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getBackground() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (transparentPixel is -1) return null;
+
+    /* Get the HDC for the device */
+    auto hDC = device.internal_new_GC(null);
+
+    /* Compute the background color */
+    BITMAP bm;
+    OS.GetObject(handle, BITMAP.sizeof, &bm);
+    auto hdcMem = OS.CreateCompatibleDC(hDC);
+    auto hOldObject = OS.SelectObject(hdcMem, handle);
+    int red = 0, green = 0, blue = 0;
+    if (bm.bmBitsPixel <= 8)  {
+        static if (OS.IsWinCE) {
+            byte[1] pBits;
+            OS.MoveMemory(pBits.ptr, bm.bmBits, 1);
+            byte oldValue = pBits[0];
+            int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
+            pBits[0] = cast(byte)((transparentPixel << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
+            OS.MoveMemory(bm.bmBits, pBits.ptr, 1);
+            int color = OS.GetPixel(hdcMem, 0, 0);
+            pBits[0] = oldValue;
+            OS.MoveMemory(bm.bmBits, pBits.ptr, 1);
+            blue = (color & 0xFF0000) >> 16;
+            green = (color & 0xFF00) >> 8;
+            red = color & 0xFF;
+        } else {
+            RGBQUAD color;
+            OS.GetDIBColorTable(hdcMem, transparentPixel, 1, &color);
+            blue = color.rgbBlue;
+            green = color.rgbGreen;
+            red = color.rgbRed;
+        }
+    } else {
+        switch (bm.bmBitsPixel) {
+            case 16:
+                blue = (transparentPixel & 0x1F) << 3;
+                green = (transparentPixel & 0x3E0) >> 2;
+                red = (transparentPixel & 0x7C00) >> 7;
+                break;
+            case 24:
+                blue = (transparentPixel & 0xFF0000) >> 16;
+                green = (transparentPixel & 0xFF00) >> 8;
+                red = transparentPixel & 0xFF;
+                break;
+            case 32:
+                blue = (transparentPixel & 0xFF000000) >>> 24;
+                green = (transparentPixel & 0xFF0000) >> 16;
+                red = (transparentPixel & 0xFF00) >> 8;
+                break;
+            default:
+                return null;
+        }
+    }
+    OS.SelectObject(hdcMem, hOldObject);
+    OS.DeleteDC(hdcMem);
+
+    /* Release the HDC for the device */
+    device.internal_dispose_GC(hDC, null);
+    return Color.win32_new(device, (blue << 16) | (green << 8) | red);
+}
+
+/**
+ * Returns the bounds of the receiver. The rectangle will always
+ * have x and y values of 0, and the width and height of the
+ * image.
+ *
+ * @return a rectangle specifying the image's bounds
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ */
+public Rectangle getBounds() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width !is -1 && height !is -1) {
+        return new Rectangle(0, 0, width, height);
+    }
+    switch (type) {
+        case SWT.BITMAP:
+            BITMAP bm;
+            OS.GetObject(handle, BITMAP.sizeof, &bm);
+            return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight);
+        case SWT.ICON:
+            static if (OS.IsWinCE) {
+                return new Rectangle(0, 0, width = data.width, height = data.height);
+            } else {
+                ICONINFO info;
+                OS.GetIconInfo(handle, &info);
+                auto hBitmap = info.hbmColor;
+                if (hBitmap is null) hBitmap = info.hbmMask;
+                BITMAP bm;
+                OS.GetObject(hBitmap, BITMAP.sizeof, &bm);
+                if (hBitmap is info.hbmMask) bm.bmHeight /= 2;
+                if (info.hbmColor !is null) OS.DeleteObject(info.hbmColor);
+                if (info.hbmMask !is null) OS.DeleteObject(info.hbmMask);
+                return new Rectangle(0, 0, width = bm.bmWidth, height = bm.bmHeight);
+            }
+        default:
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+            return null;
+    }
+}
+
+/**
+ * Returns an <code>ImageData</code> based on the receiver
+ * Modifications made to this <code>ImageData</code> will not
+ * affect the Image.
+ *
+ * @return an <code>ImageData</code> containing the image's data and attributes
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ *
+ * @see ImageData
+ */
+public ImageData getImageData() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    BITMAP bm;
+    int depth, width, height;
+    switch (type) {
+        case SWT.ICON: {
+            static if (OS.IsWinCE) return data;
+            ICONINFO info;
+            static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+            OS.GetIconInfo(handle, &info);
+            /* Get the basic BITMAP information */
+            auto hBitmap = info.hbmColor;
+            if (hBitmap is null) hBitmap = info.hbmMask;
+            OS.GetObject(hBitmap, BITMAP.sizeof, &bm);
+            depth = bm.bmPlanes * bm.bmBitsPixel;
+            width = bm.bmWidth;
+            if (hBitmap is info.hbmMask) bm.bmHeight /= 2;
+            height = bm.bmHeight;
+            int numColors = 0;
+            if (depth <= 8) numColors = 1 << depth;
+            /* Create the BITMAPINFO */
+            BITMAPINFOHEADER bmiHeader;
+            bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+            bmiHeader.biWidth = width;
+            bmiHeader.biHeight = -height;
+            bmiHeader.biPlanes = 1;
+            bmiHeader.biBitCount = cast(short)depth;
+            bmiHeader.biCompression = OS.BI_RGB;
+            byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+            OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+
+            /* Get the HDC for the device */
+            auto hDC = device.internal_new_GC(null);
+
+            /* Create the DC and select the bitmap */
+            auto hBitmapDC = OS.CreateCompatibleDC(hDC);
+            auto hOldBitmap = OS.SelectObject(hBitmapDC, hBitmap);
+            /* Select the palette if necessary */
+            HPALETTE oldPalette;
+            if (depth <= 8) {
+                auto hPalette = device.hPalette;
+                if (hPalette !is null) {
+                    oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
+                    OS.RealizePalette(hBitmapDC);
+                }
+            }
+            /* Find the size of the image and allocate data */
+            int imageSize;
+            /* Call with null lpBits to get the image size */
+            static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+            OS.GetDIBits(hBitmapDC, hBitmap, 0, height, null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+            OS.MoveMemory(&bmiHeader, bmi.ptr, BITMAPINFOHEADER.sizeof);
+            imageSize = bmiHeader.biSizeImage;
+            byte[] data = new byte[imageSize];
+            /* Get the bitmap data */
+            auto hHeap = OS.GetProcessHeap();
+            auto lpvBits = cast(byte*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+            if (lpvBits is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+            OS.GetDIBits(hBitmapDC, hBitmap, 0, height, lpvBits, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+            OS.MoveMemory(data.ptr, lpvBits, imageSize);
+            /* Calculate the palette */
+            PaletteData palette = null;
+            if (depth <= 8) {
+                RGB[] rgbs = new RGB[numColors];
+                int srcIndex = 40;
+                for (int i = 0; i < numColors; i++) {
+                    rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
+                    srcIndex += 4;
+                }
+                palette = new PaletteData(rgbs);
+            } else if (depth is 16) {
+                palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+            } else if (depth is 24) {
+                palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+            } else if (depth is 32) {
+                palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+            } else {
+                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+            }
+
+            /* Do the mask */
+            byte [] maskData = null;
+            if (info.hbmColor is null) {
+                /* Do the bottom half of the mask */
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(hBitmapDC, hBitmap, height, height, lpvBits, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                OS.MoveMemory(maskData.ptr, lpvBits, imageSize);
+            } else {
+                /* Do the entire mask */
+                /* Create the BITMAPINFO */
+                bmiHeader = BITMAPINFOHEADER.init;
+                bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                bmiHeader.biWidth = width;
+                bmiHeader.biHeight = -height;
+                bmiHeader.biPlanes = 1;
+                bmiHeader.biBitCount = 1;
+                bmiHeader.biCompression = OS.BI_RGB;
+                bmi = new byte[BITMAPINFOHEADER.sizeof + 8];
+                OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+
+                /* First color black, second color white */
+                int offset = BITMAPINFOHEADER.sizeof;
+                bmi[offset + 4] = bmi[offset + 5] = bmi[offset + 6] = cast(byte)0xFF;
+                bmi[offset + 7] = 0;
+                OS.SelectObject(hBitmapDC, info.hbmMask);
+                /* Call with null lpBits to get the image size */
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                OS.MoveMemory(&bmiHeader, bmi.ptr, BITMAPINFOHEADER.sizeof);
+                imageSize = bmiHeader.biSizeImage;
+                maskData = new byte[imageSize];
+                auto lpvMaskBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+                if (lpvMaskBits is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(hBitmapDC, info.hbmMask, 0, height, lpvMaskBits, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                OS.MoveMemory(maskData.ptr, lpvMaskBits, imageSize);
+                OS.HeapFree(hHeap, 0, lpvMaskBits);
+                /* Loop to invert the mask */
+                for (int i = 0; i < maskData.length; i++) {
+                    maskData[i] ^= -1;
+                }
+                /* Make sure mask scanlinePad is 2 */
+                int maskPad;
+                int bpl = imageSize / height;
+                for (maskPad = 1; maskPad < 128; maskPad++) {
+                    int calcBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
+                    if (calcBpl is bpl) break;
+                }
+                maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, 2);
+            }
+            /* Clean up */
+            OS.HeapFree(hHeap, 0, lpvBits);
+            OS.SelectObject(hBitmapDC, hOldBitmap);
+            if (oldPalette !is null) {
+                OS.SelectPalette(hBitmapDC, oldPalette, false);
+                OS.RealizePalette(hBitmapDC);
+            }
+            OS.DeleteDC(hBitmapDC);
+
+            /* Release the HDC for the device */
+            device.internal_dispose_GC(hDC, null);
+
+            if (info.hbmColor !is null) OS.DeleteObject(info.hbmColor);
+            if (info.hbmMask !is null) OS.DeleteObject(info.hbmMask);
+            /* Construct and return the ImageData */
+            ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
+            imageData.maskData = maskData;
+            imageData.maskPad = 2;
+            return imageData;
+        }
+        case SWT.BITMAP: {
+            /* Get the basic BITMAP information */
+            bm = BITMAP.init;
+            OS.GetObject(handle, BITMAP.sizeof, &bm);
+            depth = bm.bmPlanes * bm.bmBitsPixel;
+            width = bm.bmWidth;
+            height = bm.bmHeight;
+            /* Find out whether this is a DIB or a DDB. */
+            bool isDib = (bm.bmBits !is null);
+            /* Get the HDC for the device */
+            auto hDC = device.internal_new_GC(null);
+
+            /*
+            * Feature in WinCE.  GetDIBits is not available in WinCE.  The
+            * workaround is to create a temporary DIB from the DDB and use
+            * the bmBits field of DIBSECTION to retrieve the image data.
+            */
+            auto handle = this.handle;
+            static if (OS.IsWinCE) {
+                if (!isDib) {
+                    bool mustRestore = false;
+                    if (memGC !is null && !memGC.isDisposed()) {
+                        memGC.flush ();
+                        mustRestore = true;
+                        GCData data = memGC.data;
+                        if (data.hNullBitmap !is null) {
+                            OS.SelectObject(memGC.handle, data.hNullBitmap);
+                            data.hNullBitmap = null;
+                        }
+                    }
+                    handle = createDIBFromDDB(hDC, this.handle, width, height);
+                    if (mustRestore) {
+                        auto hOldBitmap = OS.SelectObject(memGC.handle, this.handle);
+                        memGC.data.hNullBitmap = hOldBitmap;
+                    }
+                    isDib = true;
+                }
+            }
+            DIBSECTION dib;
+            if (isDib) {
+                OS.GetObject(handle, DIBSECTION.sizeof, &dib);
+            }
+            /* Calculate number of colors */
+            int numColors = 0;
+            if (depth <= 8) {
+                if (isDib) {
+                    numColors = dib.dsBmih.biClrUsed;
+                } else {
+                    numColors = 1 << depth;
+                }
+            }
+            /* Create the BITMAPINFO */
+            byte[] bmi = null;
+            BITMAPINFOHEADER bmiHeader;
+            if (!isDib) {
+                bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                bmiHeader.biWidth = width;
+                bmiHeader.biHeight = -height;
+                bmiHeader.biPlanes = 1;
+                bmiHeader.biBitCount = cast(short)depth;
+                bmiHeader.biCompression = OS.BI_RGB;
+                bmi = new byte[BITMAPINFOHEADER.sizeof + numColors * 4];
+                OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+            }
+
+            /* Create the DC and select the bitmap */
+            auto hBitmapDC = OS.CreateCompatibleDC(hDC);
+            auto hOldBitmap = OS.SelectObject(hBitmapDC, handle);
+            /* Select the palette if necessary */
+            HPALETTE oldPalette;
+            if (!isDib && depth <= 8) {
+                auto hPalette = device.hPalette;
+                if (hPalette !is null) {
+                    oldPalette = OS.SelectPalette(hBitmapDC, hPalette, false);
+                    OS.RealizePalette(hBitmapDC);
+                }
+            }
+            /* Find the size of the image and allocate data */
+            int imageSize;
+            if (isDib) {
+                imageSize = dib.dsBmih.biSizeImage;
+            } else {
+                /* Call with null lpBits to get the image size */
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(hBitmapDC, handle, 0, height, null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                OS.MoveMemory(&bmiHeader, bmi.ptr, BITMAPINFOHEADER.sizeof);
+                imageSize = bmiHeader.biSizeImage;
+            }
+            byte[] data = new byte[imageSize];
+            /* Get the bitmap data */
+            if (isDib) {
+                if (OS.IsWinCE) {
+                    if (this.handle !is handle) {
+                        /* get image data from the temporary DIB */
+                        OS.MoveMemory(data.ptr, dib.dsBm.bmBits, imageSize);
+                    }
+                } else {
+                    OS.MoveMemory(data.ptr, bm.bmBits, imageSize);
+                }
+            } else {
+                auto hHeap = OS.GetProcessHeap();
+                auto lpvBits = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, imageSize);
+                if (lpvBits is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+                OS.GetDIBits(hBitmapDC, handle, 0, height, lpvBits, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS);
+                OS.MoveMemory(data.ptr, lpvBits, imageSize);
+                OS.HeapFree(hHeap, 0, lpvBits);
+            }
+            /* Calculate the palette */
+            PaletteData palette = null;
+            if (depth <= 8) {
+                RGB[] rgbs = new RGB[numColors];
+                if (isDib) {
+                    static if (OS.IsWinCE) {
+                        /*
+                        * Feature on WinCE.  GetDIBColorTable is not supported.
+                        * The workaround is to set a pixel to the desired
+                        * palette index and use getPixel to get the corresponding
+                        * RGB value.
+                        */
+                        int red = 0, green = 0, blue = 0;
+                        byte[1] pBits;
+                        OS.MoveMemory(pBits.ptr, bm.bmBits, 1);
+                        byte oldValue = pBits[0];
+                        int mask = (0xFF << (8 - bm.bmBitsPixel)) & 0x00FF;
+                        for (int i = 0; i < numColors; i++) {
+                            pBits[0] = cast(byte)((i << (8 - bm.bmBitsPixel)) | (pBits[0] & ~mask));
+                            OS.MoveMemory(bm.bmBits, pBits.ptr, 1);
+                            int color = OS.GetPixel(hBitmapDC, 0, 0);
+                            blue = (color & 0xFF0000) >> 16;
+                            green = (color & 0xFF00) >> 8;
+                            red = color & 0xFF;
+                            rgbs[i] = new RGB(red, green, blue);
+                        }
+                        pBits[0] = oldValue;
+                        OS.MoveMemory(bm.bmBits, pBits.ptr, 1);
+                    } else {
+                        byte[] colors = new byte[numColors * 4];
+                        OS.GetDIBColorTable(hBitmapDC, 0, numColors, cast(RGBQUAD*)colors.ptr);
+                        int colorIndex = 0;
+                        for (int i = 0; i < rgbs.length; i++) {
+                            rgbs[i] = new RGB(colors[colorIndex + 2] & 0xFF, colors[colorIndex + 1] & 0xFF, colors[colorIndex] & 0xFF);
+                            colorIndex += 4;
+                        }
+                    }
+                } else {
+                    int srcIndex = BITMAPINFOHEADER.sizeof;
+                    for (int i = 0; i < numColors; i++) {
+                        rgbs[i] = new RGB(bmi[srcIndex + 2] & 0xFF, bmi[srcIndex + 1] & 0xFF, bmi[srcIndex] & 0xFF);
+                        srcIndex += 4;
+                    }
+                }
+                palette = new PaletteData(rgbs);
+            } else if (depth is 16) {
+                palette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+            } else if (depth is 24) {
+                palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+            } else if (depth is 32) {
+                palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+            } else {
+                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+            }
+            /* Clean up */
+            OS.SelectObject(hBitmapDC, hOldBitmap);
+            if (oldPalette !is null) {
+                OS.SelectPalette(hBitmapDC, oldPalette, false);
+                OS.RealizePalette(hBitmapDC);
+            }
+            static if (OS.IsWinCE) {
+                if (handle !is this.handle) {
+                    /* free temporary DIB */
+                    OS.DeleteObject (handle);
+                }
+            }
+            OS.DeleteDC(hBitmapDC);
+
+            /* Release the HDC for the device */
+            device.internal_dispose_GC(hDC, null);
+
+            /* Construct and return the ImageData */
+            ImageData imageData = new ImageData(width, height, depth, palette, 4, data);
+            imageData.transparentPixel = this.transparentPixel;
+            imageData.alpha = alpha;
+            if (alpha is -1 && alphaData !is null) {
+                imageData.alphaData = new byte[alphaData.length];
+                System.arraycopy(alphaData, 0, imageData.alphaData, 0, alphaData.length);
+            }
+            return imageData;
+        }
+        default:
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+            return null;
+    }
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+    return cast(hash_t)handle;
+}
+
+void init_(int width, int height) {
+    if (width <= 0 || height <= 0) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    type = SWT.BITMAP;
+    auto hDC = device.internal_new_GC(null);
+    handle = OS.CreateCompatibleBitmap(hDC, width, height);
+    /*
+    * Feature in Windows.  CreateCompatibleBitmap() may fail
+    * for large images.  The fix is to create a DIB section
+    * in that case.
+    */
+    if (handle is null) {
+        int bits = OS.GetDeviceCaps(hDC, OS.BITSPIXEL);
+        int planes = OS.GetDeviceCaps(hDC, OS.PLANES);
+        int depth = bits * planes;
+        if (depth < 16) depth = 16;
+        handle = createDIB(width, height, depth);
+    }
+    if (handle !is null) {
+        auto memDC = OS.CreateCompatibleDC(hDC);
+        auto hOldBitmap = OS.SelectObject(memDC, handle);
+        OS.PatBlt(memDC, 0, 0, width, height, OS.PATCOPY);
+        OS.SelectObject(memDC, hOldBitmap);
+        OS.DeleteDC(memDC);
+    }
+    device.internal_dispose_GC(hDC, null);
+    if (handle is null) {
+        SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError());
+    }
+}
+
+static HGDIOBJ createDIB(int width, int height, int depth) {
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biWidth = width;
+    bmiHeader.biHeight = -height;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)depth;
+    static if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS;
+    else bmiHeader.biCompression = OS.BI_RGB;
+    byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)];
+    OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+    /* Set the rgb colors into the bitmap info */
+    static if (OS.IsWinCE) {
+        int redMask = 0xFF00;
+        int greenMask = 0xFF0000;
+        int blueMask = 0xFF000000;
+        /* big endian */
+        int offset = BITMAPINFOHEADER.sizeof;
+        bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+        bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+        bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+        bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+        bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+        bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+        bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+        bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+        bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+        bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+        bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+        bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
+    }
+
+    void* pBits;
+    return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+}
+
+/**
+ * Feature in WinCE.  GetIconInfo is not available in WinCE.
+ * The workaround is to cache the object ImageData for images
+ * of type SWT.ICON. The bitmaps hbmMask and hbmColor can then
+ * be reconstructed by using our version of getIconInfo.
+ * This function takes an ICONINFO object and sets the fields
+ * hbmMask and hbmColor with the corresponding bitmaps it has
+ * created.
+ * Note.  These bitmaps must be freed - as they would have to be
+ * if the regular GetIconInfo had been used.
+ */
+static void GetIconInfo(Image image, ICONINFO* info) {
+    int[] result = init_(image.device, null, image.data);
+    info.hbmColor = cast(HBITMAP)result[0];
+    info.hbmMask = cast(HBITMAP)result[1];
+}
+
+static int[] init_(Device device, Image image, ImageData i) {
+
+    /*
+     * BUG in Windows 98:
+     * A monochrome DIBSection will display as solid black
+     * on Windows 98 machines, even though it contains the
+     * correct data. The fix is to convert 1-bit ImageData
+     * into 4-bit ImageData before creating the image.
+     */
+    /* Windows does not support 2-bit images. Convert to 4-bit image. */
+    if ((OS.IsWin95 && i.depth is 1 && i.getTransparencyType() !is SWT.TRANSPARENCY_MASK) || i.depth is 2) {
+        ImageData img = new ImageData(i.width, i.height, 4, i.palette);
+        ImageData.blit(ImageData.BLIT_SRC,
+            i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, null, null, null,
+            ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+            img.data, img.depth, img.bytesPerLine, i.getByteOrder(), 0, 0, img.width, img.height, null, null, null,
+            false, false);
+        img.transparentPixel = i.transparentPixel;
+        img.maskPad = i.maskPad;
+        img.maskData = i.maskData;
+        img.alpha = i.alpha;
+        img.alphaData = i.alphaData;
+        i = img;
+    }
+    /*
+     * Windows supports 16-bit mask of (0x7C00, 0x3E0, 0x1F),
+     * 24-bit mask of (0xFF0000, 0xFF00, 0xFF) and 32-bit mask
+     * (0x00FF0000, 0x0000FF00, 0x000000FF) as documented in
+     * MSDN BITMAPINFOHEADER.  Make sure the image is
+     * Windows-supported.
+     */
+    /*
+    * Note on WinCE.  CreateDIBSection requires the biCompression
+    * field of the BITMAPINFOHEADER to be set to BI_BITFIELDS for
+    * 16 and 32 bit direct images (see MSDN for CreateDIBSection).
+    * In this case, the color mask can be set to any value.  For
+    * consistency, it is set to the same mask used by non WinCE
+    * platforms in BI_RGB mode.
+    */
+    if (i.palette.isDirect) {
+        final PaletteData palette = i.palette;
+        final int redMask = palette.redMask;
+        final int greenMask = palette.greenMask;
+        final int blueMask = palette.blueMask;
+        int newDepth = i.depth;
+        int newOrder = ImageData.MSB_FIRST;
+        PaletteData newPalette = null;
+
+        switch (i.depth) {
+            case 8:
+                newDepth = 16;
+                newOrder = ImageData.LSB_FIRST;
+                newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+                break;
+            case 16:
+                newOrder = ImageData.LSB_FIRST;
+                if (!(redMask is 0x7C00 && greenMask is 0x3E0 && blueMask is 0x1F)) {
+                    newPalette = new PaletteData(0x7C00, 0x3E0, 0x1F);
+                }
+                break;
+            case 24:
+                if (!(redMask is 0xFF && greenMask is 0xFF00 && blueMask is 0xFF0000)) {
+                    newPalette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+                }
+                break;
+            case 32:
+                if (!(redMask is 0xFF00 && greenMask is 0xFF0000 && blueMask is 0xFF000000)) {
+                    newPalette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                }
+                break;
+            default:
+                SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+        }
+        if (newPalette !is null) {
+            ImageData img = new ImageData(i.width, i.height, newDepth, newPalette);
+            ImageData.blit(ImageData.BLIT_SRC,
+                    i.data, i.depth, i.bytesPerLine, i.getByteOrder(), 0, 0, i.width, i.height, redMask, greenMask, blueMask,
+                    ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+                    img.data, img.depth, img.bytesPerLine, newOrder, 0, 0, img.width, img.height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+                    false, false);
+            if (i.transparentPixel !is -1) {
+                img.transparentPixel = newPalette.getPixel(palette.getRGB(i.transparentPixel));
+            }
+            img.maskPad = i.maskPad;
+            img.maskData = i.maskData;
+            img.alpha = i.alpha;
+            img.alphaData = i.alphaData;
+            i = img;
+        }
+    }
+    /* Construct bitmap info header by hand */
+    RGB[] rgbs = i.palette.getRGBs();
+    bool useBitfields = OS.IsWinCE && (i.depth is 16 || i.depth is 32);
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biWidth = i.width;
+    bmiHeader.biHeight = -i.height;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)i.depth;
+    if (useBitfields) bmiHeader.biCompression = OS.BI_BITFIELDS;
+    else bmiHeader.biCompression = OS.BI_RGB;
+    bmiHeader.biClrUsed = rgbs is null ? 0 : rgbs.length;
+    byte[] bmi;
+    if (i.palette.isDirect)
+        bmi = new byte[BITMAPINFOHEADER.sizeof + (useBitfields ? 12 : 0)];
+    else
+        bmi = new byte[BITMAPINFOHEADER.sizeof + rgbs.length * 4];
+    OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+    /* Set the rgb colors into the bitmap info */
+    int offset = BITMAPINFOHEADER.sizeof;
+    if (i.palette.isDirect) {
+        if (useBitfields) {
+            PaletteData palette = i.palette;
+            int redMask = palette.redMask;
+            int greenMask = palette.greenMask;
+            int blueMask = palette.blueMask;
+            /*
+             * The color masks must be written based on the
+             * endianness of the ImageData.
+             */
+            if (i.getByteOrder() is ImageData.LSB_FIRST) {
+                bmi[offset] = cast(byte)((redMask & 0xFF) >> 0);
+                bmi[offset + 1] = cast(byte)((redMask & 0xFF00) >> 8);
+                bmi[offset + 2] = cast(byte)((redMask & 0xFF0000) >> 16);
+                bmi[offset + 3] = cast(byte)((redMask & 0xFF000000) >> 24);
+                bmi[offset + 4] = cast(byte)((greenMask & 0xFF) >> 0);
+                bmi[offset + 5] = cast(byte)((greenMask & 0xFF00) >> 8);
+                bmi[offset + 6] = cast(byte)((greenMask & 0xFF0000) >> 16);
+                bmi[offset + 7] = cast(byte)((greenMask & 0xFF000000) >> 24);
+                bmi[offset + 8] = cast(byte)((blueMask & 0xFF) >> 0);
+                bmi[offset + 9] = cast(byte)((blueMask & 0xFF00) >> 8);
+                bmi[offset + 10] = cast(byte)((blueMask & 0xFF0000) >> 16);
+                bmi[offset + 11] = cast(byte)((blueMask & 0xFF000000) >> 24);
+            } else {
+                bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+                bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+                bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+                bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+                bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+                bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+                bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+                bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+                bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+                bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+                bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+                bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
+            }
+        }
+    } else {
+        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;
+        }
+    }
+    void* pBits;
+    auto hDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+    if (hDib is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    /* In case of a scanline pad other than 4, do the work to convert it */
+    byte[] data = i.data;
+    if (i.scanlinePad !is 4 && (i.bytesPerLine % 4 !is 0)) {
+        data = ImageData.convertPad(data, i.width, i.height, i.depth, i.scanlinePad, 4);
+    }
+    OS.MoveMemory(pBits, data.ptr, data.length);
+
+    int /*long*/ [] result = null;
+    if (i.getTransparencyType() is SWT.TRANSPARENCY_MASK) {
+        /* Get the HDC for the device */
+        auto hDC = device.internal_new_GC(null);
+
+        /* Create the color bitmap */
+        auto hdcSrc = OS.CreateCompatibleDC(hDC);
+        OS.SelectObject(hdcSrc, hDib);
+        auto hBitmap = OS.CreateCompatibleBitmap(hDC, i.width, i.height);
+        if (hBitmap is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        auto hdcDest = OS.CreateCompatibleDC(hDC);
+        OS.SelectObject(hdcDest, hBitmap);
+        OS.BitBlt(hdcDest, 0, 0, i.width, i.height, hdcSrc, 0, 0, OS.SRCCOPY);
+
+        /* Release the HDC for the device */
+        device.internal_dispose_GC(hDC, null);
+
+        /* Create the mask. Windows requires icon masks to have a scanline pad of 2. */
+        byte[] maskData = ImageData.convertPad(i.maskData, i.width, i.height, 1, i.maskPad, 2);
+        auto hMask = OS.CreateBitmap(i.width, i.height, 1, 1, maskData.ptr);
+        if (hMask is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        OS.SelectObject(hdcSrc, hMask);
+        OS.PatBlt(hdcSrc, 0, 0, i.width, i.height, OS.DSTINVERT);
+        OS.DeleteDC(hdcSrc);
+        OS.DeleteDC(hdcDest);
+        OS.DeleteObject(hDib);
+
+        if (image is null) {
+            result = [ cast(int) hBitmap, cast(int) hMask];
+        } else {
+            /* Create the icon */
+            ICONINFO info;
+            info.fIcon = true;
+            info.hbmColor = hBitmap;
+            info.hbmMask = hMask;
+            auto hIcon = OS.CreateIconIndirect(&info);
+            if (hIcon is null) SWT.error(SWT.ERROR_NO_HANDLES);
+            OS.DeleteObject(hBitmap);
+            OS.DeleteObject(hMask);
+            image.handle = hIcon;
+            image.type = SWT.ICON;
+            static if (OS.IsWinCE) image.data = i;
+        }
+    } else {
+        if (image is null) {
+            result = [ cast(int) hDib];
+        } else {
+            image.handle = hDib;
+            image.type = SWT.BITMAP;
+            image.transparentPixel = i.transparentPixel;
+            if (image.transparentPixel is -1) {
+                image.alpha = i.alpha;
+                if (i.alpha is -1 && i.alphaData !is null) {
+                    int length = i.alphaData.length;
+                    image.alphaData = new byte[length];
+                    System.arraycopy(i.alphaData, 0, image.alphaData, 0, length);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+static int[] init_(Device device, Image image, ImageData source, ImageData mask) {
+    /* Create a temporary image and locate the black pixel */
+    ImageData imageData;
+    int blackIndex = 0;
+    if (source.palette.isDirect) {
+        imageData = new ImageData(source.width, source.height, source.depth, source.palette);
+    } else {
+        RGB black = new RGB(0, 0, 0);
+        RGB[] rgbs = source.getRGBs();
+        if (source.transparentPixel !is -1) {
+            /*
+             * The source had transparency, so we can use the transparent pixel
+             * for black.
+             */
+            RGB[] newRGBs = new RGB[rgbs.length];
+            System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
+            if (source.transparentPixel >= newRGBs.length) {
+                /* Grow the palette with black */
+                rgbs = new RGB[source.transparentPixel + 1];
+                System.arraycopy(newRGBs, 0, rgbs, 0, newRGBs.length);
+                for (int i = newRGBs.length; i <= source.transparentPixel; i++) {
+                    rgbs[i] = new RGB(0, 0, 0);
+                }
+            } else {
+                newRGBs[source.transparentPixel] = black;
+                rgbs = newRGBs;
+            }
+            blackIndex = source.transparentPixel;
+            imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
+        } else {
+            while (blackIndex < rgbs.length) {
+                if (rgbs[blackIndex] ==/*eq*/ black) break;
+                blackIndex++;
+            }
+            if (blackIndex is rgbs.length) {
+                /*
+                 * We didn't find black in the palette, and there is no transparent
+                 * pixel we can use.
+                 */
+                if ((1 << source.depth) > rgbs.length) {
+                    /* We can grow the palette and add black */
+                    RGB[] newRGBs = new RGB[rgbs.length + 1];
+                    System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length);
+                    newRGBs[rgbs.length] = black;
+                    rgbs = newRGBs;
+                } else {
+                    /* No room to grow the palette */
+                    blackIndex = -1;
+                }
+            }
+            imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs));
+        }
+    }
+    if (blackIndex is -1) {
+        /* There was no black in the palette, so just copy the data over */
+        System.arraycopy(source.data, 0, imageData.data, 0, imageData.data.length);
+    } else {
+        /* Modify the source image to contain black wherever the mask is 0 */
+        int[] imagePixels = new int[imageData.width];
+        int[] maskPixels = new int[mask.width];
+        for (int y = 0; y < imageData.height; y++) {
+            source.getPixels(0, y, imageData.width, imagePixels, 0);
+            mask.getPixels(0, y, mask.width, maskPixels, 0);
+            for (int i = 0; i < imagePixels.length; i++) {
+                if (maskPixels[i] is 0) imagePixels[i] = blackIndex;
+            }
+            imageData.setPixels(0, y, source.width, imagePixels, 0);
+        }
+    }
+    imageData.maskPad = mask.scanlinePad;
+    imageData.maskData = mask.data;
+    return init_(device, image, imageData);
+}
+void init_(ImageData i) {
+    if (i is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(device, this, i);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public HDC internal_new_GC (GCData data) {
+    if (handle is null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    /*
+    * Create a new GC that can draw into the image.
+    * Only supported for bitmaps.
+    */
+    if (type !is SWT.BITMAP || memGC !is null) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+
+    /* Create a compatible HDC for the device */
+    auto hDC = device.internal_new_GC(null);
+    auto imageDC = OS.CreateCompatibleDC(hDC);
+    device.internal_dispose_GC(hDC, null);
+    if (imageDC is null) SWT.error(SWT.ERROR_NO_HANDLES);
+
+    if (data !is null) {
+        /* Set the GCData fields */
+        int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+        if ((data.style & mask) !is 0) {
+            data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
+        } else {
+            data.style |= SWT.LEFT_TO_RIGHT;
+        }
+        data.device = device;
+        data.image = this;
+        data.font = device.systemFont;
+    }
+    return imageDC;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (HDC hDC, GCData data) {
+    OS.DeleteDC(hDC);
+}
+
+/**
+ * Returns <code>true</code> if the image has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the image.
+ * When an image has been disposed, it is an error to
+ * invoke any other method using the image.
+ *
+ * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Sets the color to which to map the transparent pixel.
+ * <p>
+ * There are certain uses of <code>Images</code> that do not support
+ * transparency (for example, setting an image into a button or label).
+ * In these cases, it may be desired to simulate transparency by using
+ * the background color of the widget to paint the transparent pixels
+ * of the image. This method specifies the color that will be used in
+ * these cases. For example:
+ * <pre>
+ *    Button b = new Button();
+ *    image.setBackground(b.getBackground());
+ *    b.setImage(image);
+ * </pre>
+ * </p><p>
+ * The image may be modified by this operation (in effect, the
+ * transparent regions may be filled with the supplied color).  Hence
+ * this operation is not reversible and it is not legal to call
+ * this function twice or with a null argument.
+ * </p><p>
+ * This method has no effect if the receiver does not have a transparent
+ * pixel value.
+ * </p>
+ *
+ * @param color the color to use when a transparent pixel is specified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the color is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setBackground(Color color) {
+    /*
+    * Note.  Not implemented on WinCE.
+    */
+    static if (OS.IsWinCE) return;
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (color is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (transparentPixel is -1) return;
+    transparentColor = -1;
+
+    /* Get the HDC for the device */
+    auto hDC = device.internal_new_GC(null);
+
+    /* Change the background color in the image */
+    BITMAP bm;
+    OS.GetObject(handle, BITMAP.sizeof, &bm);
+    auto hdcMem = OS.CreateCompatibleDC(hDC);
+    OS.SelectObject(hdcMem, handle);
+    int maxColors = 1 << bm.bmBitsPixel;
+    byte[] colors = new byte[maxColors * 4];
+    static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+    int numColors = OS.GetDIBColorTable(hdcMem, 0, maxColors, cast(RGBQUAD*)colors.ptr);
+    int offset = transparentPixel * 4;
+    colors[offset] = cast(byte)color.getBlue();
+    colors[offset + 1] = cast(byte)color.getGreen();
+    colors[offset + 2] = cast(byte)color.getRed();
+    static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+    OS.SetDIBColorTable(hdcMem, 0, numColors, cast(RGBQUAD*)colors.ptr);
+    OS.DeleteDC(hdcMem);
+
+    /* Release the HDC for the device */
+    device.internal_dispose_GC(hDC, null);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "Image {*DISPOSED*}";
+    return Format( "Image {{{}}", handle );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new image.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param type the type of the image (<code>SWT.BITMAP</code> or <code>SWT.ICON</code>)
+ * @param handle the OS handle for the image
+ * @return a new image object containing the specified device, type and handle
+ */
+public static Image win32_new(Device device, int type, HGDIOBJ handle) {
+    Image image = new Image(device);
+    image.disposeChecking = false;
+    image.type = type;
+    image.handle = handle;
+    return image;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3676 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.ImageData;
+
+
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.ImageDataLoader;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.CloneableCompatibility;
+
+public import java.io.InputStream;
+import java.lang.System;
+import java.lang.all;
+
+
+/**
+ * Instances of this class are device-independent descriptions
+ * of images. They are typically used as an intermediate format
+ * between loading from or writing to streams and creating an
+ * <code>Image</code>.
+ * <p>
+ * Note that the public fields <code>x</code>, <code>y</code>,
+ * <code>disposalMethod</code> and <code>delayTime</code> are
+ * typically only used when the image is in a set of images used
+ * for animation.
+ * </p>
+ *
+ * @see Image
+ * @see ImageLoader
+ * @see <a href="http://www.eclipse.org/swt/snippets/#image">ImageData snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ImageAnalyzer</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class ImageData : CloneableCompatibility {
+
+    /**
+     * The width of the image, in pixels.
+     */
+    public int width;
+
+    /**
+     * The height of the image, in pixels.
+     */
+    public int height;
+
+    /**
+     * The color depth of the image, in bits per pixel.
+     * <p>
+     * Note that a depth of 8 or less does not necessarily
+     * mean that the image is palette indexed, or
+     * conversely that a depth greater than 8 means that
+     * the image is direct color.  Check the associated
+     * PaletteData's isDirect field for such determinations.
+     */
+    public int depth;
+
+    /**
+     * The scanline padding.
+     * <p>
+     * If one scanline of the image is not a multiple of
+     * this number, it will be padded with zeros until it is.
+     * </p>
+     */
+    public int scanlinePad;
+
+    /**
+     * The number of bytes per scanline.
+     * <p>
+     * This is a multiple of the scanline padding.
+     * </p>
+     */
+    public int bytesPerLine;
+
+    /**
+     * The pixel data of the image.
+     * <p>
+     * Note that for 16 bit depth images the pixel data is stored
+     * in least significant byte order; however, for 24bit and
+     * 32bit depth images the pixel data is stored in most
+     * significant byte order.
+     * </p>
+     */
+    public byte[] data;
+
+    /**
+     * The color table for the image.
+     */
+    public PaletteData palette;
+
+    /**
+     * The transparent pixel.
+     * <p>
+     * Pixels with this value are transparent.
+     * </p><p>
+     * The default is -1 which means 'no transparent pixel'.
+     * </p>
+     */
+    public int transparentPixel;
+
+    /**
+     * An icon-specific field containing the data from the icon mask.
+     * <p>
+     * This is a 1 bit bitmap stored with the most significant
+     * bit first.  The number of bytes per scanline is
+     * '((width + 7) / 8 + (maskPad - 1)) / maskPad * maskPad'.
+     * </p><p>
+     * The default is null which means 'no transparency mask'.
+     * </p>
+     */
+    public byte[] maskData;
+
+    /**
+     * An icon-specific field containing the scanline pad of the mask.
+     * <p>
+     * If one scanline of the transparency mask is not a
+     * multiple of this number, it will be padded with zeros until
+     * it is.
+     * </p>
+     */
+    public int maskPad;
+
+    /**
+     * The alpha data of the image.
+     * <p>
+     * Every pixel can have an <em>alpha blending</em> value that
+     * varies from 0, meaning fully transparent, to 255 meaning
+     * fully opaque.  The number of bytes per scanline is
+     * 'width'.
+     * </p>
+     */
+    public byte[] alphaData;
+
+    /**
+     * The global alpha value to be used for every pixel.
+     * <p>
+     * If this value is set, the <code>alphaData</code> field
+     * is ignored and when the image is rendered each pixel
+     * will be blended with the background an amount
+     * proportional to this value.
+     * </p><p>
+     * The default is -1 which means 'no global alpha value'
+     * </p>
+     */
+    public int alpha;
+
+    /**
+     * The type of file from which the image was read.
+     *
+     * It is expressed as one of the following values:
+     * <dl>
+     * <dt><code>IMAGE_BMP</code></dt>
+     * <dd>Windows BMP file format, no compression</dd>
+     * <dt><code>IMAGE_BMP_RLE</code></dt>
+     * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+     * <dt><code>IMAGE_GIF</code></dt>
+     * <dd>GIF file format</dd>
+     * <dt><code>IMAGE_ICO</code></dt>
+     * <dd>Windows ICO file format</dd>
+     * <dt><code>IMAGE_JPEG</code></dt>
+     * <dd>JPEG file format</dd>
+     * <dt><code>IMAGE_PNG</code></dt>
+     * <dd>PNG file format</dd>
+     * </dl>
+     */
+    public int type;
+
+    /**
+     * The x coordinate of the top left corner of the image
+     * within the logical screen (this field corresponds to
+     * the GIF89a Image Left Position value).
+     */
+    public int x;
+
+    /**
+     * The y coordinate of the top left corner of the image
+     * within the logical screen (this field corresponds to
+     * the GIF89a Image Top Position value).
+     */
+    public int y;
+
+    /**
+     * A description of how to dispose of the current image
+     * before displaying the next.
+     *
+     * It is expressed as one of the following values:
+     * <dl>
+     * <dt><code>DM_UNSPECIFIED</code></dt>
+     * <dd>disposal method not specified</dd>
+     * <dt><code>DM_FILL_NONE</code></dt>
+     * <dd>do nothing - leave the image in place</dd>
+     * <dt><code>DM_FILL_BACKGROUND</code></dt>
+     * <dd>fill with the background color</dd>
+     * <dt><code>DM_FILL_PREVIOUS</code></dt>
+     * <dd>restore the previous picture</dd>
+     * </dl>
+     * (this field corresponds to the GIF89a Disposal Method value)
+     */
+    public int disposalMethod;
+
+    /**
+     * The time to delay before displaying the next image
+     * in an animation (this field corresponds to the GIF89a
+     * Delay Time value).
+     */
+    public int delayTime;
+
+    /**
+     * Arbitrary channel width data to 8-bit conversion table.
+     */
+    private static byte[][] ANY_TO_EIGHT;
+    private static byte[] ONE_TO_ONE_MAPPING;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ) return;
+        synchronized {
+            if( static_this_completed ) return;
+            ANY_TO_EIGHT = new byte[][](9);
+            for (int b = 0; b < 9; ++b) {
+                byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
+                if (b is 0) continue;
+                int inc = 0;
+                for (int bit = 0x10000; (bit >>= b) !is 0;) inc |= bit;
+                for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = cast(byte)(v >> 8);
+            }
+            ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
+            static_this_completed = true;
+        }
+    }
+
+    /**
+     * Scaled 8x8 Bayer dither matrix.
+     */
+    static const int[][] DITHER_MATRIX = [
+        [ 0xfc0000, 0x7c0000, 0xdc0000, 0x5c0000, 0xf40000, 0x740000, 0xd40000, 0x540000 ],
+        [ 0x3c0000, 0xbc0000, 0x1c0000, 0x9c0000, 0x340000, 0xb40000, 0x140000, 0x940000 ],
+        [ 0xcc0000, 0x4c0000, 0xec0000, 0x6c0000, 0xc40000, 0x440000, 0xe40000, 0x640000 ],
+        [ 0x0c0000, 0x8c0000, 0x2c0000, 0xac0000, 0x040000, 0x840000, 0x240000, 0xa40000 ],
+        [ 0xf00000, 0x700000, 0xd00000, 0x500000, 0xf80000, 0x780000, 0xd80000, 0x580000 ],
+        [ 0x300000, 0xb00000, 0x100000, 0x900000, 0x380000, 0xb80000, 0x180000, 0x980000 ],
+        [ 0xc00000, 0x400000, 0xe00000, 0x600000, 0xc80000, 0x480000, 0xe80000, 0x680000 ],
+        [ 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000, 0x880000, 0x280000, 0xa80000 ]
+    ];
+
+/**
+ * Constructs a new, empty ImageData with the given width, height,
+ * depth and palette. The data will be initialized to an (all zero)
+ * array of the appropriate size.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param depth the depth of the image
+ * @param palette the palette of the image (must not be null)
+ *
+ * @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>
+ *    <li>ERROR_NULL_ARGUMENT - if the palette is null</li>
+ * </ul>
+ */
+public this(int width, int height, int depth, PaletteData palette) {
+    this(width, height, depth, palette,
+        4, null, 0, null,
+        null, -1, -1, SWT.IMAGE_UNDEFINED,
+        0, 0, 0, 0);
+}
+
+/**
+ * Constructs a new, empty ImageData with the given width, height,
+ * depth, palette, scanlinePad and data.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param depth the depth of the image
+ * @param palette the palette of the image
+ * @param scanlinePad the padding of each line, in bytes
+ * @param data the data of the image
+ *
+ * @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, 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>
+ */
+public this(int width, int height, int depth, PaletteData palette, int scanlinePad, byte[] data) {
+    this(width, height, depth, palette,
+        scanlinePad, checkData(data), 0, null,
+        null, -1, -1, SWT.IMAGE_UNDEFINED,
+        0, 0, 0, 0);
+}
+
+/**
+ * Constructs an <code>ImageData</code> loaded from the specified
+ * input stream. Throws an error if an error occurs while loading
+ * the image, or if the image has an unsupported type.  Application
+ * code is still responsible for closing the input stream.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p><p>
+ * This constructor may be used to load a resource as follows:
+ * </p>
+ * <pre>
+ *     static ImageData loadImageData (Class clazz, String string) {
+ *          InputStream stream = clazz.getResourceAsStream (string);
+ *          if (stream is null) return null;
+ *          ImageData imageData = null;
+ *          try {
+ *               imageData = new ImageData (stream);
+ *          } catch (SWTException ex) {
+ *          } finally {
+ *               try {
+ *                    stream.close ();
+ *               } catch (IOException ex) {}
+ *          }
+ *          return imageData;
+ *     }
+ * </pre>
+ *
+ * @param stream the input stream to load the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
+ * </ul>
+ *
+ * @see ImageLoader#load(InputStream)
+ */
+public this(InputStream stream) {
+    ImageData[] data = ImageDataLoader.load(stream);
+    if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    ImageData i = data[0];
+    setAllFields(
+        i.width,
+        i.height,
+        i.depth,
+        i.scanlinePad,
+        i.bytesPerLine,
+        i.data,
+        i.palette,
+        i.transparentPixel,
+        i.maskData,
+        i.maskPad,
+        i.alphaData,
+        i.alpha,
+        i.type,
+        i.x,
+        i.y,
+        i.disposalMethod,
+        i.delayTime);
+}
+
+/**
+ * Constructs an <code>ImageData</code> loaded from a file with the
+ * specified name. Throws an error if an error occurs loading the
+ * image, or if the image has an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the file contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p>
+ *
+ * @param filename the name of the file to load the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the file</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
+ * </ul>
+ */
+public this(String filename) {
+    ImageData[] data = ImageDataLoader.load(filename);
+    if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    ImageData i = data[0];
+    setAllFields(
+        i.width,
+        i.height,
+        i.depth,
+        i.scanlinePad,
+        i.bytesPerLine,
+        i.data,
+        i.palette,
+        i.transparentPixel,
+        i.maskData,
+        i.maskPad,
+        i.alphaData,
+        i.alpha,
+        i.type,
+        i.x,
+        i.y,
+        i.disposalMethod,
+        i.delayTime);
+}
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+private this() {
+}
+
+/**
+ * Constructs an image data by giving values for all non-computable fields.
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ */
+this(
+    int width, int height, int depth, PaletteData palette,
+    int scanlinePad, byte[] data, int maskPad, byte[] maskData,
+    byte[] alphaData, int alpha, int transparentPixel, int type,
+    int x, int y, int disposalMethod, int delayTime)
+{
+    if (palette is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (!(depth is 1 || depth is 2 || depth is 4 || depth is 8
+        || depth is 16 || depth is 24 || depth is 32)) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (width <= 0 || height <= 0) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (scanlinePad is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
+
+    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 SWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine;
+    if (data !is null && data.length < minBytesPerLine * height) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    setAllFields(
+        width,
+        height,
+        depth,
+        scanlinePad,
+        bytesPerLine,
+        data !is null ? data : new byte[bytesPerLine * height],
+        palette,
+        transparentPixel,
+        maskData,
+        maskPad,
+        alphaData,
+        alpha,
+        type,
+        x,
+        y,
+        disposalMethod,
+        delayTime);
+}
+
+/**
+ * Initializes all fields in the receiver. This method must be called
+ * by all public constructors to ensure that all fields are initialized
+ * for a new ImageData object. If a new field is added to the class,
+ * then it must be added to this method.
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ */
+void setAllFields(int width, int height, int depth, int scanlinePad,
+    int bytesPerLine, byte[] data, PaletteData palette, int transparentPixel,
+    byte[] maskData, int maskPad, byte[] alphaData, int alpha,
+    int type, int x, int y, int disposalMethod, int delayTime) {
+
+    this.width = width;
+    this.height = height;
+    this.depth = depth;
+    this.scanlinePad = scanlinePad;
+    this.bytesPerLine = bytesPerLine;
+    this.data = data;
+    this.palette = palette;
+    this.transparentPixel = transparentPixel;
+    this.maskData = maskData;
+    this.maskPad = maskPad;
+    this.alphaData = alphaData;
+    this.alpha = alpha;
+    this.type = type;
+    this.x = x;
+    this.y = y;
+    this.disposalMethod = disposalMethod;
+    this.delayTime = delayTime;
+}
+
+/**
+ * Invokes internal SWT functionality to create a new instance of
+ * this class.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>ImageData</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is subject
+ * to change without notice, and should never be called from
+ * application code.
+ * </p>
+ * <p>
+ * This method is for internal use, and is not described further.
+ * </p>
+ */
+public static ImageData internal_new(
+    int width, int height, int depth, PaletteData palette,
+    int scanlinePad, byte[] data, int maskPad, byte[] maskData,
+    byte[] alphaData, int alpha, int transparentPixel, int type,
+    int x, int y, int disposalMethod, int delayTime)
+{
+    return new ImageData(
+        width, height, depth, palette, scanlinePad, data, maskPad, maskData,
+        alphaData, alpha, transparentPixel, type, x, y, disposalMethod, delayTime);
+}
+
+ImageData colorMaskImage(int pixel) {
+    ImageData mask = new ImageData(width, height, 1, bwPalette(),
+        2, null, 0, null, null, -1, -1, SWT.IMAGE_UNDEFINED,
+        0, 0, 0, 0);
+    int[] row = new int[width];
+    for (int y = 0; y < height; y++) {
+        getPixels(0, y, width, row, 0);
+        for (int i = 0; i < width; i++) {
+            if (pixel !is -1 && row[i] is pixel) {
+                row[i] = 0;
+            } else {
+                row[i] = 1;
+            }
+        }
+        mask.setPixels(0, y, width, row, 0);
+    }
+    return mask;
+}
+
+static byte[] checkData(byte [] data) {
+    if (data is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    return data;
+}
+
+/**
+ * Returns a new instance of the same class as the receiver,
+ * whose slots have been filled in with <em>copies</em> of
+ * the values in the slots of the receiver. That is, the
+ * returned object is a <em>deep copy</em> of the receiver.
+ *
+ * @return a copy of the receiver.
+ */
+public Object clone() {
+    byte[] cloneData = new byte[data.length];
+    System.arraycopy(data, 0, cloneData, 0, data.length);
+    byte[] cloneMaskData = null;
+    if (maskData !is null) {
+        cloneMaskData = new byte[maskData.length];
+        System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length);
+    }
+    byte[] cloneAlphaData = null;
+    if (alphaData !is null) {
+        cloneAlphaData = new byte[alphaData.length];
+        System.arraycopy(alphaData, 0, cloneAlphaData, 0, alphaData.length);
+    }
+    return new ImageData(
+        width,
+        height,
+        depth,
+        palette,
+        scanlinePad,
+        cloneData,
+        maskPad,
+        cloneMaskData,
+        cloneAlphaData,
+        alpha,
+        transparentPixel,
+        type,
+        x,
+        y,
+        disposalMethod,
+        delayTime);
+}
+
+/**
+ * Returns the alpha value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data.
+ * The alpha value is between 0 (transparent) and
+ * 255 (opaque).
+ *
+ * @param x the x coordinate of the pixel to get the alpha value of
+ * @param y the y coordinate of the pixel to get the alpha value of
+ * @return the alpha value at the given coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if either argument is out of range</li>
+ * </ul>
+ */
+public int getAlpha(int x, int y) {
+    if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    if (alphaData is null) return 255;
+    return alphaData[y * width + x] & 0xFF;
+}
+
+/**
+ * Returns <code>getWidth</code> alpha values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's alpha
+ * data starting at <code>startIndex</code>. The alpha values
+ * are unsigned, between <code>(byte)0</code> (transparent) and
+ * <code>(byte)255</code> (opaque).
+ *
+ * @param x the x position of the pixel to begin getting alpha values
+ * @param y the y position of the pixel to begin getting alpha values
+ * @param getWidth the width of the data to get
+ * @param alphas the buffer in which to put the alpha values
+ * @param startIndex the offset into the image to begin getting alpha values
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
+ * </ul>
+ */
+public void getAlphas(int x, int y, int getWidth, byte[] alphas, int startIndex) {
+    if (alphas is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (getWidth is 0) return;
+
+    if (alphaData is null) {
+        int endIndex = startIndex + getWidth;
+        for (int i = startIndex; i < endIndex; i++) {
+            alphas[i] = cast(byte)255;
+        }
+        return;
+    }
+    // may throw an IndexOutOfBoundsException
+    System.arraycopy(alphaData, y * width + x, alphas, startIndex, getWidth);
+}
+
+/**
+ * Returns the pixel value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data.
+ *
+ * @param x the x position of the pixel to get
+ * @param y the y position of the pixel to get
+ * @return the pixel at the given coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if either argument is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public int getPixel(int x, int y) {
+    if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int index;
+    int theByte;
+    int mask;
+    switch (depth) {
+        case 32:
+            index = (y * bytesPerLine) + (x * 4);
+            return ((data[index] & 0xFF) << 24) + ((data[index+1] & 0xFF) << 16) +
+                    ((data[index+2] & 0xFF) << 8) + (data[index+3] & 0xFF);
+        case 24:
+            index = (y * bytesPerLine) + (x * 3);
+            return ((data[index] & 0xFF) << 16) + ((data[index+1] & 0xFF) << 8) +
+                (data[index+2] & 0xFF);
+        case 16:
+            index = (y * bytesPerLine) + (x * 2);
+            return ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
+        case 8:
+            index = (y * bytesPerLine) + x ;
+            return data[index] & 0xFF;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            theByte = data[index] & 0xFF;
+            if ((x & 0x1) is 0) {
+                return theByte >> 4;
+            } else {
+                return theByte & 0x0F;
+            }
+        case 2:
+            index = (y * bytesPerLine) + (x >> 2);
+            theByte = data[index] & 0xFF;
+            int offset = 3 - (x % 4);
+            mask = 3 << (offset * 2);
+            return (theByte & mask) >> (offset * 2);
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            theByte = data[index] & 0xFF;
+            mask = 1 << (7 - (x & 0x7));
+            if ((theByte & mask) is 0) {
+                return 0;
+            } else {
+                return 1;
+            }
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+    return 0;
+}
+
+/**
+ * Returns <code>getWidth</code> pixel values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's
+ * data starting at <code>startIndex</code>.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the byte array to begin storing pixels
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4 or 8
+ *        (For higher depths, use the int[] version of this method.)</li>
+ * </ul>
+ */
+public void getPixels(int x, int y, int getWidth, byte[] pixels, int startIndex) {
+    if (pixels is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (getWidth is 0) return;
+    int index;
+    int theByte;
+    int mask = 0;
+    int n = getWidth;
+    int i = startIndex;
+    int srcX = x, srcY = y;
+    switch (depth) {
+        case 8:
+            index = (y * bytesPerLine) + x;
+            for (int j = 0; j < getWidth; j++) {
+                pixels[i] = data[index];
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            return;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            if ((x & 0x1) is 1) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = cast(byte)(theByte & 0x0F);
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            while (n > 1) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = cast(byte)(theByte >> 4);
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    pixels[i] = cast(byte)(theByte & 0x0F);
+                    i++;
+                    n--;
+                    srcX++;
+                    if (srcX >= width) {
+                        srcY++;
+                        index = srcY * bytesPerLine;
+                        srcX = 0;
+                    } else {
+                        index++;
+                    }
+                }
+            }
+            if (n > 0) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = cast(byte)(theByte >> 4);
+            }
+            return;
+        case 2:
+            index = (y * bytesPerLine) + (x >> 2);
+            theByte = data[index] & 0xFF;
+            int offset;
+            while (n > 0) {
+                offset = 3 - (srcX % 4);
+                mask = 3 << (offset * 2);
+                pixels[i] = cast(byte)((theByte & mask) >> (offset * 2));
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    if (n > 0) theByte = data[index] & 0xFF;
+                    srcX = 0;
+                } else {
+                    if (offset is 0) {
+                        index++;
+                        theByte = data[index] & 0xFF;
+                    }
+                }
+            }
+            return;
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            theByte = data[index] & 0xFF;
+            while (n > 0) {
+                mask = 1 << (7 - (srcX & 0x7));
+                if ((theByte & mask) is 0) {
+                    pixels[i] = 0;
+                } else {
+                    pixels[i] = 1;
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    if (n > 0) theByte = data[index] & 0xFF;
+                    srcX = 0;
+                } else {
+                    if (mask is 1) {
+                        index++;
+                        if (n > 0) theByte = data[index] & 0xFF;
+                    }
+                }
+            }
+            return;
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns <code>getWidth</code> pixel values starting at offset
+ * <code>x</code> in scanline <code>y</code> in the receiver's
+ * data starting at <code>startIndex</code>.
+ *
+ * @param x the x position of the first pixel to get
+ * @param y the y position of the first pixel to get
+ * @param getWidth the width of the data to get
+ * @param pixels the buffer in which to put the pixels
+ * @param startIndex the offset into the buffer to begin storing pixels
+ *
+ * @exception IndexOutOfBoundsException if getWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void getPixels(int x, int y, int getWidth, int[] pixels, int startIndex) {
+    if (pixels is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (getWidth is 0) return;
+    int index;
+    int theByte;
+    int mask;
+    int n = getWidth;
+    int i = startIndex;
+    int srcX = x, srcY = y;
+    switch (depth) {
+        case 32:
+            index = (y * bytesPerLine) + (x * 4);
+            i = startIndex;
+            for (int j = 0; j < getWidth; j++) {
+                pixels[i] = ((data[index] & 0xFF) << 24) | ((data[index+1] & 0xFF) << 16)
+                    | ((data[index+2] & 0xFF) << 8) | (data[index+3] & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 4;
+                }
+            }
+            return;
+        case 24:
+            index = (y * bytesPerLine) + (x * 3);
+            for (int j = 0; j < getWidth; j++) {
+                pixels[i] = ((data[index] & 0xFF) << 16) | ((data[index+1] & 0xFF) << 8)
+                    | (data[index+2] & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 3;
+                }
+            }
+            return;
+        case 16:
+            index = (y * bytesPerLine) + (x * 2);
+            for (int j = 0; j < getWidth; j++) {
+                pixels[i] = ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 2;
+                }
+            }
+            return;
+        case 8:
+            index = (y * bytesPerLine) + x;
+            for (int j = 0; j < getWidth; j++) {
+                pixels[i] = data[index] & 0xFF;
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            return;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            if ((x & 0x1) is 1) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = theByte & 0x0F;
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            while (n > 1) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = theByte >> 4;
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    pixels[i] = theByte & 0x0F;
+                    i++;
+                    n--;
+                    srcX++;
+                    if (srcX >= width) {
+                        srcY++;
+                        index = srcY * bytesPerLine;
+                        srcX = 0;
+                    } else {
+                        index++;
+                    }
+                }
+            }
+            if (n > 0) {
+                theByte = data[index] & 0xFF;
+                pixels[i] = theByte >> 4;
+            }
+            return;
+        case 2:
+            index = (y * bytesPerLine) + (x >> 2);
+            theByte = data[index] & 0xFF;
+            int offset;
+            while (n > 0) {
+                offset = 3 - (srcX % 4);
+                mask = 3 << (offset * 2);
+                pixels[i] = cast(byte)((theByte & mask) >> (offset * 2));
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    if (n > 0) theByte = data[index] & 0xFF;
+                    srcX = 0;
+                } else {
+                    if (offset is 0) {
+                        index++;
+                        theByte = data[index] & 0xFF;
+                    }
+                }
+            }
+            return;
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            theByte = data[index] & 0xFF;
+            while (n > 0) {
+                mask = 1 << (7 - (srcX & 0x7));
+                if ((theByte & mask) is 0) {
+                    pixels[i] = 0;
+                } else {
+                    pixels[i] = 1;
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    if (n > 0) theByte = data[index] & 0xFF;
+                    srcX = 0;
+                } else {
+                    if (mask is 1) {
+                        index++;
+                        if (n > 0) theByte = data[index] & 0xFF;
+                    }
+                }
+            }
+            return;
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns an array of <code>RGB</code>s which comprise the
+ * indexed color table of the receiver, or null if the receiver
+ * has a direct color model.
+ *
+ * @return the RGB values for the image or null if direct color
+ *
+ * @see PaletteData#getRGBs()
+ */
+public RGB[] getRGBs() {
+    return palette.getRGBs();
+}
+
+/**
+ * Returns an <code>ImageData</code> which specifies the
+ * transparency mask information for the receiver. If the
+ * receiver has no transparency or is not an icon, returns
+ * an opaque mask.
+ *
+ * @return the transparency mask
+ */
+public ImageData getTransparencyMask() {
+    if (getTransparencyType() is SWT.TRANSPARENCY_MASK) {
+        return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
+    } else {
+        return colorMaskImage(transparentPixel);
+    }
+}
+
+/**
+ * Returns the image transparency type, which will be one of
+ * <code>SWT.TRANSPARENCY_NONE</code>, <code>SWT.TRANSPARENCY_MASK</code>,
+ * <code>SWT.TRANSPARENCY_PIXEL</code> or <code>SWT.TRANSPARENCY_ALPHA</code>.
+ *
+ * @return the receiver's transparency type
+ */
+public int getTransparencyType() {
+    if (maskData !is null) return SWT.TRANSPARENCY_MASK;
+    if (transparentPixel !is -1) return SWT.TRANSPARENCY_PIXEL;
+    if (alphaData !is null) return SWT.TRANSPARENCY_ALPHA;
+    return SWT.TRANSPARENCY_NONE;
+}
+
+/**
+ * Returns the byte order of the receiver.
+ *
+ * @return MSB_FIRST or LSB_FIRST
+ */
+int getByteOrder() {
+    return depth !is 16 ? MSB_FIRST : LSB_FIRST;
+}
+
+/**
+ * Returns a copy of the receiver which has been stretched or
+ * shrunk to the specified size. If either the width or height
+ * is negative, the resulting image will be inverted in the
+ * associated axis.
+ *
+ * @param width the width of the new ImageData
+ * @param height the height of the new ImageData
+ * @return a scaled copy of the image
+ */
+public ImageData scaledTo(int width, int height) {
+    /* Create a destination image with no data */
+    bool flipX = (width < 0);
+    if (flipX) width = - width;
+    bool flipY = (height < 0);
+    if (flipY) height = - height;
+
+    ImageData dest = new ImageData(
+        width, height, depth, palette,
+        scanlinePad, null, 0, null,
+        null, -1, transparentPixel, type,
+        x, y, disposalMethod, delayTime);
+
+    /* Scale the image contents */
+    if (palette.isDirect) blit(BLIT_SRC,
+        this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, 0, 0, 0,
+        ALPHA_OPAQUE, null, 0, 0, 0,
+        dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, 0, 0, 0,
+        flipX, flipY);
+    else blit(BLIT_SRC,
+        this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, null, null, null,
+        ALPHA_OPAQUE, null, 0, 0, 0,
+        dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, null, null, null,
+        flipX, flipY);
+
+    /* Scale the image mask or alpha */
+    if (maskData !is null) {
+        dest.maskPad = this.maskPad;
+        int destBpl = (dest.width + 7) / 8;
+        destBpl = (destBpl + (dest.maskPad - 1)) / dest.maskPad * dest.maskPad;
+        dest.maskData = new byte[destBpl * dest.height];
+        int srcBpl = (this.width + 7) / 8;
+        srcBpl = (srcBpl + (this.maskPad - 1)) / this.maskPad * this.maskPad;
+        blit(BLIT_SRC,
+            this.maskData, 1, srcBpl, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
+            ALPHA_OPAQUE, null, 0, 0, 0,
+            dest.maskData, 1, destBpl, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
+            flipX, flipY);
+    } else if (alpha !is -1) {
+        dest.alpha = this.alpha;
+    } else if (alphaData !is null) {
+        dest.alphaData = new byte[dest.width * dest.height];
+        blit(BLIT_SRC,
+            this.alphaData, 8, this.width, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
+            ALPHA_OPAQUE, null, 0, 0, 0,
+            dest.alphaData, 8, dest.width, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
+            flipX, flipY);
+    }
+    return dest;
+}
+
+/**
+ * Sets the alpha value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data.
+ * The alpha value must be between 0 (transparent)
+ * and 255 (opaque).
+ *
+ * @param x the x coordinate of the alpha value to set
+ * @param y the y coordinate of the alpha value to set
+ * @param alpha the value to set the alpha to
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *  </ul>
+ */
+public void setAlpha(int x, int y, int alpha) {
+    if (x >= width || y >= height || x < 0 || y < 0 || alpha < 0 || alpha > 255)
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    if (alphaData is null) alphaData = new byte[width * height];
+    alphaData[y * width + x] = cast(byte)alpha;
+}
+
+/**
+ * Sets the alpha values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's alpha data to the
+ * values from the array <code>alphas</code> starting at
+ * <code>startIndex</code>. The alpha values must be between
+ * <code>(byte)0</code> (transparent) and <code>(byte)255</code> (opaque)
+ *
+ * @param x the x coordinate of the pixel to being setting the alpha values
+ * @param y the y coordinate of the pixel to being setting the alpha values
+ * @param putWidth the width of the alpha values to set
+ * @param alphas the alpha values to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
+ * </ul>
+ */
+public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) {
+    if (alphas is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (putWidth is 0) return;
+
+    if (alphaData is null) alphaData = new byte[width * height];
+    // may throw an IndexOutOfBoundsException
+    System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth);
+}
+
+/**
+ * Sets the pixel value at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data.
+ *
+ * @param x the x coordinate of the pixel to set
+ * @param y the y coordinate of the pixel to set
+ * @param pixelValue the value to set the pixel to
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void setPixel(int x, int y, int pixelValue) {
+    if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int index;
+    byte theByte;
+    int mask;
+    switch (depth) {
+        case 32:
+            index = (y * bytesPerLine) + (x * 4);
+            data[index]  = cast(byte)((pixelValue >> 24) & 0xFF);
+            data[index + 1] = cast(byte)((pixelValue >> 16) & 0xFF);
+            data[index + 2] = cast(byte)((pixelValue >> 8) & 0xFF);
+            data[index + 3] = cast(byte)(pixelValue & 0xFF);
+            return;
+        case 24:
+            index = (y * bytesPerLine) + (x * 3);
+            data[index] = cast(byte)((pixelValue >> 16) & 0xFF);
+            data[index + 1] = cast(byte)((pixelValue >> 8) & 0xFF);
+            data[index + 2] = cast(byte)(pixelValue & 0xFF);
+            return;
+        case 16:
+            index = (y * bytesPerLine) + (x * 2);
+            data[index + 1] = cast(byte)((pixelValue >> 8) & 0xFF);
+            data[index] = cast(byte)(pixelValue & 0xFF);
+            return;
+        case 8:
+            index = (y * bytesPerLine) + x ;
+            data[index] = cast(byte)(pixelValue & 0xFF);
+            return;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            if ((x & 0x1) is 0) {
+                data[index] = cast(byte)((data[index] & 0x0F) | ((pixelValue & 0x0F) << 4));
+            } else {
+                data[index] = cast(byte)((data[index] & 0xF0) | (pixelValue & 0x0F));
+            }
+            return;
+        case 2:
+            index = (y * bytesPerLine) + (x >> 2);
+            theByte = data[index];
+            int offset = 3 - (x % 4);
+            mask = 0xFF ^ (3 << (offset * 2));
+            data[index] = cast(byte)((data[index] & mask) | (pixelValue << (offset * 2)));
+            return;
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            theByte = data[index];
+            mask = 1 << (7 - (x & 0x7));
+            if ((pixelValue & 0x1) is 1) {
+                data[index] = cast(byte)(theByte | mask);
+            } else {
+                data[index] = cast(byte)(theByte & (mask ^ -1));
+            }
+            return;
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Sets the pixel values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data to the
+ * values from the array <code>pixels</code> starting at
+ * <code>startIndex</code>.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8
+ *        (For higher depths, use the int[] version of this method.)</li>
+ * </ul>
+ */
+public void setPixels(int x, int y, int putWidth, byte[] pixels, int startIndex) {
+    if (pixels is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (putWidth is 0) return;
+    int index;
+    int theByte;
+    int mask;
+    int n = putWidth;
+    int i = startIndex;
+    int srcX = x, srcY = y;
+    switch (depth) {
+        case 8:
+            index = (y * bytesPerLine) + x;
+            for (int j = 0; j < putWidth; j++) {
+                data[index] = cast(byte)(pixels[i] & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            return;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            bool high = (x & 0x1) is 0;
+            while (n > 0) {
+                theByte = pixels[i] & 0x0F;
+                if (high) {
+                    data[index] = cast(byte)((data[index] & 0x0F) | (theByte << 4));
+                } else {
+                    data[index] = cast(byte)((data[index] & 0xF0) | theByte);
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    high = true;
+                    srcX = 0;
+                } else {
+                    if (!high) index++;
+                    high = !high;
+                }
+            }
+            return;
+        case 2:
+            byte [] masks = [ cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F ];
+            index = (y * bytesPerLine) + (x >> 2);
+            int offset = 3 - (x % 4);
+            while (n > 0) {
+                theByte = pixels[i] & 0x3;
+                data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    offset = 0;
+                    srcX = 0;
+                } else {
+                    if (offset is 0) {
+                        index++;
+                        offset = 3;
+                    } else {
+                        offset--;
+                    }
+                }
+            }
+            return;
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            while (n > 0) {
+                mask = 1 << (7 - (srcX & 0x7));
+                if ((pixels[i] & 0x1) is 1) {
+                    data[index] = cast(byte)((data[index] & 0xFF) | mask);
+                } else {
+                    data[index] = cast(byte)((data[index] & 0xFF) & (mask ^ -1));
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    if (mask is 1) {
+                        index++;
+                    }
+                }
+            }
+            return;
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Sets the pixel values starting at offset <code>x</code> in
+ * scanline <code>y</code> in the receiver's data to the
+ * values from the array <code>pixels</code> starting at
+ * <code>startIndex</code>.
+ *
+ * @param x the x position of the pixel to set
+ * @param y the y position of the pixel to set
+ * @param putWidth the width of the pixels to set
+ * @param pixels the pixels to set
+ * @param startIndex the index at which to begin setting
+ *
+ * @exception IndexOutOfBoundsException if putWidth is too large
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
+ * </ul>
+ */
+public void setPixels(int x, int y, int putWidth, int[] pixels, int startIndex) {
+    if (pixels is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (putWidth is 0) return;
+    int index;
+    int theByte;
+    int mask;
+    int n = putWidth;
+    int i = startIndex;
+    int pixel;
+    int srcX = x, srcY = y;
+    switch (depth) {
+        case 32:
+            index = (y * bytesPerLine) + (x * 4);
+            for (int j = 0; j < putWidth; j++) {
+                pixel = pixels[i];
+                data[index] = cast(byte)((pixel >> 24) & 0xFF);
+                data[index + 1] = cast(byte)((pixel >> 16) & 0xFF);
+                data[index + 2] = cast(byte)((pixel >> 8) & 0xFF);
+                data[index + 3] = cast(byte)(pixel & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 4;
+                }
+            }
+            return;
+        case 24:
+            index = (y * bytesPerLine) + (x * 3);
+            for (int j = 0; j < putWidth; j++) {
+                pixel = pixels[i];
+                data[index] = cast(byte)((pixel >> 16) & 0xFF);
+                data[index + 1] = cast(byte)((pixel >> 8) & 0xFF);
+                data[index + 2] = cast(byte)(pixel & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 3;
+                }
+            }
+            return;
+        case 16:
+            index = (y * bytesPerLine) + (x * 2);
+            for (int j = 0; j < putWidth; j++) {
+                pixel = pixels[i];
+                data[index] = cast(byte)(pixel & 0xFF);
+                data[index + 1] = cast(byte)((pixel >> 8) & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index += 2;
+                }
+            }
+            return;
+        case 8:
+            index = (y * bytesPerLine) + x;
+            for (int j = 0; j < putWidth; j++) {
+                data[index] = cast(byte)(pixels[i] & 0xFF);
+                i++;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    index++;
+                }
+            }
+            return;
+        case 4:
+            index = (y * bytesPerLine) + (x >> 1);
+            bool high = (x & 0x1) is 0;
+            while (n > 0) {
+                theByte = pixels[i] & 0x0F;
+                if (high) {
+                    data[index] = cast(byte)((data[index] & 0x0F) | (theByte << 4));
+                } else {
+                    data[index] = cast(byte)((data[index] & 0xF0) | theByte);
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    high = true;
+                    srcX = 0;
+                } else {
+                    if (!high) index++;
+                    high = !high;
+                }
+            }
+            return;
+        case 2:
+            byte [] masks = [ cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F ];
+            index = (y * bytesPerLine) + (x >> 2);
+            int offset = 3 - (x % 4);
+            while (n > 0) {
+                theByte = pixels[i] & 0x3;
+                data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    offset = 3;
+                    srcX = 0;
+                } else {
+                    if (offset is 0) {
+                        index++;
+                        offset = 3;
+                    } else {
+                        offset--;
+                    }
+                }
+            }
+            return;
+        case 1:
+            index = (y * bytesPerLine) + (x >> 3);
+            while (n > 0) {
+                mask = 1 << (7 - (srcX & 0x7));
+                if ((pixels[i] & 0x1) is 1) {
+                    data[index] = cast(byte)((data[index] & 0xFF) | mask);
+                } else {
+                    data[index] = cast(byte)((data[index] & 0xFF) & (mask ^ -1));
+                }
+                i++;
+                n--;
+                srcX++;
+                if (srcX >= width) {
+                    srcY++;
+                    index = srcY * bytesPerLine;
+                    srcX = 0;
+                } else {
+                    if (mask is 1) {
+                        index++;
+                    }
+                }
+            }
+            return;
+        default:
+    }
+    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+}
+
+/**
+ * Returns a palette with 2 colors: black & white.
+ */
+static PaletteData bwPalette() {
+    return new PaletteData( [ new RGB(0, 0, 0), new RGB(255, 255, 255) ] );
+}
+
+/**
+ * Gets the offset of the most significant bit for
+ * the given mask.
+ */
+static int getMSBOffset(int mask) {
+    for (int i = 31; i >= 0; i--) {
+        if (((mask >> i) & 0x1) !is 0) return i + 1;
+    }
+    return 0;
+}
+
+/**
+ * Finds the closest match.
+ */
+static int closestMatch(int depth, byte red, byte green, byte blue, int redMask, int greenMask, int blueMask, byte[] reds, byte[] greens, byte[] blues) {
+    if (depth > 8) {
+        int rshift = 32 - getMSBOffset(redMask);
+        int gshift = 32 - getMSBOffset(greenMask);
+        int bshift = 32 - getMSBOffset(blueMask);
+        return (((red << 24) >>> rshift) & redMask) |
+            (((green << 24) >>> gshift) & greenMask) |
+            (((blue << 24) >>> bshift) & blueMask);
+    }
+    int r, g, b;
+    int minDistance = 0x7fffffff;
+    int nearestPixel = 0;
+    int n = reds.length;
+    for (int j = 0; j < n; j++) {
+        r = (reds[j] & 0xFF) - (red & 0xFF);
+        g = (greens[j] & 0xFF) - (green & 0xFF);
+        b = (blues[j] & 0xFF) - (blue & 0xFF);
+        int distance = r*r + g*g + b*b;
+        if (distance < minDistance) {
+            nearestPixel = j;
+            if (distance is 0) break;
+            minDistance = distance;
+        }
+    }
+    return nearestPixel;
+}
+
+static final ImageData convertMask(ImageData mask) {
+    if (mask.depth is 1) return mask;
+    PaletteData palette = new PaletteData([new RGB(0, 0, 0), new RGB(255,255,255)]);
+    ImageData newMask = new ImageData(mask.width, mask.height, 1, palette);
+    /* Find index of black in mask palette */
+    int blackIndex = 0;
+    RGB[] rgbs = mask.getRGBs();
+    if (rgbs !is null) {
+        while (blackIndex < rgbs.length) {
+            if (rgbs[blackIndex] is palette.colors[0] ) break;
+            blackIndex++;
+        }
+    }
+    int[] pixels = new int[mask.width];
+    for (int y = 0; y < mask.height; y++) {
+        mask.getPixels(0, y, mask.width, pixels, 0);
+        for (int i = 0; i < pixels.length; i++) {
+            if (pixels[i] is blackIndex) {
+                pixels[i] = 0;
+            } else {
+                pixels[i] = 1;
+            }
+        }
+        newMask.setPixels(0, y, mask.width, pixels, 0);
+    }
+    return newMask;
+}
+
+static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
+    if (pad is newPad) return data;
+    int stride = (width * depth + 7) / 8;
+    int bpl = (stride + (pad - 1)) / pad * pad;
+    int newBpl = (stride + (newPad - 1)) / newPad * newPad;
+    byte[] newData = new byte[height * newBpl];
+    int srcIndex = 0, destIndex = 0;
+    for (int y = 0; y < height; y++) {
+        System.arraycopy(data, srcIndex, newData, destIndex, stride);
+        srcIndex += bpl;
+        destIndex += newBpl;
+    }
+    return newData;
+}
+
+/**
+ * Blit operation bits to be OR'ed together to specify the desired operation.
+ */
+static const int
+    BLIT_SRC = 1,     // copy source directly, else applies logic operations
+    BLIT_ALPHA = 2,   // enable alpha blending
+    BLIT_DITHER = 4;  // enable dithering in low color modes
+
+/**
+ * Alpha mode, values 0 - 255 specify global alpha level
+ */
+static const int
+    ALPHA_OPAQUE = 255,           // Fully opaque (ignores any alpha data)
+    ALPHA_TRANSPARENT = 0,        // Fully transparent (ignores any alpha data)
+    ALPHA_CHANNEL_SEPARATE = -1,  // Use alpha channel from separate alphaData
+    ALPHA_CHANNEL_SOURCE = -2,    // Use alpha channel embedded in sourceData
+    ALPHA_MASK_UNPACKED = -3,     // Use transparency mask formed by bytes in alphaData (non-zero is opaque)
+    ALPHA_MASK_PACKED = -4,       // Use transparency mask formed by packed bits in alphaData
+    ALPHA_MASK_INDEX = -5,        // Consider source palette indices transparent if in alphaData array
+    ALPHA_MASK_RGB = -6;          // Consider source RGBs transparent if in RGB888 format alphaData array
+
+/**
+ * Byte and bit order constants.
+ */
+static const int LSB_FIRST = 0;
+static const int MSB_FIRST = 1;
+
+/**
+ * Data types (internal)
+ */
+private static const int
+    // direct / true color formats with arbitrary masks & shifts
+    TYPE_GENERIC_8 = 0,
+    TYPE_GENERIC_16_MSB = 1,
+    TYPE_GENERIC_16_LSB = 2,
+    TYPE_GENERIC_24 = 3,
+    TYPE_GENERIC_32_MSB = 4,
+    TYPE_GENERIC_32_LSB = 5,
+    // palette indexed color formats
+    TYPE_INDEX_8 = 6,
+    TYPE_INDEX_4 = 7,
+    TYPE_INDEX_2 = 8,
+    TYPE_INDEX_1_MSB = 9,
+    TYPE_INDEX_1_LSB = 10;
+
+/**
+ * Blits a direct palette image into a direct palette image.
+ * <p>
+ * Note: When the source and destination depth, order and masks
+ * are pairwise equal and the blitter operation is BLIT_SRC,
+ * the masks are ignored.  Hence when not changing the image
+ * data format, 0 may be specified for the masks.
+ * </p>
+ *
+ * @param op the blitter operation: a combination of BLIT_xxx flags
+ *        (see BLIT_xxx constants)
+ * @param srcData the source byte array containing image data
+ * @param srcDepth the source depth: one of 8, 16, 24, 32
+ * @param srcStride the source number of bytes per line
+ * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if srcDepth is not 16 or 32
+ * @param srcX the top-left x-coord of the source blit region
+ * @param srcY the top-left y-coord of the source blit region
+ * @param srcWidth the width of the source blit region
+ * @param srcHeight the height of the source blit region
+ * @param srcRedMask the source red channel mask
+ * @param srcGreenMask the source green channel mask
+ * @param srcBlueMask the source blue channel mask
+ * @param alphaMode the alpha blending or mask mode, may be
+ *        an integer 0-255 for global alpha; ignored if BLIT_ALPHA
+ *        not specified in the blitter operations
+ *        (see ALPHA_MODE_xxx constants)
+ * @param alphaData the alpha blending or mask data, varies depending
+ *        on the value of alphaMode and sometimes ignored
+ * @param alphaStride the alpha data number of bytes per line
+ * @param alphaX the top-left x-coord of the alpha blit region
+ * @param alphaY the top-left y-coord of the alpha blit region
+ * @param destData the destination byte array containing image data
+ * @param destDepth the destination depth: one of 8, 16, 24, 32
+ * @param destStride the destination number of bytes per line
+ * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if destDepth is not 16 or 32
+ * @param destX the top-left x-coord of the destination blit region
+ * @param destY the top-left y-coord of the destination blit region
+ * @param destWidth the width of the destination blit region
+ * @param destHeight the height of the destination blit region
+ * @param destRedMask the destination red channel mask
+ * @param destGreenMask the destination green channel mask
+ * @param destBlueMask the destination blue channel mask
+ * @param flipX if true the resulting image is flipped along the vertical axis
+ * @param flipY if true the resulting image is flipped along the horizontal axis
+ */
+static void blit(int op,
+    byte[] srcData, int srcDepth, int srcStride, int srcOrder,
+    int srcX, int srcY, int srcWidth, int srcHeight,
+    int srcRedMask, int srcGreenMask, int srcBlueMask,
+    int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
+    byte[] destData, int destDepth, int destStride, int destOrder,
+    int destX, int destY, int destWidth, int destHeight,
+    int destRedMask, int destGreenMask, int destBlueMask,
+    bool flipX, bool flipY) {
+
+    static_this();
+
+    if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
+
+    // these should be supplied as params later
+    const int srcAlphaMask = 0, destAlphaMask = 0;
+
+    /*** Prepare scaling data ***/
+    int dwm1 = destWidth - 1;
+    int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
+    int dhm1 = destHeight - 1;
+    int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
+
+    /*** Prepare source-related data ***/
+    int sbpp, stype;
+    switch (srcDepth) {
+        case 8:
+            sbpp = 1;
+            stype = TYPE_GENERIC_8;
+            break;
+        case 16:
+            sbpp = 2;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
+            break;
+        case 24:
+            sbpp = 3;
+            stype = TYPE_GENERIC_24;
+            break;
+        case 32:
+            sbpp = 4;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int spr = srcY * srcStride + srcX * sbpp;
+
+    /*** Prepare destination-related data ***/
+    int dbpp, dtype;
+    switch (destDepth) {
+        case 8:
+            dbpp = 1;
+            dtype = TYPE_GENERIC_8;
+            break;
+        case 16:
+            dbpp = 2;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
+            break;
+        case 24:
+            dbpp = 3;
+            dtype = TYPE_GENERIC_24;
+            break;
+        case 32:
+            dbpp = 4;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid destination type");
+            return;
+    }
+    int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp;
+    int dprxi = (flipX) ? -dbpp : dbpp;
+    int dpryi = (flipY) ? -destStride : destStride;
+
+    /*** Prepare special processing data ***/
+    int apr;
+    if ((op & BLIT_ALPHA) !is 0) {
+        switch (alphaMode) {
+            case ALPHA_MASK_UNPACKED:
+            case ALPHA_CHANNEL_SEPARATE:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_PACKED:
+                if (alphaData is null) alphaMode = 0x10000;
+                alphaStride <<= 3;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_INDEX:
+                //throw new IllegalArgumentException("Invalid alpha type");
+                return;
+            case ALPHA_MASK_RGB:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = 0;
+                break;
+            default:
+                alphaMode = (alphaMode << 16) / 255; // prescale
+            case ALPHA_CHANNEL_SOURCE:
+                apr = 0;
+                break;
+        }
+    } else {
+        alphaMode = 0x10000;
+        apr = 0;
+    }
+
+    /*** Blit ***/
+    int dp = dpr;
+    int sp = spr;
+    if ((alphaMode is 0x10000) && (stype is dtype) &&
+        (srcRedMask is destRedMask) && (srcGreenMask is destGreenMask) &&
+        (srcBlueMask is destBlueMask) && (srcAlphaMask is destAlphaMask)) {
+        /*** Fast blit (straight copy) ***/
+        switch (sbpp) {
+            case 1:
+                for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                    for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                        destData[dp] = srcData[sp];
+                        sp += (sfx >>> 16);
+                    }
+                }
+                break;
+            case 2:
+                for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                    for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                        destData[dp] = srcData[sp];
+                        destData[dp + 1] = srcData[sp + 1];
+                        sp += (sfx >>> 16) * 2;
+                    }
+                }
+                break;
+            case 3:
+                for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                    for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                        destData[dp] = srcData[sp];
+                        destData[dp + 1] = srcData[sp + 1];
+                        destData[dp + 2] = srcData[sp + 2];
+                        sp += (sfx >>> 16) * 3;
+                    }
+                }
+                break;
+            case 4:
+                for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                    for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                        destData[dp] = srcData[sp];
+                        destData[dp + 1] = srcData[sp + 1];
+                        destData[dp + 2] = srcData[sp + 2];
+                        destData[dp + 3] = srcData[sp + 3];
+                        sp += (sfx >>> 16) * 4;
+                    }
+                }
+                break;
+        default:
+        }
+        return;
+    }
+    /*** Comprehensive blit (apply transformations) ***/
+    int srcRedShift = getChannelShift(srcRedMask);
+    byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
+    int srcGreenShift = getChannelShift(srcGreenMask);
+    byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
+    int srcBlueShift = getChannelShift(srcBlueMask);
+    byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
+    int srcAlphaShift = getChannelShift(srcAlphaMask);
+    byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];
+
+    int destRedShift = getChannelShift(destRedMask);
+    int destRedWidth = getChannelWidth(destRedMask, destRedShift);
+    byte[] destReds = ANY_TO_EIGHT[destRedWidth];
+    int destRedPreShift = 8 - destRedWidth;
+    int destGreenShift = getChannelShift(destGreenMask);
+    int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
+    byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
+    int destGreenPreShift = 8 - destGreenWidth;
+    int destBlueShift = getChannelShift(destBlueMask);
+    int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
+    byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
+    int destBluePreShift = 8 - destBlueWidth;
+    int destAlphaShift = getChannelShift(destAlphaMask);
+    int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
+    byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
+    int destAlphaPreShift = 8 - destAlphaWidth;
+
+    int ap = apr, alpha = alphaMode;
+    int r = 0, g = 0, b = 0, a = 0;
+    int rq = 0, gq = 0, bq = 0, aq = 0;
+    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
+            sp = spr += (sfy >>> 16) * srcStride,
+            ap = apr += (sfy >>> 16) * alphaStride,
+            sfy = (sfy & 0xffff) + sfyi,
+            dp = dpr += dpryi) {
+        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
+                dp += dprxi,
+                sfx = (sfx & 0xffff) + sfxi) {
+            /*** READ NEXT PIXEL ***/
+            switch (stype) {
+                case TYPE_GENERIC_8: {
+                    int data = srcData[sp] & 0xff;
+                    sp += (sfx >>> 16);
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_16_MSB: {
+                    int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff);
+                    sp += (sfx >>> 16) * 2;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_16_LSB: {
+                    int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff);
+                    sp += (sfx >>> 16) * 2;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_24: {
+                    int data = (( ((srcData[sp] & 0xff) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp + 2] & 0xff);
+                    sp += (sfx >>> 16) * 3;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_32_MSB: {
+                    int data = (( (( ((srcData[sp] & 0xff) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp + 2] & 0xff)) << 8) |
+                        (srcData[sp + 3] & 0xff);
+                    sp += (sfx >>> 16) * 4;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_32_LSB: {
+                    int data = (( (( ((srcData[sp + 3] & 0xff) << 8) |
+                        (srcData[sp + 2] & 0xff)) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp] & 0xff);
+                    sp += (sfx >>> 16) * 4;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                default:
+            }
+
+            /*** DO SPECIAL PROCESSING IF REQUIRED ***/
+            switch (alphaMode) {
+                case ALPHA_CHANNEL_SEPARATE:
+                    alpha = ((alphaData[ap] & 0xff) << 16) / 255;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_CHANNEL_SOURCE:
+                    alpha = (a << 16) / 255;
+                    break;
+                case ALPHA_MASK_UNPACKED:
+                    alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_PACKED:
+                    alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_RGB:
+                    alpha = 0x10000;
+                    for (int i = 0; i < alphaData.length; i += 3) {
+                        if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) {
+                            alpha = 0x0000;
+                            break;
+                        }
+                    }
+                    break;
+                default:
+            }
+            if (alpha !is 0x10000) {
+                if (alpha is 0x0000) continue;
+                switch (dtype) {
+                    case TYPE_GENERIC_8: {
+                        int data = destData[dp] & 0xff;
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_16_MSB: {
+                        int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_16_LSB: {
+                        int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_24: {
+                        int data = (( ((destData[dp] & 0xff) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp + 2] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_32_MSB: {
+                        int data = (( (( ((destData[dp] & 0xff) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp + 2] & 0xff)) << 8) |
+                            (destData[dp + 3] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_32_LSB: {
+                        int data = (( (( ((destData[dp + 3] & 0xff) << 8) |
+                            (destData[dp + 2] & 0xff)) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    default:
+                }
+                // Perform alpha blending
+                a = aq + ((a - aq) * alpha >> 16);
+                r = rq + ((r - rq) * alpha >> 16);
+                g = gq + ((g - gq) * alpha >> 16);
+                b = bq + ((b - bq) * alpha >> 16);
+            }
+
+            /*** WRITE NEXT PIXEL ***/
+            int data =
+                (r >>> destRedPreShift << destRedShift) |
+                (g >>> destGreenPreShift << destGreenShift) |
+                (b >>> destBluePreShift << destBlueShift) |
+                (a >>> destAlphaPreShift << destAlphaShift);
+            switch (dtype) {
+                case TYPE_GENERIC_8: {
+                    destData[dp] = cast(byte) data;
+                } break;
+                case TYPE_GENERIC_16_MSB: {
+                    destData[dp] = cast(byte) (data >>> 8);
+                    destData[dp + 1] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_16_LSB: {
+                    destData[dp] = cast(byte) (data & 0xff);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                } break;
+                case TYPE_GENERIC_24: {
+                    destData[dp] = cast(byte) (data >>> 16);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                    destData[dp + 2] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_32_MSB: {
+                    destData[dp] = cast(byte) (data >>> 24);
+                    destData[dp + 1] = cast(byte) (data >>> 16);
+                    destData[dp + 2] = cast(byte) (data >>> 8);
+                    destData[dp + 3] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_32_LSB: {
+                    destData[dp] = cast(byte) (data & 0xff);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                    destData[dp + 2] = cast(byte) (data >>> 16);
+                    destData[dp + 3] = cast(byte) (data >>> 24);
+                } break;
+                default:
+            }
+        }
+    }
+}
+
+/**
+ * Blits an index palette image into an index palette image.
+ * <p>
+ * Note: The source and destination red, green, and blue
+ * arrays may be null if no alpha blending or dither is to be
+ * performed.
+ * </p>
+ *
+ * @param op the blitter operation: a combination of BLIT_xxx flags
+ *        (see BLIT_xxx constants)
+ * @param srcData the source byte array containing image data
+ * @param srcDepth the source depth: one of 1, 2, 4, 8
+ * @param srcStride the source number of bytes per line
+ * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if srcDepth is not 1
+ * @param srcX the top-left x-coord of the source blit region
+ * @param srcY the top-left y-coord of the source blit region
+ * @param srcWidth the width of the source blit region
+ * @param srcHeight the height of the source blit region
+ * @param srcReds the source palette red component intensities
+ * @param srcGreens the source palette green component intensities
+ * @param srcBlues the source palette blue component intensities
+ * @param alphaMode the alpha blending or mask mode, may be
+ *        an integer 0-255 for global alpha; ignored if BLIT_ALPHA
+ *        not specified in the blitter operations
+ *        (see ALPHA_MODE_xxx constants)
+ * @param alphaData the alpha blending or mask data, varies depending
+ *        on the value of alphaMode and sometimes ignored
+ * @param alphaStride the alpha data number of bytes per line
+ * @param alphaX the top-left x-coord of the alpha blit region
+ * @param alphaY the top-left y-coord of the alpha blit region
+ * @param destData the destination byte array containing image data
+ * @param destDepth the destination depth: one of 1, 2, 4, 8
+ * @param destStride the destination number of bytes per line
+ * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if destDepth is not 1
+ * @param destX the top-left x-coord of the destination blit region
+ * @param destY the top-left y-coord of the destination blit region
+ * @param destWidth the width of the destination blit region
+ * @param destHeight the height of the destination blit region
+ * @param destReds the destination palette red component intensities
+ * @param destGreens the destination palette green component intensities
+ * @param destBlues the destination palette blue component intensities
+ * @param flipX if true the resulting image is flipped along the vertical axis
+ * @param flipY if true the resulting image is flipped along the horizontal axis
+ */
+static void blit(int op,
+    byte[] srcData, int srcDepth, int srcStride, int srcOrder,
+    int srcX, int srcY, int srcWidth, int srcHeight,
+    byte[] srcReds, byte[] srcGreens, byte[] srcBlues,
+    int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
+    byte[] destData, int destDepth, int destStride, int destOrder,
+    int destX, int destY, int destWidth, int destHeight,
+    byte[] destReds, byte[] destGreens, byte[] destBlues,
+    bool flipX, bool flipY) {
+
+    static_this();
+
+    if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
+
+    /*** Prepare scaling data ***/
+    int dwm1 = destWidth - 1;
+    int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
+    int dhm1 = destHeight - 1;
+    int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
+
+    /*** Prepare source-related data ***/
+    int stype;
+    switch (srcDepth) {
+        case 8:
+            stype = TYPE_INDEX_8;
+            break;
+        case 4:
+            srcStride <<= 1;
+            stype = TYPE_INDEX_4;
+            break;
+        case 2:
+            srcStride <<= 2;
+            stype = TYPE_INDEX_2;
+            break;
+        case 1:
+            srcStride <<= 3;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int spr = srcY * srcStride + srcX;
+
+    /*** Prepare destination-related data ***/
+    int dtype;
+    switch (destDepth) {
+        case 8:
+            dtype = TYPE_INDEX_8;
+            break;
+        case 4:
+            destStride <<= 1;
+            dtype = TYPE_INDEX_4;
+            break;
+        case 2:
+            destStride <<= 2;
+            dtype = TYPE_INDEX_2;
+            break;
+        case 1:
+            destStride <<= 3;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX);
+    int dprxi = (flipX) ? -1 : 1;
+    int dpryi = (flipY) ? -destStride : destStride;
+
+    /*** Prepare special processing data ***/
+    int apr;
+    if ((op & BLIT_ALPHA) !is 0) {
+        switch (alphaMode) {
+            case ALPHA_MASK_UNPACKED:
+            case ALPHA_CHANNEL_SEPARATE:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_PACKED:
+                if (alphaData is null) alphaMode = 0x10000;
+                alphaStride <<= 3;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_INDEX:
+            case ALPHA_MASK_RGB:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = 0;
+                break;
+            default:
+                alphaMode = (alphaMode << 16) / 255; // prescale
+            case ALPHA_CHANNEL_SOURCE:
+                apr = 0;
+                break;
+        }
+    } else {
+        alphaMode = 0x10000;
+        apr = 0;
+    }
+    bool ditherEnabled = (op & BLIT_DITHER) !is 0;
+
+    /*** Blit ***/
+    int dp = dpr;
+    int sp = spr;
+    int ap = apr;
+    int destPaletteSize = 1 << destDepth;
+    if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length;
+    byte[] paletteMapping = null;
+    bool isExactPaletteMapping = true;
+    switch (alphaMode) {
+        case 0x10000:
+            /*** If the palettes and formats are equivalent use a one-to-one mapping ***/
+            if ((stype is dtype) &&
+                (srcReds is destReds) && (srcGreens is destGreens) && (srcBlues is destBlues)) {
+                paletteMapping = ONE_TO_ONE_MAPPING;
+                break;
+            /*** If palettes have not been supplied, supply a suitable mapping ***/
+            } else if ((srcReds is null) || (destReds is null)) {
+                if (srcDepth <= destDepth) {
+                    paletteMapping = ONE_TO_ONE_MAPPING;
+                } else {
+                    paletteMapping = new byte[1 << srcDepth];
+                    int mask = (0xff << destDepth) >>> 8;
+                    for (int i = 0; i < paletteMapping.length; ++i) paletteMapping[i] = cast(byte)(i & mask);
+                }
+                break;
+            }
+        case ALPHA_MASK_UNPACKED:
+        case ALPHA_MASK_PACKED:
+        case ALPHA_MASK_INDEX:
+        case ALPHA_MASK_RGB:
+            /*** Generate a palette mapping ***/
+            int srcPaletteSize = 1 << srcDepth;
+            paletteMapping = new byte[srcPaletteSize];
+            if ((srcReds !is null) && (srcReds.length < srcPaletteSize)) srcPaletteSize = srcReds.length;
+            for (int i = 0, r, g, b, index; i < srcPaletteSize; ++i) {
+                r = srcReds[i] & 0xff;
+                g = srcGreens[i] & 0xff;
+                b = srcBlues[i] & 0xff;
+                index = 0;
+                int minDistance = 0x7fffffff;
+                for (int j = 0, dr, dg, db, distance; j < destPaletteSize; ++j) {
+                    dr = (destReds[j] & 0xff) - r;
+                    dg = (destGreens[j] & 0xff) - g;
+                    db = (destBlues[j] & 0xff) - b;
+                    distance = dr * dr + dg * dg + db * db;
+                    if (distance < minDistance) {
+                        index = j;
+                        if (distance is 0) break;
+                        minDistance = distance;
+                    }
+                }
+                paletteMapping[i] = cast(byte)index;
+                if (minDistance !is 0) isExactPaletteMapping = false;
+            }
+            break;
+        default:
+    }
+    if ((paletteMapping !is null) && (isExactPaletteMapping || ! ditherEnabled)) {
+        if ((stype is dtype) && (alphaMode is 0x10000)) {
+            /*** Fast blit (copy w/ mapping) ***/
+            switch (stype) {
+                case TYPE_INDEX_8:
+                    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                            destData[dp] = paletteMapping[srcData[sp] & 0xff];
+                            sp += (sfx >>> 16);
+                        }
+                    }
+                    break;
+                case TYPE_INDEX_4:
+                    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                            int v;
+                            if ((sp & 1) !is 0) v = paletteMapping[srcData[sp >> 1] & 0x0f];
+                            else v = (srcData[sp >> 1] >>> 4) & 0x0f;
+                            sp += (sfx >>> 16);
+                            if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | v);
+                            else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (v << 4));
+                        }
+                    }
+                    break;
+                case TYPE_INDEX_2:
+                    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                            int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03];
+                            sp += (sfx >>> 16);
+                            int shift = 6 - (dp & 3) * 2;
+                            destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift));
+                        }
+                    }
+                    break;
+                case TYPE_INDEX_1_MSB:
+                    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                            int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01];
+                            sp += (sfx >>> 16);
+                            int shift = 7 - (dp & 7);
+                            destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                        }
+                    }
+                    break;
+                case TYPE_INDEX_1_LSB:
+                    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
+                        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
+                            int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01];
+                            sp += (sfx >>> 16);
+                            int shift = dp & 7;
+                            destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                        }
+                    }
+                    break;
+                default:
+            }
+        } else {
+            /*** Convert between indexed modes using mapping and mask ***/
+            for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
+                    sp = spr += (sfy >>> 16) * srcStride,
+                    sfy = (sfy & 0xffff) + sfyi,
+                    dp = dpr += dpryi) {
+                for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
+                        dp += dprxi,
+                        sfx = (sfx & 0xffff) + sfxi) {
+                    int index;
+                    /*** READ NEXT PIXEL ***/
+                    switch (stype) {
+                        case TYPE_INDEX_8:
+                            index = srcData[sp] & 0xff;
+                            sp += (sfx >>> 16);
+                            break;
+                        case TYPE_INDEX_4:
+                            if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f;
+                            else index = (srcData[sp >> 1] >>> 4) & 0x0f;
+                            sp += (sfx >>> 16);
+                            break;
+                        case TYPE_INDEX_2:
+                            index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03;
+                            sp += (sfx >>> 16);
+                            break;
+                        case TYPE_INDEX_1_MSB:
+                            index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01;
+                            sp += (sfx >>> 16);
+                            break;
+                        case TYPE_INDEX_1_LSB:
+                            index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
+                            sp += (sfx >>> 16);
+                            break;
+                        default:
+                            return;
+                    }
+                    /*** APPLY MASK ***/
+                    switch (alphaMode) {
+                        case ALPHA_MASK_UNPACKED: {
+                            byte mask = alphaData[ap];
+                            ap += (sfx >> 16);
+                            if (mask is 0) continue;
+                        } break;
+                        case ALPHA_MASK_PACKED: {
+                            int mask = alphaData[ap >> 3] & (1 << (ap & 7));
+                            ap += (sfx >> 16);
+                            if (mask is 0) continue;
+                        } break;
+                        case ALPHA_MASK_INDEX: {
+                            int i = 0;
+                            while (i < alphaData.length) {
+                                if (index is (alphaData[i] & 0xff)) break;
+                            }
+                            if (i < alphaData.length) continue;
+                        } break;
+                        case ALPHA_MASK_RGB: {
+                            byte r = srcReds[index], g = srcGreens[index], b = srcBlues[index];
+                            int i = 0;
+                            while (i < alphaData.length) {
+                                if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) break;
+                                i += 3;
+                            }
+                            if (i < alphaData.length) continue;
+                        } break;
+                        default:
+                    }
+                    index = paletteMapping[index] & 0xff;
+
+                    /*** WRITE NEXT PIXEL ***/
+                    switch (dtype) {
+                        case TYPE_INDEX_8:
+                            destData[dp] = cast(byte) index;
+                            break;
+                        case TYPE_INDEX_4:
+                            if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | index);
+                            else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (index << 4));
+                            break;
+                        case TYPE_INDEX_2: {
+                            int shift = 6 - (dp & 3) * 2;
+                            destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift));
+                        } break;
+                        case TYPE_INDEX_1_MSB: {
+                            int shift = 7 - (dp & 7);
+                            destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                        } break;
+                        case TYPE_INDEX_1_LSB: {
+                            int shift = dp & 7;
+                            destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
+                        } break;
+                        default:
+                    }
+                }
+            }
+        }
+        return;
+    }
+
+    /*** Comprehensive blit (apply transformations) ***/
+    int alpha = alphaMode;
+    int index = 0;
+    int indexq = 0;
+    int lastindex = 0, lastr = -1, lastg = -1, lastb = -1;
+    int[] rerr, gerr, berr;
+    if (ditherEnabled) {
+        rerr = new int[destWidth + 2];
+        gerr = new int[destWidth + 2];
+        berr = new int[destWidth + 2];
+    } else {
+        rerr = null; gerr = null; berr = null;
+    }
+    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
+            sp = spr += (sfy >>> 16) * srcStride,
+            ap = apr += (sfy >>> 16) * alphaStride,
+            sfy = (sfy & 0xffff) + sfyi,
+            dp = dpr += dpryi) {
+        int lrerr = 0, lgerr = 0, lberr = 0;
+        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
+                dp += dprxi,
+                sfx = (sfx & 0xffff) + sfxi) {
+            /*** READ NEXT PIXEL ***/
+            switch (stype) {
+                case TYPE_INDEX_8:
+                    index = srcData[sp] & 0xff;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_4:
+                    if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f;
+                    else index = (srcData[sp >> 1] >>> 4) & 0x0f;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_2:
+                    index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_1_MSB:
+                    index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_1_LSB:
+                    index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
+                    sp += (sfx >>> 16);
+                    break;
+                default:
+            }
+
+            /*** DO SPECIAL PROCESSING IF REQUIRED ***/
+            int r = srcReds[index] & 0xff, g = srcGreens[index] & 0xff, b = srcBlues[index] & 0xff;
+            switch (alphaMode) {
+                case ALPHA_CHANNEL_SEPARATE:
+                    alpha = ((alphaData[ap] & 0xff) << 16) / 255;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_UNPACKED:
+                    alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_PACKED:
+                    alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices
+                    int i = 0;
+                    while (i < alphaData.length) {
+                        if (index is (alphaData[i] & 0xff)) break;
+                    }
+                    if (i < alphaData.length) continue;
+                } break;
+                case ALPHA_MASK_RGB: {
+                    int i = 0;
+                    while (i < alphaData.length) {
+                        if ((r is (alphaData[i] & 0xff)) &&
+                            (g is (alphaData[i + 1] & 0xff)) &&
+                            (b is (alphaData[i + 2] & 0xff))) break;
+                        i += 3;
+                    }
+                    if (i < alphaData.length) continue;
+                } break;
+                default:
+            }
+            if (alpha !is 0x10000) {
+                if (alpha is 0x0000) continue;
+                switch (dtype) {
+                    case TYPE_INDEX_8:
+                        indexq = destData[dp] & 0xff;
+                        break;
+                    case TYPE_INDEX_4:
+                        if ((dp & 1) !is 0) indexq = destData[dp >> 1] & 0x0f;
+                        else indexq = (destData[dp >> 1] >>> 4) & 0x0f;
+                        break;
+                    case TYPE_INDEX_2:
+                        indexq = (destData[dp >> 2] >>> (6 - (dp & 3) * 2)) & 0x03;
+                        break;
+                    case TYPE_INDEX_1_MSB:
+                        indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01;
+                        break;
+                    case TYPE_INDEX_1_LSB:
+                        indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01;
+                        break;
+                    default:
+                }
+                // Perform alpha blending
+                int rq = destReds[indexq] & 0xff;
+                int gq = destGreens[indexq] & 0xff;
+                int bq = destBlues[indexq] & 0xff;
+                r = rq + ((r - rq) * alpha >> 16);
+                g = gq + ((g - gq) * alpha >> 16);
+                b = bq + ((b - bq) * alpha >> 16);
+            }
+
+            /*** MAP COLOR TO THE PALETTE ***/
+            if (ditherEnabled) {
+                // Floyd-Steinberg error diffusion
+                r += rerr[dx] >> 4;
+                if (r < 0) r = 0; else if (r > 255) r = 255;
+                g += gerr[dx] >> 4;
+                if (g < 0) g = 0; else if (g > 255) g = 255;
+                b += berr[dx] >> 4;
+                if (b < 0) b = 0; else if (b > 255) b = 255;
+                rerr[dx] = lrerr;
+                gerr[dx] = lgerr;
+                berr[dx] = lberr;
+            }
+            if (r !is lastr || g !is lastg || b !is lastb) {
+                // moving the variable declarations out seems to make the JDK JIT happier...
+                for (int j = 0, dr, dg, db, distance, minDistance = 0x7fffffff; j < destPaletteSize; ++j) {
+                    dr = (destReds[j] & 0xff) - r;
+                    dg = (destGreens[j] & 0xff) - g;
+                    db = (destBlues[j] & 0xff) - b;
+                    distance = dr * dr + dg * dg + db * db;
+                    if (distance < minDistance) {
+                        lastindex = j;
+                        if (distance is 0) break;
+                        minDistance = distance;
+                    }
+                }
+                lastr = r; lastg = g; lastb = b;
+            }
+            if (ditherEnabled) {
+                // Floyd-Steinberg error diffusion, cont'd...
+                int dxm1 = dx - 1, dxp1 = dx + 1;
+                int acc;
+                rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr;
+                rerr[dx] += acc += lrerr + lrerr;
+                rerr[dxm1] += acc + lrerr + lrerr;
+                gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr;
+                gerr[dx] += acc += lgerr + lgerr;
+                gerr[dxm1] += acc + lgerr + lgerr;
+                berr[dxp1] += acc = (lberr = b - (destBlues[lastindex] & 0xff)) + lberr + lberr;
+                berr[dx] += acc += lberr + lberr;
+                berr[dxm1] += acc + lberr + lberr;
+            }
+
+            /*** WRITE NEXT PIXEL ***/
+            switch (dtype) {
+                case TYPE_INDEX_8:
+                    destData[dp] = cast(byte) lastindex;
+                    break;
+                case TYPE_INDEX_4:
+                    if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex);
+                    else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
+                    break;
+                case TYPE_INDEX_2: {
+                    int shift = 6 - (dp & 3) * 2;
+                    destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
+                } break;
+                case TYPE_INDEX_1_MSB: {
+                    int shift = 7 - (dp & 7);
+                    destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                } break;
+                case TYPE_INDEX_1_LSB: {
+                    int shift = dp & 7;
+                    destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                } break;
+                default:
+            }
+        }
+    }
+}
+
+/**
+ * Blits an index palette image into a direct palette image.
+ * <p>
+ * Note: The source and destination masks and palettes must
+ * always be fully specified.
+ * </p>
+ *
+ * @param op the blitter operation: a combination of BLIT_xxx flags
+ *        (see BLIT_xxx constants)
+ * @param srcData the source byte array containing image data
+ * @param srcDepth the source depth: one of 1, 2, 4, 8
+ * @param srcStride the source number of bytes per line
+ * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if srcDepth is not 1
+ * @param srcX the top-left x-coord of the source blit region
+ * @param srcY the top-left y-coord of the source blit region
+ * @param srcWidth the width of the source blit region
+ * @param srcHeight the height of the source blit region
+ * @param srcReds the source palette red component intensities
+ * @param srcGreens the source palette green component intensities
+ * @param srcBlues the source palette blue component intensities
+ * @param alphaMode the alpha blending or mask mode, may be
+ *        an integer 0-255 for global alpha; ignored if BLIT_ALPHA
+ *        not specified in the blitter operations
+ *        (see ALPHA_MODE_xxx constants)
+ * @param alphaData the alpha blending or mask data, varies depending
+ *        on the value of alphaMode and sometimes ignored
+ * @param alphaStride the alpha data number of bytes per line
+ * @param alphaX the top-left x-coord of the alpha blit region
+ * @param alphaY the top-left y-coord of the alpha blit region
+ * @param destData the destination byte array containing image data
+ * @param destDepth the destination depth: one of 8, 16, 24, 32
+ * @param destStride the destination number of bytes per line
+ * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if destDepth is not 16 or 32
+ * @param destX the top-left x-coord of the destination blit region
+ * @param destY the top-left y-coord of the destination blit region
+ * @param destWidth the width of the destination blit region
+ * @param destHeight the height of the destination blit region
+ * @param destRedMask the destination red channel mask
+ * @param destGreenMask the destination green channel mask
+ * @param destBlueMask the destination blue channel mask
+ * @param flipX if true the resulting image is flipped along the vertical axis
+ * @param flipY if true the resulting image is flipped along the horizontal axis
+ */
+static void blit(int op,
+    byte[] srcData, int srcDepth, int srcStride, int srcOrder,
+    int srcX, int srcY, int srcWidth, int srcHeight,
+    byte[] srcReds, byte[] srcGreens, byte[] srcBlues,
+    int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
+    byte[] destData, int destDepth, int destStride, int destOrder,
+    int destX, int destY, int destWidth, int destHeight,
+    int destRedMask, int destGreenMask, int destBlueMask,
+    bool flipX, bool flipY) {
+
+    static_this();
+
+    if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
+
+    // these should be supplied as params later
+    int destAlphaMask = 0;
+
+    /*** Prepare scaling data ***/
+    int dwm1 = destWidth - 1;
+    int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
+    int dhm1 = destHeight - 1;
+    int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
+
+    /*** Prepare source-related data ***/
+    int stype;
+    switch (srcDepth) {
+        case 8:
+            stype = TYPE_INDEX_8;
+            break;
+        case 4:
+            srcStride <<= 1;
+            stype = TYPE_INDEX_4;
+            break;
+        case 2:
+            srcStride <<= 2;
+            stype = TYPE_INDEX_2;
+            break;
+        case 1:
+            srcStride <<= 3;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int spr = srcY * srcStride + srcX;
+
+    /*** Prepare destination-related data ***/
+    int dbpp, dtype;
+    switch (destDepth) {
+        case 8:
+            dbpp = 1;
+            dtype = TYPE_GENERIC_8;
+            break;
+        case 16:
+            dbpp = 2;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
+            break;
+        case 24:
+            dbpp = 3;
+            dtype = TYPE_GENERIC_24;
+            break;
+        case 32:
+            dbpp = 4;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid destination type");
+            return;
+    }
+    int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp;
+    int dprxi = (flipX) ? -dbpp : dbpp;
+    int dpryi = (flipY) ? -destStride : destStride;
+
+    /*** Prepare special processing data ***/
+    int apr;
+    if ((op & BLIT_ALPHA) !is 0) {
+        switch (alphaMode) {
+            case ALPHA_MASK_UNPACKED:
+            case ALPHA_CHANNEL_SEPARATE:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_PACKED:
+                if (alphaData is null) alphaMode = 0x10000;
+                alphaStride <<= 3;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_INDEX:
+            case ALPHA_MASK_RGB:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = 0;
+                break;
+            default:
+                alphaMode = (alphaMode << 16) / 255; // prescale
+            case ALPHA_CHANNEL_SOURCE:
+                apr = 0;
+                break;
+        }
+    } else {
+        alphaMode = 0x10000;
+        apr = 0;
+    }
+
+    /*** Comprehensive blit (apply transformations) ***/
+    int destRedShift = getChannelShift(destRedMask);
+    int destRedWidth = getChannelWidth(destRedMask, destRedShift);
+    byte[] destReds = ANY_TO_EIGHT[destRedWidth];
+    int destRedPreShift = 8 - destRedWidth;
+    int destGreenShift = getChannelShift(destGreenMask);
+    int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
+    byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
+    int destGreenPreShift = 8 - destGreenWidth;
+    int destBlueShift = getChannelShift(destBlueMask);
+    int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
+    byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
+    int destBluePreShift = 8 - destBlueWidth;
+    int destAlphaShift = getChannelShift(destAlphaMask);
+    int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
+    byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
+    int destAlphaPreShift = 8 - destAlphaWidth;
+
+    int dp = dpr;
+    int sp = spr;
+    int ap = apr, alpha = alphaMode;
+    int r = 0, g = 0, b = 0, a = 0, index = 0;
+    int rq = 0, gq = 0, bq = 0, aq = 0;
+    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
+            sp = spr += (sfy >>> 16) * srcStride,
+            ap = apr += (sfy >>> 16) * alphaStride,
+            sfy = (sfy & 0xffff) + sfyi,
+            dp = dpr += dpryi) {
+        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
+                dp += dprxi,
+                sfx = (sfx & 0xffff) + sfxi) {
+            /*** READ NEXT PIXEL ***/
+            switch (stype) {
+                case TYPE_INDEX_8:
+                    index = srcData[sp] & 0xff;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_4:
+                    if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f;
+                    else index = (srcData[sp >> 1] >>> 4) & 0x0f;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_2:
+                    index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_1_MSB:
+                    index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01;
+                    sp += (sfx >>> 16);
+                    break;
+                case TYPE_INDEX_1_LSB:
+                    index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
+                    sp += (sfx >>> 16);
+                    break;
+                default:
+            }
+
+            /*** DO SPECIAL PROCESSING IF REQUIRED ***/
+            r = srcReds[index] & 0xff;
+            g = srcGreens[index] & 0xff;
+            b = srcBlues[index] & 0xff;
+            switch (alphaMode) {
+                case ALPHA_CHANNEL_SEPARATE:
+                    alpha = ((alphaData[ap] & 0xff) << 16) / 255;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_UNPACKED:
+                    alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_PACKED:
+                    alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices
+                    int i = 0;
+                    while (i < alphaData.length) {
+                        if (index is (alphaData[i] & 0xff)) break;
+                    }
+                    if (i < alphaData.length) continue;
+                } break;
+                case ALPHA_MASK_RGB: {
+                    int i = 0;
+                    while (i < alphaData.length) {
+                        if ((r is (alphaData[i] & 0xff)) &&
+                            (g is (alphaData[i + 1] & 0xff)) &&
+                            (b is (alphaData[i + 2] & 0xff))) break;
+                        i += 3;
+                    }
+                    if (i < alphaData.length) continue;
+                } break;
+                default:
+            }
+            if (alpha !is 0x10000) {
+                if (alpha is 0x0000) continue;
+                switch (dtype) {
+                    case TYPE_GENERIC_8: {
+                        int data = destData[dp] & 0xff;
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_16_MSB: {
+                        int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_16_LSB: {
+                        int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_24: {
+                        int data = (( ((destData[dp] & 0xff) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp + 2] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_32_MSB: {
+                        int data = (( (( ((destData[dp] & 0xff) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp + 2] & 0xff)) << 8) |
+                            (destData[dp + 3] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    case TYPE_GENERIC_32_LSB: {
+                        int data = (( (( ((destData[dp + 3] & 0xff) << 8) |
+                            (destData[dp + 2] & 0xff)) << 8) |
+                            (destData[dp + 1] & 0xff)) << 8) |
+                            (destData[dp] & 0xff);
+                        rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
+                        gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
+                        bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
+                        aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
+                    } break;
+                    default:
+                }
+                // Perform alpha blending
+                a = aq + ((a - aq) * alpha >> 16);
+                r = rq + ((r - rq) * alpha >> 16);
+                g = gq + ((g - gq) * alpha >> 16);
+                b = bq + ((b - bq) * alpha >> 16);
+            }
+
+            /*** WRITE NEXT PIXEL ***/
+            int data =
+                (r >>> destRedPreShift << destRedShift) |
+                (g >>> destGreenPreShift << destGreenShift) |
+                (b >>> destBluePreShift << destBlueShift) |
+                (a >>> destAlphaPreShift << destAlphaShift);
+            switch (dtype) {
+                case TYPE_GENERIC_8: {
+                    destData[dp] = cast(byte) data;
+                } break;
+                case TYPE_GENERIC_16_MSB: {
+                    destData[dp] = cast(byte) (data >>> 8);
+                    destData[dp + 1] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_16_LSB: {
+                    destData[dp] = cast(byte) (data & 0xff);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                } break;
+                case TYPE_GENERIC_24: {
+                    destData[dp] = cast(byte) (data >>> 16);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                    destData[dp + 2] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_32_MSB: {
+                    destData[dp] = cast(byte) (data >>> 24);
+                    destData[dp + 1] = cast(byte) (data >>> 16);
+                    destData[dp + 2] = cast(byte) (data >>> 8);
+                    destData[dp + 3] = cast(byte) (data & 0xff);
+                } break;
+                case TYPE_GENERIC_32_LSB: {
+                    destData[dp] = cast(byte) (data & 0xff);
+                    destData[dp + 1] = cast(byte) (data >>> 8);
+                    destData[dp + 2] = cast(byte) (data >>> 16);
+                    destData[dp + 3] = cast(byte) (data >>> 24);
+                } break;
+                default:
+            }
+        }
+    }
+}
+
+/**
+ * Blits a direct palette image into an index palette image.
+ * <p>
+ * Note: The source and destination masks and palettes must
+ * always be fully specified.
+ * </p>
+ *
+ * @param op the blitter operation: a combination of BLIT_xxx flags
+ *        (see BLIT_xxx constants)
+ * @param srcData the source byte array containing image data
+ * @param srcDepth the source depth: one of 8, 16, 24, 32
+ * @param srcStride the source number of bytes per line
+ * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if srcDepth is not 16 or 32
+ * @param srcX the top-left x-coord of the source blit region
+ * @param srcY the top-left y-coord of the source blit region
+ * @param srcWidth the width of the source blit region
+ * @param srcHeight the height of the source blit region
+ * @param srcRedMask the source red channel mask
+ * @param srcGreenMask the source green channel mask
+ * @param srcBlueMask the source blue channel mask
+ * @param alphaMode the alpha blending or mask mode, may be
+ *        an integer 0-255 for global alpha; ignored if BLIT_ALPHA
+ *        not specified in the blitter operations
+ *        (see ALPHA_MODE_xxx constants)
+ * @param alphaData the alpha blending or mask data, varies depending
+ *        on the value of alphaMode and sometimes ignored
+ * @param alphaStride the alpha data number of bytes per line
+ * @param alphaX the top-left x-coord of the alpha blit region
+ * @param alphaY the top-left y-coord of the alpha blit region
+ * @param destData the destination byte array containing image data
+ * @param destDepth the destination depth: one of 1, 2, 4, 8
+ * @param destStride the destination number of bytes per line
+ * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST;
+ *        ignored if destDepth is not 1
+ * @param destX the top-left x-coord of the destination blit region
+ * @param destY the top-left y-coord of the destination blit region
+ * @param destWidth the width of the destination blit region
+ * @param destHeight the height of the destination blit region
+ * @param destReds the destination palette red component intensities
+ * @param destGreens the destination palette green component intensities
+ * @param destBlues the destination palette blue component intensities
+ * @param flipX if true the resulting image is flipped along the vertical axis
+ * @param flipY if true the resulting image is flipped along the horizontal axis
+ */
+static void blit(int op,
+    byte[] srcData, int srcDepth, int srcStride, int srcOrder,
+    int srcX, int srcY, int srcWidth, int srcHeight,
+    int srcRedMask, int srcGreenMask, int srcBlueMask,
+    int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
+    byte[] destData, int destDepth, int destStride, int destOrder,
+    int destX, int destY, int destWidth, int destHeight,
+    byte[] destReds, byte[] destGreens, byte[] destBlues,
+    bool flipX, bool flipY) {
+
+    static_this();
+
+    if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
+
+    // these should be supplied as params later
+    int srcAlphaMask = 0;
+
+    /*** Prepare scaling data ***/
+    int dwm1 = destWidth - 1;
+    int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
+    int dhm1 = destHeight - 1;
+    int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
+
+    /*** Prepare source-related data ***/
+    int sbpp, stype;
+    switch (srcDepth) {
+        case 8:
+            sbpp = 1;
+            stype = TYPE_GENERIC_8;
+            break;
+        case 16:
+            sbpp = 2;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
+            break;
+        case 24:
+            sbpp = 3;
+            stype = TYPE_GENERIC_24;
+            break;
+        case 32:
+            sbpp = 4;
+            stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int spr = srcY * srcStride + srcX * sbpp;
+
+    /*** Prepare destination-related data ***/
+    int dtype;
+    switch (destDepth) {
+        case 8:
+            dtype = TYPE_INDEX_8;
+            break;
+        case 4:
+            destStride <<= 1;
+            dtype = TYPE_INDEX_4;
+            break;
+        case 2:
+            destStride <<= 2;
+            dtype = TYPE_INDEX_2;
+            break;
+        case 1:
+            destStride <<= 3;
+            dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
+            break;
+        default:
+            //throw new IllegalArgumentException("Invalid source type");
+            return;
+    }
+    int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX);
+    int dprxi = (flipX) ? -1 : 1;
+    int dpryi = (flipY) ? -destStride : destStride;
+
+    /*** Prepare special processing data ***/
+    int apr;
+    if ((op & BLIT_ALPHA) !is 0) {
+        switch (alphaMode) {
+            case ALPHA_MASK_UNPACKED:
+            case ALPHA_CHANNEL_SEPARATE:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_PACKED:
+                if (alphaData is null) alphaMode = 0x10000;
+                alphaStride <<= 3;
+                apr = alphaY * alphaStride + alphaX;
+                break;
+            case ALPHA_MASK_INDEX:
+                //throw new IllegalArgumentException("Invalid alpha type");
+                return;
+            case ALPHA_MASK_RGB:
+                if (alphaData is null) alphaMode = 0x10000;
+                apr = 0;
+                break;
+            default:
+                alphaMode = (alphaMode << 16) / 255; // prescale
+            case ALPHA_CHANNEL_SOURCE:
+                apr = 0;
+                break;
+        }
+    } else {
+        alphaMode = 0x10000;
+        apr = 0;
+    }
+    bool ditherEnabled = (op & BLIT_DITHER) !is 0;
+
+    /*** Comprehensive blit (apply transformations) ***/
+    int srcRedShift = getChannelShift(srcRedMask);
+    byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
+    int srcGreenShift = getChannelShift(srcGreenMask);
+    byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
+    int srcBlueShift = getChannelShift(srcBlueMask);
+    byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
+    int srcAlphaShift = getChannelShift(srcAlphaMask);
+    byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];
+
+    int dp = dpr;
+    int sp = spr;
+    int ap = apr, alpha = alphaMode;
+    int r = 0, g = 0, b = 0, a = 0;
+    int indexq = 0;
+    int lastindex = 0, lastr = -1, lastg = -1, lastb = -1;
+    int[] rerr, gerr, berr;
+    int destPaletteSize = 1 << destDepth;
+    if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length;
+    if (ditherEnabled) {
+        rerr = new int[destWidth + 2];
+        gerr = new int[destWidth + 2];
+        berr = new int[destWidth + 2];
+    } else {
+        rerr = null; gerr = null; berr = null;
+    }
+    for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
+            sp = spr += (sfy >>> 16) * srcStride,
+            ap = apr += (sfy >>> 16) * alphaStride,
+            sfy = (sfy & 0xffff) + sfyi,
+            dp = dpr += dpryi) {
+        int lrerr = 0, lgerr = 0, lberr = 0;
+        for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
+                dp += dprxi,
+                sfx = (sfx & 0xffff) + sfxi) {
+            /*** READ NEXT PIXEL ***/
+            switch (stype) {
+                case TYPE_GENERIC_8: {
+                    int data = srcData[sp] & 0xff;
+                    sp += (sfx >>> 16);
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_16_MSB: {
+                    int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff);
+                    sp += (sfx >>> 16) * 2;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_16_LSB: {
+                    int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff);
+                    sp += (sfx >>> 16) * 2;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_24: {
+                    int data = (( ((srcData[sp] & 0xff) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp + 2] & 0xff);
+                    sp += (sfx >>> 16) * 3;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_32_MSB: {
+                    int data = (( (( ((srcData[sp] & 0xff) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp + 2] & 0xff)) << 8) |
+                        (srcData[sp + 3] & 0xff);
+                    sp += (sfx >>> 16) * 4;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                case TYPE_GENERIC_32_LSB: {
+                    int data = (( (( ((srcData[sp + 3] & 0xff) << 8) |
+                        (srcData[sp + 2] & 0xff)) << 8) |
+                        (srcData[sp + 1] & 0xff)) << 8) |
+                        (srcData[sp] & 0xff);
+                    sp += (sfx >>> 16) * 4;
+                    r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
+                    g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
+                    b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
+                    a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
+                } break;
+                default:
+            }
+
+            /*** DO SPECIAL PROCESSING IF REQUIRED ***/
+            switch (alphaMode) {
+                case ALPHA_CHANNEL_SEPARATE:
+                    alpha = ((alphaData[ap] & 0xff) << 16) / 255;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_CHANNEL_SOURCE:
+                    alpha = (a << 16) / 255;
+                    break;
+                case ALPHA_MASK_UNPACKED:
+                    alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_PACKED:
+                    alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
+                    ap += (sfx >> 16);
+                    break;
+                case ALPHA_MASK_RGB:
+                    alpha = 0x10000;
+                    for (int i = 0; i < alphaData.length; i += 3) {
+                        if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) {
+                            alpha = 0x0000;
+                            break;
+                        }
+                    }
+                    break;
+                default:
+            }
+            if (alpha !is 0x10000) {
+                if (alpha is 0x0000) continue;
+                switch (dtype) {
+                    case TYPE_INDEX_8:
+                        indexq = destData[dp] & 0xff;
+                        break;
+                    case TYPE_INDEX_4:
+                        if ((dp & 1) !is 0) indexq = destData[dp >> 1] & 0x0f;
+                        else indexq = (destData[dp >> 1] >>> 4) & 0x0f;
+                        break;
+                    case TYPE_INDEX_2:
+                        indexq = (destData[dp >> 2] >>> (6 - (dp & 3) * 2)) & 0x03;
+                        break;
+                    case TYPE_INDEX_1_MSB:
+                        indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01;
+                        break;
+                    case TYPE_INDEX_1_LSB:
+                        indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01;
+                        break;
+                    default:
+                }
+                // Perform alpha blending
+                int rq = destReds[indexq] & 0xff;
+                int gq = destGreens[indexq] & 0xff;
+                int bq = destBlues[indexq] & 0xff;
+                r = rq + ((r - rq) * alpha >> 16);
+                g = gq + ((g - gq) * alpha >> 16);
+                b = bq + ((b - bq) * alpha >> 16);
+            }
+
+            /*** MAP COLOR TO THE PALETTE ***/
+            if (ditherEnabled) {
+                // Floyd-Steinberg error diffusion
+                r += rerr[dx] >> 4;
+                if (r < 0) r = 0; else if (r > 255) r = 255;
+                g += gerr[dx] >> 4;
+                if (g < 0) g = 0; else if (g > 255) g = 255;
+                b += berr[dx] >> 4;
+                if (b < 0) b = 0; else if (b > 255) b = 255;
+                rerr[dx] = lrerr;
+                gerr[dx] = lgerr;
+                berr[dx] = lberr;
+            }
+            if (r !is lastr || g !is lastg || b !is lastb) {
+                // moving the variable declarations out seems to make the JDK JIT happier...
+                for (int j = 0, dr, dg, db, distance, minDistance = 0x7fffffff; j < destPaletteSize; ++j) {
+                    dr = (destReds[j] & 0xff) - r;
+                    dg = (destGreens[j] & 0xff) - g;
+                    db = (destBlues[j] & 0xff) - b;
+                    distance = dr * dr + dg * dg + db * db;
+                    if (distance < minDistance) {
+                        lastindex = j;
+                        if (distance is 0) break;
+                        minDistance = distance;
+                    }
+                }
+                lastr = r; lastg = g; lastb = b;
+            }
+            if (ditherEnabled) {
+                // Floyd-Steinberg error diffusion, cont'd...
+                int dxm1 = dx - 1, dxp1 = dx + 1;
+                int acc;
+                rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr;
+                rerr[dx] += acc += lrerr + lrerr;
+                rerr[dxm1] += acc + lrerr + lrerr;
+                gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr;
+                gerr[dx] += acc += lgerr + lgerr;
+                gerr[dxm1] += acc + lgerr + lgerr;
+                berr[dxp1] += acc = (lberr = b - (destBlues[lastindex] & 0xff)) + lberr + lberr;
+                berr[dx] += acc += lberr + lberr;
+                berr[dxm1] += acc + lberr + lberr;
+            }
+
+            /*** WRITE NEXT PIXEL ***/
+            switch (dtype) {
+                case TYPE_INDEX_8:
+                    destData[dp] = cast(byte) lastindex;
+                    break;
+                case TYPE_INDEX_4:
+                    if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex);
+                    else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
+                    break;
+                case TYPE_INDEX_2: {
+                    int shift = 6 - (dp & 3) * 2;
+                    destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
+                } break;
+                case TYPE_INDEX_1_MSB: {
+                    int shift = 7 - (dp & 7);
+                    destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                } break;
+                case TYPE_INDEX_1_LSB: {
+                    int shift = dp & 7;
+                    destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
+                } break;
+                default:
+            }
+        }
+    }
+}
+
+/**
+ * Computes the required channel shift from a mask.
+ */
+static int getChannelShift(int mask) {
+    if (mask is 0) return 0;
+    int i;
+    for (i = 0; ((mask & 1) is 0) && (i < 32); ++i) {
+        mask >>>= 1;
+    }
+    return i;
+}
+
+/**
+ * Computes the required channel width (depth) from a mask.
+ */
+static int getChannelWidth(int mask, int shift) {
+    if (mask is 0) return 0;
+    int i;
+    mask >>>= shift;
+    for (i = shift; ((mask & 1) !is 0) && (i < 32); ++i) {
+        mask >>>= 1;
+    }
+    return i - shift;
+}
+
+/**
+ * Extracts a field from packed RGB data given a mask for that field.
+ */
+static byte getChannelField(int data, int mask) {
+    static_this();
+    int shift = getChannelShift(mask);
+    return ANY_TO_EIGHT[getChannelWidth(mask, shift)][(data & mask) >>> shift];
+}
+
+/**
+ * Creates an ImageData containing one band's worth of a gradient filled
+ * block.  If <code>vertical</code> is true, the band must be tiled
+ * horizontally to fill a region, otherwise it must be tiled vertically.
+ *
+ * @param width the width of the region to be filled
+ * @param height the height of the region to be filled
+ * @param vertical if true sweeps from top to bottom, else
+ *        sweeps from left to right
+ * @param fromRGB the color to start with
+ * @param toRGB the color to end with
+ * @param redBits the number of significant red bits, 0 for palette modes
+ * @param greenBits the number of significant green bits, 0 for palette modes
+ * @param blueBits the number of significant blue bits, 0 for palette modes
+ * @return the new ImageData
+ */
+static ImageData createGradientBand(
+    int width, int height, bool vertical,
+    RGB fromRGB, RGB toRGB,
+    int redBits, int greenBits, int blueBits) {
+    /* Gradients are drawn as tiled bands */
+    int bandWidth, bandHeight, bitmapDepth;
+    byte[] bitmapData;
+    PaletteData paletteData;
+    /* Select an algorithm depending on the depth of the screen */
+    if (redBits !is 0 && greenBits !is 0 && blueBits !is 0) {
+        paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000);
+        bitmapDepth = 32;
+        if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) {
+            /* Precise color */
+            int steps;
+            if (vertical) {
+                bandWidth = 1;
+                bandHeight = height;
+                steps = bandHeight > 1 ? bandHeight - 1 : 1;
+            } else {
+                bandWidth = width;
+                bandHeight = 1;
+                steps = bandWidth > 1 ? bandWidth - 1 : 1;
+            }
+            int bytesPerLine = bandWidth * 4;
+            bitmapData = new byte[bandHeight * bytesPerLine];
+            buildPreciseGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine);
+            buildPreciseGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine);
+            buildPreciseGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine);
+        } else {
+            /* Dithered color */
+            int steps;
+            if (vertical) {
+                bandWidth = (width < 8) ? width : 8;
+                bandHeight = height;
+                steps = bandHeight > 1 ? bandHeight - 1 : 1;
+            } else {
+                bandWidth = width;
+                bandHeight = (height < 8) ? height : 8;
+                steps = bandWidth > 1 ? bandWidth - 1 : 1;
+            }
+            int bytesPerLine = bandWidth * 4;
+            bitmapData = new byte[bandHeight * bytesPerLine];
+            buildDitheredGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine, blueBits);
+            buildDitheredGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine, greenBits);
+            buildDitheredGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine, redBits);
+        }
+    } else {
+        /* Dithered two tone */
+        paletteData = new PaletteData([ fromRGB, toRGB ]);
+        bitmapDepth = 8;
+        int blendi;
+        if (vertical) {
+            bandWidth = (width < 8) ? width : 8;
+            bandHeight = height;
+            blendi = (bandHeight > 1) ? 0x1040000 / (bandHeight - 1) + 1 : 1;
+        } else {
+            bandWidth = width;
+            bandHeight = (height < 8) ? height : 8;
+            blendi = (bandWidth > 1) ? 0x1040000 / (bandWidth - 1) + 1 : 1;
+        }
+        int bytesPerLine = (bandWidth + 3) & -4;
+        bitmapData = new byte[bandHeight * bytesPerLine];
+        if (vertical) {
+            for (int dy = 0, blend = 0, dp = 0; dy < bandHeight;
+                ++dy, blend += blendi, dp += bytesPerLine) {
+                for (int dx = 0; dx < bandWidth; ++dx) {
+                    bitmapData[dp + dx] = (blend + DITHER_MATRIX[dy & 7][dx]) <
+                        0x1000000 ? cast(byte)0 : cast(byte)1;
+                }
+            }
+        } else {
+            for (int dx = 0, blend = 0; dx < bandWidth; ++dx, blend += blendi) {
+                for (int dy = 0, dptr = dx; dy < bandHeight; ++dy, dptr += bytesPerLine) {
+                    bitmapData[dptr] = (blend + DITHER_MATRIX[dy][dx & 7]) <
+                        0x1000000 ? cast(byte)0 : cast(byte)1;
+                }
+            }
+        }
+    }
+    return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData, 4, bitmapData);
+}
+
+/*
+ * Fill in gradated values for a color channel
+ */
+static final void buildPreciseGradientChannel(int from, int to, int steps,
+    int bandWidth, int bandHeight, bool vertical,
+    byte[] bitmapData, int dp, int bytesPerLine) {
+    int val = from << 16;
+    int inc = ((to << 16) - val) / steps + 1;
+    if (vertical) {
+        for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+            bitmapData[dp] = cast(byte)(val >>> 16);
+            val += inc;
+        }
+    } else {
+        for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+            bitmapData[dp] = cast(byte)(val >>> 16);
+            val += inc;
+        }
+    }
+}
+
+/*
+ * Fill in dithered gradated values for a color channel
+ */
+static final void buildDitheredGradientChannel(int from, int to, int steps,
+    int bandWidth, int bandHeight, bool vertical,
+    byte[] bitmapData, int dp, int bytesPerLine, int bits) {
+    int mask = 0xff00 >>> bits;
+    int val = from << 16;
+    int inc = ((to << 16) - val) / steps + 1;
+    if (vertical) {
+        for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
+            for (int dx = 0, dptr = dp; dx < bandWidth; ++dx, dptr += 4) {
+                int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
+                int temp = val + thresh;
+                if (temp > 0xffffff) bitmapData[dptr] = -1;
+                else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
+            }
+            val += inc;
+        }
+    } else {
+        for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
+            for (int dy = 0, dptr = dp; dy < bandHeight; ++dy, dptr += bytesPerLine) {
+                int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
+                int temp = val + thresh;
+                if (temp > 0xffffff) bitmapData[dptr] = -1;
+                else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
+            }
+            val += inc;
+        }
+    }
+}
+
+/**
+ * Renders a gradient onto a GC.
+ * <p>
+ * This is a GC helper.
+ * </p>
+ *
+ * @param gc the GC to render the gradient onto
+ * @param device the device the GC belongs to
+ * @param x the top-left x coordinate of the region to be filled
+ * @param y the top-left y coordinate of the region to be filled
+ * @param width the width of the region to be filled
+ * @param height the height of the region to be filled
+ * @param vertical if true sweeps from top to bottom, else
+ *        sweeps from left to right
+ * @param fromRGB the color to start with
+ * @param toRGB the color to end with
+ * @param redBits the number of significant red bits, 0 for palette modes
+ * @param greenBits the number of significant green bits, 0 for palette modes
+ * @param blueBits the number of significant blue bits, 0 for palette modes
+ */
+static void fillGradientRectangle(GC gc, Device device,
+    int x, int y, int width, int height, bool vertical,
+    RGB fromRGB, RGB toRGB,
+    int redBits, int greenBits, int blueBits) {
+    /* Create the bitmap and tile it */
+    ImageData band = createGradientBand(width, height, vertical,
+        fromRGB, toRGB, redBits, greenBits, blueBits);
+    Image image = new Image(device, band);
+    if ((band.width is 1) || (band.height is 1)) {
+        gc.drawImage(image, 0, 0, band.width, band.height, x, y, width, height);
+    } else {
+        if (vertical) {
+            for (int dx = 0; dx < width; dx += band.width) {
+                int blitWidth = width - dx;
+                if (blitWidth > band.width) blitWidth = band.width;
+                gc.drawImage(image, 0, 0, blitWidth, band.height, dx + x, y, blitWidth, band.height);
+            }
+        } else {
+            for (int dy = 0; dy < height; dy += band.height) {
+                int blitHeight = height - dy;
+                if (blitHeight > band.height) blitHeight = band.height;
+                gc.drawImage(image, 0, 0, band.width, blitHeight, x, dy + y, band.width, blitHeight);
+            }
+        }
+    }
+    image.dispose();
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageDataLoader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.ImageDataLoader;
+
+public import org.eclipse.swt.graphics.ImageData;
+public import java.io.InputStream;
+
+import org.eclipse.swt.graphics.ImageLoader;
+import java.lang.all;
+
+/**
+ * Internal class that separates ImageData from ImageLoader
+ * to allow removal of ImageLoader from the toolkit.
+ */
+class ImageDataLoader {
+
+    public static ImageData[] load(InputStream stream) {
+        return (new ImageLoader()).load(stream);
+    }
+
+    public static ImageData[] load(String filename) {
+        return (new ImageLoader()).load(filename);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.ImageLoader;
+
+
+public import org.eclipse.swt.graphics.ImageLoaderListener;
+public import org.eclipse.swt.graphics.ImageLoaderEvent;
+public import org.eclipse.swt.graphics.ImageData;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.image.FileFormat;
+
+import tango.core.Exception;
+import tango.core.Array;
+import java.lang.all;
+
+
+/**
+ * Instances of this class are used to load images from,
+ * and save images to, a file or stream.
+ * <p>
+ * Currently supported image formats are:
+ * </p><ul>
+ * <li>BMP (Windows or OS/2 Bitmap)</li>
+ * <li>ICO (Windows Icon)</li>
+ * <li>JPEG</li>
+ * <li>GIF</li>
+ * <li>PNG</li>
+ * <li>TIFF</li>
+ * </ul>
+ * <code>ImageLoaders</code> can be used to:
+ * <ul>
+ * <li>load/save single images in all formats</li>
+ * <li>load/save multiple images (GIF/ICO/TIFF)</li>
+ * <li>load/save animated GIF images</li>
+ * <li>load interlaced GIF/PNG images</li>
+ * <li>load progressive JPEG images</li>
+ * </ul>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ImageAnalyzer</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class ImageLoader {
+
+    /**
+     * the array of ImageData objects in this ImageLoader.
+     * This array is read in when the load method is called,
+     * and it is written out when the save method is called
+     */
+    public ImageData[] data;
+
+    /**
+     * the width of the logical screen on which the images
+     * reside, in pixels (this corresponds to the GIF89a
+     * Logical Screen Width value)
+     */
+    public int logicalScreenWidth;
+
+    /**
+     * the height of the logical screen on which the images
+     * reside, in pixels (this corresponds to the GIF89a
+     * Logical Screen Height value)
+     */
+    public int logicalScreenHeight;
+
+    /**
+     * the background pixel for the logical screen (this
+     * corresponds to the GIF89a Background Color Index value).
+     * The default is -1 which means 'unspecified background'
+     *
+     */
+    public int backgroundPixel;
+
+    /**
+     * the number of times to repeat the display of a sequence
+     * of animated images (this corresponds to the commonly-used
+     * GIF application extension for "NETSCAPE 2.0 01").
+     * The default is 1. A value of 0 means 'display repeatedly'
+     */
+    public int repeatCount;
+
+    /*
+     * the set of ImageLoader event listeners, created on demand
+     */
+    ImageLoaderListener[] imageLoaderListeners;
+
+/**
+ * Construct a new empty ImageLoader.
+ */
+public this() {
+    reset();
+}
+
+/**
+ * Resets the fields of the ImageLoader, except for the
+ * <code>imageLoaderListeners</code> field.
+ */
+void reset() {
+    data = null;
+    logicalScreenWidth = 0;
+    logicalScreenHeight = 0;
+    backgroundPixel = -1;
+    repeatCount = 1;
+}
+
+/**
+ * Loads an array of <code>ImageData</code> objects from the
+ * specified input stream. Throws an error if either an error
+ * occurs while loading the images, or if the images are not
+ * of a supported type. Returns the loaded image data array.
+ *
+ * @param stream the input stream to load the images from
+ * @return an array of <code>ImageData</code> objects loaded from the specified input stream
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
+ * </ul>
+ */
+public ImageData[] load(InputStream stream) {
+    if (stream is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    reset();
+    data = FileFormat.load(stream, this);
+    return data;
+}
+
+/**
+ * Loads an array of <code>ImageData</code> objects from the
+ * file with the specified name. Throws an error if either
+ * an error occurs while loading the images, or if the images are
+ * not of a supported type. Returns the loaded image data array.
+ *
+ * @param filename the name of the file to load the images from
+ * @return an array of <code>ImageData</code> objects loaded from the specified file
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while reading from the file</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
+ * </ul>
+ */
+public ImageData[] load(String filename) {
+    if (filename is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    InputStream stream = null;
+    void close(){
+        try {
+            if( stream !is null ) stream.close();
+        } catch (IOException e) {
+            // Ignore error
+        }
+    }
+    try {
+        stream = Compatibility.newFileInputStream(filename);
+        scope(exit) close();
+
+        return load(stream);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return null;
+}
+
+/**
+ * Saves the image data in this ImageLoader to the specified stream.
+ * The format parameter can have one of the following values:
+ * <dl>
+ * <dt><code>IMAGE_BMP</code></dt>
+ * <dd>Windows BMP file format, no compression</dd>
+ * <dt><code>IMAGE_BMP_RLE</code></dt>
+ * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+ * <dt><code>IMAGE_GIF</code></dt>
+ * <dd>GIF file format</dd>
+ * <dt><code>IMAGE_ICO</code></dt>
+ * <dd>Windows ICO file format</dd>
+ * <dt><code>IMAGE_JPEG</code></dt>
+ * <dd>JPEG file format</dd>
+ * <dt><code>IMAGE_PNG</code></dt>
+ * <dd>PNG file format</dd>
+ * </dl>
+ *
+ * @param stream the output stream to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while writing to the stream</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
+ * </ul>
+ */
+public void save(OutputStream stream, int format) {
+    if (stream is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    FileFormat.save(stream, format, this);
+}
+
+/**
+ * Saves the image data in this ImageLoader to a file with the specified name.
+ * The format parameter can have one of the following values:
+ * <dl>
+ * <dt><code>IMAGE_BMP</code></dt>
+ * <dd>Windows BMP file format, no compression</dd>
+ * <dt><code>IMAGE_BMP_RLE</code></dt>
+ * <dd>Windows BMP file format, RLE compression if appropriate</dd>
+ * <dt><code>IMAGE_GIF</code></dt>
+ * <dd>GIF file format</dd>
+ * <dt><code>IMAGE_ICO</code></dt>
+ * <dd>Windows ICO file format</dd>
+ * <dt><code>IMAGE_JPEG</code></dt>
+ * <dd>JPEG file format</dd>
+ * <dt><code>IMAGE_PNG</code></dt>
+ * <dd>PNG file format</dd>
+ * </dl>
+ *
+ * @param filename the name of the file to write the images to
+ * @param format the format to write the images in
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_IO - if an IO error occurs while writing to the file</li>
+ *    <li>ERROR_INVALID_IMAGE - if the image data contains invalid data</li>
+ *    <li>ERROR_UNSUPPORTED_FORMAT - if the image data cannot be saved to the requested format</li>
+ * </ul>
+ */
+public void save(String filename, int format) {
+    if (filename is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    OutputStream stream = null;
+    try {
+        stream = Compatibility.newFileOutputStream(filename);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    save(stream, format);
+    try {
+        stream.close();
+    } catch (IOException e) {
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will be
+ * notified when image data is either partially or completely loaded.
+ * <p>
+ * An ImageLoaderListener should be added before invoking
+ * one of the receiver's load methods. The listener's
+ * <code>imageDataLoaded</code> method is called when image
+ * data has been partially loaded, as is supported by interlaced
+ * GIF/PNG or progressive JPEG images.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @see ImageLoaderListener
+ * @see ImageLoaderEvent
+ */
+public void addImageLoaderListener(ImageLoaderListener listener) {
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    imageLoaderListeners ~= listener;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will be
+ * notified when image data is either partially or completely loaded.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ *
+ * @see #addImageLoaderListener(ImageLoaderListener)
+ */
+public void removeImageLoaderListener(ImageLoaderListener listener) {
+    if (listener is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (imageLoaderListeners.length == 0 ) return;
+    imageLoaderListeners.length = tango.core.Array.remove( imageLoaderListeners, listener, delegate bool(ImageLoaderListener l1, ImageLoaderListener l2 ){ return l1 is l2; });
+}
+
+/**
+ * Returns <code>true</code> if the receiver has image loader
+ * listeners, and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if there are <code>ImageLoaderListener</code>s, and <code>false</code> otherwise
+ *
+ * @see #addImageLoaderListener(ImageLoaderListener)
+ * @see #removeImageLoaderListener(ImageLoaderListener)
+ */
+public bool hasListeners() {
+    return imageLoaderListeners.length > 0;
+}
+
+/**
+ * Notifies all image loader listeners that an image loader event
+ * has occurred. Pass the specified event object to each listener.
+ *
+ * @param event the <code>ImageLoaderEvent</code> to send to each <code>ImageLoaderListener</code>
+ */
+public void notifyListeners(ImageLoaderEvent event) {
+    if (!hasListeners()) return;
+    foreach( listener; imageLoaderListeners ){
+        listener.imageDataLoaded(event);
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.ImageLoaderEvent;
+
+
+public import org.eclipse.swt.internal.SWTEventObject;
+public import org.eclipse.swt.graphics.ImageLoader;
+public import org.eclipse.swt.graphics.ImageData;
+import java.lang.all;
+
+import tango.text.convert.Format;
+
+/**
+ * Instances of this class are sent as a result of the incremental
+ * loading of image data.
+ * <p>
+ * <b>Notes:</b>
+ * </p><ul>
+ * <li>The number of events which will be sent when loading images
+ * is not constant. It varies by image type, and for JPEG images it
+ * varies from image to image.</li>
+ * <li>For image sources which contain multiple images, the
+ * <code>endOfImage</code> flag in the event will be set to true
+ * after each individual image is loaded.</li>
+ * </ul>
+ *
+ * @see ImageLoader
+ * @see ImageLoaderListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class ImageLoaderEvent : SWTEventObject {
+
+    /**
+     * if the <code>endOfImage</code> flag is false, then this is a
+     * partially complete copy of the current <code>ImageData</code>,
+     * otherwise this is a completely loaded <code>ImageData</code>
+     */
+    public ImageData imageData;
+
+    /**
+     * the zero-based count of image data increments -- this is
+     * equivalent to the number of events that have been generated
+     * while loading a particular image
+     */
+    public int incrementCount;
+
+    /**
+     * If this flag is true, then the current image data has been
+     * completely loaded, otherwise the image data is only partially
+     * loaded, and further ImageLoader events will occur unless an
+     * exception is thrown
+     */
+    public bool endOfImage;
+
+    //static final long serialVersionUID = 3257284738325558065L;
+
+/**
+ * Constructs a new instance of this class given the event source and
+ * the values to store in its fields.
+ *
+ * @param source the ImageLoader that was loading when the event occurred
+ * @param imageData the image data for the event
+ * @param incrementCount the image data increment for the event
+ * @param endOfImage the end of image flag for the event
+ */
+public this(ImageLoader source, ImageData imageData, int incrementCount, bool endOfImage) {
+    super(source);
+    this.imageData = imageData;
+    this.incrementCount = incrementCount;
+    this.endOfImage = endOfImage;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString () {
+    return Format( "ImageLoaderEvent {source={} imageData={} incrementCount={} endOfImage={}}", source, imageData, incrementCount, endOfImage); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/ImageLoaderListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.ImageLoaderListener;
+
+
+public import org.eclipse.swt.graphics.ImageLoaderEvent;
+public import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the incremental loading of image data.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to an image loader using the
+ * <code>addImageLoaderListener</code> method and removed using
+ * the <code>removeImageLoaderListener</code> method. When
+ * image data is either partially or completely loaded, this
+ * method will be invoked.
+ * </p>
+ *
+ * @see ImageLoader
+ * @see ImageLoaderEvent
+ */
+
+public interface ImageLoaderListener : SWTEventListener {
+
+/**
+ * Sent when image data is either partially or completely loaded.
+ * <p>
+ * The timing of when this method is called varies depending on
+ * the format of the image being loaded.
+ * </p>
+ *
+ * @param e an event containing information about the image loading operation
+ */
+public void imageDataLoaded(ImageLoaderEvent e);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/LineAttributes.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.LineAttributes;
+
+import org.eclipse.swt.SWT;
+
+/**
+ * <code>LineAttributes</code> defines a set of line attributes that
+ * can be modified in a GC.
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see GC#getLineAttributes()
+ * @see GC#setLineAttributes(LineAttributes)
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+public class LineAttributes {
+
+    /**
+     * The line width.
+     */
+    public float width;
+
+    /**
+     * The line style.
+     *
+     * @see org.eclipse.swt.SWT#LINE_CUSTOM
+     * @see org.eclipse.swt.SWT#LINE_DASH
+     * @see org.eclipse.swt.SWT#LINE_DASHDOT
+     * @see org.eclipse.swt.SWT#LINE_DASHDOTDOT
+     * @see org.eclipse.swt.SWT#LINE_DOT
+     * @see org.eclipse.swt.SWT#LINE_SOLID
+     */
+    public int style;
+
+    /**
+     * The line cap style.
+     *
+     * @see org.eclipse.swt.SWT#CAP_FLAT
+     * @see org.eclipse.swt.SWT#CAP_ROUND
+     * @see org.eclipse.swt.SWT#CAP_SQUARE
+     */
+    public int cap;
+
+    /**
+     * The line join style.
+     *
+     * @see org.eclipse.swt.SWT#JOIN_BEVEL
+     * @see org.eclipse.swt.SWT#JOIN_MITER
+     * @see org.eclipse.swt.SWT#JOIN_ROUND
+     */
+    public int join;
+
+    /**
+     * The line dash style for SWT.LINE_CUSTOM.
+     */
+    public float[] dash;
+
+    /**
+     * The line dash style offset for SWT.LINE_CUSTOM.
+     */
+    public float dashOffset;
+
+    /**
+     * The line miter limit.
+     */
+    public float miterLimit;
+
+/**
+ * Create a new line attributes with the specified line width.
+ *
+ * @param width the line width
+ */
+public this(float width) {
+    this(width, SWT.CAP_FLAT, SWT.JOIN_MITER, SWT.LINE_SOLID, null, 0, 10);
+}
+
+/**
+ * Create a new line attributes with the specified line cap, join and width.
+ *
+ * @param width the line width
+ * @param cap the line cap style
+ * @param join the line join style
+ */
+public this(float width, int cap, int join) {
+    this(width, cap, join, SWT.LINE_SOLID, null, 0, 10);
+}
+
+/**
+ * Create a new line attributes with the specified arguments.
+ *
+ * @param width the line width
+ * @param cap the line cap style
+ * @param join the line join style
+ * @param style the line style
+ * @param dash the line dash style
+ * @param dashOffset the line dash style offset
+ * @param miterLimit the line miter limit
+ */
+public this(float width, int cap, int join, int style, float[] dash, float dashOffset, float miterLimit) {
+    this.width = width;
+    this.cap = cap;
+    this.join = join;
+    this.style = style;
+    this.dash = dash;
+    this.dashOffset = dashOffset;
+    this.miterLimit = miterLimit;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/PaletteData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.PaletteData;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Instances of this class describe the color data used by an image.
+ * <p>
+ * Depending on the depth of the image, the PaletteData can take one
+ * of two forms, indicated by the isDirect field:
+ * </p>
+ * <dl>
+ * <dt>
+ * <em>isDirect is false</em>
+ * </dt>
+ * <dd>
+ * If isDirect is <code>false</code>, this palette is an indexed
+ * palette which maps pixel values to RGBs. The actual RGB values
+ * may be retrieved by using the getRGBs() method.
+ * </dd>
+ * <dt>
+ * <em>isDirect is true</em>
+ * </dt>
+ * <dd>
+ * If isDirect is <code>true</code>, this palette is a direct color
+ * palette. Instead of containing RGB values, it contains red,
+ * green and blue mask and shift information which indicates how
+ * the color components may be extracted from a given pixel.
+ * This means that the RGB value is actually encoded in the pixel value.
+ * <p>
+ * In this case, the shift data is the number of bits required to shift
+ * the RGB value to the left in order to align the high bit of the
+ * corresponding mask with the high bit of the first byte. This number
+ * may be negative, so care must be taken when shifting. For example,
+ * with a red mask of 0xFF0000, the red shift would be -16. With a red
+ * mask of 0x1F, the red shift would be 3.
+ * </p>
+ * </dd>
+ * </dl>
+ *
+ * @see Image
+ * @see RGB
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class PaletteData {
+
+    /**
+     * true if the receiver is a direct palette,
+     * and false otherwise
+     */
+    public bool isDirect;
+
+    /**
+     * the RGB values for an indexed palette, where the
+     * indices of the array correspond to pixel values
+     */
+    public RGB[] colors;
+
+    /**
+     * the red mask for a direct palette
+     */
+    public int redMask;
+
+    /**
+     * the green mask for a direct palette
+     */
+    public int greenMask;
+
+    /**
+     * the blue mask for a direct palette
+     */
+    public int blueMask;
+
+    /**
+     * the red shift for a direct palette
+     */
+    public int redShift;
+
+    /**
+     * the green shift for a direct palette
+     */
+    public int greenShift;
+
+    /**
+     * the blue shift for a direct palette
+     */
+    public int blueShift;
+
+/**
+ * Constructs a new indexed palette given an array of RGB values.
+ *
+ * @param colors the array of <code>RGB</code>s for the palette
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public this(RGB[] colors) {
+    if (colors is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    this.colors = colors;
+    this.isDirect = false;
+}
+
+/**
+ * Constructs a new direct palette given the red, green and blue masks.
+ *
+ * @param redMask the red mask
+ * @param greenMask the green mask
+ * @param blueMask the blue mask
+ */
+public this(int redMask, int greenMask, int blueMask) {
+    this.redMask = redMask;
+    this.greenMask = greenMask;
+    this.blueMask = blueMask;
+    this.isDirect = true;
+    this.redShift = shiftForMask(redMask);
+    this.greenShift = shiftForMask(greenMask);
+    this.blueShift = shiftForMask(blueMask);
+}
+
+/**
+ * Returns the pixel value corresponding to the given <code>RGB</code>.
+ *
+ * @param rgb the RGB to get the pixel value for
+ * @return the pixel value for the given RGB
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
+ * </ul>
+ */
+public int getPixel(RGB rgb) {
+    if (rgb is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (isDirect) {
+        int pixel = 0;
+        pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask;
+        pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask;
+        pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask;
+        return pixel;
+    } else {
+        for (int i = 0; i < colors.length; i++) {
+            if (colors[i].opEquals(rgb)) return i;
+        }
+        /* The RGB did not exist in the palette */
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        return 0;
+    }
+}
+
+/**
+ * Returns an <code>RGB</code> corresponding to the given pixel value.
+ *
+ * @param pixel the pixel to get the RGB value for
+ * @return the RGB value for the given pixel
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
+ * </ul>
+ */
+public RGB getRGB(int pixel) {
+    if (isDirect) {
+        int r = pixel & redMask;
+        r = (redShift < 0) ? r >>> -redShift : r << redShift;
+        int g = pixel & greenMask;
+        g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
+        int b = pixel & blueMask;
+        b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
+        return new RGB(r, g, b);
+    } else {
+        if (pixel < 0 || pixel >= colors.length) {
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+        return colors[pixel];
+    }
+}
+
+/**
+ * Returns all the RGB values in the receiver if it is an
+ * indexed palette, or null if it is a direct palette.
+ *
+ * @return the <code>RGB</code>s for the receiver or null
+ */
+public RGB[] getRGBs() {
+    return colors;
+}
+
+/**
+ * Computes the shift value for a given mask.
+ *
+ * @param mask the mask to compute the shift for
+ * @return the shift amount
+ *
+ * @see PaletteData
+ */
+int shiftForMask(int mask) {
+    for (int i = 31; i >= 0; i--) {
+        if (((mask >> i) & 0x1) !is 0) return 7 - i;
+    }
+    return 32;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Path.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,622 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Path;
+
+import org.eclipse.swt.internal.gdip.Gdip;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.PathData;
+
+import java.lang.System;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent paths through the two-dimensional
+ * coordinate system. Paths do not have to be continuous, and can be
+ * described using lines, rectangles, arcs, cubic or quadratic bezier curves,
+ * glyphs, or other paths.
+ * <p>
+ * Application code must explicitly invoke the <code>Path.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#path">Path, Pattern snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.1
+ */
+public class Path : Resource {
+
+    alias Resource.init_ init_;
+
+    /**
+     * the OS resource for the Path
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public Gdip.Path handle;
+
+    Gdip.PointF currentPoint, startPoint;
+
+/**
+ * Constructs a new empty Path.
+ * <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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this (Device device) {
+    super(device);
+    this.device.checkGDIP();
+    handle = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    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 SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <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) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (path.isDisposed()) SWT.error(SWT.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) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new Path 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 SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <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) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    init_(data);
+}
+
+/**
+ * Adds to the receiver a circular or elliptical arc that lies within
+ * the specified rectangular area.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees.
+ * Angles are interpreted such that 0 degrees is at the 3 o'clock
+ * position. A positive value indicates a counter-clockwise rotation
+ * while a negative value indicates a clockwise rotation.
+ * </p><p>
+ * The center of the arc is the center of the rectangle whose origin
+ * is (<code>x</code>, <code>y</code>) and whose size is specified by the
+ * <code>width</code> and <code>height</code> arguments.
+ * </p><p>
+ * The resulting arc covers an area <code>width + 1</code> pixels wide
+ * by <code>height + 1</code> pixels tall.
+ * </p>
+ *
+ * @param x the x coordinate of the upper-left corner of the arc
+ * @param y the y coordinate of the upper-left corner of the arc
+ * @param width the width of the arc
+ * @param height the height of the arc
+ * @param startAngle the beginning angle
+ * @param arcAngle the angular extent of the arc, relative to the start angle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addArc(float x, float y, float width, float height, float startAngle, float arcAngle) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width < 0) {
+        x = x + width;
+        width = -width;
+    }
+    if (height < 0) {
+        y = y + height;
+        height = -height;
+    }
+    if (width is 0 || height is 0 || arcAngle is 0) return;
+    if (width is height) {
+        Gdip.GraphicsPath_AddArcF(handle, x, y, width, height, -startAngle, -arcAngle);
+    } else {
+        auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+        if (path is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        auto matrix = Gdip.Matrix_new(width, 0, 0, height, x, y);
+        if (matrix is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        Gdip.GraphicsPath_AddArc(path, 0, 0, 1, 1, -startAngle, -arcAngle);
+        Gdip.GraphicsPath_Transform(path, matrix);
+        Gdip.GraphicsPath_AddPath(handle, path, true);
+        Gdip.Matrix_delete(matrix);
+        Gdip.GraphicsPath_delete(path);
+    }
+    Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
+}
+
+/**
+ * Adds to the receiver the path described by the parameter.
+ *
+ * @param path the path to add to the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addPath(Path path) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (path is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    //TODO - expose connect?
+    Gdip.GraphicsPath_AddPath(handle, path.handle, false);
+    currentPoint.X = path.currentPoint.X;
+    currentPoint.Y = path.currentPoint.Y;
+}
+
+/**
+ * Adds to the receiver the rectangle specified by x, y, width and height.
+ *
+ * @param x the x coordinate of the rectangle to add
+ * @param y the y coordinate of the rectangle to add
+ * @param width the width of the rectangle to add
+ * @param height the height of the rectangle to add
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addRectangle(float x, float y, float width, float height) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.RectF rect;
+    rect.X = x;
+    rect.Y = y;
+    rect.Width = width;
+    rect.Height = height;
+    Gdip.GraphicsPath_AddRectangle(handle, rect);
+    currentPoint.X = x;
+    currentPoint.Y = y;
+}
+
+/**
+ * Adds to the receiver the pattern of glyphs generated by drawing
+ * the given string using the given font starting at the point (x, y).
+ *
+ * @param string the text to use
+ * @param x the x coordinate of the starting point
+ * @param y the y coordinate of the starting point
+ * @param font the font to use
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the font is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addString(String string, float x, float y, Font font) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (font is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    wchar[] wstr = StrToWCHARs( string );
+    wchar* buffer = wstr.ptr;
+    int length = wstr.length;
+    auto hDC = device.internal_new_GC(null);
+    auto gdipFont = GC.createGdipFont(hDC, font.handle);
+    Gdip.PointF point;
+    point.X = x - (Gdip.Font_GetSize(gdipFont) / 6);
+    point.Y = y;
+    auto family = Gdip.FontFamily_new();
+    Gdip.Font_GetFamily(gdipFont, family);
+    int style = Gdip.Font_GetStyle(gdipFont);
+    float size = Gdip.Font_GetSize(gdipFont);
+    Gdip.GraphicsPath_AddString(handle, buffer, length, family, style, size, point, null);
+    Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
+    Gdip.FontFamily_delete(family);
+    Gdip.Font_delete(gdipFont);
+    device.internal_dispose_GC(hDC, null);
+}
+
+/**
+ * Closes the current sub path by adding to the receiver a line
+ * from the current point of the path back to the starting point
+ * of the sub path.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void close() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.GraphicsPath_CloseFigure(handle);
+    /*
+    * Feature in GDI+. CloseFigure() does affect the last
+    * point, so GetLastPoint() does not return the starting
+    * point of the subpath after calling CloseFigure().  The
+    * fix is to remember the subpath starting point and use
+    * it instead.
+    */
+    currentPoint.X = startPoint.X;
+    currentPoint.Y = startPoint.Y;
+}
+
+/**
+ * Returns <code>true</code> if the specified point is contained by
+ * the receiver and false otherwise.
+ * <p>
+ * If outline is <code>true</code>, the point (x, y) checked for containment in
+ * the receiver's outline. If outline is <code>false</code>, the point is
+ * checked to see if it is contained within the bounds of the (closed) area
+ * covered by the receiver.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @param gc the GC to use when testing for containment
+ * @param outline controls whether to check the outline or contained area of the path
+ * @return <code>true</code> if the path contains the point and <code>false</code> otherwise
+ *
+ * @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 SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool contains(float x, float y, GC gc, bool outline) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (gc is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    //TODO - should use GC transformation
+    gc.initGdip();
+    gc.checkGC(GC.LINE_CAP | GC.LINE_JOIN | GC.LINE_STYLE | GC.LINE_WIDTH);
+    int mode = OS.GetPolyFillMode(gc.handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
+    Gdip.GraphicsPath_SetFillMode(handle, mode);
+    if (outline) {
+        return Gdip.GraphicsPath_IsOutlineVisible(handle, x, y, gc.data.gdipPen, gc.data.gdipGraphics);
+    } else {
+        return Gdip.GraphicsPath_IsVisible(handle, x, y, gc.data.gdipGraphics);
+    }
+}
+
+/**
+ * Adds to the receiver a cubic bezier curve based on the parameters.
+ *
+ * @param cx1 the x coordinate of the first control point of the spline
+ * @param cy1 the y coordinate of the first control of the spline
+ * @param cx2 the x coordinate of the second control of the spline
+ * @param cy2 the y coordinate of the second control of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.GraphicsPath_AddBezier(handle, currentPoint.X, currentPoint.Y, cx1, cy1, cx2, cy2, x, y);
+    Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
+}
+
+void destroy() {
+    Gdip.GraphicsPath_delete(handle);
+    handle = null;
+}
+
+/**
+ * Replaces the first four elements in the parameter with values that
+ * describe the smallest rectangle that will completely contain the
+ * receiver (i.e. the bounding box).
+ *
+ * @param bounds the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the bounding box</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getBounds(float[] bounds) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (bounds is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    Gdip.RectF rect;
+    Gdip.GraphicsPath_GetBounds(handle, rect, null, null);
+    bounds[0] = rect.X;
+    bounds[1] = rect.Y;
+    bounds[2] = rect.Width;
+    bounds[3] = rect.Height;
+}
+
+/**
+ * Replaces the first two elements in the parameter with values that
+ * describe the current point of the path.
+ *
+ * @param point the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the end point</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getCurrentPoint(float[] point) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (point is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (point.length < 2) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    point[0] = currentPoint.X;
+    point[1] = currentPoint.Y;
+}
+
+/**
+ * Returns a device independent representation of the receiver.
+ *
+ * @return the PathData for the receiver
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see PathData
+ */
+public PathData getPathData() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    int count = Gdip.GraphicsPath_GetPointCount(handle);
+    byte[] gdipTypes = new byte[count];
+    float[] points = new float[count * 2];
+    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) {
+        byte type = gdipTypes[index];
+        bool close = false;
+        switch (type & Gdip.PathPointTypePathTypeMask) {
+            case Gdip.PathPointTypeStart:
+                types[typesIndex++] = SWT.PATH_MOVE_TO;
+                close = (type & Gdip.PathPointTypeCloseSubpath) !is 0;
+                index += 1;
+                break;
+            case Gdip.PathPointTypeLine:
+                types[typesIndex++] = SWT.PATH_LINE_TO;
+                close = (type & Gdip.PathPointTypeCloseSubpath) !is 0;
+                index += 1;
+                break;
+            case Gdip.PathPointTypeBezier:
+                types[typesIndex++] = SWT.PATH_CUBIC_TO;
+                close = (gdipTypes[index + 2] & Gdip.PathPointTypeCloseSubpath) !is 0;
+                index += 3;
+                break;
+            default:
+                index++;
+        }
+        if (close) {
+            types[typesIndex++] = SWT.PATH_CLOSE;
+        }
+    }
+    if (typesIndex !is types.length) {
+        byte[] newTypes = new byte[typesIndex];
+        System.arraycopy(types, 0, newTypes, 0, typesIndex);
+        types = newTypes;
+    }
+    PathData result = new PathData();
+    result.types = types;
+    result.points = points;
+    return result;
+}
+
+/**
+ * Adds to the receiver a line from the current point to
+ * the point specified by (x, y).
+ *
+ * @param x the x coordinate of the end of the line to add
+ * @param y the y coordinate of the end of the line to add
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void lineTo(float x, float y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.GraphicsPath_AddLine(handle, currentPoint.X, currentPoint.Y, x, y);
+    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 SWT.PATH_MOVE_TO:
+                moveTo(points[j++], points[j++]);
+                break;
+            case SWT.PATH_LINE_TO:
+                lineTo(points[j++], points[j++]);
+                break;
+            case SWT.PATH_CUBIC_TO:
+                cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]);
+                break;
+            case SWT.PATH_QUAD_TO:
+                quadTo(points[j++], points[j++], points[j++], points[j++]);
+                break;
+            case SWT.PATH_CLOSE:
+                close();
+                break;
+            default:
+                dispose();
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+}
+
+/**
+ * Returns <code>true</code> if the Path has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Path.
+ * When a Path has been disposed, it is an error to
+ * invoke any other method using the Path.
+ *
+ * @return <code>true</code> when the Path is disposed, and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Sets the current point of the receiver to the point
+ * specified by (x, y). Note that this starts a new
+ * sub path.
+ *
+ * @param x the x coordinate of the new end point
+ * @param y the y coordinate of the new end point
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void moveTo(float x, float y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.GraphicsPath_StartFigure(handle);
+    currentPoint.X = startPoint.X = x;
+    currentPoint.Y = startPoint.Y = y;
+}
+
+/**
+ * Adds to the receiver a quadratic curve based on the parameters.
+ *
+ * @param cx the x coordinate of the control point of the spline
+ * @param cy the y coordinate of the control point of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void quadTo(float cx, float cy, float x, float y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    float cx1 = currentPoint.X + 2 * (cx - currentPoint.X) / 3;
+    float cy1 = currentPoint.Y + 2 * (cy - currentPoint.Y) / 3;
+    float cx2 = cx1 + (x - currentPoint.X) / 3;
+    float cy2 = cy1 + (y - currentPoint.Y) / 3;
+    Gdip.GraphicsPath_AddBezier(handle, currentPoint.X, currentPoint.Y, cx1, cy1, cx2, cy2, x, y);
+    Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString() {
+    if (isDisposed()) return "Path {*DISPOSED*}";
+    return Format( "Path {{{}}", handle );
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/PathData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.PathData;
+
+
+/**
+ * Instances of this class describe device-independent paths.
+ *
+ * @see Path
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public final class PathData {
+
+    /**
+     * The type of each point.
+     */
+    public byte[] types;
+
+    /**
+     * The points of a path.
+     */
+    public float[] points;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Pattern.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.gdip.Gdip;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Image;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent patterns to use while drawing. Patterns
+ * can be specified either as bitmaps or gradients.
+ * <p>
+ * Application code must explicitly invoke the <code>Pattern.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#path">Path, Pattern snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public class Pattern : Resource {
+    alias Resource.init_ init_;
+    /**
+     * the OS resource for the Pattern
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public Gdip.Brush handle;
+
+/**
+ * Constructs a new Pattern given an image. Drawing with the resulting
+ * pattern will cause the image to be tiled over the resulting area.
+ * <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 pattern
+ * @param image the image that the pattern will draw
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device, or the image is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this(Device device, Image image) {
+    super(device);
+    if (image is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    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);
+    Gdip.Bitmap_delete( cast(Gdip.Bitmap)img);
+    if (gdipImage[1] !is 0) {
+        auto hHeap = OS.GetProcessHeap ();
+        OS.HeapFree(hHeap, 0, cast(void*)gdipImage[1]);
+    }
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ * <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 pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param color2 the ending color of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ *                              or if either color1 or color2 is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this(Device device, float x1, float y1, float x2, float y2, Color color1, Color color2) {
+    this(device, x1, y1, x2, y2, color1, 0xFF, color2, 0xFF);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ * <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 pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param alpha1 the starting alpha value of the gradient
+ * @param color2 the ending color of the gradient
+ * @param alpha2 the ending alpha value of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ *                              or if either color1 or color2 is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ *
+ * @since 3.2
+ */
+public this(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
+    super(device);
+    if (color1 is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (color2 is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    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);
+    if (x1 is x2 && y1 is y2) {
+        handle = cast(Gdip.Brush)Gdip.SolidBrush_new(foreColor);
+        if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    } else {
+        auto colorRef2 = color2.handle;
+        rgb = ((colorRef2 >> 16) & 0xFF) | (colorRef2 & 0xFF00) | ((colorRef2 & 0xFF) << 16);
+        auto backColor = Gdip.Color_new((alpha2 & 0xFF) << 24 | rgb);
+        Gdip.PointF p1;
+        p1.X = x1;
+        p1.Y = y1;
+        Gdip.PointF p2;
+        p2.X = x2;
+        p2.Y = y2;
+        handle = cast(Gdip.Brush)Gdip.LinearGradientBrush_new(p1, p2, foreColor, backColor);
+        if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        if (alpha1 != 0xFF || alpha2 !is 0xFF) {
+            int a = cast(int)((alpha1 & 0xFF) * 0.5f + (alpha2 & 0xFF) * 0.5f);
+            int r = cast(int)(((colorRef1 & 0xFF) >> 0) * 0.5f + ((colorRef2 & 0xFF) >> 0) * 0.5f);
+            int g = cast(int)(((colorRef1 & 0xFF00) >> 8) * 0.5f + ((colorRef2 & 0xFF00) >> 8) * 0.5f);
+            int b = cast(int)(((colorRef1 & 0xFF0000) >> 16) * 0.5f + ((colorRef2 & 0xFF0000) >> 16) * 0.5f);
+            auto midColor = Gdip.Color_new(a << 24 | r << 16 | g << 8 | b);
+            Gdip.ARGB[3] c;
+            c[0] = foreColor;
+            c[1] = midColor;
+            c[2] = backColor;
+            float[3] f;
+            f[0] = 0;
+            f[1] = 0.5f;
+            f[2] = 1;
+            Gdip.LinearGradientBrush_SetInterpolationColors( cast(Gdip.LinearGradientBrush)handle, c.ptr, f.ptr, 3);
+            Gdip.Color_delete(midColor);
+        }
+        Gdip.Color_delete(backColor);
+    }
+    Gdip.Color_delete(foreColor);
+    init_();
+}
+
+void destroy() {
+    int type = Gdip.Brush_GetType(handle);
+    switch (type) {
+        case Gdip.BrushTypeSolidColor:
+            Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)handle);
+            break;
+        case Gdip.BrushTypeHatchFill:
+            Gdip.HatchBrush_delete(cast(Gdip.HatchBrush)handle);
+            break;
+        case Gdip.BrushTypeLinearGradient:
+            Gdip.LinearGradientBrush_delete(cast(Gdip.LinearGradientBrush)handle);
+            break;
+        case Gdip.BrushTypeTextureFill:
+            Gdip.TextureBrush_delete(cast(Gdip.TextureBrush)handle);
+            break;
+        default:
+    }
+    handle = null;
+}
+
+/**
+ * Returns <code>true</code> if the Pattern has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Pattern.
+ * When a Pattern has been disposed, it is an error to
+ * invoke any other method using the Pattern.
+ *
+ * @return <code>true</code> when the Pattern is disposed, and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString() {
+    if (isDisposed()) return "Pattern {*DISPOSED*}";
+    return Format( "Pattern {{{}}", handle );
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Point.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Point;
+
+
+public import org.eclipse.swt.internal.SerializableCompatibility;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent places on the (x, y)
+ * coordinate plane.
+ * <p>
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ * </p>
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Rectangle
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Point : SerializableCompatibility {
+
+    /**
+     * the x coordinate of the point
+     */
+    public int x;
+
+    /**
+     * the y coordinate of the point
+     */
+    public int y;
+
+    //static final long serialVersionUID = 3257002163938146354L;
+
+/**
+ * Constructs a new point with the given x and y coordinates.
+ *
+ * @param x the x coordinate of the new point
+ * @param y the y coordinate of the new point
+ */
+public this (int x, int y) {
+    this.x = x;
+    this.y = y;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+    if (object is this) return true;
+    if ( auto p = cast(Point)object ){
+        return (p.x is this.x) && (p.y is this.y);
+    }
+    return false;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+override public hash_t toHash () {
+    return x ^ y;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the point
+ */
+override public String toString () {
+    return Format( "Point {{{}, {}}", x, y );; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/RGB.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.RGB;
+
+public import org.eclipse.swt.internal.SerializableCompatibility;
+
+import org.eclipse.swt.SWT;
+import Math = tango.math.Math : min, max;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are descriptions of colors in
+ * terms of the primary additive color model (red, green and
+ * blue). A color may be described in terms of the relative
+ * intensities of these three primary colors. The brightness
+ * of each color is specified by a value in the range 0 to 255,
+ * where 0 indicates no color (blackness) and 255 indicates
+ * maximum intensity.
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Color
+ * @see <a href="http://www.eclipse.org/swt/snippets/#color">Color and RGB snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class RGB : SerializableCompatibility {
+
+    /**
+     * the red component of the RGB
+     */
+    public int red;
+
+    /**
+     * the green component of the RGB
+     */
+    public int green;
+
+    /**
+     * the blue component of the RGB
+     */
+    public int blue;
+
+    //static final long serialVersionUID = 3258415023461249074L;
+
+/**
+ * Constructs an instance of this class with the given
+ * red, green and blue values.
+ *
+ * @param red the red component of the new instance
+ * @param green the green component of the new instance
+ * @param blue the blue component of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ */
+public this (int red, int green, int blue) {
+    if ((red > 255) || (red < 0) ||
+        (green > 255) || (green < 0) ||
+        (blue > 255) || (blue < 0))
+            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    this.red = red;
+    this.green = green;
+    this.blue = blue;
+}
+
+/**
+* Constructs an instance of this class with the given
+* hue, saturation, and brightness.
+*
+* @param hue the hue value for the HSB color (from 0 to 360)
+* @param saturation the saturation value for the HSB color (from 0 to 1)
+* @param brightness the brightness value for the HSB color (from 0 to 1)
+*
+* @exception IllegalArgumentException <ul>
+*    <li>ERROR_INVALID_ARGUMENT - if the hue is not between 0 and 360 or
+*    the saturation or brightness is not between 0 and 1</li>
+* </ul>
+*
+* @since 3.2
+*/
+public this (float hue, float saturation, float brightness) {
+    if (hue < 0 || hue > 360 || saturation < 0 || saturation > 1 ||
+        brightness < 0 || brightness > 1) {
+        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    float r, g, b;
+    if (saturation is 0) {
+        r = g = b = brightness;
+    } else {
+        if (hue is 360) hue = 0;
+        hue /= 60;
+        int i = cast(int)hue;
+        float f = hue - i;
+        float p = brightness * (1 - saturation);
+        float q = brightness * (1 - saturation * f);
+        float t = brightness * (1 - saturation * (1 - f));
+        switch(i) {
+            case 0:
+                r = brightness;
+                g = t;
+                b = p;
+                break;
+            case 1:
+                r = q;
+                g = brightness;
+                b = p;
+                break;
+            case 2:
+                r = p;
+                g = brightness;
+                b = t;
+                break;
+            case 3:
+                r = p;
+                g = q;
+                b = brightness;
+                break;
+            case 4:
+                r = t;
+                g = p;
+                b = brightness;
+                break;
+            case 5:
+            default:
+                r = brightness;
+                g = p;
+                b = q;
+                break;
+        }
+    }
+    red = cast(int)(r * 255 + 0.5);
+    green = cast(int)(g * 255 + 0.5);
+    blue = cast(int)(b * 255 + 0.5);
+}
+
+/**
+ * Returns the hue, saturation, and brightness of the color.
+ *
+ * @return color space values in float format (hue, saturation, brightness)
+ *
+ * @since 3.2
+ */
+public float[] getHSB() {
+    float r = red / 255f;
+    float g = green / 255f;
+    float b = blue / 255f;
+    float max = Math.max(Math.max(r, g), b);
+    float min = Math.min(Math.min(r, g), b);
+    float delta = max - min;
+    float hue = 0;
+    float brightness = max;
+    float saturation = max is 0 ? 0 : (max - min) / max;
+    if (delta !is 0) {
+        if (r is max) {
+            hue = (g  - b) / delta;
+        } else {
+            if (g is max) {
+                hue = 2 + (b - r) / delta;
+            } else {
+                hue = 4 + (r - g) / delta;
+            }
+        }
+        hue *= 60;
+        if (hue < 0) hue += 360;
+    }
+    return [ hue, saturation, brightness ];
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals(Object object) {
+    if (object is this) return true;
+    if( auto rgb = cast(RGB) object ){
+        return (rgb.red is this.red) && (rgb.green is this.green) && (rgb.blue is this.blue);
+    }
+    return false;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+override public hash_t toHash() {
+    return (blue << 16) | (green << 8) | red;
+}
+
+/**
+ * Returns a String containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a String representation of the <code>RGB</code>
+ */
+public override String toString() {
+    return Format( "RGB {{{}, {}, {}}", red, green, blue ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Rectangle.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,353 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Rectangle;
+
+public import org.eclipse.swt.graphics.Point;
+public import org.eclipse.swt.internal.SerializableCompatibility;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent rectangular areas in an
+ * (x, y) coordinate system. The top left corner of the rectangle
+ * is specified by its x and y values, and the extent of the
+ * rectangle is specified by its width and height.
+ * <p>
+ * The coordinate space for rectangles and points is considered
+ * to have increasing values downward and to the right from its
+ * origin making this the normal, computer graphics oriented notion
+ * of (x, y) coordinates rather than the strict mathematical one.
+ * </p>
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Point
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Rectangle : SerializableCompatibility {
+
+    /**
+     * the x coordinate of the rectangle
+     */
+    public int x;
+
+    /**
+     * the y coordinate of the rectangle
+     */
+    public int y;
+
+    /**
+     * the width of the rectangle
+     */
+    public int width;
+
+    /**
+     * the height of the rectangle
+     */
+    public int height;
+
+    //static final long serialVersionUID = 3256439218279428914L;
+
+/**
+ * Construct a new instance of this class given the
+ * x, y, width and height values.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+public this (int x, int y, int width, int height) {
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+}
+
+/**
+ * Destructively replaces the x, y, width and height values
+ * in the receiver with ones which represent the union of the
+ * rectangles specified by the receiver and the given rectangle.
+ * <p>
+ * The union of two rectangles is the smallest single rectangle
+ * that completely covers both of the areas covered by the two
+ * given rectangles.
+ * </p>
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public void add (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    int left = x < rect.x ? x : rect.x;
+    int top = y < rect.y ? y : rect.y;
+    int lhs = x + width;
+    int rhs = rect.x + rect.width;
+    int right = lhs > rhs ? lhs : rhs;
+    lhs = y + height;
+    rhs = rect.y + rect.height;
+    int bottom = lhs > rhs ? lhs : rhs;
+    x = left;  y = top;  width = right - left;  height = bottom - top;
+}
+
+/**
+ * Returns <code>true</code> if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
+ */
+public bool contains (int x, int y) {
+    return (x >= this.x) && (y >= this.y) && ((x - this.x) < width) && ((y - this.y) < height);
+}
+
+/**
+ * Returns <code>true</code> if the given point is inside the
+ * area specified by the receiver, and <code>false</code>
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return <code>true</code> if the rectangle contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public bool contains (Point pt) {
+    if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    return contains(pt.x, pt.y);
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+    if (object is this) return true;
+    if( auto r = cast(Rectangle) object ){
+        return (r.x is this.x) && (r.y is this.y) && (r.width is this.width) && (r.height is this.height);
+    }
+    return false;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash () {
+    return x ^ y ^ width ^ height;
+}
+
+/**
+ * Destructively replaces the x, y, width and height values
+ * in the receiver with ones which represent the intersection of the
+ * rectangles specified by the receiver and the given rectangle.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * since 3.0
+ */
+public void intersect (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (this is rect) return;
+    int left = x > rect.x ? x : rect.x;
+    int top = y > rect.y ? y : rect.y;
+    int lhs = x + width;
+    int rhs = rect.x + rect.width;
+    int right = lhs < rhs ? lhs : rhs;
+    lhs = y + height;
+    rhs = rect.y + rect.height;
+    int bottom = lhs < rhs ? lhs : rhs;
+    x = right < left ? 0 : left;
+    y = bottom < top ? 0 : top;
+    width = right < left ? 0 : right - left;
+    height = bottom < top ? 0 : bottom - top;
+}
+
+/**
+ * Returns a new rectangle which represents the intersection
+ * of the receiver and the given rectangle.
+ * <p>
+ * The intersection of two rectangles is the rectangle that
+ * covers the area which is contained within both rectangles.
+ * </p>
+ *
+ * @param rect the rectangle to intersect with the receiver
+ * @return the intersection of the receiver and the argument
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ */
+public Rectangle intersection (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (this is rect) return new Rectangle (x, y, width, height);
+    int left = x > rect.x ? x : rect.x;
+    int top = y > rect.y ? y : rect.y;
+    int lhs = x + width;
+    int rhs = rect.x + rect.width;
+    int right = lhs < rhs ? lhs : rhs;
+    lhs = y + height;
+    rhs = rect.y + rect.height;
+    int bottom = lhs < rhs ? lhs : rhs;
+    return new Rectangle (
+        right < left ? 0 : left,
+        bottom < top ? 0 : top,
+        right < left ? 0 : right - left,
+        bottom < top ? 0 : bottom - top);
+}
+
+/**
+ * Returns <code>true</code> if the rectangle described by the
+ * arguments intersects with the receiver and <code>false</code>
+ * otherwise.
+ * <p>
+ * Two rectangles intersect if the area of the rectangle
+ * representing their intersection is not empty.
+ * </p>
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * @see #intersection(Rectangle)
+ * @see #isEmpty()
+ *
+ * @since 3.0
+ */
+public bool intersects (int x, int y, int width, int height) {
+    return (x < this.x + this.width) && (y < this.y + this.height) &&
+        (x + width > this.x) && (y + height > this.y);
+}
+
+/**
+ * Returns <code>true</code> if the given rectangle intersects
+ * with the receiver and <code>false</code> otherwise.
+ * <p>
+ * Two rectangles intersect if the area of the rectangle
+ * representing their intersection is not empty.
+ * </p>
+ *
+ * @param rect the rectangle to test for intersection
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * @see #intersection(Rectangle)
+ * @see #isEmpty()
+ */
+public bool intersects (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    return rect is this || intersects (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and <code>false</code> if
+ * the receiver does cover some area in the plane.
+ * <p>
+ * A rectangle is considered to <em>cover area</em> in the
+ * (x, y) coordinate plane if both its width and height are
+ * non-zero.
+ * </p>
+ *
+ * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
+ */
+public bool isEmpty () {
+    return (width <= 0) || (height <= 0);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the rectangle
+ */
+public override String toString () {
+    return Format( "Rectangle {{{}, {}, {}, {}}", x, y, width, height ); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+}
+
+/**
+ * Returns a new rectangle which represents the union of
+ * the receiver and the given rectangle.
+ * <p>
+ * The union of two rectangles is the smallest single rectangle
+ * that completely covers both of the areas covered by the two
+ * given rectangles.
+ * </p>
+ *
+ * @param rect the rectangle to perform union with
+ * @return the union of the receiver and the argument
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ *
+ * @see #add(Rectangle)
+ */
+public Rectangle makeUnion (Rectangle rect) {
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    int left = x < rect.x ? x : rect.x;
+    int top = y < rect.y ? y : rect.y;
+    int lhs = x + width;
+    int rhs = rect.x + rect.width;
+    int right = lhs > rhs ? lhs : rhs;
+    lhs = y + height;
+    rhs = rect.y + rect.height;
+    int bottom = lhs > rhs ? lhs : rhs;
+    return new Rectangle (left, top, right - left, bottom - top);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Region.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,612 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Region;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Device;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent areas of an x-y coordinate
+ * system that are aggregates of the areas covered by a number
+ * of polygons.
+ * <p>
+ * Application code must explicitly invoke the <code>Region.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class Region : Resource {
+    alias Resource.init_ init_;
+
+    /**
+     * the OS resource for the region
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HRGN handle;
+
+/**
+ * Constructs a new empty region.
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ */
+public this () {
+    this(null);
+}
+
+/**
+ * Constructs a new empty region.
+ * <p>
+ * You must dispose the region when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the region
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ *
+ * @see #dispose
+ *
+ * @since 3.0
+ */
+public this (Device device) {
+    super(device);
+    handle = OS.CreateRectRgn (0, 0, 0, 0);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new region given a handle to the operating
+ * system resources that it should represent.
+ *
+ * @param handle the handle for the result
+ */
+this(Device device, HRGN handle) {
+    super(device);
+    this.handle = handle;
+}
+
+/**
+ * Adds the given polygon to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+*
+ */
+public void add (int[] pointArray) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+    auto polyRgn = OS.CreatePolygonRgn(cast(POINT*)pointArray.ptr, pointArray.length / 2, OS.ALTERNATE);
+    OS.CombineRgn (handle, handle, polyRgn, OS.RGN_OR);
+    OS.DeleteObject (polyRgn);
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Rectangle rect) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    add (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void add (int x, int y, int width, int height) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+    OS.CombineRgn (handle, handle, rectRgn, OS.RGN_OR);
+    OS.DeleteObject (rectRgn);
+}
+
+/**
+ * Adds all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to merge
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Region region) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    OS.CombineRgn (handle, handle, region.handle, OS.RGN_OR);
+}
+
+/**
+ * Returns <code>true</code> if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool contains (int x, int y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return cast(bool) OS.PtInRegion (handle, x, y);
+}
+
+/**
+ * Returns <code>true</code> if the given point is inside the
+ * area specified by the receiver, and <code>false</code>
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool contains (Point pt) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    return contains(pt.x, pt.y);
+}
+
+void destroy () {
+    OS.DeleteObject(handle);
+    handle = null;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode
+ */
+override public int opEquals (Object object) {
+    if (this is object) return true;
+    if (!(cast(Region)object)) return false;
+    Region rgn = cast(Region)object;
+    return handle is rgn.handle;
+}
+
+/**
+ * Returns a rectangle which represents the rectangular
+ * union of the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @return a bounding rectangle for the region
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#union
+ */
+public Rectangle getBounds() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    RECT rect;
+    OS.GetRgnBox(handle, &rect);
+    return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals
+ */
+override public hash_t toHash () {
+    return cast(hash_t)handle;
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Rectangle rect) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    intersect (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void intersect (int x, int y, int width, int height) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+    OS.CombineRgn (handle, handle, rectRgn, OS.RGN_AND);
+    OS.DeleteObject (rectRgn);
+}
+
+/**
+ * Intersects all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to intersect
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Region region) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    OS.CombineRgn (handle, handle, region.handle, OS.RGN_AND);
+}
+
+/**
+ * Returns <code>true</code> if the rectangle described by the
+ * arguments intersects with any of the polygons the receiver
+ * maintains to describe its area, and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public bool intersects (int x, int y, int width, int height) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    RECT r;
+    OS.SetRect (&r, x, y, x + width, y + height);
+    return cast(bool) OS.RectInRegion (handle, &r);
+}
+
+/**
+ * Returns <code>true</code> if the given rectangle intersects
+ * with any of the polygons the receiver maintains to describe
+ * its area and <code>false</code> otherwise.
+ *
+ * @param rect the rectangle to test for intersection
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public bool intersects (Rectangle rect) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    return intersects(rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns <code>true</code> if the region has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the region.
+ * When a region has been disposed, it is an error to
+ * invoke any other method using the region.
+ *
+ * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Returns <code>true</code> if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and <code>false</code> if
+ * the receiver does cover some area in the plane.
+ *
+ * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public bool isEmpty () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    RECT rect;
+    auto result = OS.GetRgnBox (handle, &rect);
+    if (result is OS.NULLREGION) return true;
+    return ((rect.right - rect.left) <= 0) || ((rect.bottom - rect.top) <= 0);
+}
+
+/**
+ * Subtracts the given polygon from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (int[] pointArray) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+    auto polyRgn = OS.CreatePolygonRgn(cast(POINT*)pointArray.ptr, pointArray.length / 2, OS.ALTERNATE);
+    OS.CombineRgn (handle, handle, polyRgn, OS.RGN_DIFF);
+    OS.DeleteObject (polyRgn);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to subtract from the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Rectangle rect) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (rect is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    subtract (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void subtract (int x, int y, int width, int height) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    auto rectRgn = OS.CreateRectRgn (x, y, x + width, y + height);
+    OS.CombineRgn (handle, handle, rectRgn, OS.RGN_DIFF);
+    OS.DeleteObject (rectRgn);
+}
+
+/**
+ * Subtracts all of the polygons which make up the area covered
+ * by the argument from the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to subtract
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Region region) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (region is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    OS.CombineRgn (handle, handle, region.handle, OS.RGN_DIFF);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param x the x coordinate of the point to translate
+ * @param y the y coordinate of the point to translate
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (int x, int y) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    OS.OffsetRgn (handle, x, y);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param pt the point to translate
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (Point pt) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pt is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    translate (pt.x, pt.y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "Region {*DISPOSED*}";
+    return Format( "Region {{{}}", handle );
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new region.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Region</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the region
+ * @param handle the handle for the region
+ * @return a new region object containing the specified device and handle
+ */
+public static Region win32_new(Device device, HRGN handle) {
+    auto region = new Region(device, handle);
+    region.disposeChecking = false;
+    return region;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Resource.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Resource;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Device;
+
+/**
+ * This class is the abstract superclass of all graphics resource objects.
+ * Resources created by the application must be disposed.
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation. However, it has not been marked
+ * final to allow those outside of the SWT development team to implement
+ * patched versions of the class in order to get around specific
+ * limitations in advance of when those limitations can be addressed
+ * by the team.  Any class built using subclassing to access the internals
+ * of this class will likely fail to compile or run between releases and
+ * may be strongly platform specific. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the workings of the
+ * hierarchy. No support is provided for user-written classes which are
+ * implemented as subclasses of this class.
+ * </p>
+ *
+ * @see #dispose
+ * @see #isDisposed
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public abstract class Resource {
+
+    /// SWT extension for D: do no dispose check
+    public bool disposeChecking = true;
+    /// SWT extension for D: do no dispose check
+    public static bool globalDisposeChecking = true;
+
+    /**
+     * the device where this resource was created
+     */
+    Device device;
+
+public this() {
+}
+
+this(Device device) {
+    if (device is null) device = Device.getDevice();
+    if (device is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    this.device = device;
+}
+
+~this(){
+    if( globalDisposeChecking && disposeChecking && !isDisposed() ){
+        SWT.error( 0, null, " Resource deleted, but is not yet disposed. "
+                "This check can be disabled with "
+                "\"import org.eclipse.swt.graphics.Resource; "
+                "Resource.globalDisposeChecking = false; \". "
+                "This problem occured with type " ~ this.classinfo.name ~
+                " this.toString()=" ~ this.toString() );
+    }
+}
+
+void destroy() {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * this resource. Applications must dispose of all resources
+ * which they allocate.
+ */
+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
+ * created.
+ *
+ * @return <code>Device</code> the device of the receiver
+ *
+ * @since 3.2
+ */
+public Device getDevice() {
+    Device device = this.device;
+    if (device is null || isDisposed ()) SWT.error (SWT.ERROR_GRAPHIC_DISPOSED);
+    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.
+ * <p>
+ * This method gets the dispose state for the resource.
+ * When a resource has been disposed, it is an error to
+ * invoke any other method using the resource.
+ *
+ * @return <code>true</code> when the resource is disposed and <code>false</code> otherwise
+ */
+public abstract bool isDisposed();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3170 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.TextLayout;
+
+/++
+ + SWT Changes to make the port work.
+ + The USER API is utf8, the Windows API is utf16. In addition to the fields 'text' and 'segmentsText' fields are added to help.
+ + wtext: same as text but utf16
+ + segmentsWText: same as segmentsText but utf16
+ + index8to16: translate indexes from segmentsText to segmentsWText
+ + index16to8: translate indexes from segmentsWText to segmentsText
+ +
+ + 'text' is the original user text, 'segmentsText' is the user text stuffed with
+ + RTL/LTR markers for each line or in addition for User supplied segments. A segment
+ + is a range where Bidi char reordering can happen.
+ + The 'runs' are those ranges with an idiviual style.
+ +/
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.gdip.Gdip;
+
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.GlyphMetrics;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.TextStyle;
+
+import tango.text.convert.Format;
+import Utf = tango.text.convert.Utf;
+import java.lang.all;
+import java.lang.System;
+
+
+/**
+ * <code>TextLayout</code> is a graphic object that represents
+ * styled text.
+ * <p>
+ * Instances of this class provide support for drawing, cursor
+ * navigation, hit testing, text wrapping, alignment, tab expansion
+ * line breaking, etc.  These are aspects required for rendering internationalized text.
+ * </p><p>
+ * Application code must explicitly invoke the <code>TextLayout#dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#textlayout">TextLayout, TextStyle snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: CustomControlExample, StyledText tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.0
+ */
+public final class TextLayout : Resource {
+
+    alias Resource.init_ init_;
+
+/++
+ +  SWT doku
+ +  The styles has at minimum 2 member, each with a start. The last element is the end marker.
+ +
+ +  invariant{
+ +      assert( stylesCount >= 2 );
+ +      assert( stylesCount <= styles.length );
+ +      assert( styles[stylesCount-1] );
+ +      assert( styles[stylesCount-1].start is text.length );
+ +  }
+ +/
+
+
+    Font font;
+    String  text;
+    wchar[] wtext;
+    char[]  segmentsText;
+    wchar[] segmentsWText; // SWT
+    int[]   index8to16; // SWT
+    int[]   index16to8; // SWT
+    int lineSpacing;
+    int ascent, descent;
+    int alignment;
+    int wrapWidth;
+    int orientation;
+    int indent;
+    bool justify;
+    int[] tabs;
+    int[] segments; // indices in 'text'
+    int[] wsegments; // SWT indices in 'wtext'
+    StyleItem[] styles;
+    int stylesCount;
+
+    StyleItem[] allRuns;
+    StyleItem[][] runs;
+    int[] lineOffset, lineY, lineWidth;
+    void* mLangFontLink2;
+
+    static const dchar LTR_MARK = '\u200E', RTL_MARK = '\u200F';
+    static const wchar LTR_MARKw = '\u200E', RTL_MARKw = '\u200F';
+    static const String STR_LTR_MARK = "\u200E", STR_RTL_MARK = "\u200F";
+    static const wchar[] WSTR_LTR_MARK = "\u200E"w, WSTR_RTL_MARK = "\u200F"w;
+    static const int MARK_SIZE = 3;
+    static const int WMARK_SIZE = 1;
+    static const int SCRIPT_VISATTR_SIZEOF = 2;
+    static const int GOFFSET_SIZEOF = 8;
+    private static byte[16] CLSID_CMultiLanguage;
+    private static byte[16] IID_IMLangFontLink2;
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        // in case of allready initialized, we can check and leave without lock
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( !static_this_completed ){
+                OS.IIDFromString("{275c23e2-3747-11d0-9fea-00aa003f8646}\0".toWCharArray().ptr, CLSID_CMultiLanguage.ptr);
+                OS.IIDFromString("{DCCFC162-2B38-11d2-B7EC-00C04F8F5D9A}\0".toWCharArray().ptr, IID_IMLangFontLink2.ptr);
+                static_this_completed = true;
+            }
+        }
+    }
+
+    /* 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;
+        // SWT: start, lenght relative to segmentsText
+        int start, length;
+        bool lineBreak, softBreak, tab;
+
+        /*Script cache and analysis */
+        SCRIPT_ANALYSIS analysis;
+        SCRIPT_CACHE* psc;
+
+        /*Shape info (malloc when the run is shaped) */
+        WORD* glyphs;
+        int glyphCount;
+        WORD* clusters;
+        SCRIPT_VISATTR* visAttrs;
+
+        /*Place info (malloc when the run is placed) */
+        int* advances;
+        GOFFSET* goffsets;
+        int width;
+        int ascent;
+        int descent;
+        int leading;
+        int x;
+        int underlinePos, underlineThickness;
+        int strikeoutPos, strikeoutThickness;
+
+        /* Justify info (malloc during computeRuns) */
+        int* justify;
+
+        /* ScriptBreak */
+        SCRIPT_LOGATTR* psla;
+
+        HFONT fallbackFont;
+
+    void free() {
+        auto hHeap = OS.GetProcessHeap();
+        if (psc !is null) {
+            OS.ScriptFreeCache (psc);
+            OS.HeapFree(hHeap, 0, psc);
+            psc = null;
+        }
+        if (glyphs !is null) {
+            OS.HeapFree(hHeap, 0, glyphs);
+            glyphs = null;
+            glyphCount = 0;
+        }
+        if (clusters !is null) {
+            OS.HeapFree(hHeap, 0, clusters);
+            clusters = null;
+        }
+        if (visAttrs !is null) {
+            OS.HeapFree(hHeap, 0, visAttrs);
+            visAttrs = null;
+        }
+        if (advances !is null) {
+            OS.HeapFree(hHeap, 0, advances);
+            advances = null;
+        }
+        if (goffsets !is null) {
+            OS.HeapFree(hHeap, 0, goffsets);
+            goffsets = null;
+        }
+        if (justify !is null) {
+            OS.HeapFree(hHeap, 0, justify);
+            justify = null;
+        }
+        if (psla !is null) {
+            OS.HeapFree(hHeap, 0, psla);
+            psla = null;
+        }
+        if (fallbackFont !is null) {
+            OS.DeleteObject(fallbackFont);
+            fallbackFont = null;
+        }
+        width = 0;
+        ascent = 0;
+        descent = 0;
+        x = 0;
+        lineBreak = softBreak = false;
+    }
+    override public String toString () {
+        return Format( "StyleItem {{{}, {}}", start, style );
+    }
+    }
+
+/**
+ * Constructs a new instance of this class on the given device.
+ * <p>
+ * You must dispose the text layout when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the text layout
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this (Device device) {
+    static_this();
+    super(device);
+    wrapWidth = ascent = descent = -1;
+    lineSpacing = 0;
+    orientation = SWT.LEFT_TO_RIGHT;
+    styles = new StyleItem[2];
+    styles[0] = new StyleItem();
+    styles[1] = new StyleItem();
+    stylesCount = 2;
+    text = ""; //$NON-NLS-1$
+    wtext = ""w;
+    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;
+    }
+    init_();
+}
+
+void breakRun(StyleItem run) {
+    if (run.psla !is null) return;
+    wchar[] chars = segmentsWText[ index8to16[ run.start ] .. index8to16[ run.start + run.length ] ];
+    auto hHeap = OS.GetProcessHeap();
+    run.psla = cast(SCRIPT_LOGATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_LOGATTR.sizeof * chars.length);
+    if (run.psla is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    OS.ScriptBreak(chars.ptr, chars.length, &run.analysis, run.psla);
+}
+
+void checkLayout () {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+}
+
+/*
+*  Compute the runs: itemize, shape, place, and reorder the runs.
+*   Break paragraphs into lines, wraps the text, and initialize caches.
+*/
+void computeRuns (GC gc) {
+    if (runs !is null) return;
+    auto hDC = gc !is null ? gc.handle : device.internal_new_GC(null);
+    auto srcHdc = OS.CreateCompatibleDC(hDC);
+    allRuns = itemize();
+    for (int i=0; i<allRuns.length - 1; i++) {
+        StyleItem run = allRuns[i];
+        OS.SelectObject(srcHdc, getItemFont(run));
+        shape(srcHdc, run);
+    }
+    SCRIPT_LOGATTR* logAttr;
+    SCRIPT_PROPERTIES* properties;
+    int lineWidth = indent, lineStart = 0, lineCount = 1;
+    for (int i=0; i<allRuns.length - 1; i++) {
+        StyleItem run = allRuns[i];
+        if (run.length is 1) {
+            char ch = segmentsText.charAt(run.start);
+            switch (ch) {
+                case '\t': {
+                    run.tab = true;
+                    if (tabs is null) break;
+                    int tabsLength = tabs.length, j;
+                    for (j = 0; j < tabsLength; j++) {
+                        if (tabs[j] > lineWidth) {
+                            run.width = tabs[j] - lineWidth;
+                            break;
+                        }
+                    }
+                    if (j is tabsLength) {
+                        int tabX = tabs[tabsLength-1];
+                        int lastTabWidth = tabsLength > 1 ? tabs[tabsLength-1] - tabs[tabsLength-2] : tabs[0];
+                        if (lastTabWidth > 0) {
+                            while (tabX <= lineWidth) tabX += lastTabWidth;
+                            run.width = tabX - lineWidth;
+                        }
+                    }
+                    break;
+                }
+                case '\n': {
+                    run.lineBreak = true;
+                    break;
+                }
+                case '\r': {
+                    run.lineBreak = true;
+                    StyleItem next = allRuns[i + 1];
+                    if (next.length !is 0 && segmentsText.charAt(next.start) is '\n') {
+                        run.length += 1;
+                        next.free();
+                        StyleItem[] newAllRuns = new StyleItem[allRuns.length - 1];
+                        System.arraycopy(allRuns, 0, newAllRuns, 0, i + 1);
+                        System.arraycopy(allRuns, i + 2, newAllRuns, i + 1, allRuns.length - i - 2);
+                        allRuns = newAllRuns;
+                    }
+                    break;
+                }
+                default:
+            }
+        }
+        if (wrapWidth !is -1 && lineWidth + run.width > wrapWidth && !run.tab) {
+            int start = 0;
+            int[] piDx = new int[run.length];
+            if (run.style !is null && run.style.metrics !is null) {
+                piDx[0] = run.width;
+            } else {
+                OS.ScriptGetLogicalWidths(&run.analysis, run.length, run.glyphCount, run.advances, run.clusters, run.visAttrs, piDx.ptr);
+            }
+            int width = 0, maxWidth = wrapWidth - lineWidth;
+            while (width + piDx[start] < maxWidth) {
+                width += piDx[start++];
+            }
+            int firstStart = start;
+            int firstIndice = i;
+            while (i >= lineStart) {
+                breakRun(run);
+                while (start >= 0) {
+                    logAttr = run.psla + start;
+                    //OS.MoveMemory(logAttr, run.psla + (start * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                    if (logAttr.fSoftBreak || logAttr.fWhiteSpace) break;
+                    start--;
+                }
+
+                /*
+                *  Bug in Windows. For some reason Uniscribe sets the fSoftBreak flag for the first letter
+                *  after a letter with an accent. This cause a break line to be set in the middle of a word.
+                *  The fix is to detect the case and ignore fSoftBreak forcing the algorithm keep searching.
+                */
+                if (start is 0 && i !is lineStart && !run.tab) {
+                    if (logAttr.fSoftBreak && !logAttr.fWhiteSpace) {
+                        properties = device.scripts[run.analysis.eScript];
+                        //OS.MoveMemory(properties, device.scripts[run.analysis.eScript], SCRIPT_PROPERTIES.sizeof);
+                        int langID = properties.langid;
+                        StyleItem pRun = allRuns[i - 1];
+                        //OS.MoveMemory(properties, device.scripts[pRun.analysis.eScript], SCRIPT_PROPERTIES.sizeof);
+                        if (properties.langid is langID || langID is OS.LANG_NEUTRAL || properties.langid is OS.LANG_NEUTRAL) {
+                            breakRun(pRun);
+                            logAttr = pRun.psla + (pRun.length - 1);
+                            //OS.MoveMemory(logAttr, pRun.psla + ((pRun.length - 1) * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                            if (!logAttr.fWhiteSpace) start = -1;
+                        }
+                    }
+                }
+                if (start >= 0 || i is lineStart) break;
+                run = allRuns[--i];
+                start = run.length - 1;
+            }
+            if (start is 0 && i !is lineStart && !run.tab) {
+                run = allRuns[--i];
+            } else  if (start <= 0 && i is lineStart) {
+                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) {
+                logAttr = run.psla + start;
+                //OS.MoveMemory(logAttr, run.psla + (start * SCRIPT_LOGATTR.sizeof), SCRIPT_LOGATTR.sizeof);
+                if (!logAttr.fWhiteSpace) break;
+                start++;
+            }
+            if (0 < start && start < run.length) {
+                StyleItem newRun = new StyleItem();
+                newRun.start = run.start + start;
+                newRun.length = run.length - start;
+                newRun.style = run.style;
+                newRun.analysis = cloneScriptAnalysis(run.analysis);
+                run.free();
+                run.length = start;
+                OS.SelectObject(srcHdc, getItemFont(run));
+                run.analysis.fNoGlyphIndex = false;
+                shape (srcHdc, run);
+                OS.SelectObject(srcHdc, getItemFont(newRun));
+                newRun.analysis.fNoGlyphIndex = false;
+                shape (srcHdc, newRun);
+                StyleItem[] newAllRuns = new StyleItem[allRuns.length + 1];
+                System.arraycopy(allRuns, 0, newAllRuns, 0, i + 1);
+                System.arraycopy(allRuns, i + 1, newAllRuns, i + 2, allRuns.length - i - 1);
+                allRuns = newAllRuns;
+                allRuns[i + 1] = newRun;
+            }
+            if (i !is allRuns.length - 2) {
+                run.softBreak = run.lineBreak = true;
+            }
+        }
+        lineWidth += run.width;
+        if (run.lineBreak) {
+            lineStart = i + 1;
+            lineWidth = run.softBreak ?  0 : indent;
+            lineCount++;
+        }
+    }
+    lineWidth = 0;
+    runs = new StyleItem[][](lineCount);
+    lineOffset = new int[lineCount + 1];
+    lineY = new int[lineCount + 1];
+    this.lineWidth = new int[lineCount];
+    int lineRunCount = 0, line = 0;
+    int ascent = Math.max(0, this.ascent);
+    int descent = Math.max(0, this.descent);
+    StyleItem[] lineRuns = new StyleItem[allRuns.length];
+    for (int i=0; i<allRuns.length; i++) {
+        StyleItem run = allRuns[i];
+        lineRuns[lineRunCount++] = run;
+        lineWidth += run.width;
+        ascent = Math.max(ascent, run.ascent);
+        descent = Math.max(descent, run.descent);
+        if (run.lineBreak || i is allRuns.length - 1) {
+            /* Update the run metrics if the last run is a hard break. */
+            if (lineRunCount is 1 && i is allRuns.length - 1) {
+                TEXTMETRIC lptm;
+                OS.SelectObject(srcHdc, getItemFont(run));
+                OS.GetTextMetrics(srcHdc, &lptm);
+                run.ascent = lptm.tmAscent;
+                run.descent = lptm.tmDescent;
+                ascent = Math.max(ascent, run.ascent);
+                descent = Math.max(descent, run.descent);
+            }
+            runs[line] = new StyleItem[lineRunCount];
+            System.arraycopy(lineRuns, 0, runs[line], 0, lineRunCount);
+
+            if (justify && wrapWidth !is -1 && run.softBreak && lineWidth > 0) {
+                if (line is 0) {
+                    lineWidth += indent;
+                } else {
+                    StyleItem[] previousLine = runs[line - 1];
+                    StyleItem previousRun = previousLine[previousLine.length - 1];
+                    if (previousRun.lineBreak && !previousRun.softBreak) {
+                        lineWidth += indent;
+                    }
+                }
+                auto hHeap = OS.GetProcessHeap();
+                int newLineWidth = 0;
+                for (int j = 0; j < runs[line].length; j++) {
+                    StyleItem item = runs[line][j];
+                    int iDx = item.width * wrapWidth / lineWidth;
+                    if (iDx !is item.width) {
+                        item.justify = cast(int*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, item.glyphCount * 4);
+                        if (item.justify is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                        OS.ScriptJustify(item.visAttrs, item.advances, item.glyphCount, iDx - item.width, 2, item.justify);
+                        item.width = iDx;
+                    }
+                    newLineWidth += item.width;
+                }
+                lineWidth = newLineWidth;
+            }
+            this.lineWidth[line] = lineWidth;
+
+            StyleItem lastRun = runs[line][lineRunCount - 1];
+            int lastOffset = lastRun.start + lastRun.length;
+            runs[line] = reorder(runs[line], i is allRuns.length - 1);
+            lastRun = runs[line][lineRunCount - 1];
+            if (run.softBreak && run !is lastRun) {
+                run.softBreak = run.lineBreak = false;
+                lastRun.softBreak = lastRun.lineBreak = true;
+            }
+
+            lineWidth = getLineIndent(line);
+            for (int j = 0; j < runs[line].length; j++) {
+                runs[line][j].x = lineWidth;
+                lineWidth += runs[line][j].width;
+            }
+            line++;
+            lineY[line] = lineY[line - 1] + ascent + descent + lineSpacing;
+            lineOffset[line] = lastOffset;
+            lineRunCount = lineWidth = 0;
+            ascent = Math.max(0, this.ascent);
+            descent = Math.max(0, this.descent);
+        }
+    }
+    if (srcHdc !is null) OS.DeleteDC(srcHdc);
+    if (gc is null) device.internal_dispose_GC(hDC, null);
+}
+
+void destroy () {
+    freeRuns();
+    font = null;
+    text = null;
+    wtext = null;
+    segmentsText = null;
+    segmentsWText = null;
+    tabs = null;
+    styles = null;
+    runs = null;
+    lineOffset = null;
+    lineY = null;
+    lineWidth = null;
+    if (mLangFontLink2 !is null) {
+        /* Release() */
+        OS.VtblCall(2, mLangFontLink2);
+        mLangFontLink2 = null;
+    }
+    OS.OleUninitialize();
+}
+
+SCRIPT_ANALYSIS cloneScriptAnalysis ( inout SCRIPT_ANALYSIS src) {
+    SCRIPT_ANALYSIS dst;
+    dst.eScript = src.eScript;
+    dst.fRTL = src.fRTL;
+    dst.fLayoutRTL = src.fLayoutRTL;
+    dst.fLinkBefore = src.fLinkBefore;
+    dst.fLinkAfter = src.fLinkAfter;
+    dst.fLogicalOrder = src.fLogicalOrder;
+    dst.fNoGlyphIndex = src.fNoGlyphIndex;
+    dst.s.uBidiLevel = src.s.uBidiLevel; 
+    dst.s.fOverrideDirection = src.s.fOverrideDirection;
+    dst.s.fInhibitSymSwap = src.s.fInhibitSymSwap;
+    dst.s.fCharShape = src.s.fCharShape;
+    dst.s.fDigitSubstitute = src.s.fDigitSubstitute;
+    dst.s.fInhibitLigate = src.s.fInhibitLigate;
+    dst.s.fDisplayZWG = src.s.fDisplayZWG;
+    dst.s.fArabicNumContext = src.s.fArabicNumContext;
+    dst.s.fGcpClusters = src.s.fGcpClusters;
+    dst.s.fReserved = src.s.fReserved;
+    dst.s.fEngineReserved = src.s.fEngineReserved;
+    return dst;
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y) {
+    draw(gc, x, y, -1, -1, null, null);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+    draw(gc, x, y, selectionStart, selectionEnd, selectionForeground, selectionBackground, 0);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ * <p>
+ * The parameter <code>flags</code> can include one of <code>SWT.DELIMITER_SELECTION</code>
+ * or <code>SWT.FULL_SELECTION</code> to specify the selection behavior on all lines except
+ * for the last line, and can also include <code>SWT.LAST_LINE_SELECTION</code> to extend
+ * the specified selection behavior to the last line.
+ * </p>
+ * @param gc the GC to draw
+ * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
+ * @param selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ * @param flags drawing options
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground, int flags) {
+    checkLayout();
+    computeRuns(gc);
+    if (gc is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (selectionForeground !is null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (selectionBackground !is null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    int length = text.length;
+    int wlength = wtext.length;
+    if (length is 0 && flags is 0) return;
+    auto hdc = gc.handle;
+    Rectangle clip = gc.getClipping();
+    GCData data = gc.data;
+    auto gdipGraphics = data.gdipGraphics;
+    auto foreground = data.foreground;
+    auto alpha = data.alpha;
+    bool gdip = gdipGraphics !is null && (alpha !is 0xFF || data.foregroundPattern !is null);
+    HRGN clipRgn;
+    float[] lpXform = null;
+    Gdip.Rect gdipRect;
+    if (gdipGraphics !is null && !gdip) {
+        auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
+        if (matrix is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        Gdip.Graphics_GetTransform(gdipGraphics, matrix);
+        auto identity_ = gc.identity();
+        Gdip.Matrix_Invert(identity_);
+        Gdip.Matrix_Multiply(matrix, identity_, Gdip.MatrixOrderAppend);
+        Gdip.Matrix_delete(identity_);
+        if (!Gdip.Matrix_IsIdentity(matrix)) {
+            lpXform = new float[6];
+            Gdip.Matrix_GetElements(matrix, lpXform.ptr);
+        }
+        Gdip.Matrix_delete(matrix);
+        if ((data.style & SWT.MIRRORED) !is 0 && lpXform !is null) {
+            gdip = true;
+            lpXform = null;
+        } else {
+            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
+            auto rgn = Gdip.Region_new();
+            Gdip.Graphics_GetClip(gdipGraphics, rgn);
+            if (!Gdip.Region_IsInfinite(rgn, gdipGraphics)) {
+                clipRgn = Gdip.Region_GetHRGN(rgn, gdipGraphics);
+            }
+            Gdip.Region_delete(rgn);
+            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
+            hdc = Gdip.Graphics_GetHDC(gdipGraphics);
+        }
+    }
+    Gdip.Brush foregroundBrush;
+    int state = 0;
+    if (gdip) {
+        gc.checkGC(GC.FOREGROUND);
+        foregroundBrush = gc.getFgBrush();
+    } else {
+        state = OS.SaveDC(hdc);
+        if ((data.style & SWT.MIRRORED) !is 0) {
+            OS.SetLayout(hdc, OS.GetLayout(hdc) | OS.LAYOUT_RTL);
+        }
+        if (lpXform !is null) {
+            OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
+            OS.SetWorldTransform(hdc, cast(XFORM*)lpXform.ptr);
+        }
+        if (clipRgn !is null) {
+            OS.SelectClipRgn(hdc, clipRgn);
+            OS.DeleteObject(clipRgn);
+        }
+    }
+    bool hasSelection = selectionStart <= selectionEnd && selectionStart !is -1 && selectionEnd !is -1;
+    if (hasSelection || (flags & SWT.LAST_LINE_SELECTION) !is 0) {
+        selectionStart = Math.min(Math.max(0, selectionStart), length - 1);
+        selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1);
+        if (selectionForeground is null) selectionForeground = device.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
+        if (selectionBackground is null) selectionBackground = device.getSystemColor(SWT.COLOR_LIST_SELECTION);
+        selectionStart = translateOffset(selectionStart);
+        selectionEnd = translateOffset(selectionEnd);
+    }
+    RECT rect;
+    Gdip.Brush selBrush;
+    Gdip.Pen selPen;
+    Gdip.Brush selBrushFg;
+
+    if (hasSelection || (flags & SWT.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 = 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 = 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 = cast(Gdip.Brush)OS.CreateSolidBrush(selectionBackground.handle);
+            selPen = cast(Gdip.Pen)OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle);
+        }
+    }
+    int offset = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? -1 : 0;
+    OS.SetBkMode(hdc, OS.TRANSPARENT);
+    for (int line=0; line<runs.length; line++) {
+        int drawX = x + getLineIndent(line);
+        int drawY = y + lineY[line];
+        StyleItem[] lineRuns = runs[line];
+        int lineHeight = lineY[line+1] - lineY[line] - lineSpacing;
+        if (flags !is 0 && (hasSelection || (flags & SWT.LAST_LINE_SELECTION) !is 0)) {
+            bool extents = false;
+            if (line is runs.length - 1 && (flags & SWT.LAST_LINE_SELECTION) !is 0) {
+                extents = true;
+            } else {
+                StyleItem run = lineRuns[lineRuns.length - 1];
+                if (run.lineBreak && !run.softBreak) {
+                    if (selectionStart <= run.start && run.start <= selectionEnd) extents = true;
+                } else {
+                    int endOffset = segmentsText.getAbsoluteCodePointOffset( run.start + run.length, -1 );
+                    if (selectionStart <= endOffset && endOffset < selectionEnd && (flags & SWT.FULL_SELECTION) !is 0) {
+                        extents = true;
+                    }
+                }
+            }
+            if (extents) {
+                int width;
+                if ((flags & SWT.FULL_SELECTION) !is 0) {
+                    width = OS.IsWin95 ? 0x7FFF : 0x6FFFFFF;
+                } else {
+                    width = lineHeight / 3;
+                }
+                if (gdip) {
+                    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, 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++) {
+            StyleItem run = lineRuns[i];
+            if (run.length is 0) continue;
+            if (drawX > clip.x + clip.width) break;
+            if (drawX + run.width >= clip.x) {
+                if (!run.lineBreak || run.softBreak) {
+                    int end = segmentsText.getAbsoluteCodePointOffset( run.start + run.length, -1 );
+                    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);
+                        } else {
+                            OS.SelectObject(hdc, selBrush);
+                            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;
+                            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, 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, drawY, run.width, lineHeight, OS.PATCOPY);
+                                OS.SelectObject(hdc, oldBrush);
+                                OS.DeleteObject(hBrush);
+                            }
+                        }
+                        bool partialSelection = hasSelection && !(selectionStart > end || run.start > selectionEnd);
+                        if (partialSelection) {
+                            int selStart = index8to16[ Math.max(selectionStart, run.start) ] - index8to16[run.start];
+                            int selEnd = index8to16[ Math.min(selectionEnd, end) ] - index8to16[ run.start ];
+                            int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar
+                            int gGlyphs = run.glyphCount;
+                            int piX;
+                            int* advances = run.justify !is null ? run.justify : run.advances;
+                            OS.ScriptCPtoX(selStart, false, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                            int runX = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
+                            rect.left = drawX + runX;
+                            rect.top = drawY;
+                            OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                            runX = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
+                            rect.right = drawX + runX;
+                            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);
+                                OS.PatBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+                            }
+                        }
+                    }
+                }
+            }
+            drawX += run.width;
+        }
+        RECT* borderClip = null;
+        drawX = alignmentX;
+        for (int i = 0; i < lineRuns.length; i++) {
+            StyleItem run = lineRuns[i];
+            if (run.length is 0) continue;
+            if (drawX > clip.x + clip.width) break;
+            if (drawX + run.width >= clip.x) {
+                if (!run.tab && (!run.lineBreak || run.softBreak) && !(run.style !is null && run.style.metrics !is null)) {
+                    int end = run.start + run.length - 1;
+                    bool fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
+                    bool partialSelection = hasSelection && !fullSelection && !(selectionStart > end || run.start > selectionEnd);
+                    OS.SelectObject(hdc, getItemFont(run));
+                    int drawRunY = drawY + (baseline - run.ascent);
+                    if (partialSelection) {
+                        int selStart = Math.max(index8to16[selectionStart], index8to16[run.start]) - index8to16[run.start];
+                        int selEnd = Math.min(index8to16[selectionEnd], index8to16[end]) - index8to16[run.start];
+                        int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar
+                        int gGlyphs = run.glyphCount;
+                        int piX;
+                        int* advances = run.justify !is null ? run.justify : run.advances;
+                        OS.ScriptCPtoX(selStart, false, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                        int runX = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
+                        rect.left = drawX + runX;
+                        rect.top = drawY;
+                        OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                        runX = (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
+                        rect.right = drawX + runX;
+                        rect.bottom = drawY + lineHeight;
+                    }
+                    if (gdip) {
+                        OS.BeginPath(hdc);
+                        OS.ScriptTextOut(hdc, run.psc, drawX, drawRunY, 0, null, &run.analysis , null, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets);
+                        OS.EndPath(hdc);
+                        int count = OS.GetPath(hdc, null, null, 0);
+                        int[] points = new int[count*2];
+                        ubyte[] types = new ubyte[count];
+                        OS.GetPath(hdc, cast(POINT*)points.ptr, types.ptr, count);
+                        for (int typeIndex = 0; typeIndex < types.length; typeIndex++) {
+                            int newType = 0;
+                            int type = types[typeIndex] & 0xFF;
+                            switch (type & ~OS.PT_CLOSEFIGURE) {
+                                case OS.PT_MOVETO: newType = Gdip.PathPointTypeStart; break;
+                                case OS.PT_LINETO: newType = Gdip.PathPointTypeLine; break;
+                                case OS.PT_BEZIERTO: newType = Gdip.PathPointTypeBezier; break;
+                                default:
+                            }
+                            if ((type & OS.PT_CLOSEFIGURE) !is 0) newType |= Gdip.PathPointTypeCloseSubpath;
+                            types[typeIndex] = cast(byte)newType;
+                        }
+                        auto path = Gdip.GraphicsPath_new(cast(Gdip.Point*)points.ptr, types.ptr, count, Gdip.FillModeAlternate);
+                        if (path is null) SWT.error(SWT.ERROR_NO_HANDLES);
+                        auto brush = foregroundBrush;
+                        if (fullSelection) {
+                            brush = cast(Gdip.Brush)selBrushFg;
+                        } else {
+                            if (run.style !is null && run.style.foreground !is null) {
+                                auto fg = run.style.foreground.handle;
+                                int argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16);
+                                auto color = Gdip.Color_new(argb);
+                                brush = cast(Gdip.Brush)Gdip.SolidBrush_new(color);
+                                Gdip.Color_delete(color);
+                            }
+                        }
+                        int gstate = 0;
+                        if (partialSelection) {
+                            gdipRect.X = rect.left;
+                            gdipRect.Y = rect.top;
+                            gdipRect.Width = rect.right - rect.left;
+                            gdipRect.Height = rect.bottom - rect.top;
+                            gstate = Gdip.Graphics_Save(gdipGraphics);
+                            Gdip.Graphics_SetClip(gdipGraphics, &gdipRect, Gdip.CombineModeExclude);
+                        }
+                        int antialias = Gdip.Graphics_GetSmoothingMode(gdipGraphics), textAntialias = 0;
+                        int mode = Gdip.Graphics_GetTextRenderingHint(data.gdipGraphics);
+                        switch (mode) {
+                            case Gdip.TextRenderingHintSystemDefault: textAntialias = Gdip.SmoothingModeAntiAlias; break;
+                            case Gdip.TextRenderingHintSingleBitPerPixel:
+                            case Gdip.TextRenderingHintSingleBitPerPixelGridFit: textAntialias = Gdip.SmoothingModeNone; break;
+                            case Gdip.TextRenderingHintAntiAlias:
+                            case Gdip.TextRenderingHintAntiAliasGridFit:
+                            case Gdip.TextRenderingHintClearTypeGridFit: textAntialias = Gdip.SmoothingModeAntiAlias; break;
+                            default:
+                        }
+                        Gdip.Graphics_SetSmoothingMode(gdipGraphics, textAntialias);
+                        int gstate2 = 0;
+                        if ((data.style & SWT.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, brush, path);
+                        if ((data.style & SWT.MIRRORED) !is 0) {
+                            Gdip.Graphics_Restore(gdipGraphics, gstate2);
+                        }
+                        Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias);
+                        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);
+                            if ((data.style & SWT.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 & SWT.MIRRORED) !is 0) {
+                                Gdip.Graphics_Restore(gdipGraphics, gstate2);
+                            }
+                            Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias);
+                            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 {
+                            auto fg = foreground;
+                            if (fullSelection) {
+                                fg = selectionForeground.handle;
+                            } else {
+                                if (run.style !is null && run.style.foreground !is null) fg = run.style.foreground.handle;
+                        }
+                        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);
+                        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);
+                            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);
+                    }
+                }
+            }
+            drawX += run.width;
+        }
+    }
+    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(selPen);
+    } else {
+        OS.RestoreDC(hdc, state);
+        if (gdipGraphics !is null) Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
+        if (selBrush !is null) OS.DeleteObject (selBrush);
+        if (selPen !is null) OS.DeleteObject (selPen);
+    }
+}
+
+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 SWT.UNDERLINE_SQUIGGLE:
+                case SWT.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 SWT.UNDERLINE_SINGLE:
+                    Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY, run.width, run.underlineThickness);
+                    break;
+                case SWT.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;
+                }
+                default:
+            }
+            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 SWT.UNDERLINE_SQUIGGLE:
+                case SWT.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 SWT.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 SWT.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;
+                }
+                default:
+            }
+        }
+        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 SWT.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 & SWT.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 SWT.BORDER_SOLID: break;
+                case SWT.BORDER_DASH: lineStyle = Gdip.DashStyleDash; break;
+                case SWT.BORDER_DOT: lineStyle = Gdip.DashStyleDot; break;
+                default:
+            }
+            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 SWT.BORDER_SOLID: break;
+                case SWT.BORDER_DASH: lineStyle = OS.PS_DASH; break;
+                case SWT.BORDER_DOT: lineStyle = OS.PS_DOT; break;
+                default:
+            }
+            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++) {
+        StyleItem run = allRuns[i];
+        run.free();
+    }
+    allRuns = null;
+    runs = null;
+    segmentsText = null;
+    segmentsWText = null;
+}
+
+/**
+ * Returns the receiver's horizontal text alignment, which will be one
+ * of <code>SWT.LEFT</code>, <code>SWT.CENTER</code> or
+ * <code>SWT.RIGHT</code>.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getAlignment () {
+    checkLayout();
+    return alignment;
+}
+
+/**
+ * Returns the ascent of the receiver.
+ *
+ * @return the ascent
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getDescent()
+ * @see #setDescent(int)
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getAscent () {
+    checkLayout();
+    return ascent;
+}
+
+/**
+ * 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 SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setWidth(int)
+ * @see #getLineBounds(int)
+ */
+public Rectangle getBounds () {
+    checkLayout();
+    computeRuns(null);
+    int width = 0;
+    if (wrapWidth !is -1) {
+        width = wrapWidth;
+    } else {
+        for (int line=0; line<runs.length; line++) {
+            width = Math.max(width, lineWidth[line] + getLineIndent(line));
+        }
+    }
+    return new Rectangle (0, 0, width, lineY[lineY.length - 1]);
+}
+
+/**
+ * Returns the bounds for the specified range of characters. The
+ * bounds is the smallest rectangle that encompasses all characters
+ * in the range. The start and end offsets are inclusive and will be
+ * clamped if out of range.
+ *
+ * @param start the start offset
+ * @param end the end offset
+ * @return the bounds of the character range
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+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);
+    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 = translateOffset(start);
+    end = translateOffset(end);
+    int left = 0x7fffffff, right = 0;
+    int top = 0x7fffffff, bottom = 0;
+    bool isRTL = (orientation & SWT.RIGHT_TO_LEFT) !is 0;
+    for (int i = 0; i < allRuns.length - 1; i++) {
+        StyleItem run = allRuns[i];
+        int runEnd = run.start + run.length;
+        if (runEnd <= start) continue;
+        if (run.start > end) break;
+        int runLead = run.x;
+        int runTrail = run.x + run.width;
+        if (run.start <= start && start < runEnd) {
+            int cx = 0;
+            if (run.style !is null && run.style.metrics !is null) {
+                GlyphMetrics metrics = run.style.metrics;
+                cx = metrics.width * (index8to16[start] - index8to16[run.start]);
+            } else if (!run.tab) {
+                int piX;
+                int* advances = run.justify !is null ? run.justify : run.advances;
+                int wlength = index8to16[ run.start+run.length] - index8to16[run.start];
+                OS.ScriptCPtoX(index8to16[start] - index8to16[run.start], false, wlength, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                cx = isRTL ? run.width - piX : piX;
+            }
+            if (run.analysis.fRTL ^ isRTL) {
+                runTrail = run.x + cx;
+            } else {
+                runLead = run.x + cx;
+            }
+        }
+        if (run.start <= end && end < runEnd) {
+            int cx = run.width;
+            if (run.style !is null && run.style.metrics !is null) {
+                GlyphMetrics metrics = run.style.metrics;
+                cx = metrics.width * (index8to16[end] - index8to16[run.start] + 1);
+            } else if (!run.tab) {
+                int piX;
+                int* advances = run.justify !is null ? run.justify : run.advances;
+                int wlength = index8to16[ run.start+run.length] - index8to16[run.start];
+                OS.ScriptCPtoX(index8to16[end] - index8to16[run.start], true, wlength, run.glyphCount, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                cx = isRTL ? run.width - piX : piX;
+            }
+            if (run.analysis.fRTL ^ isRTL) {
+                runLead = run.x + cx;
+            } else {
+                runTrail = run.x + cx;
+            }
+        }
+        int lineIndex = 0;
+        while (lineIndex < runs.length && lineOffset[lineIndex + 1] <= run.start) {
+            lineIndex++;
+        }
+        left = Math.min(left, runLead);
+        right = Math.max(right, runTrail);
+        top = Math.min(top, lineY[lineIndex]);
+        bottom = Math.max(bottom, lineY[lineIndex + 1] - lineSpacing);
+    }
+    return new Rectangle(left, top, right - left, bottom - top);
+}
+
+/**
+ * Returns the descent of the receiver.
+ *
+ * @return the descent
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getAscent()
+ * @see #setAscent(int)
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getDescent () {
+    checkLayout();
+    return descent;
+}
+
+/**
+ * Returns the default font currently being used by the receiver
+ * to draw and measure text.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getFont () {
+    checkLayout();
+    return font;
+}
+
+/**
+* Returns the receiver's indent.
+*
+* @return the receiver's indent
+*
+* @exception SWTException <ul>
+*    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public int getIndent () {
+    checkLayout();
+    return indent;
+}
+
+/**
+* Returns the receiver's justification.
+*
+* @return the receiver's justification
+*
+* @exception SWTException <ul>
+*    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public bool getJustify () {
+    checkLayout();
+    return justify;
+}
+
+HFONT getItemFont (StyleItem item) {
+    if (item.fallbackFont !is null) return cast(HFONT) item.fallbackFont;
+    if (item.style !is null && item.style.font !is null) {
+        return item.style.font.handle;
+    }
+    if (this.font !is null) {
+        return this.font.handle;
+    }
+    return device.systemFont.handle;
+}
+
+/**
+ * Returns the embedding level for the specified character offset. The
+ * embedding level is usually used to determine the directionality of a
+ * character in bidirectional text.
+ *
+ * @param offset the character offset
+ * @return the embedding level
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ */
+public int getLevel (int offset) {
+    checkLayout();
+    computeRuns(null);
+    int length = text.length;
+    if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    offset = translateOffset(offset);
+    for (int i=1; i<allRuns.length; i++) {
+        if (allRuns[i].start > offset) {
+            return allRuns[i - 1].analysis.s.uBidiLevel;
+        }
+    }
+    return (orientation & SWT.RIGHT_TO_LEFT) !is 0 ? 1 : 0;
+}
+
+/**
+ * Returns the bounds of the line for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the line bounds
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getLineBounds(int lineIndex) {
+    checkLayout();
+    computeRuns(null);
+    if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    int x = getLineIndent(lineIndex);
+    int y = lineY[lineIndex];
+    int width = lineWidth[lineIndex];
+    int height = lineY[lineIndex + 1] - y - lineSpacing;
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the receiver's line count. This includes lines caused
+ * by wrapping.
+ *
+ * @return the line count
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineCount () {
+    checkLayout();
+    computeRuns(null);
+    return runs.length;
+}
+
+int getLineIndent (int lineIndex) {
+    int lineIndent = 0;
+    if (lineIndex is 0) {
+        lineIndent = indent;
+    } else {
+        StyleItem[] previousLine = runs[lineIndex - 1];
+        StyleItem previousRun = previousLine[previousLine.length - 1];
+        if (previousRun.lineBreak && !previousRun.softBreak) {
+            lineIndent = indent;
+        }
+    }
+    if (wrapWidth !is -1) {
+        bool partialLine = true;
+        if (justify) {
+            StyleItem[] lineRun = runs[lineIndex];
+            if (lineRun[lineRun.length - 1].softBreak) {
+                partialLine = false;
+            }
+        }
+        if (partialLine) {
+            int lineWidth = this.lineWidth[lineIndex] + lineIndent;
+            switch (alignment) {
+                case SWT.CENTER: lineIndent += (wrapWidth - lineWidth) / 2; break;
+                case SWT.RIGHT: lineIndent += wrapWidth - lineWidth; break;
+                default:
+            }
+        }
+    }
+    return lineIndent;
+}
+
+/**
+ * Returns the index of the line that contains the specified
+ * character offset.
+ *
+ * @param offset the character offset
+ * @return the line index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineIndex (int offset) {
+    checkLayout();
+    computeRuns(null);
+    int length = text.length;
+    if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    offset = translateOffset(offset);
+    for (int line=0; line<runs.length; line++) {
+        if (lineOffset[line + 1] > offset) {
+            return line;
+        }
+    }
+    return runs.length - 1;
+}
+
+/**
+ * Returns the font metrics for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the font metrics
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontMetrics getLineMetrics (int lineIndex) {
+    checkLayout();
+    computeRuns(null);
+    if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    auto hDC = device.internal_new_GC(null);
+    auto srcHdc = OS.CreateCompatibleDC(hDC);
+    TEXTMETRIC lptm;
+    OS.SelectObject(srcHdc, font !is null ? font.handle : device.systemFont.handle);
+    OS.GetTextMetrics(srcHdc, &lptm);
+    OS.DeleteDC(srcHdc);
+    device.internal_dispose_GC(hDC, null);
+
+    int ascent = Math.max(lptm.tmAscent, this.ascent);
+    int descent = Math.max(lptm.tmDescent, this.descent);
+    int leading = lptm.tmInternalLeading;
+    if (text.length !is 0) {
+        StyleItem[] lineRuns = runs[lineIndex];
+        for (int i = 0; i<lineRuns.length; i++) {
+            StyleItem run = lineRuns[i];
+            if (run.ascent > ascent) {
+                ascent = run.ascent;
+                leading = run.leading;
+            }
+            descent = Math.max(descent, run.descent);
+        }
+    }
+    lptm.tmAscent = ascent;
+    lptm.tmDescent = descent;
+    lptm.tmHeight = ascent + descent;
+    lptm.tmInternalLeading = leading;
+    lptm.tmAveCharWidth = 0;
+    return FontMetrics.win32_new(&lptm);
+}
+
+/**
+ * Returns the line offsets.  Each value in the array is the
+ * offset for the first character in a line except for the last
+ * value, which contains the length of the text.
+ *
+ * @return the line offsets
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getLineOffsets () {
+    checkLayout();
+    computeRuns(null);
+    int[] offsets = new int[lineOffset.length];
+    for (int i = 0; i < offsets.length; i++) {
+        offsets[i] = untranslateOffset(lineOffset[i]);
+    }
+    return offsets;
+}
+
+/**
+ * Returns the location for the specified character offset. The
+ * <code>trailing</code> argument indicates whether the offset
+ * corresponds to the leading or trailing edge of the cluster.
+ *
+ * @param offset the character offset
+ * @param trailing the trailing flag
+ * @return the location of the character offset
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getOffset(Point, int[])
+ * @see #getOffset(int, int, int[])
+ */
+public Point getLocation (int offset, bool trailing) {
+    checkLayout();
+    computeRuns(null);
+    int length = text.length;
+    if (!(0 <= offset && offset <= length)) SWT.error(SWT.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);
+    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 = index8to16[offset] - index8to16[run.start];
+                int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar
+                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 & SWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
+            }
+            return new Point(run.x + width, lineY[line]);
+        }
+    }
+    return new Point(0, 0);
+}
+
+/**
+ * Returns the next offset for the specified offset and movement
+ * type.  The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code>, <code>SWT.MOVEMENT_WORD</code>,
+ * <code>SWT.MOVEMENT_WORD_END</code> or <code>SWT.MOVEMENT_WORD_START</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getPreviousOffset(int, int)
+ */
+public int getNextOffset (int offset, int movement) {
+    checkLayout();
+    return _getOffset (offset, movement, true);
+}
+
+int _getOffset(int offset, int movement, bool forward) {
+    computeRuns(null);
+    int length = text.length;
+    if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    if (forward && offset is length) return length;
+    if (!forward && offset is 0) return 0;
+    int step = forward ? 1 : -1;
+    if ((movement & SWT.MOVEMENT_CHAR) !is 0) return offset + step;
+    length = segmentsText.length;
+    offset = translateOffset(offset);
+    SCRIPT_LOGATTR* logAttr;
+    SCRIPT_PROPERTIES* properties;
+    int i = forward ? 0 : allRuns.length - 1;
+    offset = validadeOffset(offset, step);
+    do {
+        StyleItem run = allRuns[i];
+        if (run.start <= offset && offset < run.start + run.length) {
+            if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start);
+            if (run.tab) return untranslateOffset(run.start);
+            properties = device.scripts[run.analysis.eScript];
+            bool isComplex = properties.fNeedsCaretInfo || properties.fNeedsWordBreaking;
+            if (isComplex) breakRun(run);
+            while (run.start <= offset && offset < run.start + run.length) {
+                if (isComplex) {
+                    logAttr = run.psla + (index8to16[offset] - index8to16[run.start]);
+                }
+                switch (movement) {
+                    case SWT.MOVEMENT_CLUSTER: {
+                        if (properties.fNeedsCaretInfo) {
+                            if (!logAttr.fInvalid && logAttr.fCharStop) return untranslateOffset(offset);
+                        } else {
+                            return untranslateOffset(offset);
+                        }
+                        break;
+                    }
+                    case SWT.MOVEMENT_WORD_START:
+                    case SWT.MOVEMENT_WORD: {
+                        if (properties.fNeedsWordBreaking) {
+                            if (!logAttr.fInvalid && logAttr.fWordStop) return untranslateOffset(offset);
+                        } else {
+                            if (offset > 0) {
+                                bool letterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset));
+                                bool previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset - 1));
+                                if (letterOrDigit !is previousLetterOrDigit || !letterOrDigit) {
+                                    if (!Compatibility.isWhitespace(segmentsText[offset..$].firstCodePoint())) {
+                                        return untranslateOffset(offset);
+                                    }
+                                }
+                            }
+                        }
+                        break;
+                    }
+                    case SWT.MOVEMENT_WORD_END: {
+                        if (offset > 0) {
+                            bool isLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText.charAt(offset));
+                            bool previousLetterOrDigit = Compatibility.isLetterOrDigit(segmentsText[offset - 1.. $].firstCodePoint());
+                            if (!isLetterOrDigit && previousLetterOrDigit) {
+                                return untranslateOffset(offset);
+                            }
+                        }
+                        break;
+                    }
+                    default:
+                }
+                offset = validadeOffset(offset, step);
+            }
+        }
+        i += step;
+    } while (0 <= i && i < allRuns.length - 1 && 0 <= offset && offset < length);
+    return forward ? text.length : 0;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1).  When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param point the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, bool)
+ */
+public int getOffset (Point point, int[] trailing) {
+    checkLayout();
+    if (point is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return getOffset (point.x, point.y, trailing) ;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1).  When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, bool)
+ */
+public int getOffset (int x, int y, int[] trailing) {
+    checkLayout();
+    computeRuns(null);
+    if (trailing !is null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    int line;
+    int lineCount = runs.length;
+    for (line=0; line<lineCount; line++) {
+        if (lineY[line + 1] > y) break;
+    }
+    line = Math.min(line, runs.length - 1);
+    StyleItem[] lineRuns = runs[line];
+    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) {
+                    if (trailing !is null) {
+                        trailing[0] = (xRun % metrics.width < metrics.width / 2) ? 0 : 1;
+                    }
+                    return untranslateOffset(run.start + xRun / metrics.width);
+                }
+            }
+            if (run.tab) {
+                if (trailing !is null) trailing[0] = x < (run.x + run.width / 2) ? 0 : 1;
+                return untranslateOffset(run.start);
+            }
+            int cChars = index8to16[run.start+run.length] - index8to16[run.start]; // make it wchar
+            int cGlyphs = run.glyphCount;
+            int piCP;
+            int piTrailing;
+            if ((orientation & SWT.RIGHT_TO_LEFT) !is 0) {
+                xRun = run.width - xRun;
+            }
+            int* advances = run.justify !is null ? run.justify : run.advances;
+            OS.ScriptXtoCP(xRun, cChars, cGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piCP, &piTrailing);
+            if (trailing !is null) trailing[0] = piTrailing;
+
+            // SWT: back from codepoints to utf8 index
+            int offsetIndex = segmentsText[ run.start .. $ ].codepointIndexToIndex( piCP );
+            return untranslateOffset(run.start + offsetIndex);
+        }
+    }
+    if (trailing !is null) trailing[0] = 0;
+    return untranslateOffset(lineOffset[line + 1]);
+}
+
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getOrientation () {
+    checkLayout();
+    return orientation;
+}
+
+/**
+ * Returns the previous offset for the specified offset and movement
+ * type.  The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code> or <code>SWT.MOVEMENT_WORD</code>,
+ * <code>SWT.MOVEMENT_WORD_END</code> or <code>SWT.MOVEMENT_WORD_START</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the previous offset
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getNextOffset(int, int)
+ */
+public int getPreviousOffset (int offset, int movement) {
+    checkLayout();
+    return _getOffset (offset, movement, false);
+}
+
+/**
+ * Gets the ranges of text that are associated with a <code>TextStyle</code>.
+ *
+ * @return the ranges, an array of offsets representing the start and end of each
+ * text style.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getStyles()
+ *
+ * @since 3.2
+ */
+public int[] getRanges () {
+    checkLayout();
+    int[] result = new int[stylesCount * 2];
+    int count = 0;
+    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;
+        }
+    }
+    if (count !is result.length) {
+        int[] newResult = new int[count];
+        System.arraycopy(result, 0, newResult, 0, count);
+        result = newResult;
+    }
+    return result;
+}
+
+/**
+ * Returns the text segments offsets of the receiver.
+ *
+ * @return the text segments offsets
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getSegments () {
+    checkLayout();
+    return segments;
+}
+
+void getSegmentsText( out char[] resUtf8, out wchar[] resUtf16 ) {
+
+    void buildIndexTables() { // build the index translation tables.
+        index8to16.length = resUtf8.length + 1;
+        index16to8.length = resUtf16.length + 1;
+
+        int idx8, idx16;
+        while( idx8 < resUtf8.length ){
+            int ate8, ate16;
+            dchar d8 = resUtf8[ idx8 .. $ ].firstCodePoint( ate8 );
+            dchar d16 = resUtf16[ idx16 .. $ ].firstCodePoint( ate16 );
+            assert( d8 is d16 );
+            index16to8[ idx16 .. idx16 +ate16 ] = idx8;
+            index8to16[ idx8  .. idx8  +ate8  ] = idx16;
+            idx8  += ate8;
+            idx16 += ate16;
+        }
+        index16to8[ resUtf16.length ] = resUtf8.length;
+        index8to16[ resUtf8.length  ] = resUtf16.length;
+    }
+
+    if (segments is null) {
+        resUtf8 = text;
+        resUtf16 = wtext;
+        buildIndexTables();
+        return;
+    }
+    int nSegments = segments.length;
+    if (nSegments <= 1) {
+        resUtf8 = text;
+        resUtf16 = wtext;
+        buildIndexTables();
+        return;
+    }
+    int length_ = text.length;
+    int wlength_ = wtext.length;
+    if (length_ is 0) {
+        resUtf8 = text;
+        resUtf16 = wtext;
+        buildIndexTables();
+        return;
+    }
+    if (nSegments is 2) {
+        if (segments[0] is 0 && segments[1] is length_) {
+            resUtf8 = text;
+            resUtf16 = wtext;
+            buildIndexTables();
+            return;
+        }
+    }
+    {
+        char[] oldChars = text;
+        // SWT: MARK is now 3 chars long
+        String separator = orientation is SWT.RIGHT_TO_LEFT ? STR_RTL_MARK : STR_LTR_MARK;
+        assert( separator.length is MARK_SIZE );
+        char[] newChars = new char[length_ + nSegments*MARK_SIZE];
+
+        int charCount = 0, segmentCount = 0;
+        while (charCount < length_) {
+            if (segmentCount < nSegments && charCount is segments[segmentCount]) {
+                int start = charCount + (segmentCount*MARK_SIZE);
+                newChars[ start .. start + MARK_SIZE ] = separator;
+                segmentCount++;
+            } else {
+                newChars[charCount + (segmentCount*MARK_SIZE)] = oldChars[charCount];
+                charCount++;
+            }
+        }
+        if (segmentCount < nSegments) {
+            segments[segmentCount] = charCount;
+            int start = charCount + (segmentCount*MARK_SIZE);
+            newChars[ start .. start + MARK_SIZE ] = separator;
+            segmentCount++;
+        }
+        resUtf8 = newChars[ 0 .. Math.min(charCount + (segmentCount*MARK_SIZE), newChars.length)];
+    }
+    // now for the wide chars
+    {
+        wchar[] oldWChars = wtext;
+        wchar[] wseparator = orientation is SWT.RIGHT_TO_LEFT ? WSTR_RTL_MARK : WSTR_LTR_MARK;
+        assert( wseparator.length is 1 );
+        wchar[] newWChars = new wchar[wlength_ + nSegments];
+
+        int charCount = 0, segmentCount = 0;
+        while (charCount < wlength_) {
+            if (segmentCount < nSegments && charCount is wsegments[segmentCount]) {
+                int start = charCount + (segmentCount*WMARK_SIZE);
+                newWChars[ start .. start + WMARK_SIZE ] = wseparator;
+                segmentCount++;
+            } else {
+                newWChars[charCount + (segmentCount*WMARK_SIZE)] = oldWChars[charCount];
+                charCount++;
+            }
+        }
+        if (segmentCount < nSegments) {
+            wsegments[segmentCount] = charCount;
+            int start = charCount + (segmentCount*WMARK_SIZE);
+            newWChars[ start .. start + WMARK_SIZE ] = wseparator;
+            segmentCount++;
+        }
+        resUtf16 = newWChars[ 0 .. Math.min(charCount + (segmentCount*WMARK_SIZE), newWChars.length)];
+    }
+    buildIndexTables();
+}
+
+/**
+ * Returns the line spacing of the receiver.
+ *
+ * @return the line spacing
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getSpacing () {
+    checkLayout();
+    return lineSpacing;
+}
+
+/**
+ * Gets the style of the receiver at the specified character offset.
+ *
+ * @param offset the text offset
+ * @return the style or <code>null</code> if not set
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public TextStyle getStyle (int offset) {
+    checkLayout();
+    int length = text.length;
+    if (!(0 <= offset && offset < length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+    for (int i=1; i<stylesCount; i++) {
+        if (styles[i].start > offset) {
+            return styles[i - 1].style;
+        }
+    }
+    return null;
+}
+
+/**
+ * Gets all styles of the receiver.
+ *
+ * @return the styles
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getRanges()
+ *
+ * @since 3.2
+ */
+public TextStyle[] getStyles () {
+    checkLayout();
+    TextStyle[] result = new TextStyle[stylesCount];
+    int count = 0;
+    for (int i=0; i<stylesCount; i++) {
+        if (styles[i].style !is null) {
+            result[count++] = styles[i].style;
+        }
+    }
+    if (count !is result.length) {
+        TextStyle[] newResult = new TextStyle[count];
+        System.arraycopy(result, 0, newResult, 0, count);
+        result = newResult;
+    }
+    return result;
+}
+
+/**
+ * Returns the tab list of the receiver.
+ *
+ * @return the tab list
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getTabs () {
+    checkLayout();
+    return tabs;
+}
+
+/**
+ * Gets the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public String getText () {
+    checkLayout();
+    return text;
+}
+
+/**
+ * Returns the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getWidth () {
+    checkLayout();
+    return wrapWidth;
+}
+
+/**
+ * Returns <code>true</code> if the text layout has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the text layout.
+ * When a text layout has been disposed, it is an error to
+ * invoke any other method using the text layout.
+ * </p>
+ *
+ * @return <code>true</code> when the text layout is disposed and <code>false</code> otherwise
+ */
+override public bool isDisposed () {
+    return device is null;
+}
+
+/*
+ *  Itemize the receiver text
+ */
+StyleItem[] itemize () {
+    // SWT: itemize is the process of finding changes in direction
+    getSegmentsText(segmentsText, segmentsWText );
+    int length = segmentsText.length;
+    SCRIPT_CONTROL scriptControl;
+    SCRIPT_STATE scriptState;
+    final int MAX_ITEM = length + 1;
+
+    if ((orientation & SWT.RIGHT_TO_LEFT) !is 0) {
+        scriptState.uBidiLevel = 1;
+        scriptState.fArabicNumContext = true;
+        SCRIPT_DIGITSUBSTITUTE psds;
+        OS.ScriptRecordDigitSubstitution(OS.LOCALE_USER_DEFAULT, &psds);
+        OS.ScriptApplyDigitSubstitution(&psds, &scriptControl, &scriptState);
+    }
+
+    auto hHeap = OS.GetProcessHeap();
+    auto pItems = cast(SCRIPT_ITEM*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, MAX_ITEM * SCRIPT_ITEM.sizeof);
+    if (pItems is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    int pcItems;
+    wchar[] chars = segmentsWText;
+    OS.ScriptItemize(chars.ptr, chars.length, MAX_ITEM, &scriptControl, &scriptState, pItems, &pcItems);
+//  if (hr is E_OUTOFMEMORY) //TODO handle it
+    // SWT pcItems is not inclusive the trailing item
+
+    StyleItem[] runs = merge(pItems, pcItems);
+    OS.HeapFree(hHeap, 0, pItems);
+    return runs;
+}
+
+/*
+ *  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 + stylesCount];
+    SCRIPT_ITEM* scriptItem;
+    bool linkBefore = false;
+    while (start < end) {
+        StyleItem item = new StyleItem();
+        item.start = start;
+        item.style = styles[styleIndex].style;
+        runs[count++] = item;
+        scriptItem = items + itemIndex;
+        item.analysis = scriptItem.a;
+        if (linkBefore) {
+            item.analysis.fLinkBefore = true;
+            linkBefore = false;
+        }
+        //scriptItem.a = new SCRIPT_ANALYSIS();
+        scriptItem = items + (itemIndex + 1);
+        int itemLimit = index16to8[scriptItem.iCharPos];
+        int styleLimit = translateOffset(styles[styleIndex + 1].start);
+        if (styleLimit <= itemLimit) {
+            styleIndex++;
+            start = styleLimit;
+            if (start < itemLimit && 0 < start && start < end) {
+                dchar pChar = segmentsText[ segmentsText.getAbsoluteCodePointOffset(start, -1) ..$].firstCodePoint();
+                dchar tChar = segmentsText[start     ..$].firstCodePoint();
+                if (Compatibility.isLetter(pChar) && Compatibility.isLetter(tChar)) {
+                    item.analysis.fLinkAfter = true;
+                    linkBefore = true;
+                }
+            }
+        }
+        if (itemLimit <= styleLimit) {
+            itemIndex++;
+            start = itemLimit;
+        }
+        item.length = start - item.start;
+    }
+    StyleItem item = new StyleItem();
+    item.start = end;
+    scriptItem = items + itemCount;
+    item.analysis = scriptItem.a;
+    runs[count++] = item;
+    if (runs.length !is count) {
+        StyleItem[] result = new StyleItem[count];
+        System.arraycopy(runs, 0, result, 0, count);
+        return result;
+    }
+    return runs;
+}
+
+/*
+ *  Reorder the run
+ */
+StyleItem[] reorder (StyleItem[] runs, bool terminate) {
+    int length_ = runs.length;
+    if (length_ <= 1) return runs;
+    ubyte[] bidiLevels = new ubyte[length_];
+    for (int i=0; i<length_; i++) {
+        bidiLevels[i] = cast(byte)(runs[i].analysis.s.uBidiLevel & 0x1F);
+    }
+    /*
+    * Feature in Windows.  If the orientation is RTL Uniscribe will
+    * resolve the level of line breaks to 1, this can cause the line
+    * break to be reorder to the middle of the line. The fix is to set
+    * the level to zero to prevent it to be reordered.
+    */
+    StyleItem lastRun = runs[length_ - 1];
+    if (lastRun.lineBreak && !lastRun.softBreak) {
+        bidiLevels[length_ - 1] = 0;
+    }
+    int[] log2vis = new int[length_];
+    OS.ScriptLayout(length_, bidiLevels.ptr, null, log2vis.ptr);
+    StyleItem[] result = new StyleItem[length_];
+    for (int i=0; i<length_; i++) {
+        result[log2vis[i]] = runs[i];
+    }
+    if ((orientation & SWT.RIGHT_TO_LEFT) !is 0) {
+        if (terminate) length_--;
+        for (int i = 0; i < length_ / 2 ; i++) {
+            StyleItem tmp = result[i];
+            result[i] = result[length_ - i - 1];
+            result[length_ - i - 1] = tmp;
+        }
+    }
+    return result;
+}
+
+/**
+ * Sets the text alignment for the receiver. The alignment controls
+ * how a line of text is positioned horizontally. The argument should
+ * be one of <code>SWT.LEFT</code>, <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>.
+ * <p>
+ * The default alignment is <code>SWT.LEFT</code>.  Note that the receiver's
+ * width must be set in order to use <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>
+ * alignment.
+ * </p>
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setWidth(int)
+ */
+public void setAlignment (int alignment) {
+    checkLayout();
+    int mask = SWT.LEFT | SWT.CENTER | SWT.RIGHT;
+    alignment &= mask;
+    if (alignment is 0) return;
+    if ((alignment & SWT.LEFT) !is 0) alignment = SWT.LEFT;
+    if ((alignment & SWT.RIGHT) !is 0) alignment = SWT.RIGHT;
+    if (this.alignment is alignment) return;
+    freeRuns();
+    this.alignment = alignment;
+}
+
+/**
+ * Sets the ascent of the receiver. The ascent is distance in pixels
+ * from the baseline to the top of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * ascent is calculated from the line fonts.
+ *
+ * @param ascent the new ascent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the ascent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setAscent(int ascent) {
+    checkLayout();
+    if (ascent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (this.ascent is ascent) return;
+    freeRuns();
+    this.ascent = ascent;
+}
+
+/**
+ * Sets the descent of the receiver. The descent is distance in pixels
+ * from the baseline to the bottom of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * descent is calculated from the line fonts.
+ *
+ * @param descent the new descent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the descent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setDescent(int descent) {
+    checkLayout();
+    if (descent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (this.descent is descent) return;
+    freeRuns();
+    this.descent = descent;
+}
+
+/**
+ * Sets the default font which will be used by the receiver
+ * to draw and measure text. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead. Note that a text
+ * style can override the default font.
+ *
+ * @param font the new font for the receiver, or null to indicate a default font
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setFont (Font font) {
+    checkLayout();
+    if (font !is null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    Font oldFont = this.font;
+    if (oldFont is font) return;
+    this.font = font;
+    if (oldFont !is null && oldFont.opEquals(font)) return;
+    freeRuns();
+}
+
+/**
+ * Sets the indent of the receiver. This indent it applied of the first line of
+ * each paragraph.
+ *
+ * @param indent new indent
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setIndent (int indent) {
+    checkLayout();
+    if (indent < 0) return;
+    if (this.indent is indent) return;
+    freeRuns();
+    this.indent = indent;
+}
+
+/**
+ * Sets the justification of the receiver. Note that the receiver's
+ * width must be set in order to use justification.
+ *
+ * @param justify new justify
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setJustify (bool justify) {
+    checkLayout();
+    if (this.justify is justify) return;
+    freeRuns();
+    this.justify = justify;
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setOrientation (int orientation) {
+    checkLayout();
+    int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+    orientation &= mask;
+    if (orientation is 0) return;
+    if ((orientation & SWT.LEFT_TO_RIGHT) !is 0) orientation = SWT.LEFT_TO_RIGHT;
+    if (this.orientation is orientation) return;
+    this.orientation = orientation;
+    freeRuns();
+}
+
+/**
+ * Sets the offsets of the receiver's text segments. Text segments are used to
+ * override the default behaviour of the bidirectional algorithm.
+ * Bidirectional reordering can happen within a text segment but not
+ * between two adjacent segments.
+ * <p>
+ * Each text segment is determined by two consecutive offsets in the
+ * <code>segments</code> arrays. The first element of the array should
+ * always be zero and the last one should always be equals to length of
+ * the text.
+ * </p>
+ *
+ * @param segments the text segments offset
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSegments(int[] segments) {
+    checkLayout();
+    if (this.segments is null && segments is null) return;
+    if (this.segments !is null && segments !is null) {
+        if (this.segments.length is segments.length) {
+            int i;
+            for (i = 0; i <segments.length; i++) {
+                if (this.segments[i] !is segments[i]) break;
+            }
+            if (i is segments.length) return;
+        }
+    }
+    freeRuns();
+    this.segments  = segments.dup;
+
+    // SWT: create the wsegments ...
+    this.wsegments.length = segments.length;
+    uint index8, index16;
+    uint segIndex = 1;
+    while(index8 < text.length ){
+        int ate8;
+        int ate16;
+        dchar d8 = text[ index8 .. $ ].firstCodePoint( ate8 );
+        dchar d16 = wtext[ index16 .. $ ].firstCodePoint( ate16 );
+        assert( d8 is d16 );
+        assert( ate8 > 0 );
+        assert( ate16 > 0 );
+        index8 += ate8;
+        index16 += ate16;
+        if( segments[segIndex] is index8 ){
+            wsegments[segIndex] = index16;
+        }
+    }
+    assert( index16 is wtext.length );
+    assert( segIndex is segments.length );
+}
+
+/**
+ * Sets the line spacing of the receiver.  The line spacing
+ * is the space left between lines.
+ *
+ * @param spacing the new line spacing
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the spacing is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSpacing (int spacing) {
+    checkLayout();
+    if (spacing < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (this.lineSpacing is spacing) return;
+    freeRuns();
+    this.lineSpacing = spacing;
+}
+
+/**
+ * Sets the style of the receiver for the specified range.  Styles previously
+ * set for that range will be overwritten.  The start and end offsets are
+ * inclusive and will be clamped if out of range.
+ *
+ * @param style the style
+ * @param start the start offset
+ * @param end the end offset
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setStyle (TextStyle style, int start, int end) {
+    checkLayout();
+    int length = text.length;
+    if (length is 0) return;
+    if (start > end) return;
+    start = Math.min(Math.max(0, start), length - 1);
+    end = Math.min(Math.max(0, end), length - 1);
+    int low = -1;
+    int high = stylesCount;
+    while (high - low > 1) {
+        int index = (high + low) / 2;
+        if (styles[index + 1].start > start) {
+            high = index;
+        } else {
+            low = index;
+        }
+    }
+    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) {
+                if (item.style is null) return;
+            } else {
+                if (style.opEquals(item.style)) return;
+            }
+        }
+    }
+    freeRuns();
+    int modifyStart = high;
+    int modifyEnd = modifyStart;
+    while (modifyEnd < stylesCount) {
+        if (styles[modifyEnd + 1].start > end) break;
+        modifyEnd++;
+    }
+    if (modifyStart is modifyEnd) {
+        int styleStart = styles[modifyStart].start;
+        int styleEnd = styles[modifyEnd + 1].start - 1;
+        if (styleStart is start && styleEnd is end) {
+            styles[modifyStart].style = style;
+            return;
+        }
+        if (styleStart !is start && styleEnd !is end) {
+            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;
+            styles[modifyStart + 1] = item;
+            item = new StyleItem();
+            item.start = end + 1;
+            item.style = styles[modifyStart].style;
+            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 = 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;
+    styles[modifyStart + 1] = item;
+    styles[modifyStart + 2].start = end + 1;
+    stylesCount = newLength;
+}
+
+/**
+ * Sets the receiver's tab list. Each value in the tab list specifies
+ * the space in pixels from the origin of the text layout to the respective
+ * tab stop.  The last tab stop width is repeated continuously.
+ *
+ * @param tabs the new tab list
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setTabs (int[] tabs) {
+    checkLayout();
+    if (this.tabs is null && tabs is null) return;
+    if (this.tabs !is null && tabs !is null) {
+        if (this.tabs.length is tabs.length) {
+            int i;
+            for (i = 0; i <tabs.length; i++) {
+                if (this.tabs[i] !is tabs[i]) break;
+            }
+            if (i is tabs.length) return;
+        }
+    }
+    freeRuns();
+    this.tabs = tabs;
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param text the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setText (String text) {
+    checkLayout();
+
+    //PORTING_CHANGE: allow null argument
+    //if (text is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (text.equals(this.text)) return;
+    freeRuns();
+    this.text  = text.dup;
+    this.wtext = StrToWCHARs(text);
+    styles = new StyleItem[2];
+    styles[0] = new StyleItem();
+    styles[1] = new StyleItem();
+    styles[1].start = text.length;
+    stylesCount = 2;
+}
+
+/**
+ * Sets the line width of the receiver, which determines how
+ * text should be wrapped and aligned. The default value is
+ * <code>-1</code> which means wrapping is disabled.
+ *
+ * @param width the new width
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the width is <code>0</code> or less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAlignment(int)
+ */
+public void setWidth (int width) {
+    checkLayout();
+    if (width < -1 || width is 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (this.wrapWidth is width) return;
+    freeRuns();
+    this.wrapWidth = width;
+}
+
+bool shape (HDC hdc, StyleItem run, wchar[] wchars, int[] glyphCount, int maxGlyphs, SCRIPT_PROPERTIES* sp) {
+    bool useCMAPcheck = !sp.fComplex && !run.analysis.fNoGlyphIndex;
+    if (useCMAPcheck) {
+        scope ushort[] glyphs = new ushort[wchars.length];
+        if (OS.ScriptGetCMap(hdc, run.psc, wchars.ptr, wchars.length, 0, glyphs.ptr) !is OS.S_OK) {
+            if (run.psc !is null) {
+                OS.ScriptFreeCache(run.psc);
+                glyphCount[0] = 0;
+                int[1] one = 1;
+                *cast(int*)run.psc = 0;
+            }
+            return false;
+        }
+    }
+    auto hr = OS.ScriptShape(hdc, run.psc, wchars.ptr, wchars.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, glyphCount.ptr);
+    run.glyphCount = glyphCount[0];
+    if (useCMAPcheck) return true;
+    
+    if (hr !is OS.USP_E_SCRIPT_NOT_IN_FONT) {
+        if (run.analysis.fNoGlyphIndex) return true;
+        SCRIPT_FONTPROPERTIES fp;
+        fp.cBytes = SCRIPT_FONTPROPERTIES.sizeof;
+        OS.ScriptGetFontProperties(hdc, run.psc, &fp);
+        ushort[] glyphs = run.glyphs[ 0 .. glyphCount[0] ];
+        int i;
+        for (i = 0; i < glyphs.length; i++) {
+            if (glyphs[i] is fp.wgDefault) break;
+        }
+        if (i is glyphs.length) return true;
+    }
+    if (run.psc !is null) {
+        OS.ScriptFreeCache(run.psc);
+        glyphCount[0] = 0;
+        *cast(int*)run.psc = 0;
+    }
+    run.glyphCount = 0;
+    return false;
+}
+
+
+/*
+ * Generate glyphs for one Run.
+ */
+void shape (HDC hdc, StyleItem run) {
+    int[1] buffer;
+    wchar[] wchars = segmentsWText[ index8to16[ run.start ] .. index8to16[ run.start + run.length ] ];
+    int maxGlyphs = (wchars.length * 3 / 2) + 16;
+    auto hHeap = OS.GetProcessHeap();
+    run.glyphs = cast(ushort*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * 2);
+    if (run.glyphs is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    run.clusters = cast(WORD*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * 2);
+    if (run.clusters is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    run.visAttrs = cast(SCRIPT_VISATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * SCRIPT_VISATTR_SIZEOF);
+    if (run.visAttrs is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    run.psc = cast(SCRIPT_CACHE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, (void*).sizeof);
+    if (run.psc is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    short script = run.analysis.eScript;
+    SCRIPT_PROPERTIES sp = *device.scripts[script];
+    bool shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp);
+int res;
+    if (!shapeSucceed) {
+        auto hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT);
+        auto ssa = cast(SCRIPT_STRING_ANALYSIS*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, SCRIPT_STRING_ANALYSIS.sizeof);
+        auto metaFileDc = OS.CreateEnhMetaFile(hdc, null, null, null);
+        auto oldMetaFont = OS.SelectObject(metaFileDc, hFont);
+        int flags = OS.SSA_METAFILE | OS.SSA_FALLBACK | OS.SSA_GLYPHS | OS.SSA_LINK;
+        if (OS.ScriptStringAnalyse(metaFileDc, wchars.ptr, wchars.length, 0, -1, flags, 0, null, null, null, null, null, ssa) is OS.S_OK) {
+            OS.ScriptStringOut(*ssa, 0, 0, 0, null, 0, 0, false);
+            OS.ScriptStringFree(ssa);
+        }
+        OS.HeapFree(hHeap, 0, ssa);
+        OS.SelectObject(metaFileDc, oldMetaFont);
+        auto metaFile = OS.CloseEnhMetaFile(metaFileDc);
+        static extern(Windows) int metaFileEnumProc (HDC hDC, HANDLETABLE* table, ENHMETARECORD* record, int nObj, LPARAM lpData) {
+            EMREXTCREATEFONTINDIRECTW* emr_ = cast(EMREXTCREATEFONTINDIRECTW*)lpData;
+            OS.MoveMemory(&emr_.emr, record, EMR.sizeof);
+            switch (emr_.emr.iType) {
+                case OS.EMR_EXTCREATEFONTINDIRECTW:
+                    OS.MoveMemory(emr_, record, EMREXTCREATEFONTINDIRECTW.sizeof);
+                    break;
+                case OS.EMR_EXTTEXTOUTW:
+                    return 0;
+                default:
+            }
+            return 1;
+        }
+
+        EMREXTCREATEFONTINDIRECTW emr;
+        OS.EnumEnhMetaFile(null, metaFile, &metaFileEnumProc, &emr, null);
+        res = OS.DeleteEnhMetaFile(metaFile);
+        assert( res !is 0 );
+
+        auto newFont = OS.CreateFontIndirectW(&emr.elfw.elfLogFont);
+        assert( newFont !is null );
+
+        OS.SelectObject(hdc, newFont);
+        if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) {
+            run.fallbackFont = newFont;
+        }
+        if (!shapeSucceed) {
+            if (!sp.fComplex) {
+                run.analysis.fNoGlyphIndex = true;
+                if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) {
+                    run.fallbackFont = newFont;
+                } else {
+                    run.analysis.fNoGlyphIndex = false;
+                }
+            }
+        }
+        if (!shapeSucceed) {
+            if (mLangFontLink2 !is null) {
+                HANDLE hNewFont;
+                int dwCodePages, cchCodePages;
+                /* GetStrCodePages() */
+                OS.VtblCall(4, mLangFontLink2, cast(int)wchars.ptr, wchars.length, 0, cast(int)&dwCodePages, cast(int)&cchCodePages);
+                /* MapFont() */
+                if (OS.VtblCall(10, mLangFontLink2, cast(int)hdc, dwCodePages, cast(int)wchars[0], cast(int)&hNewFont) is OS.S_OK) {
+                    LOGFONT logFont;
+                    OS.GetObject( hNewFont, LOGFONT.sizeof, &logFont );
+                    /* ReleaseFont() */
+                    OS.VtblCall(8, mLangFontLink2, cast(int)hNewFont);
+                    auto mLangFont = OS.CreateFontIndirect(&logFont);
+                    auto oldFont = OS.SelectObject(hdc, mLangFont);
+                    if ((shapeSucceed = shape(hdc, run, wchars, buffer,  maxGlyphs, &sp)) is true ) {
+                        run.fallbackFont = mLangFont;
+                    } else {
+                        OS.SelectObject(hdc, oldFont);
+                        OS.DeleteObject(mLangFont);
+                    }
+                }
+            }
+        }
+        if (!shapeSucceed) OS.SelectObject(hdc, hFont);
+        if (newFont !is run.fallbackFont) OS.DeleteObject(newFont);
+    }
+
+    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.
+        */
+        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) SWT.error(SWT.ERROR_NO_HANDLES);
+    run.goffsets = cast(GOFFSET*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * GOFFSET_SIZEOF);
+    if (run.goffsets is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    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 {
+        TEXTMETRIC lptm;
+        OS.GetTextMetrics(hdc, &lptm);
+        run.ascent = lptm.tmAscent;
+        run.descent = lptm.tmDescent;
+        run.leading = lptm.tmInternalLeading;
+    }
+}
+
+int validadeOffset(int offset, int step) {
+    offset = segmentsText.toAbsoluteCodePointStartOffset( offset );
+    offset += segmentsText.getRelativeCodePointOffset( offset, step );
+    if (segments !is null && segments.length > 2) {
+        for (int i = 0; i < segments.length; i++) {
+            if (translateOffset(segments[i]) - 1 is offset) {
+                offset += step;
+                break;
+            }
+        }
+    }
+    return offset;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    if (isDisposed()) return "TextLayout {*DISPOSED*}";
+    return "TextLayout {}";
+}
+
+int translateOffset(int offset) {
+    if (segments is null) return offset;
+    int nSegments = segments.length;
+    if (nSegments <= 1) return offset;
+    int length = text.length;
+    if (length is 0) return offset;
+    if (nSegments is 2) {
+        if (segments[0] is 0 && segments[1] is length) return offset;
+    }
+    for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) {
+        offset+=MARK_SIZE;
+    }
+    return offset;
+}
+
+int untranslateOffset(int offset) {
+    if (segments is null) return offset;
+    int nSegments = segments.length;
+    if (nSegments <= 1) return offset;
+    int length = text.length;
+    if (length is 0) return offset;
+    if (nSegments is 2) {
+        if (segments[0] is 0 && segments[1] is length) return offset;
+    }
+    for (int i = 0; i < nSegments && offset > segments[i]; i++) {
+        offset-=MARK_SIZE;
+    }
+    return offset;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/TextStyle.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,344 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.TextStyle;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GlyphMetrics;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * <code>TextStyle</code> defines a set of styles that can be applied
+ * to a range of text.
+ * <p>
+ * The hashCode() method in this class uses the values of the public
+ * fields to compute the hash value. When storing instances of the
+ * class in hashed collections, do not modify these fields after the
+ * object has been inserted.
+ * </p>
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see TextLayout
+ * @see Font
+ * @see Color
+ * @see <a href="http://www.eclipse.org/swt/snippets/#textlayout">TextLayout, TextStyle snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class TextStyle {
+
+    /**
+     * the font of the style
+     */
+    public Font font;
+
+    /**
+     * the foreground of the style
+     */
+    public Color foreground;
+
+    /**
+     * the background of the style
+     */
+    public Color background;
+
+    /**
+     * the underline flag of the style. The default underline
+     * style is <code>SWT.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>SWT.UNDERLINE_SINGLE</code>,
+     * <code>SWT.UNDERLINE_DOUBLE</code>, <code>SWT.UNDERLINE_ERROR</code>,
+     * or <code>SWT.UNDERLINE_SQUIGGLE</code>.
+     * </p>
+     *
+     * @see SWT#UNDERLINE_SINGLE
+     * @see SWT#UNDERLINE_DOUBLE
+     * @see SWT#UNDERLINE_ERROR
+     * @see SWT#UNDERLINE_SQUIGGLE
+     *
+     * @since 3.4
+     */
+    public int underlineStyle;
+
+    /**
+     * the strikeout flag of the style
+     *
+     * @since 3.1
+     */
+    public bool strikeout;
+
+    /**
+     * the strikeout color of the style
+     *
+     * @since 3.4
+     */
+    public Color strikeoutColor;
+
+    /**
+     * the border style. The default border style is <code>SWT.NONE</code>.
+     * <p>
+     * This value should be one of <code>SWT.BORDER_SOLID</code>,
+     * <code>SWT.BORDER_DASH</code>,<code>SWT.BORDER_DOT</code> or
+     * <code>SWT.NONE</code>.
+     * </p>
+     *
+     * @see SWT#BORDER_SOLID
+     * @see SWT#BORDER_DASH
+     * @see SWT#BORDER_DOT
+     * @see SWT#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
+     */
+    public GlyphMetrics metrics;
+
+    /**
+     * the baseline rise of the style.
+     *
+     * @since 3.2
+     */
+    public int rise;
+
+/**
+ * Create an empty text style.
+ *
+ * @since 3.4
+ */
+public this () {
+}
+
+/**
+ * Create a new text style with the specified font, foreground
+ * and background.
+ *
+ * @param font the font of the style, <code>null</code> if none
+ * @param foreground the foreground color of the style, <code>null</code> if none
+ * @param background the background color of the style, <code>null</code> if none
+ */
+public this (Font font, Color foreground, Color background) {
+    if (font !is null && font.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    if (foreground !is null && foreground.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    if (background !is null && background.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    this.font = font;
+    this.foreground = foreground;
+    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) SWT.error (SWT.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
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals(Object object) {
+    if (object is this) return true;
+    if (object is null) return false;
+    if (!(cast(TextStyle)object)) return false;
+    TextStyle style = cast(TextStyle)object;
+    if (foreground !is null) {
+        if ( foreground !is style.foreground ) return false;
+    } else if (style.foreground !is null) return false;
+    if (background !is null) {
+        if ( background !is style.background ) return false;
+    } else if (style.background !is null) return false;
+    if (font !is null) {
+        if (font !is style.font) return false;
+    } 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;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash() {
+    int hash = 0;
+    if (foreground !is null) hash ^= foreground.toHash();
+    if (background !is null) hash ^= background.toHash();
+    if (font !is null) hash ^= font.toHash();
+    if (metrics !is null) hash ^= metrics.toHash();
+    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.
+ *
+ * @return a string representation of the <code>TextStyle</code>
+ */
+override public String toString () {
+    String buffer = "TextStyle {";
+    int startLength = buffer.length;
+    if (font !is null) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "font=";
+        buffer ~= font.toString;
+    }
+    if (foreground !is null) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "foreground=";
+        buffer ~= foreground.toString;
+    }
+    if (background !is null) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "background=";
+        buffer ~= background.toString;
+    }
+    if (underline) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "underlined";
+    }
+    if (strikeout) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "striked out";
+    }
+    if (rise !is 0) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "rise=";
+        buffer ~= to!(String)(rise);
+    }
+    if (metrics !is null) {
+        if (buffer.length > startLength) buffer ~= ", ";
+        buffer ~= "metrics=";
+        buffer ~= metrics.toString;
+    }
+    buffer ~= "}";
+    return buffer;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/Transform.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.graphics.Transform;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.gdip.Gdip;
+
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.graphics.Device;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class represent transformation matrices for
+ * points expressed as (x, y) pairs of floating point numbers.
+ * <p>
+ * Application code must explicitly invoke the <code>Transform.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <p>
+ * This class requires the operating system's advanced graphics subsystem
+ * which may not be available on some platforms.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.1
+ */
+public class Transform : Resource {
+    alias Resource.init_ init_;
+    /**
+     * the OS resource for the Transform
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public Gdip.Matrix handle;
+
+/**
+ * Constructs a new identity Transform.
+ * <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 Transform
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this (Device device) {
+    this(device, 1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Constructs a new Transform given an array of elements that represent the
+ * matrix that describes the transformation.
+ * <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 Transform
+ * @param elements an array of floats that describe the transformation matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device, or the elements array is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the elements array is too small to hold the matrix values</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this(Device device, float[] elements) {
+    this (device, checkTransform(elements)[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
+}
+
+/**
+ * Constructs a new Transform given all of the elements that represent the
+ * matrix that describes the transformation.
+ * <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 Transform
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public this (Device device, float m11, float m12, float m21, float m22, float dx, float dy) {
+    super(device);
+    this.device.checkGDIP();
+    handle = Gdip.Matrix_new(m11, m12, m21, m22, dx, dy);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+static float[] checkTransform(float[] elements) {
+    if (elements is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    return elements;
+}
+
+void destroy() {
+    Gdip.Matrix_delete(handle);
+    handle = null;
+}
+
+/**
+ * Fills the parameter with the values of the transformation matrix
+ * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}.
+ *
+ * @param elements array to hold the matrix values
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the matrix values</li>
+ * </ul>
+ */
+public void getElements(float[] elements) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (elements is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    Gdip.Matrix_GetElements(handle, elements.ptr);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * identity matrix.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void identity() {
+    if (isDisposed()) SWT.error(SWT.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 SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_CANNOT_INVERT_MATRIX - if the matrix is not invertible</li>
+ * </ul>
+ */
+public void invert() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (Gdip.Matrix_Invert(handle) !is 0) SWT.error(SWT.ERROR_CANNOT_INVERT_MATRIX);
+}
+
+/**
+ * Returns <code>true</code> if the Transform has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Transform.
+ * When a Transform has been disposed, it is an error to
+ * invoke any other method using the Transform.
+ *
+ * @return <code>true</code> when the Transform is disposed, and <code>false</code> otherwise
+ */
+override public bool isDisposed() {
+    return handle is null;
+}
+
+/**
+ * Returns <code>true</code> if the Transform represents the identity matrix
+ * and false otherwise.
+ *
+ * @return <code>true</code> if the receiver is an identity Transform, and <code>false</code> otherwise
+ */
+public bool isIdentity() {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    return cast(bool) Gdip.Matrix_IsIdentity(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the result of multiplying the matrix it previously represented by the
+ * argument.
+ *
+ * @param matrix the matrix to multiply the receiver by
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
+ * </ul>
+ */
+public void multiply(Transform matrix) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (matrix is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    if (matrix.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    Gdip.Matrix_Multiply(handle, matrix.handle, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation rotated by the specified angle.
+ * The angle is specified in degrees and for the identity transform 0 degrees
+ * is at the 3 o'clock position. A positive value indicates a clockwise rotation
+ * while a negative value indicates a counter-clockwise rotation.
+ *
+ * @param angle the angle to rotate the transformation by
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void rotate(float angle) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_Rotate(handle, angle, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation scaled by (scaleX, scaleY).
+ *
+ * @param scaleX the amount to scale in the X direction
+ * @param scaleY the amount to scale in the Y direction
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void scale(float scaleX, float scaleY) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_Scale(handle, scaleX, scaleY, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Modifies the receiver to represent a new transformation given all of
+ * the elements that represent the matrix that describes that transformation.
+ *
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setElements(float m11, float m12, float m21, float m22, float dx, float dy) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_SetElements(handle, m11, m12, m21, m22, dx, dy);
+}
+
+/**
+ * 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 SWTException <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()) SWT.error(SWT.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.
+ *
+ * @param pointArray an array of alternating x and y values to be transformed
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void transform(float[] pointArray) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    if (pointArray is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+    Gdip.Matrix_TransformPoints(handle, cast(Gdip.PointF*)pointArray.ptr, pointArray.length / 2);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation translated by (offsetX, offsetY).
+ *
+ * @param offsetX the distance to translate in the X direction
+ * @param offsetY the distance to translate in the Y direction
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void translate(float offsetX, float offsetY) {
+    if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_Translate(handle, offsetX, offsetY, Gdip.MatrixOrderPrepend);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString() {
+    if (isDisposed()) return "Transform {*DISPOSED*}";
+    float[6] elements;
+    getElements(elements);
+    return Format("Transform {{{},{},{},{},{}}", elements [0], elements [1], elements [2], elements [3], elements [4], elements [5] );
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/graphics/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,34 @@
+module org.eclipse.swt.graphics.all;
+
+public import org.eclipse.swt.graphics.Color;
+public import org.eclipse.swt.graphics.Cursor;
+public import org.eclipse.swt.graphics.Device;
+public import org.eclipse.swt.graphics.DeviceData;
+public import org.eclipse.swt.graphics.Drawable;
+public import org.eclipse.swt.graphics.Font;
+public import org.eclipse.swt.graphics.FontData;
+public import org.eclipse.swt.graphics.FontMetrics;
+public import org.eclipse.swt.graphics.GC;
+public import org.eclipse.swt.graphics.GCData;
+public import org.eclipse.swt.graphics.GlyphMetrics;
+public import org.eclipse.swt.graphics.Image;
+public import org.eclipse.swt.graphics.ImageData;
+public import org.eclipse.swt.graphics.ImageDataLoader;
+public import org.eclipse.swt.graphics.ImageLoader;
+public import org.eclipse.swt.graphics.ImageLoaderEvent;
+public import org.eclipse.swt.graphics.ImageLoaderListener;
+public import org.eclipse.swt.graphics.LineAttributes;
+public import org.eclipse.swt.graphics.PaletteData;
+public import org.eclipse.swt.graphics.Path;
+public import org.eclipse.swt.graphics.PathData;
+public import org.eclipse.swt.graphics.Pattern;
+public import org.eclipse.swt.graphics.Point;
+public import org.eclipse.swt.graphics.RGB;
+public import org.eclipse.swt.graphics.Rectangle;
+public import org.eclipse.swt.graphics.Region;
+public import org.eclipse.swt.graphics.Resource;
+public import org.eclipse.swt.graphics.TextLayout;
+public import org.eclipse.swt.graphics.TextStyle;
+public import org.eclipse.swt.graphics.Transform;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/BidiUtil.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,670 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.BidiUtil;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import tango.util.Convert;
+import java.lang.all;
+import java.lang.Runnable;
+
+/*
+ * Wraps Win32 API used to bidi enable the StyledText widget.
+ */
+public class BidiUtil {
+
+    // Keyboard language ids
+    public static const int KEYBOARD_NON_BIDI = 0;
+    public static const int KEYBOARD_BIDI = 1;
+
+    // bidi flag
+    static int isBidiPlatform_ = -1;
+
+    // getRenderInfo flag values
+    public static const int CLASSIN = 1;
+    public static const int LINKBEFORE = 2;
+    public static const int LINKAFTER = 4;
+
+    // variables used for providing a listener mechanism for keyboard language
+    // switching
+    static Runnable[HWND] languageMap;
+    static Runnable[HWND] keyMap;
+    static WNDPROC[HWND] oldProcMap;
+    /*
+     * This code is intentionally commented.  In order
+     * to support CLDC, .class cannot be used because
+     * it does not compile on some Java compilers when
+     * they are targeted for CLDC.
+     */
+    //  static Callback callback = new Callback (BidiUtil.class, "windowProc", 4);
+    static const String CLASS_NAME = "org.eclipse.swt.internal.BidiUtil"; //$NON-NLS-1$
+//     static this() {
+//         try {
+//             callback = new Callback (Class.forName (CLASS_NAME), "windowProc", 4); //$NON-NLS-1$
+//             if (callback.getAddress () is 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+//         } catch (ClassNotFoundException e) {}
+//     }
+
+    // GetCharacterPlacement constants
+    static const int GCP_REORDER = 0x0002;
+    static const int GCP_GLYPHSHAPE = 0x0010;
+    static const int GCP_LIGATE = 0x0020;
+    static const int GCP_CLASSIN = 0x00080000;
+    static const byte GCPCLASS_ARABIC = 2;
+    static const byte GCPCLASS_HEBREW = 2;
+    static const byte GCPCLASS_LOCALNUMBER = 4;
+    static const byte GCPCLASS_LATINNUMBER = 5;
+    static const int GCPGLYPH_LINKBEFORE = 0x8000;
+    static const int GCPGLYPH_LINKAFTER = 0x4000;
+    // ExtTextOut constants
+    static const int ETO_CLIPPED = 0x4;
+    static const int ETO_GLYPH_INDEX = 0x0010;
+    // Windows primary language identifiers
+    static const int LANG_ARABIC = 0x01;
+    static const int LANG_HEBREW = 0x0d;
+    // code page identifiers
+    static const String CD_PG_HEBREW = "1255"; //$NON-NLS-1$
+    static const String CD_PG_ARABIC = "1256"; //$NON-NLS-1$
+    // ActivateKeyboard constants
+    static const int HKL_NEXT = 1;
+    static const int HKL_PREV = 0;
+
+    /*
+     * Public character class constants are the same as Windows
+     * platform constants.
+     * Saves conversion of class array in getRenderInfo to arbitrary
+     * constants for now.
+     */
+    public static const int CLASS_HEBREW = GCPCLASS_ARABIC;
+    public static const int CLASS_ARABIC = GCPCLASS_HEBREW;
+    public static const int CLASS_LOCALNUMBER = GCPCLASS_LOCALNUMBER;
+    public static const int CLASS_LATINNUMBER = GCPCLASS_LATINNUMBER;
+    public static const int REORDER = GCP_REORDER;
+    public static const int LIGATE = GCP_LIGATE;
+    public static const int GLYPHSHAPE = GCP_GLYPHSHAPE;
+
+/**
+ * Adds a language listener. The listener will get notified when the language of
+ * the keyboard changes (via Alt-Shift on Win platforms).  Do this by creating a
+ * window proc for the Control so that the window messages for the Control can be
+ * monitored.
+ * <p>
+ *
+ * @param hwnd the handle of the Control that is listening for keyboard language
+ *  changes
+ * @param runnable the code that should be executed when a keyboard language change
+ *  occurs
+ */
+public static void addLanguageListener (HWND hwnd, Runnable runnable) {
+    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.
+ */
+static extern(Windows) int EnumSystemLanguageGroupsProc(uint lpLangGrpId, wchar* lpLangGrpIdString, wchar* lpLangGrpName, uint options, int lParam) {
+    if (lpLangGrpId is OS.LGRPID_HEBREW) {
+        isBidiPlatform_ = 1;
+        return 0;
+    }
+    if (lpLangGrpId is OS.LGRPID_ARABIC) {
+        isBidiPlatform_ = 1;
+        return 0;
+    }
+    return 1;
+}
+/**
+ * Wraps the ExtTextOut function.
+ * <p>
+ *
+ * @param gc the gc to use for rendering
+ * @param renderBuffer the glyphs to render as an array of characters
+ * @param renderDx the width of each glyph in renderBuffer
+ * @param x x position to start rendering
+ * @param y y position to start rendering
+ */
+public static void drawGlyphs(GC gc, wchar[] renderBuffer, int[] renderDx, int x, int y) {
+    int length_ = renderDx.length;
+
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        if (OS.GetLayout (gc.handle) !is 0) {
+            reverse(renderDx);
+            renderDx[length_-1]--;               //fixes bug 40006
+            reverse(renderBuffer);
+        }
+    }
+    // render transparently to avoid overlapping segments. fixes bug 40006
+    int oldBkMode = OS.SetBkMode(gc.handle, OS.TRANSPARENT);
+    OS.ExtTextOutW(gc.handle, x, y, ETO_GLYPH_INDEX , null, renderBuffer.ptr, renderBuffer.length, renderDx.ptr);
+    OS.SetBkMode(gc.handle, oldBkMode);
+}
+/**
+ * Return ordering and rendering information for the given text.  Wraps the GetFontLanguageInfo
+ * and GetCharacterPlacement functions.
+ * <p>
+ *
+ * @param gc the GC to use for measuring of this line, input parameter
+ * @param text text that bidi data should be calculated for, input parameter
+ * @param order an array of integers representing the visual position of each character in
+ *  the text array, output parameter
+ * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW,
+ *  LOCALNUMBER) of each character in the text array, input/output parameter
+ * @param dx an array of integers representing the pixel width of each glyph in the returned
+ *  glyph buffer, output parameter
+ * @param flags an integer representing rendering flag information, input parameter
+ * @param offsets text segments that should be measured and reordered separately, input
+ *  parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
+ * @return buffer with the glyphs that should be rendered for the given text
+ */
+public static char[] getRenderInfo(GC gc, String text, int[] order, byte[] classBuffer, int[] dx, int flags, int [] offsets) {
+    auto fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
+    auto hHeap = OS.GetProcessHeap();
+    int[8] lpCs;
+    int cs = OS.GetTextCharset(gc.handle);
+    bool isRightOriented = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        isRightOriented = OS.GetLayout(gc.handle) !is 0;
+    }
+    OS.TranslateCharsetInfo( cast(uint*)cs, cast(CHARSETINFO*)lpCs.ptr, OS.TCI_SRCCHARSET);
+    TCHAR[] textBuffer = StrToTCHARs(lpCs[1], text, false);
+    int byteCount = textBuffer.length;
+    bool linkBefore = (flags & LINKBEFORE) is LINKBEFORE;
+    bool linkAfter = (flags & LINKAFTER) is LINKAFTER;
+
+    GCP_RESULTS result;
+    result.lStructSize = GCP_RESULTS.sizeof;
+    result.nGlyphs = byteCount;
+    auto lpOrder = result.lpOrder = cast(uint*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+    auto lpDx = result.lpDx = cast(int*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+    auto lpClass = result.lpClass = cast(CHAR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    auto lpGlyphs = result.lpGlyphs = cast(wchar*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 2);
+
+    // set required dwFlags
+    int dwFlags = 0;
+    int glyphFlags = 0;
+    // Always reorder.  We assume that if we are calling this function we're
+    // on a platform that supports bidi.  Fixes 20690.
+    dwFlags |= GCP_REORDER;
+    if ((fontLanguageInfo & GCP_LIGATE) is GCP_LIGATE) {
+        dwFlags |= GCP_LIGATE;
+        glyphFlags |= 0;
+    }
+    if ((fontLanguageInfo & GCP_GLYPHSHAPE) is GCP_GLYPHSHAPE) {
+        dwFlags |= GCP_GLYPHSHAPE;
+        if (linkBefore) {
+            glyphFlags |= GCPGLYPH_LINKBEFORE;
+        }
+        if (linkAfter) {
+            glyphFlags |= GCPGLYPH_LINKAFTER;
+        }
+    }
+    byte[] lpGlyphs2;
+    if (linkBefore || linkAfter) {
+        lpGlyphs2 = new byte[2];
+        lpGlyphs2[0]=cast(byte)glyphFlags;
+        lpGlyphs2[1]=cast(byte)(glyphFlags >> 8);
+    }
+    else {
+        lpGlyphs2 = [cast(byte) glyphFlags];
+    }
+    OS.MoveMemory(result.lpGlyphs, lpGlyphs2.ptr, lpGlyphs2.length);
+
+    if ((flags & CLASSIN) is CLASSIN) {
+        // set classification values for the substring
+        dwFlags |= GCP_CLASSIN;
+        OS.MoveMemory(result.lpClass, classBuffer.ptr, classBuffer.length);
+    }
+
+    wchar[] glyphBuffer = new wchar[result.nGlyphs];
+    int glyphCount = 0;
+    for (int i=0; i<offsets.length-1; i++) {
+        int offset = offsets [i];
+        int length_ = offsets [i+1] - offsets [i];
+
+        // The number of glyphs expected is <= length (segment length);
+        // the actual number returned may be less in case of Arabic ligatures.
+        result.nGlyphs = length_;
+        TCHAR[] textBuffer2 = StrToTCHARs(lpCs[1], text.substring(offset, offset + length_), false);
+        OS.GetCharacterPlacement(gc.handle, textBuffer2.ptr, textBuffer2.length, 0, &result, dwFlags);
+
+        if (dx !is null) {
+            int [] dx2 = new int [result.nGlyphs];
+            OS.MoveMemory(dx2.ptr, result.lpDx, dx2.length * 4);
+            if (isRightOriented) {
+                reverse(dx2);
+            }
+            System.arraycopy (dx2, 0, dx, glyphCount, dx2.length);
+        }
+        if (order !is null) {
+            int [] order2 = new int [length_];
+            OS.MoveMemory(order2.ptr, result.lpOrder, order2.length * 4);
+            translateOrder(order2, glyphCount, isRightOriented);
+            System.arraycopy (order2, 0, order, offset, length_);
+        }
+        if (classBuffer !is null) {
+            byte [] classBuffer2 = new byte [length_];
+            OS.MoveMemory(classBuffer2.ptr, result.lpClass, classBuffer2.length);
+            System.arraycopy (classBuffer2, 0, classBuffer, offset, length_);
+        }
+        wchar[] glyphBuffer2 = new wchar[result.nGlyphs];
+        OS.MoveMemory(glyphBuffer2.ptr, result.lpGlyphs, glyphBuffer2.length * 2);
+        if (isRightOriented) {
+            reverse(glyphBuffer2);
+        }
+        System.arraycopy (glyphBuffer2, 0, glyphBuffer, glyphCount, glyphBuffer2.length);
+        glyphCount += glyphBuffer2.length;
+
+        // We concatenate successive results of calls to GCP.
+        // For Arabic, it is the only good method since the number of output
+        // glyphs might be less than the number of input characters.
+        // This assumes that the whole line is built by successive adjacent
+        // segments without overlapping.
+        result.lpOrder += length_ * 4;
+        result.lpDx += length_ * 4;
+        result.lpClass += length_;
+        result.lpGlyphs += glyphBuffer2.length * 2;
+    }
+
+    /* Free the memory that was allocated. */
+    OS.HeapFree(hHeap, 0, lpGlyphs);
+    OS.HeapFree(hHeap, 0, lpClass);
+    OS.HeapFree(hHeap, 0, lpDx);
+    OS.HeapFree(hHeap, 0, lpOrder);
+    return WCHARsToStr(glyphBuffer);
+}
+/**
+ * Return bidi ordering information for the given text.  Does not return rendering
+ * information (e.g., glyphs, glyph distances).  Use this method when you only need
+ * ordering information.  Doing so will improve performance.  Wraps the
+ * GetFontLanguageInfo and GetCharacterPlacement functions.
+ * <p>
+ *
+ * @param gc the GC to use for measuring of this line, input parameter
+ * @param text text that bidi data should be calculated for, input parameter
+ * @param order an array of integers representing the visual position of each character in
+ *  the text array, output parameter
+ * @param classBuffer an array of integers representing the type (e.g., ARABIC, HEBREW,
+ *  LOCALNUMBER) of each character in the text array, input/output parameter
+ * @param flags an integer representing rendering flag information, input parameter
+ * @param offsets text segments that should be measured and reordered separately, input
+ *  parameter. See org.eclipse.swt.custom.BidiSegmentEvent for details.
+ */
+public static void getOrderInfo(GC gc, String text, int[] order, byte[] classBuffer, int flags, int [] offsets) {
+    int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
+    auto hHeap = OS.GetProcessHeap();
+    int[8] lpCs;
+    int cs = OS.GetTextCharset(gc.handle);
+    OS.TranslateCharsetInfo( cast(uint*) cs, cast(CHARSETINFO*)lpCs.ptr, OS.TCI_SRCCHARSET);
+    TCHAR[] textBuffer = StrToTCHARs(lpCs[1], text, false);
+    int byteCount = textBuffer.length;
+    bool isRightOriented = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        isRightOriented = OS.GetLayout(gc.handle) !is 0;
+    }
+
+    GCP_RESULTS result;
+    result.lStructSize = GCP_RESULTS.sizeof;
+    result.nGlyphs = byteCount;
+    auto lpOrder = result.lpOrder = cast(uint*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount * 4);
+    auto lpClass = result.lpClass = cast(CHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+
+    // set required dwFlags, these values will affect how the text gets rendered and
+    // ordered
+    int dwFlags = 0;
+    // Always reorder.  We assume that if we are calling this function we're
+    // on a platform that supports bidi.  Fixes 20690.
+    dwFlags |= GCP_REORDER;
+    if ((fontLanguageInfo & GCP_LIGATE) is GCP_LIGATE) {
+        dwFlags |= GCP_LIGATE;
+    }
+    if ((fontLanguageInfo & GCP_GLYPHSHAPE) is GCP_GLYPHSHAPE) {
+        dwFlags |= GCP_GLYPHSHAPE;
+    }
+    if ((flags & CLASSIN) is CLASSIN) {
+        // set classification values for the substring, classification values
+        // can be specified on input
+        dwFlags |= GCP_CLASSIN;
+        OS.MoveMemory(result.lpClass, classBuffer.ptr, classBuffer.length);
+    }
+
+    int glyphCount = 0;
+    for (int i=0; i<offsets.length-1; i++) {
+        int offset = offsets [i];
+        int length_ = offsets [i+1] - offsets [i];
+        // The number of glyphs expected is <= length (segment length);
+        // the actual number returned may be less in case of Arabic ligatures.
+        result.nGlyphs = length_;
+        TCHAR[] textBuffer2 = StrToTCHARs(lpCs[1], text.substring(offset, offset + length_), false);
+        OS.GetCharacterPlacement(gc.handle, textBuffer2.ptr, textBuffer2.length, 0, &result, dwFlags);
+
+        if (order !is null) {
+            int [] order2 = new int [length_];
+            OS.MoveMemory(order2.ptr, result.lpOrder, order2.length * 4);
+            translateOrder(order2, glyphCount, isRightOriented);
+            System.arraycopy (order2, 0, order, offset, length_);
+        }
+        if (classBuffer !is null) {
+            byte [] classBuffer2 = new byte [length_];
+            OS.MoveMemory(classBuffer2.ptr, result.lpClass, classBuffer2.length);
+            System.arraycopy (classBuffer2, 0, classBuffer, offset, length_);
+        }
+        glyphCount += result.nGlyphs;
+
+        // We concatenate successive results of calls to GCP.
+        // For Arabic, it is the only good method since the number of output
+        // glyphs might be less than the number of input characters.
+        // This assumes that the whole line is built by successive adjacent
+        // segments without overlapping.
+        result.lpOrder += length_ * 4;
+        result.lpClass += length_;
+    }
+
+    /* Free the memory that was allocated. */
+    OS.HeapFree(hHeap, 0, lpClass);
+    OS.HeapFree(hHeap, 0, lpOrder);
+}
+/**
+ * Return bidi attribute information for the font in the specified gc.
+ * <p>
+ *
+ * @param gc the gc to query
+ * @return bitwise OR of the REORDER, LIGATE and GLYPHSHAPE flags
+ *  defined by this class.
+ */
+public static int getFontBidiAttributes(GC gc) {
+    int fontStyle = 0;
+    int fontLanguageInfo = OS.GetFontLanguageInfo(gc.handle);
+    if (((fontLanguageInfo & GCP_REORDER) !is 0)) {
+        fontStyle |= REORDER;
+    }
+    if (((fontLanguageInfo & GCP_LIGATE) !is 0)) {
+        fontStyle |= LIGATE;
+    }
+    if (((fontLanguageInfo & GCP_GLYPHSHAPE) !is 0)) {
+        fontStyle |= GLYPHSHAPE;
+    }
+    return fontStyle;
+}
+/**
+ * Return the active keyboard language type.
+ * <p>
+ *
+ * @return an integer representing the active keyboard language (KEYBOARD_BIDI,
+ *  KEYBOARD_NON_BIDI)
+ */
+public static int getKeyboardLanguage() {
+    int layout = cast(int) OS.GetKeyboardLayout(0);
+    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;
+}
+/**
+ * Return the languages that are installed for the keyboard.
+ * <p>
+ *
+ * @return integer array with an entry for each installed language
+ */
+static void*[] getKeyboardLanguageList() {
+    int maxSize = 10;
+    void*[] tempList = new void*[maxSize];
+    int size = OS.GetKeyboardLayoutList(maxSize, tempList.ptr);
+    void*[] list = new void*[size];
+    System.arraycopy(tempList, 0, list, 0, size);
+    return list;
+}
+/**
+ * Return whether or not the platform supports a bidi language.  Determine this
+ * by looking at the languages that are installed.
+ * <p>
+ *
+ * @return true if bidi is supported, false otherwise. Always
+ *  false on Windows CE.
+ */
+public static bool isBidiPlatform() {
+    if (OS.IsWinCE) return false;
+    if (isBidiPlatform_ !is -1) return isBidiPlatform_ is 1; // already set
+
+    isBidiPlatform_ = 0;
+
+    // The following test is a workaround for bug report 27629. On WinXP,
+    // both bidi and complex script (e.g., Thai) languages must be installed
+    // at the same time.  Since the bidi platform calls do not support
+    // double byte characters, there is no way to run Eclipse using the
+    // complex script languages on XP, so constrain this test to answer true
+    // only if a bidi input language is defined.  Doing so will allow complex
+    // script languages to work (e.g., one can install bidi and complex script
+    // languages, but only install the Thai keyboard).
+    if (!isKeyboardBidi()) return false;
+
+    //Callback callback = null;
+    //try {
+        //callback = new Callback (Class.forName (CLASS_NAME), "EnumSystemLanguageGroupsProc", 5); //$NON-NLS-1$
+        //int lpEnumSystemLanguageGroupsProc = callback.getAddress ();
+        //if (lpEnumSystemLanguageGroupsProc is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+        OS.EnumSystemLanguageGroups(&EnumSystemLanguageGroupsProc, OS.LGRPID_INSTALLED, 0);
+        //callback.dispose ();
+    //} catch (ClassNotFoundException e) {
+        //if (callback !is null) callback.dispose();
+    //}
+    if (isBidiPlatform_ is 1) return true;
+    // need to look at system code page for NT & 98 platforms since EnumSystemLanguageGroups is
+    // not supported for these platforms
+    String codePage = to!(String)(OS.GetACP());
+    if (CD_PG_ARABIC==/*eq*/codePage || CD_PG_HEBREW==/*eq*/codePage) {
+        isBidiPlatform_ = 1;
+    }
+    return isBidiPlatform_ is 1;
+}
+/**
+ * Return whether or not the keyboard supports input of a bidi language.  Determine this
+ * by looking at the languages that are installed for the keyboard.
+ * <p>
+ *
+ * @return true if bidi is supported, false otherwise.
+ */
+public static bool isKeyboardBidi() {
+    void*[] list = getKeyboardLanguageList();
+    for (int i=0; i<list.length; i++) {
+        int id = OS.PRIMARYLANGID(OS.LOWORD( cast(int) list[i]));
+        if ((id is LANG_ARABIC) || (id is LANG_HEBREW)) {
+            return true;
+        }
+    }
+    return false;
+}
+/**
+ * Removes the specified language listener.
+ * <p>
+ *
+ * @param hwnd the handle of the Control that is listening for keyboard language changes
+ */
+public static void removeLanguageListener (HWND hwnd) {
+    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
+ * set the keyboard to the first language of the given type.
+ * <p>
+ *
+ * @param language integer representing language. One of
+ *  KEYBOARD_BIDI, KEYBOARD_NON_BIDI.
+ */
+public static void setKeyboardLanguage(int language) {
+    // don't switch the keyboard if it doesn't need to be
+    if (language is getKeyboardLanguage()) return;
+
+    if (language is KEYBOARD_BIDI) {
+        // get the list of active languages
+        void*[] list = getKeyboardLanguageList();
+        // set to first bidi language
+        for (int i=0; i<list.length; i++) {
+            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;
+            }
+        }
+    } else {
+        // get the list of active languages
+        void*[] list = getKeyboardLanguageList();
+        // set to the first non-bidi language (anything not
+        // Hebrew or Arabic)
+        for (int i=0; i<list.length; i++) {
+            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;
+            }
+        }
+    }
+}
+/**
+ * Sets the orientation (writing order) of the specified control. Text will
+ * be right aligned for right to left writing order.
+ * <p>
+ *
+ * @param hwnd the handle of the Control to change the orientation of
+ * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ * @return true if the orientation was changed, false if the orientation
+ *  could not be changed
+ */
+public static bool setOrientation (HWND hwnd, int orientation) {
+    if (OS.IsWinCE) return false;
+    if (OS.WIN32_VERSION < OS.VERSION(4, 10)) return false;
+    int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+    if ((orientation & SWT.RIGHT_TO_LEFT) !is 0) {
+        bits |= OS.WS_EX_LAYOUTRTL;
+    } else {
+        bits &= ~OS.WS_EX_LAYOUTRTL;
+    }
+    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.
+ *
+ * @param hwnd control to override the window proc of
+ */
+static void subclass(HWND hwnd) {
+    HWND key = hwnd;
+    if ( ( key in oldProcMap ) is null) {
+        int /*long*/ oldProc = OS.GetWindowLongPtr(hwnd, OS.GWLP_WNDPROC);
+        oldProcMap[key] = cast(WNDPROC)oldProc;
+        WNDPROC t = &windowProc; // test signature
+        OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, cast(LONG_PTR)&windowProc);
+    }
+}
+/**
+ *  Reverse the character array.  Used for right orientation.
+ *
+ * @param charArray character array to reverse
+ */
+static void reverse(wchar[] charArray) {
+    int length_ = charArray.length;
+    for (int i = 0; i <= (length_  - 1) / 2; i++) {
+        wchar tmp = charArray[i];
+        charArray[i] = charArray[length_ - 1 - i];
+        charArray[length_ - 1 - i] = tmp;
+    }
+}
+/**
+ *  Reverse the integer array.  Used for right orientation.
+ *
+ * @param intArray integer array to reverse
+ */
+static void reverse(int[] intArray) {
+    int length_ = intArray.length;
+    for (int i = 0; i <= (length_  - 1) / 2; i++) {
+        int tmp = intArray[i];
+        intArray[i] = intArray[length_ - 1 - i];
+        intArray[length_ - 1 - i] = tmp;
+    }
+}
+/**
+ * Adjust the order array so that it is relative to the start of the line.  Also reverse the order array if the orientation
+ * is to the right.
+ *
+ * @param orderArray  integer array of order values to translate
+ * @param glyphCount  number of glyphs that have been processed for the current line
+ * @param isRightOriented  flag indicating whether or not current orientation is to the right
+*/
+static void translateOrder(int[] orderArray, int glyphCount, bool isRightOriented) {
+    int maxOrder = 0;
+    int length_ = orderArray.length;
+    if (isRightOriented) {
+        for (int i=0; i<length_; i++) {
+            maxOrder = Math.max(maxOrder, orderArray[i]);
+        }
+    }
+    for (int i=0; i<length_; i++) {
+        if (isRightOriented) orderArray[i] = maxOrder - orderArray[i];
+        orderArray [i] += glyphCount;
+    }
+}
+/**
+ * Remove the overridden the window proc.
+ *
+ * @param hwnd control to remove the window proc override for
+ */
+static void unsubclass(HWND hwnd) {
+    HWND key = hwnd;
+    if (( key in languageMap ) is null && ( key in keyMap ) is null) {
+        WNDPROC proc;
+        if( auto p = key in oldProcMap ){
+            proc = *p;
+            oldProcMap.remove( key );
+        }
+        if (proc is null) return;
+        OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) proc );
+    }
+}
+/**
+ * Window proc to intercept keyboard language switch event (WS_INPUTLANGCHANGE)
+ * and widget orientation changes.
+ * Run the Control's registered runnable when the keyboard language is switched.
+ *
+ * @param hwnd handle of the control that is listening for the keyboard language
+ *  change event
+ * @param msg window message
+ */
+static extern(Windows) int windowProc (HWND hwnd, uint msg, uint wParam, int lParam) {
+    HWND key = hwnd;
+    switch (msg) {
+        case 0x51 /*OS.WM_INPUTLANGCHANGE*/:
+            Runnable runnable = languageMap[key];
+            if (runnable !is null) runnable.run ();
+            break;
+        default:
+        }
+    auto oldProc = oldProcMap[key];
+    return oldProc( hwnd, msg, wParam, lParam);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/C.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module org.eclipse.swt.internal.C;
+
+import org.eclipse.swt.internal.Platform;
+
+static import tango.stdc.string;
+
+public class C : Platform {
+    alias tango.stdc.string.memmove MoveMemory;
+//public static final native void free (int /*long*/ ptr);
+//public static final native int /*long*/ getenv (byte[] wcsToMbcs);
+//public static final native int /*long*/ malloc (int /*long*/ size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/CloneableCompatibility.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.CloneableCompatibility;
+
+//PORTING_TYPE
+interface Cloneable{}
+
+/**
+ * This interface is the cross-platform version of the
+ * java.lang.Cloneable interface.
+ * <p>
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement CloneableCompatibility instead of java.lang.Cloneable.
+ * </p>
+ * <p>
+ * Note: java.lang.Cloneable is not part of CLDC.
+ * </p>
+ */
+public interface CloneableCompatibility : Cloneable {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Compatibility.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,424 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.Compatibility;
+
+/+
+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;
++/
+
+import org.eclipse.swt.SWT;
+public import java.io.FileInputStream;
+public import java.io.FileOutputStream;
+public import java.util.zip.InflaterInputStream;
+
+import Math = tango.math.Math;
+import Unicode = tango.text.Unicode;
+import tango.sys.Process;
+import java.lang.all;
+import java.util.ResourceBundle;
+import tango.io.Path;
+import tango.text.convert.Format;
+
+/**
+ * This class is a placeholder for utility methods commonly
+ * used on J2SE platforms but not supported on some J2ME
+ * profiles.
+ * <p>
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms.
+ * </p>
+ * <p>
+ * IMPORTANT: some of the methods have been modified from their
+ * J2SE parents. Refer to the description of each method for
+ * specific changes.
+ * </p>
+ * <ul>
+ * <li>Exceptions thrown may differ since J2ME's set of
+ * exceptions is a subset of J2SE's one.
+ * </li>
+ * <li>The range of the mathematic functions is subject to
+ * change.
+ * </li>
+ * </ul>
+ */
+public final class Compatibility {
+
+/**
+ * Returns the PI constant as a double.
+ */
+public static const real PI = Math.PI;
+
+static const real toRadians = PI / 180;
+
+/**
+ * Answers the length of the side adjacent to the given angle
+ * of a right triangle. In other words, it returns the integer
+ * conversion of length * cos (angle).
+ * <p>
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the argument. length must be between -32767 and 32767 (inclusive).
+ * </p>
+ *
+ * @param angle the angle in degrees
+ * @param length the length of the triangle's hypotenuse
+ * @return the integer conversion of length * cos (angle)
+ */
+public static int cos(int angle, int length) {
+    return cast(int)(Math.cos(angle * toRadians) * length);
+}
+
+/**
+ * Answers the length of the side opposite to the given angle
+ * of a right triangle. In other words, it returns the integer
+ * conversion of length * sin (angle).
+ * <p>
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the argument. length must be between -32767 and 32767 (inclusive).
+ * </p>
+ *
+ * @param angle the angle in degrees
+ * @param length the length of the triangle's hypotenuse
+ * @return the integer conversion of length * sin (angle)
+ */
+public static int sin(int angle, int length) {
+    return cast(int)(Math.sin(angle * toRadians) * length);
+}
+
+/**
+ * Answers the most negative (i.e. closest to negative infinity)
+ * integer value which is greater than the number obtained by dividing
+ * the first argument p by the second argument q.
+ *
+ * @param p numerator
+ * @param q denominator (must be different from zero)
+ * @return the ceiling of the rational number p / q.
+ */
+public static int ceil(int p, int q) {
+    return cast(int)Math.ceil(cast(float)p / q);
+}
+
+/**
+ * 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.
+ *
+ * @param p numerator
+ * @param q denominator (must be different from zero)
+ * @return the floor of the rational number p / q.
+ */
+public static int floor(int p, int q) {
+    return cast(int)Math.floor(cast(double)p / q);
+}
+
+/**
+ * Answers the result of rounding to the closest integer the number obtained
+ * by dividing the first argument p by the second argument q.
+ * <p>
+ * IMPORTANT: the j2me version has an additional restriction on
+ * the arguments. p must be within the range 0 - 32767 (inclusive).
+ * q must be within the range 1 - 32767 (inclusive).
+ * </p>
+ *
+ * @param p numerator
+ * @param q denominator (must be different from zero)
+ * @return the closest integer to the rational number p / q
+ */
+public static int round(int p, int q) {
+    return cast(int)Math.round(cast(float)p / q);
+}
+
+/**
+ * Returns 2 raised to the power of the argument.
+ *
+ * @param n an int value between 0 and 30 (inclusive)
+ * @return 2 raised to the power of the argument
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the argument is not between 0 and 30 (inclusive)</li>
+ * </ul>
+ */
+public static int pow2(int n) {
+    if (n >= 1 && n <= 30)
+        return 2 << (n - 1);
+    else if (n != 0) {
+        SWT.error(SWT.ERROR_INVALID_RANGE);
+    }
+    return 1;
+}
+
+/**
+ * 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
+ * @return a stream on the file if it could be opened.
+ * @exception IOException
+ */
+public static InputStream newFileInputStream(String filename) {
+    return new FileInputStream(filename);
+}
+
+/**
+ * Open a file if such things are supported.
+ *
+ * @param filename the name of the file to open
+ * @return a stream on the file if it could be opened.
+ * @exception IOException
+ */
+public static OutputStream newFileOutputStream(String filename) {
+    return new FileOutputStream(filename);
+}
+
+/**
+ * Create an InflaterInputStream if such things are supported.
+ *
+ * @param stream the input stream
+ * @return a inflater stream or <code>null</code>
+ * @exception IOException
+ *
+ * @since 3.3
+ */
+public static InflaterInputStream newInflaterInputStream(InputStream stream) {
+    return new InflaterInputStream(stream);
+}
+
+/**
+ * Answers whether the character is a letter.
+ *
+ * @param c the character
+ * @return true when the character is a letter
+ */
+public static bool isLetter(dchar c) {
+    return Unicode.isLetter(c);
+}
+
+/**
+ * Answers whether the character is a letter or a digit.
+ *
+ * @param c the character
+ * @return true when the character is a letter or a digit
+ */
+public static bool isLetterOrDigit(dchar c) {
+    return Unicode.isLetterOrDigit(c);
+}
+
+/**
+ * Answers whether the character is a Unicode space character.
+ *
+ * @param c  the character
+ * @return true when the character is a Unicode space character
+ */
+public static bool isSpaceChar(dchar c) {
+    return Unicode.isSpace(c);
+}
+
+/**
+ * Answers whether the character is a whitespace character.
+ *
+ * @param c the character to test
+ * @return true if the character is whitespace
+ */
+public static bool isWhitespace(dchar c) {
+    return Unicode.isWhitespace(c);
+}
+
+/**
+ * Execute a program in a separate platform process if the
+ * underlying platform support this.
+ * <p>
+ * The new process inherits the environment of the caller.
+ * </p>
+ *
+ * @param prog the name of the program to execute
+ *
+ * @exception ProcessException
+ *  if the program cannot be executed
+ */
+public static void exec(String prog) {
+    auto proc = new Process( prog );
+    proc.execute;
+}
+
+/**
+ * Execute progArray[0] in a separate platform process if the
+ * underlying platform support this.
+ * <p>
+ * The new process inherits the environment of the caller.
+ * <p>
+ *
+ * @param progArray array containing the program to execute and its arguments
+ *
+ * @exception ProcessException
+ *  if the program cannot be executed
+ */
+public static void exec(String[] progArray) {
+    auto proc = new Process( progArray );
+    proc.execute;
+}
+
+const ImportData[] SWTMessagesBundleData = [
+    getImportData!( "swt.internal.SWTMessages.properties" ),
+    getImportData!( "swt.internal.SWTMessages_ar.properties" ),
+    getImportData!( "swt.internal.SWTMessages_cs.properties" ),
+    getImportData!( "swt.internal.SWTMessages_da.properties" ),
+    getImportData!( "swt.internal.SWTMessages_de.properties" ),
+    getImportData!( "swt.internal.SWTMessages_el.properties" ),
+    getImportData!( "swt.internal.SWTMessages_es.properties" ),
+    getImportData!( "swt.internal.SWTMessages_fi.properties" ),
+    getImportData!( "swt.internal.SWTMessages_fr.properties" ),
+    getImportData!( "swt.internal.SWTMessages_hu.properties" ),
+    getImportData!( "swt.internal.SWTMessages_it.properties" ),
+    getImportData!( "swt.internal.SWTMessages_iw.properties" ),
+    getImportData!( "swt.internal.SWTMessages_ja.properties" ),
+    getImportData!( "swt.internal.SWTMessages_ko.properties" ),
+    getImportData!( "swt.internal.SWTMessages_nl.properties" ),
+    getImportData!( "swt.internal.SWTMessages_no.properties" ),
+    getImportData!( "swt.internal.SWTMessages_pl.properties" ),
+    getImportData!( "swt.internal.SWTMessages_pt_BR.properties" ),
+    getImportData!( "swt.internal.SWTMessages_pt.properties" ),
+    getImportData!( "swt.internal.SWTMessages_ru.properties" ),
+    getImportData!( "swt.internal.SWTMessages_sv.properties" ),
+    getImportData!( "swt.internal.SWTMessages_tr.properties" ),
+    getImportData!( "swt.internal.SWTMessages_zh_HK.properties" ),
+    getImportData!( "swt.internal.SWTMessages_zh.properties" ),
+    getImportData!( "swt.internal.SWTMessages_zh_TW.properties" )
+];
+
+private static ResourceBundle msgs = null;
+
+/**
+ * Returns the NLS'ed message for the given argument. This is only being
+ * called from SWT.
+ *
+ * @param key the key to look up
+ * @return the message for the given key
+ *
+ * @see SWT#getMessage(String)
+ */
+public static String getMessage(String key) {
+    String answer = key;
+
+    if (key is null) {
+        SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    }
+    if (msgs is null) {
+        try {
+            msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$
+        } catch (MissingResourceException ex) {
+            answer = key ~ " (no resource bundle)"; //$NON-NLS-1$
+        }
+    }
+    if (msgs !is null) {
+        try {
+            answer = msgs.getString(key);
+        } catch (MissingResourceException ex2) {}
+    }
+    return answer;
+}
+
+public static String getMessage(String key, Object[] args) {
+    String answer = key;
+
+    if (key is null || args is null) {
+        SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    }
+    if (msgs is null) {
+        try {
+            msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$
+        } catch (MissingResourceException ex) {
+            answer = key ~ " (no resource bundle)"; //$NON-NLS-1$
+        }
+    }
+    if (msgs !is null) {
+        try {
+            char[] frmt = msgs.getString(key);
+            switch( args.length ){
+            case 0: answer = Format(frmt); break;
+            case 1: answer = Format(frmt, args[0]); break;
+            case 2: answer = Format(frmt, args[0], args[1]); break;
+            case 3: answer = Format(frmt, args[0], args[1], args[2]); break;
+            case 4: answer = Format(frmt, args[0], args[1], args[2], args[3]); break;
+            case 5: answer = Format(frmt, args[0], args[1], args[2], args[3], args[4]); break;
+            default:
+                implMissing(__FILE__, __LINE__ );
+            }
+        } catch (MissingResourceException ex2) {}
+    }
+    return answer;
+}
+
+
+/**
+ * Interrupt the current thread.
+ * <p>
+ * Note that this is not available on CLDC.
+ * </p>
+ */
+public static void interrupt() {
+    //PORTING_FIXME: how to implement??
+    //Thread.currentThread().interrupt();
+}
+
+/**
+ * Compares two instances of class String ignoring the case of the
+ * characters and answers if they are equal.
+ *
+ * @param s1 string
+ * @param s2 string
+ * @return true if the two instances of class String are equal
+ */
+public static bool equalsIgnoreCase(String s1, String s2) {
+    String s1b = new char[ s1.length ];
+    String s2b = new char[ s1.length ];
+    scope(exit){
+        delete s1b;
+        delete s2b;
+    }
+    String s1c = Unicode.toFold( s1, s1b );
+    String s2c = Unicode.toFold( s2, s2b );
+    return s1c == s2c;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ImageList.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,475 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.ImageList;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+import java.lang.System;
+
+public class ImageList {
+    HIMAGELIST handle;
+    int style, refCount;
+    Image [] images;
+
+public this (int style) {
+    this.style = style;
+    int flags = OS.ILC_MASK;
+    static if (OS.IsWinCE) {
+        flags |= OS.ILC_COLOR;
+    } else {
+        if (OS.COMCTL32_MAJOR >= 6) {
+            flags |= OS.ILC_COLOR32;
+        } else {
+            auto hDC = OS.GetDC (null);
+            auto bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+            auto planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+            OS.ReleaseDC (null, hDC);
+            int depth = bits * planes;
+            switch (depth) {
+                case 4: flags |= OS.ILC_COLOR4; break;
+                case 8: flags |= OS.ILC_COLOR8; break;
+                case 16: flags |= OS.ILC_COLOR16; break;
+                case 24: flags |= OS.ILC_COLOR24; break;
+                case 32: flags |= OS.ILC_COLOR32; break;
+                default: flags |= OS.ILC_COLOR; break;
+            }
+        }
+    }
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) flags |= OS.ILC_MIRROR;
+    handle = OS.ImageList_Create (32, 32, flags, 16, 16);
+    images = new Image [4];
+}
+
+public int add (Image image) {
+    int count = OS.ImageList_GetImageCount (handle);
+    int index = 0;
+    while (index < count) {
+        if (images [index] !is null) {
+            if (images [index].isDisposed ()) images [index] = null;
+        }
+        if (images [index] is null) break;
+        index++;
+    }
+    if (count is 0) {
+        Rectangle rect = image.getBounds ();
+        OS.ImageList_SetIconSize (handle, rect.width, rect.height);
+    }
+    set (index, image, count);
+    if (index is images.length) {
+        Image [] newImages = new Image [images.length + 4];
+        System.arraycopy (images, 0, newImages, 0, images.length);
+        images = newImages;
+    }
+    images [index] = image;
+    return index;
+}
+
+public int addRef() {
+    return ++refCount;
+}
+
+HBITMAP copyBitmap (HBITMAP hImage, int width, int height) {
+    BITMAP bm;
+    OS.GetObject (hImage, BITMAP.sizeof, &bm);
+    auto hDC = OS.GetDC (null);
+    auto hdc1 = OS.CreateCompatibleDC (hDC);
+    OS.SelectObject (hdc1, hImage);
+    auto hdc2 = OS.CreateCompatibleDC (hDC);
+    /*
+    * Feature in Windows.  If a bitmap has a 32-bit depth and any
+    * pixel has an alpha value different than zero, common controls
+    * version 6.0 assumes that the bitmap should be alpha blended.
+    * AlphaBlend() composes the alpha channel of a destination 32-bit
+    * depth image with the alpha channel of the source image. This
+    * may cause opaque images to draw transparently.  The fix is
+    * remove the alpha channel of opaque images by down sampling
+    * it to 24-bit depth.
+    */
+    HBITMAP hBitmap;
+    if (bm.bmBitsPixel is 32 && OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        BITMAPINFOHEADER bmiHeader;
+        bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+        bmiHeader.biWidth = width;
+        bmiHeader.biHeight = -height;
+        bmiHeader.biPlanes = 1;
+        bmiHeader.biBitCount = cast(short)24;
+        static if (OS.IsWinCE) bmiHeader.biCompression = OS.BI_BITFIELDS;
+        else bmiHeader.biCompression = OS.BI_RGB;
+        byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + (OS.IsWinCE ? 12 : 0)];
+        *cast(BITMAPINFOHEADER*)bmi.ptr = bmiHeader;
+        //OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+        /* Set the rgb colors into the bitmap info */
+        static if (OS.IsWinCE) {
+            int redMask = 0xFF00;
+            int greenMask = 0xFF0000;
+            int blueMask = 0xFF000000;
+            /* big endian */
+            int offset = BITMAPINFOHEADER.sizeof;
+            bmi[offset] = cast(byte)((redMask & 0xFF000000) >> 24);
+            bmi[offset + 1] = cast(byte)((redMask & 0xFF0000) >> 16);
+            bmi[offset + 2] = cast(byte)((redMask & 0xFF00) >> 8);
+            bmi[offset + 3] = cast(byte)((redMask & 0xFF) >> 0);
+            bmi[offset + 4] = cast(byte)((greenMask & 0xFF000000) >> 24);
+            bmi[offset + 5] = cast(byte)((greenMask & 0xFF0000) >> 16);
+            bmi[offset + 6] = cast(byte)((greenMask & 0xFF00) >> 8);
+            bmi[offset + 7] = cast(byte)((greenMask & 0xFF) >> 0);
+            bmi[offset + 8] = cast(byte)((blueMask & 0xFF000000) >> 24);
+            bmi[offset + 9] = cast(byte)((blueMask & 0xFF0000) >> 16);
+            bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
+            bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 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);
+    }
+    OS.SelectObject (hdc2, hBitmap);
+    if (width !is bm.bmWidth || height !is bm.bmHeight) {
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
+        OS.StretchBlt (hdc2, 0, 0, width, height, hdc1, 0, 0, bm.bmWidth, bm.bmHeight, OS.SRCCOPY);
+    } else {
+        OS.BitBlt (hdc2, 0, 0, width, height, hdc1, 0, 0, OS.SRCCOPY);
+    }
+    OS.DeleteDC (hdc1);
+    OS.DeleteDC (hdc2);
+    OS.ReleaseDC (null, hDC);
+    return hBitmap;
+}
+
+HBITMAP copyIcon (HBITMAP hImage, int width, int height) {
+    static if (OS.IsWinCE) SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+    auto hIcon = OS.CopyImage (hImage, OS.IMAGE_ICON, width, height, 0);
+    return hIcon !is null ? hIcon : hImage;
+}
+
+HBITMAP copyWithAlpha (HBITMAP hBitmap, int background, byte[] alphaData, int destWidth, int destHeight) {
+    BITMAP bm;
+    OS.GetObject (hBitmap, 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, hBitmap);
+    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;
+    byte [] bmi = new byte[BITMAPINFOHEADER.sizeof];
+    *cast(BITMAPINFOHEADER*)bmi.ptr = bmiHeader;
+    //OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+    if (memDib is null) SWT.error (SWT.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].dup;
+    //OS.MoveMemory (srcData, dibBM.bmBits, sizeInBytes);
+
+    /* Merge the alpha channel in place */
+    if (alphaData !is null) {
+        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) {
+                srcData [sp] = alphaData [ap++];
+                sp += 4;
+            }
+            sp += spinc;
+        }
+    } else {
+        byte transRed = cast(byte)(background & 0xFF);
+        byte transGreen = cast(byte)((background >> 8) & 0xFF);
+        byte transBlue = cast(byte)((background >> 16) & 0xFF);
+        final int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+        int sp = 3;
+        for (int y = 0; y < srcHeight; ++y) {
+            for (int x = 0; x < srcWidth; ++x) {
+                srcData [sp] = (srcData[sp-1] is transRed && srcData[sp-2] is transGreen && srcData[sp-3] is transBlue) ? 0 : cast(byte)255;
+                sp += 4;
+            }
+            sp += spinc;
+        }
+    }
+    (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes] = srcData;
+    //OS.MoveMemory (dibBM.bmBits, srcData, sizeInBytes);
+
+    /* Stretch and free resources */
+    if (srcWidth !is destWidth || srcHeight !is destHeight) {
+        BITMAPINFOHEADER bmiHeader2;
+        bmiHeader2.biSize = BITMAPINFOHEADER.sizeof;
+        bmiHeader2.biWidth = destWidth;
+        bmiHeader2.biHeight = -destHeight;
+        bmiHeader2.biPlanes = 1;
+        bmiHeader2.biBitCount = 32;
+        bmiHeader2.biCompression = OS.BI_RGB;
+        byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof];
+        *cast(BITMAPINFOHEADER*)bmi2.ptr = bmiHeader2;
+        //OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof);
+        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);
+        OS.StretchBlt (memHdc2, 0, 0, destWidth, destHeight, memHdc, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        OS.SelectObject (memHdc2, oldMemBitmap2);
+        OS.DeleteDC (memHdc2);
+        OS.SelectObject (memHdc, oldMemBitmap);
+        OS.DeleteDC (memHdc);
+        OS.DeleteObject (memDib);
+        memDib = memDib2;
+    } else {
+        OS.SelectObject (memHdc, oldMemBitmap);
+        OS.DeleteDC (memHdc);
+    }
+    OS.SelectObject (srcHdc, oldSrcBitmap);
+    OS.DeleteDC (srcHdc);
+    OS.ReleaseDC (null, hdc);
+    return memDib;
+}
+
+HBITMAP createMaskFromAlpha (ImageData data, int destWidth, int destHeight) {
+    int srcWidth = data.width;
+    int srcHeight = data.height;
+    ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1,
+            new PaletteData([new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)]),
+            2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0);
+    int ap = 0;
+    for (int y = 0; y < mask.height; y++) {
+        for (int x = 0; x < mask.width; x++) {
+            mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0);
+        }
+    }
+    auto hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data.ptr);
+    if (srcWidth !is destWidth || srcHeight !is destHeight) {
+        auto hdc = OS.GetDC (null);
+        auto hdc1 = OS.CreateCompatibleDC (hdc);
+        OS.SelectObject (hdc1, hMask);
+        auto hdc2 = OS.CreateCompatibleDC (hdc);
+        auto hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+        OS.SelectObject (hdc2, hMask2);
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
+        OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        OS.DeleteDC (hdc1);
+        OS.DeleteDC (hdc2);
+        OS.ReleaseDC (null, hdc);
+        OS.DeleteObject(hMask);
+        hMask = hMask2;
+    }
+    return hMask;
+}
+
+HBITMAP createMask (HBITMAP hBitmap, int destWidth, int destHeight, int background, int transparentPixel) {
+    BITMAP bm;
+    OS.GetObject (hBitmap, BITMAP.sizeof, &bm);
+    int srcWidth = bm.bmWidth;
+    int srcHeight = bm.bmHeight;
+    auto hMask = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+    auto hDC = OS.GetDC (null);
+    auto hdc1 = OS.CreateCompatibleDC (hDC);
+    if (background !is -1) {
+        OS.SelectObject (hdc1, hBitmap);
+
+        /*
+        * If the image has a palette with multiple entries having
+        * the same color and one of those entries is the transparentPixel,
+        * only the first entry becomes transparent. To avoid this
+        * problem, temporarily change the image palette to a palette
+        * where the transparentPixel is white and everything else is
+        * black.
+        */
+        bool isDib = bm.bmBits !is null;
+        byte[] originalColors = null;
+        if (!OS.IsWinCE && transparentPixel !is -1 && isDib && bm.bmBitsPixel <= 8) {
+            int maxColors = 1 << bm.bmBitsPixel;
+            byte[] oldColors = new byte[maxColors * 4];
+            OS.GetDIBColorTable(hdc1, 0, maxColors, cast(RGBQUAD*)oldColors.ptr);
+            int offset = transparentPixel * 4;
+            byte[] newColors = new byte[oldColors.length];
+            newColors[offset] = cast(byte)0xFF;
+            newColors[offset+1] = cast(byte)0xFF;
+            newColors[offset+2] = cast(byte)0xFF;
+            OS.SetDIBColorTable(hdc1, 0, maxColors, cast(RGBQUAD*)newColors.ptr);
+            originalColors = oldColors;
+            OS.SetBkColor (hdc1, 0xFFFFFF);
+        } else {
+            OS.SetBkColor (hdc1, background);
+        }
+
+        auto hdc2 = OS.CreateCompatibleDC (hDC);
+        OS.SelectObject (hdc2, hMask);
+        if (destWidth !is srcWidth || destHeight !is srcHeight) {
+            static if (!OS.IsWinCE) OS.SetStretchBltMode (hdc2, OS.COLORONCOLOR);
+            OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        } else {
+            OS.BitBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, OS.SRCCOPY);
+        }
+        OS.DeleteDC (hdc2);
+
+        /* Put back the original palette */
+        if (originalColors !is null) OS.SetDIBColorTable(hdc1, 0, 1 << bm.bmBitsPixel, cast(RGBQUAD*)originalColors.ptr);
+    } else {
+        auto hOldBitmap = OS.SelectObject (hdc1, hMask);
+        OS.PatBlt (hdc1, 0, 0, destWidth, destHeight, OS.BLACKNESS);
+        OS.SelectObject (hdc1, hOldBitmap);
+    }
+    OS.ReleaseDC (null, hDC);
+    OS.DeleteDC (hdc1);
+    return hMask;
+}
+
+public void dispose () {
+    if (handle !is null) OS.ImageList_Destroy (handle);
+    handle = null;
+    images = null;
+}
+
+public Image get (int index) {
+    return images [index];
+}
+
+public int getStyle () {
+    return style;
+}
+
+public HIMAGELIST getHandle () {
+    return handle;
+}
+
+public Point getImageSize() {
+    int cx, cy;
+    OS.ImageList_GetIconSize (handle, &cx, &cy);
+    return new Point (cx, cy);
+}
+
+public int indexOf (Image image) {
+    int count = OS.ImageList_GetImageCount (handle);
+    for (int i=0; i<count; i++) {
+        if (images [i] !is null) {
+            if (images [i].isDisposed ()) images [i] = null;
+            if (images [i] !is null && images [i]==/*eq*/image) return i;
+        }
+    }
+    return -1;
+}
+
+public void put (int index, Image image) {
+    int count = OS.ImageList_GetImageCount (handle);
+    if (!(0 <= index && index < count)) return;
+    if (image !is null) set(index, image, count);
+    images [index] = image;
+}
+
+public void remove (int index) {
+    int count = OS.ImageList_GetImageCount (handle);
+    if (!(0 <= index && index < count)) return;
+    OS.ImageList_Remove (handle, index);
+    System.arraycopy (images, index + 1, images, index, --count - index);
+    images [index] = null;
+}
+
+public int removeRef() {
+    return --refCount;
+}
+
+void set (int index, Image image, int count) {
+    auto hImage = image.handle;
+    int cx , cy ;
+    OS.ImageList_GetIconSize (handle, &cx, &cy);
+    switch (image.type) {
+        case SWT.BITMAP: {
+            /*
+            * Note that the image size has to match the image list icon size.
+            */
+            HBITMAP hBitmap, hMask;
+            ImageData data = image.getImageData ();
+            switch (data.getTransparencyType ()) {
+                case SWT.TRANSPARENCY_ALPHA:
+                    if (OS.COMCTL32_MAJOR >= 6) {
+                        hBitmap = copyWithAlpha (hImage, -1, data.alphaData, cx, cy);
+                    } else {
+                        hBitmap = copyBitmap (hImage, cx, cy);
+                        hMask = createMaskFromAlpha (data, cx, cy);
+                    }
+                    break;
+                case SWT.TRANSPARENCY_PIXEL:
+                    int background = -1;
+                    Color color = image.getBackground ();
+                    if (color !is null) background = color.handle;
+                    hBitmap = copyBitmap (hImage, cx, cy);
+                    hMask = createMask (hImage, cx, cy, background, data.transparentPixel);
+                    break;
+                case SWT.TRANSPARENCY_NONE:
+                default:
+                    hBitmap = copyBitmap (hImage, cx, cy);
+                    if (index !is count) hMask = createMask (hImage, cx, cy, -1, -1);
+                    break;
+            }
+            if (index is count) {
+                OS.ImageList_Add (handle, hBitmap, hMask);
+            } else {
+                /* Note that the mask must always be replaced even for TRANSPARENCY_NONE */
+                OS.ImageList_Replace (handle, index, hBitmap, hMask);
+            }
+            if (hMask !is null) OS.DeleteObject (hMask);
+            if (hBitmap !is hImage) OS.DeleteObject (hBitmap);
+            break;
+        }
+        case SWT.ICON: {
+            static if (OS.IsWinCE) {
+                OS.ImageList_ReplaceIcon (handle, index is count ? -1 : index, hImage);
+            } else {
+                auto hIcon = copyIcon (hImage, cx, cy);
+                OS.ImageList_ReplaceIcon (handle, index is count ? -1 : index, hIcon);
+                OS.DestroyIcon (hIcon);
+            }
+            break;
+        }
+        default:
+    }
+}
+
+public int size () {
+    int result = 0;
+    int count = OS.ImageList_GetImageCount (handle);
+    for (int i=0; i<count; i++) {
+        if (images [i] !is null) {
+            if (images [i].isDisposed ()) images [i] = null;
+            if (images [i] !is null) result++;
+        }
+    }
+    return result;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Library.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.Library;
+
+import tango.util.Convert;
+import java.lang.all;
+
+// do it here, so it can be evaluated at compile time
+// this saves a static ctor.
+private int buildSWT_VERSION (int major, int minor) {
+    return major * 1000 + minor;
+}
+
+
+public class Library {
+
+    /* SWT Version - Mmmm (M=major, mmm=minor) */
+
+    /**
+     * SWT Major version number (must be >= 0)
+     */
+    static const int MAJOR_VERSION = 3;
+
+    /**
+     * SWT Minor version number (must be in the range 0..999)
+     */
+    static const int MINOR_VERSION = 449;
+
+    /**
+     * SWT revision number (must be >= 0)
+     */
+    static const int REVISION = 0;
+
+    /**
+     * The JAVA and SWT versions
+     */
+    //public static const int JAVA_VERSION;
+    public static const int SWT_VERSION = .buildSWT_VERSION(MAJOR_VERSION, MINOR_VERSION);
+
+    version( Windows ){
+        static const String SEPARATOR = "\r\n";
+    }
+    else {
+        static assert( false, "only windows supported for this port" );
+    }
+
+
+static int parseVersion(String aVersion) {
+    if (aVersion == null) return 0;
+    int major = 0, minor = 0, micro = 0;
+    int length = aVersion.length, index = 0, start = 0;
+    bool isDigit( char c ){
+        return c >= '0' && c <= '9';
+    }
+    while (index < length && isDigit(aVersion[index])) index++;
+    try {
+        if (start < length) major = to!(int)( aVersion[start .. index] );
+    } catch (ConversionException e) {}
+    start = ++index;
+    while (index < length && isDigit(aVersion[index])) index++;
+    try {
+        if (start < length) minor = to!(int)(aVersion[start .. index]);
+    } catch (ConversionException e) {}
+    start = ++index;
+    while (index < length && isDigit(aVersion[index])) index++;
+    try {
+        if (start < length) micro = to!(int)(aVersion[start .. index]);
+    } catch (ConversionException e) {}
+    return buildJAVA_VERSION(major, minor, micro);
+}
+
+/**
+ * Returns the Java version number as an integer.
+ *
+ * @param major
+ * @param minor
+ * @param micro
+ * @return the version
+ */
+public static int buildJAVA_VERSION (int major, int minor, int micro) {
+    return (major << 16) + (minor << 8) + micro;
+}
+
+/**
+ * Returns the SWT version number as an integer.
+ *
+ * @param major
+ * @param minor
+ * @return the version
+ */
+public static int buildSWT_VERSION (int major, int minor) {
+    return .buildSWT_VERSION(major, minor);
+}
+/+ PORTING_LEFT
+static bool extract (String fileName, String mappedName) {
+    FileOutputStream os = null;
+    InputStream is = null;
+    File file = new File(fileName);
+    try {
+        if (!file.exists ()) {
+            is = Library.class.getResourceAsStream ("/" + mappedName); //$NON-NLS-1$
+            if (is != null) {
+                int read;
+                byte [] buffer = new byte [4096];
+                os = new FileOutputStream (fileName);
+                while ((read = is.read (buffer)) != -1) {
+                    os.write(buffer, 0, read);
+                }
+                os.close ();
+                is.close ();
+                if (!Platform.PLATFORM.equals ("win32")) { //$NON-NLS-1$
+                    try {
+                        Runtime.getRuntime ().exec (new String []{"chmod", "755", fileName}).waitFor(); //$NON-NLS-1$ //$NON-NLS-2$
+                    } catch (Throwable e) {}
+                }
+                if (load (fileName)) return true;
+            }
+        }
+    } catch (Throwable e) {
+        try {
+            if (os != null) os.close ();
+        } catch (IOException e1) {}
+        try {
+            if (is != null) is.close ();
+        } catch (IOException e1) {}
+    }
+    if (file.exists ()) file.delete ();
+    return false;
+}
+
+static bool load (String libName) {
+    try {
+        if (libName.indexOf (SEPARATOR) != -1) {
+            System.load (libName);
+        } else {
+            System.loadLibrary (libName);
+        }
+        return true;
+    } catch (UnsatisfiedLinkError e) {}
+    return false;
+}
+
+/**
+ * Loads the shared library that matches the version of the
+ * Java code which is currently running.  SWT shared libraries
+ * follow an encoding scheme where the major, minor and revision
+ * numbers are embedded in the library name and this along with
+ * <code>name</code> is used to load the library.  If this fails,
+ * <code>name</code> is used in another attempt to load the library,
+ * this time ignoring the SWT version encoding scheme.
+ *
+ * @param name the name of the library to load
+ */
+public static void loadLibrary (String name) {
+    loadLibrary (name, true);
+}
+
+/**
+ * Loads the shared library that matches the version of the
+ * Java code which is currently running.  SWT shared libraries
+ * follow an encoding scheme where the major, minor and revision
+ * numbers are embedded in the library name and this along with
+ * <code>name</code> is used to load the library.  If this fails,
+ * <code>name</code> is used in another attempt to load the library,
+ * this time ignoring the SWT version encoding scheme.
+ *
+ * @param name the name of the library to load
+ * @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 SWT 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 SWT libraries on 64-bit JVM"); //$NON-NLS-1$
+            }       
+        }
+    }
+
+    /* Compute the library name and mapped name */
+    String libName1, libName2, mappedName1, mappedName2;
+    if (mapName) {
+        String version = System.getProperty ("swt.version"); //$NON-NLS-1$
+        if (version == null) {
+            version = "" + MAJOR_VERSION; //$NON-NLS-1$
+            /* Force 3 digits in minor version number */
+            if (MINOR_VERSION < 10) {
+                version += "00"; //$NON-NLS-1$
+            } else {
+                if (MINOR_VERSION < 100) version += "0"; //$NON-NLS-1$
+            }
+            version += MINOR_VERSION;
+            /* No "r" until first revision */
+            if (REVISION > 0) version += "r" + REVISION; //$NON-NLS-1$
+        }
+        libName1 = name + "-" + Platform.PLATFORM + "-" + version;  //$NON-NLS-1$ //$NON-NLS-2$
+        libName2 = name + "-" + Platform.PLATFORM;  //$NON-NLS-1$
+        mappedName1 = System.mapLibraryName (libName1);
+        mappedName2 = System.mapLibraryName (libName2);
+    } else {
+        libName1 = libName2 = mappedName1 = mappedName2 = name;
+    }
+
+    /* Try loading library from swt library path */
+    String path = System.getProperty ("swt.library.path"); //$NON-NLS-1$
+    if (path != null) {
+        path = new File (path).getAbsolutePath ();
+        if (load (path + SEPARATOR + mappedName1)) return;
+        if (mapName && load (path + SEPARATOR + mappedName2)) return;
+    }
+
+    /* Try loading library from java library path */
+    if (load (libName1)) return;
+    if (mapName && load (libName2)) return;
+
+    /* Try loading library from the tmp directory if swt library path is not specified */
+    if (path == null) {
+        path = System.getProperty ("java.io.tmpdir"); //$NON-NLS-1$
+        path = new File (path).getAbsolutePath ();
+        if (load (path + SEPARATOR + mappedName1)) return;
+        if (mapName && load (path + SEPARATOR + mappedName2)) return;
+    }
+
+    /* Try extracting and loading library from jar */
+    if (path != null) {
+        if (extract (path + SEPARATOR + mappedName1, mappedName1)) return;
+        if (mapName && extract (path + SEPARATOR + mappedName2, mappedName2)) return;
+    }
+
+    /* Failed to find the library */
+    throw new UnsatisfiedLinkError ("no " + libName1 + " or " + libName2 + " in swt.library.path, java.library.path or the jar file"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+}
++/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Lock.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.Lock;
+
+import tango.core.Thread;
+import tango.core.sync.Mutex;
+import tango.core.sync.Condition;
+
+/**
+ * Instance of this represent a recursive monitor.
+ */
+public class Lock {
+    int count, waitCount;
+    Thread owner;
+    Mutex mutex;
+    Condition cond;
+
+    public this() {
+        mutex = new Mutex;
+        cond = new Condition(mutex);
+    }
+/**
+ * Locks the monitor and returns the lock count. If
+ * the lock is owned by another thread, wait until
+ * the lock is released.
+ *
+ * @return the lock count
+ */
+public int lock() {
+    synchronized (mutex) {
+        Thread current = Thread.getThis();
+        if (owner !is current) {
+            waitCount++;
+            while (count > 0) {
+                try {
+                    cond.wait();
+                } catch (SyncException e) {
+                    /* Wait forever, just like synchronized blocks */
+                }
+            }
+            --waitCount;
+            owner = current;
+        }
+        return ++count;
+    }
+}
+
+/**
+ * Unlocks the monitor. If the current thread is not
+ * the monitor owner, do nothing.
+ */
+public void unlock() {
+    synchronized (mutex) {
+        Thread current = Thread.getThis();
+        if (owner is current) {
+            if (--count is 0) {
+                owner = null;
+                if (waitCount > 0) cond.notifyAll();
+            }
+        }
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/Platform.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module org.eclipse.swt.internal.Platform;
+import java.lang.all;
+
+public class Platform {
+
+public static const String PLATFORM = "win32"; //$NON-NLS-1$
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SWTEventListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.SWTEventListener;
+
+import java.lang.all;
+
+/**
+ * This interface is the cross-platform version of the
+ * java.util.EventListener interface.
+ * <p>
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement SWTEventListener instead of java.util.EventListener.
+ * </p>
+ * <p>
+ * Note: java.util.EventListener is not part of CDC and CLDC.
+ * </p>
+ */
+public interface SWTEventListener : EventListener {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SWTEventObject.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.SWTEventObject;
+
+
+//import java.util.EventObject;
+import tango.core.Exception;
+import java.lang.all;
+
+/**
+ * This class is the cross-platform version of the
+ * java.util.EventObject class.
+ * <p>
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * extend SWTEventObject instead of java.util.EventObject.
+ * </p>
+ * <p>
+ * Note: java.util.EventObject is not part of CDC and CLDC.
+ * </p>
+ */
+public class SWTEventObject : EventObject {
+
+    //static final long serialVersionUID = 3258125873411470903L;
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param source the object which fired the event
+ */
+public this(Object source) {
+    super(source);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/SerializableCompatibility.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.SerializableCompatibility;
+
+
+//import java.io.Serializable;
+///PORTING_TYPE
+interface Serializable{}
+
+/**
+ * This interface is the cross-platform version of the
+ * java.io.Serializable interface.
+ * <p>
+ * It is part of our effort to provide support for both J2SE
+ * and J2ME platforms. Under this scheme, classes need to
+ * implement SerializableCompatibility instead of
+ * java.io.Serializable.
+ * </p>
+ * <p>
+ * Note: java.io.Serializable is not part of CLDC.
+ * </p>
+ */
+public interface SerializableCompatibility : Serializable {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/gdip/Gdip.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2331 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *    John Reimer <terminal.node@gmail.com>
+ *    Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+
+module org.eclipse.swt.internal.gdip.Gdip;
+
+import org.eclipse.swt.internal.gdip.native;
+
+import org.eclipse.swt.internal.Library;
+import org.eclipse.swt.internal.Platform;
+import org.eclipse.swt.internal.win32.WINTYPES;
+import org.eclipse.swt.internal.win32.WINAPI;
+import org.eclipse.swt.internal.win32.OS;
+version(TANGOSVN){
+import tango.sys.win32.UserGdi;
+}
+
+alias org.eclipse.swt.internal.gdip.native.GdiplusStartupInput  GdiplusStartupInput;
+alias org.eclipse.swt.internal.gdip.native.GdiplusStartupOutput GdiplusStartupOutput;
+
+/******************************************************************************
+
+    Gdip Class: provides access to the Gdi+ interface
+
+/*****************************************************************************/
+
+public class Gdip : Platform
+{
+    static this(){
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            loadLib_Gdip();
+        }
+    }
+    /**************************************************************************
+
+    **************************************************************************/
+
+private:
+
+    static FontFamily GenericSansSerifFontFamily = null;
+    static FontFamily GenericSerifFontFamily     = null;
+    static FontFamily GenericMonospaceFontFamily = null;
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    struct FontFamily_T
+    {
+        Handle  nativeFamily;
+        Status  lastResult;
+    }
+
+    struct StringFormat_T
+    {
+
+        StringFormat format;
+        Status  lastError;
+    }
+
+    static ubyte GenericTypographicStringFormatBuffer[StringFormat_T.sizeof] = 0;
+    static ubyte GenericDefaultStringFormatBuffer [StringFormat_T.sizeof] = 0;
+    static ubyte GenericSansSerifFontFamilyBuffer [FontFamily_T.sizeof] = 0;
+    static ubyte GenericSerifFontFamilyBuffer     [FontFamily_T.sizeof] = 0;
+    static ubyte GenericMonospaceFontFamilyBuffer [FontFamily_T.sizeof] = 0;
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+public:
+
+    alias GpPoint           Point;
+    alias GpPointF          PointF;
+    alias GpRect            Rect;
+    alias GpRectF           RectF;
+    alias GpBitmapData      BitmapData;
+    alias GpColorPalette    ColorPalette;
+    alias GpDrawImageAbort  DrawImageAbort;
+    alias GpColorMatrix     ColorMatrix;
+
+    alias GpFontFamily          FontFamily;
+    alias GpImage               Image;
+    alias GpBrush               Brush;
+    alias GpFont                Font;
+    alias GpFontCollection      FontCollection;
+    alias GpGraphics            Graphics;
+    alias GpGraphicsPath        GraphicsPath;
+    alias GpImageAttributes     ImageAttributes;
+    alias GpHatchBrush          HatchBrush;
+    alias GpLinearGradientBrush LinearGradientBrush;
+    alias GpMatrix              Matrix;
+    alias GpPen                 Pen;
+    alias GpRegion              Region;
+    alias GpSolidBrush          SolidBrush;
+    alias GpStringFormat        StringFormat;
+    alias GpTextureBrush        TextureBrush;
+    alias GpPath                Path;
+
+    alias Image  Bitmap;
+
+    alias  uint  ARGB;
+
+    alias org.eclipse.swt.internal.gdip.native.GdiplusStartupInput  GdiplusStartupInput;
+    alias org.eclipse.swt.internal.gdip.native.GdiplusStartupOutput GdiplusStartupOutput;
+
+    /**************************************************************************
+
+        Gdi+ Constants
+
+    **************************************************************************/
+
+    enum {
+        BrushTypeSolidColor = 0,
+        BrushTypeHatchFill = 1,
+        BrushTypeTextureFill = 2,
+        BrushTypePathGradient = 3,
+        BrushTypeLinearGradient = 4,
+        //  ColorAdjustTypeBitmap = 1,
+        ColorMatrixFlagsDefault = 0,
+        CombineModeReplace = 0,
+        CombineModeIntersect = 1,
+        CombineModeUnion = 2,
+        CombineModeXor = 3,
+        CombineModeExclude = 4,
+        CombineModeComplement = 5,
+        FillModeAlternate = 0,
+        FillModeWinding = 1,
+        DashCapFlat = 0,
+        DashCapRound = 2,
+        DashCapTriangle = 3,
+        DashStyleSolid = 0,
+        DashStyleDash = 1,
+        DashStyleDot = 2,
+        DashStyleDashDot = 3,
+        DashStyleDashDotDot = 4,
+        DashStyleCustom = 5,
+        FontStyleRegular = 0,
+        FontStyleBold = 1,
+        FontStyleItalic = 2,
+        FontStyleBoldItalic = 3,
+        FontStyleUnderline = 4,
+        FontStyleStrikeout = 8,
+        PaletteFlagsHasAlpha = 0x0001,
+        FlushIntentionFlush = 0,
+        FlushIntentionSync = 1,
+        HotkeyPrefixNone = 0,
+        HotkeyPrefixShow = 1,
+        HotkeyPrefixHide = 2,
+        LineJoinMiter = 0,
+        LineJoinBevel = 1,
+        LineJoinRound = 2,
+        LineCapFlat = 0,
+        LineCapSquare = 1,
+        LineCapRound = 2,
+        MatrixOrderPrepend = 0,
+        MatrixOrderAppend = 1,
+        QualityModeDefault = 0,
+        QualityModeLow = 1,
+        QualityModeHigh = 2,
+        InterpolationModeInvalid = -1,
+        InterpolationModeDefault = QualityModeDefault,
+        InterpolationModeLowQuality = QualityModeLow,
+        InterpolationModeHighQuality = QualityModeHigh,
+        InterpolationModeBilinear = QualityModeHigh + 1,
+        InterpolationModeBicubic = QualityModeHigh + 2,
+        InterpolationModeNearestNeighbor = QualityModeHigh + 3,
+        InterpolationModeHighQualityBilinear = QualityModeHigh + 4,
+        InterpolationModeHighQualityBicubic = QualityModeHigh + 5,
+        PathPointTypeStart = 0,
+        PathPointTypeLine = 1,
+        PathPointTypeBezier = 3,
+        PathPointTypePathTypeMask = 0x7,
+        PathPointTypePathDashMode = 0x10,
+        PathPointTypePathMarker = 0x20,
+        PathPointTypeCloseSubpath = 0x80,
+        PathPointTypeBezier3 = 3,
+        PixelFormatIndexed = 0x00010000,
+        PixelFormatGDI = 0x00020000,
+        PixelFormatAlpha = 0x00040000,
+        PixelFormatPAlpha = 0x00080000,
+        PixelFormatExtended = 0x00100000,
+        PixelFormatCanonical = 0x00200000,
+        PixelFormat1bppIndexed = (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI),
+        PixelFormat4bppIndexed = (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI),
+        PixelFormat8bppIndexed = (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI),
+        PixelFormat16bppGrayScale = (4 | (16 << 8) | PixelFormatExtended),
+        PixelFormat16bppRGB555 = (5 | (16 << 8) | PixelFormatGDI),
+        PixelFormat16bppRGB565 = (6 | (16 << 8) | PixelFormatGDI),
+        PixelFormat16bppARGB1555 = (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI),
+        PixelFormat24bppRGB = (8 | (24 << 8) | PixelFormatGDI),
+        PixelFormat32bppRGB = (9 | (32 << 8) | PixelFormatGDI),
+        PixelFormat32bppARGB = (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical),
+        PixelFormat32bppPARGB = (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI),
+        PixelFormat48bppRGB = (12 | (48 << 8) | PixelFormatExtended),
+        PixelFormat64bppARGB = (13 | (64 << 8) | PixelFormatAlpha  | PixelFormatCanonical | PixelFormatExtended),
+        PixelFormat64bppPARGB = (14 | (64 << 8) | PixelFormatAlpha  | PixelFormatPAlpha | PixelFormatExtended),
+        PixelFormatMax = 15,
+        PixelOffsetModeNone = QualityModeHigh + 1,
+        PixelOffsetModeHalf = QualityModeHigh + 2,
+        SmoothingModeInvalid = -1,
+        SmoothingModeDefault = QualityModeDefault,
+        SmoothingModeHighSpeed = QualityModeLow,
+        SmoothingModeHighQuality = QualityModeHigh,
+        SmoothingModeNone = 3,
+        SmoothingModeAntiAlias8x4 = 4,
+        SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4,
+        SmoothingModeAntiAlias8x8 = 5,
+        StringFormatFlagsDirectionRightToLeft = 0x00000001,
+        StringFormatFlagsDirectionVertical = 0x00000002,
+        StringFormatFlagsNoFitBlackBox = 0x00000004,
+        StringFormatFlagsDisplayFormatControl = 0x00000020,
+        StringFormatFlagsNoFontFallback = 0x00000400,
+        StringFormatFlagsMeasureTrailingSpaces = 0x00000800,
+        StringFormatFlagsNoWrap = 0x00001000,
+        StringFormatFlagsLineLimit = 0x00002000,
+        StringFormatFlagsNoClip = 0x00004000,
+        TextRenderingHintSystemDefault = 0,
+        TextRenderingHintSingleBitPerPixelGridFit = 1,
+        TextRenderingHintSingleBitPerPixel = 2,
+        TextRenderingHintAntiAliasGridFit = 3,
+        TextRenderingHintAntiAlias = 4,
+        TextRenderingHintClearTypeGridFit = 5,
+        //  UnitPixel = 2,
+        WrapModeTile = 0,
+        WrapModeTileFlipX = 1,
+        WrapModeTileFlipY = 2,
+        WrapModeTileFlipXY = 3,
+        WrapModeClamp = 4
+    }
+
+    enum
+    {
+        PenTypeSolidColor       = BrushTypeSolidColor,
+        PenTypeHatchFill        = BrushTypeHatchFill,
+        PenTypeTextureFill      = BrushTypeTextureFill,
+        PenTypePathGradient     = BrushTypePathGradient,
+        PenTypeLinearGradient   = BrushTypeLinearGradient,
+        PenTypeUnknown          = -1
+    }
+
+    enum
+    {
+        UnitWorld,      // 0 -- World coordinate (non-physical unit)
+        UnitDisplay,    // 1 -- Variable -- for PageTransform only
+        UnitPixel,      // 2 -- Each unit is one device pixel.
+        UnitPoint,      // 3 -- Each unit is a printer's point, or 1/72 inch.
+        UnitInch,       // 4 -- Each unit is 1 inch.
+        UnitDocument,   // 5 -- Each unit is 1/300 inch.
+        UnitMillimeter  // 6 -- Each unit is 1 millimeter.
+    }
+
+    enum
+    {
+        AliceBlue            = 0xFFF0F8FF,
+        AntiqueWhite         = 0xFFFAEBD7,
+        Aqua                 = 0xFF00FFFF,
+        Aquamarine           = 0xFF7FFFD4,
+        Azure                = 0xFFF0FFFF,
+        Beige                = 0xFFF5F5DC,
+        Bisque               = 0xFFFFE4C4,
+        Black                = 0xFF000000,
+        BlanchedAlmond       = 0xFFFFEBCD,
+        Blue                 = 0xFF0000FF,
+        BlueViolet           = 0xFF8A2BE2,
+        Brown                = 0xFFA52A2A,
+        BurlyWood            = 0xFFDEB887,
+        CadetBlue            = 0xFF5F9EA0,
+        Chartreuse           = 0xFF7FFF00,
+        Chocolate            = 0xFFD2691E,
+        Coral                = 0xFFFF7F50,
+        CornflowerBlue       = 0xFF6495ED,
+        Cornsilk             = 0xFFFFF8DC,
+        Crimson              = 0xFFDC143C,
+        Cyan                 = 0xFF00FFFF,
+        DarkBlue             = 0xFF00008B,
+        DarkCyan             = 0xFF008B8B,
+        DarkGoldenrod        = 0xFFB8860B,
+        DarkGray             = 0xFFA9A9A9,
+        DarkGreen            = 0xFF006400,
+        DarkKhaki            = 0xFFBDB76B,
+        DarkMagenta          = 0xFF8B008B,
+        DarkOliveGreen       = 0xFF556B2F,
+        DarkOrange           = 0xFFFF8C00,
+        DarkOrchid           = 0xFF9932CC,
+        DarkRed              = 0xFF8B0000,
+        DarkSalmon           = 0xFFE9967A,
+        DarkSeaGreen         = 0xFF8FBC8B,
+        DarkSlateBlue        = 0xFF483D8B,
+        DarkSlateGray        = 0xFF2F4F4F,
+        DarkTurquoise        = 0xFF00CED1,
+        DarkViolet           = 0xFF9400D3,
+        DeepPink             = 0xFFFF1493,
+        DeepSkyBlue          = 0xFF00BFFF,
+        DimGray              = 0xFF696969,
+        DodgerBlue           = 0xFF1E90FF,
+        Firebrick            = 0xFFB22222,
+        FloralWhite          = 0xFFFFFAF0,
+        ForestGreen          = 0xFF228B22,
+        Fuchsia              = 0xFFFF00FF,
+        Gainsboro            = 0xFFDCDCDC,
+        GhostWhite           = 0xFFF8F8FF,
+        Gold                 = 0xFFFFD700,
+        Goldenrod            = 0xFFDAA520,
+        Gray                 = 0xFF808080,
+        Green                = 0xFF008000,
+        GreenYellow          = 0xFFADFF2F,
+        Honeydew             = 0xFFF0FFF0,
+        HotPink              = 0xFFFF69B4,
+        IndianRed            = 0xFFCD5C5C,
+        Indigo               = 0xFF4B0082,
+        Ivory                = 0xFFFFFFF0,
+        Khaki                = 0xFFF0E68C,
+        Lavender             = 0xFFE6E6FA,
+        LavenderBlush        = 0xFFFFF0F5,
+        LawnGreen            = 0xFF7CFC00,
+        LemonChiffon         = 0xFFFFFACD,
+        LightBlue            = 0xFFADD8E6,
+        LightCoral           = 0xFFF08080,
+        LightCyan            = 0xFFE0FFFF,
+        LightGoldenrodYellow = 0xFFFAFAD2,
+        LightGray            = 0xFFD3D3D3,
+        LightGreen           = 0xFF90EE90,
+        LightPink            = 0xFFFFB6C1,
+        LightSalmon          = 0xFFFFA07A,
+        LightSeaGreen        = 0xFF20B2AA,
+        LightSkyBlue         = 0xFF87CEFA,
+        LightSlateGray       = 0xFF778899,
+        LightSteelBlue       = 0xFFB0C4DE,
+        LightYellow          = 0xFFFFFFE0,
+        Lime                 = 0xFF00FF00,
+        LimeGreen            = 0xFF32CD32,
+        Linen                = 0xFFFAF0E6,
+        Magenta              = 0xFFFF00FF,
+        Maroon               = 0xFF800000,
+        MediumAquamarine     = 0xFF66CDAA,
+        MediumBlue           = 0xFF0000CD,
+        MediumOrchid         = 0xFFBA55D3,
+        MediumPurple         = 0xFF9370DB,
+        MediumSeaGreen       = 0xFF3CB371,
+        MediumSlateBlue      = 0xFF7B68EE,
+        MediumSpringGreen    = 0xFF00FA9A,
+        MediumTurquoise      = 0xFF48D1CC,
+        MediumVioletRed      = 0xFFC71585,
+        MidnightBlue         = 0xFF191970,
+        MintCream            = 0xFFF5FFFA,
+        MistyRose            = 0xFFFFE4E1,
+        Moccasin             = 0xFFFFE4B5,
+        NavajoWhite          = 0xFFFFDEAD,
+        Navy                 = 0xFF000080,
+        OldLace              = 0xFFFDF5E6,
+        Olive                = 0xFF808000,
+        OliveDrab            = 0xFF6B8E23,
+        Orange               = 0xFFFFA500,
+        OrangeRed            = 0xFFFF4500,
+        Orchid               = 0xFFDA70D6,
+        PaleGoldenrod        = 0xFFEEE8AA,
+        PaleGreen            = 0xFF98FB98,
+        PaleTurquoise        = 0xFFAFEEEE,
+        PaleVioletRed        = 0xFFDB7093,
+        PapayaWhip           = 0xFFFFEFD5,
+        PeachPuff            = 0xFFFFDAB9,
+        Peru                 = 0xFFCD853F,
+        Pink                 = 0xFFFFC0CB,
+        Plum                 = 0xFFDDA0DD,
+        PowderBlue           = 0xFFB0E0E6,
+        Purple               = 0xFF800080,
+        Red                  = 0xFFFF0000,
+        RosyBrown            = 0xFFBC8F8F,
+        RoyalBlue            = 0xFF4169E1,
+        SaddleBrown          = 0xFF8B4513,
+        Salmon               = 0xFFFA8072,
+        SandyBrown           = 0xFFF4A460,
+        SeaGreen             = 0xFF2E8B57,
+        SeaShell             = 0xFFFFF5EE,
+        Sienna               = 0xFFA0522D,
+        Silver               = 0xFFC0C0C0,
+        SkyBlue              = 0xFF87CEEB,
+        SlateBlue            = 0xFF6A5ACD,
+        SlateGray            = 0xFF708090,
+        Snow                 = 0xFFFFFAFA,
+        SpringGreen          = 0xFF00FF7F,
+        SteelBlue            = 0xFF4682B4,
+        Tan                  = 0xFFD2B48C,
+        Teal                 = 0xFF008080,
+        Thistle              = 0xFFD8BFD8,
+        Tomato               = 0xFFFF6347,
+        Transparent          = 0x00FFFFFF,
+        Turquoise            = 0xFF40E0D0,
+        Violet               = 0xFFEE82EE,
+        Wheat                = 0xFFF5DEB3,
+        White                = 0xFFFFFFFF,
+        WhiteSmoke           = 0xFFF5F5F5,
+        Yellow               = 0xFFFFFF00,
+        YellowGreen          = 0xFF9ACD32
+    }
+
+    // Shift count and bit mask for A, R, G, B components
+
+    enum
+    {
+        AlphaShift  = 24,
+        RedShift    = 16,
+        GreenShift  = 8,
+        BlueShift   = 0
+    }
+
+    enum
+    {
+        AlphaMask   = 0xff000000,
+        RedMask     = 0x00ff0000,
+        GreenMask   = 0x0000ff00,
+        BlueMask    = 0x000000ff
+    }
+
+    enum
+    {
+        ColorAdjustTypeDefault,
+        ColorAdjustTypeBitmap,
+        ColorAdjustTypeBrush,
+        ColorAdjustTypePen,
+        ColorAdjustTypeText,
+        ColorAdjustTypeCount,
+        ColorAdjustTypeAny      // Reserved
+    }
+
+    static ARGB MakeARGB( ubyte a,
+                          ubyte r,
+                          ubyte g,
+                          ubyte b )
+    {
+        return ((cast(ARGB) (b) <<  Gdip.BlueShift) |
+                (cast(ARGB) (g) <<  Gdip.GreenShift) |
+                (cast(ARGB) (r) <<  Gdip.RedShift) |
+                (cast(ARGB) (a) <<  Gdip.AlphaShift));
+    }
+
+/**************************************************************************
+
+    Error Status control
+
+**************************************************************************/
+
+    private static Status SetStatus( Status status )
+    {
+        if (status != Status.OK)
+            return ( lastResult = status );
+        else
+            return status;
+    }
+
+    private static Status lastResult;
+
+/**************************************************************************
+
+    GDI+ Bitmap Wrap Interface
+
+**************************************************************************/
+
+public:
+
+    static void BitmapData_delete (BitmapData* bitmapdata)
+    {
+        delete bitmapdata;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static BitmapData* BitmapData_new()
+    {
+        return new BitmapData;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Bitmap_GetHBITMAP( Bitmap bitmap, ARGB colorBackground,
+                                        out HBITMAP hbmReturn                )
+    {
+        return SetStatus( GdipCreateHBITMAPFromBitmap( bitmap, hbmReturn,
+                                                       colorBackground ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Bitmap_GetHICON( Bitmap bitmap, out HICON hIconReturn)
+    {
+        return SetStatus( GdipCreateHICONFromBitmap( bitmap, hIconReturn ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Bitmap_LockBits( Bitmap bitmap, Rect* rect,
+                                      uint flags, PixelFormat pixelFormat,
+                                    BitmapData* lockedBitmapData        )
+    {
+        return SetStatus( GdipBitmapLockBits( bitmap, rect, flags,
+                                        pixelFormat, lockedBitmapData ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Bitmap_UnlockBits( Bitmap bitmap, BitmapData* lockedBitmapData )
+    {
+        return SetStatus( GdipBitmapUnlockBits( bitmap, lockedBitmapData ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Bitmap_delete( Bitmap bitmap )
+    {
+        GdipDisposeImage( bitmap );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Bitmap Bitmap_new( HICON hicon )
+    {
+        Bitmap bitmap;
+        Gdip.lastResult = GdipCreateBitmapFromHICON( hicon, bitmap );
+        return bitmap;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Bitmap Bitmap_new( HBITMAP hbm, HPALETTE hpal )
+    {
+        Bitmap bitmap;
+        Gdip.lastResult = GdipCreateBitmapFromHBITMAP( hbm, hpal, bitmap );
+        return bitmap;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Bitmap Bitmap_new( int width, int height, int stride,
+                       PixelFormat format, ubyte* scan0  )
+    {
+        Bitmap bitmap;
+        Gdip.lastResult = GdipCreateBitmapFromScan0( width, height, stride,
+                                                    format, scan0,
+                                                    bitmap );
+        return bitmap;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Bitmap Bitmap_new( wchar* filename, bool useIcm )
+    {
+        Bitmap bitmap;
+        if (useIcm) {
+            Gdip.lastResult = GdipCreateBitmapFromFileICM( filename, bitmap );
+        } else {
+            Gdip.lastResult = GdipCreateBitmapFromFile( filename, bitmap );
+        }
+        return bitmap;
+    }
+
+
+/**************************************************************************
+
+    Gdi+ Image Wrap Interface
+
+**************************************************************************/
+
+    static Status Image_GetLastStatus( Image image )
+    {
+        Status lastStatus = Gdip.lastResult;
+        Gdip.lastResult = Status.OK;
+        return lastStatus;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static PixelFormat Image_GetPixelFormat( Image image )
+    {
+        PixelFormat format;
+        SetStatus( GdipGetImagePixelFormat( image, format ) );
+        return format;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static uint Image_GetWidth( Image image )
+    {
+        uint width = 0;
+        SetStatus( GdipGetImageWidth( image, width ) );
+        return width;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static uint Image_GetHeight( Image image )
+    {
+        uint height = 0;
+        SetStatus( GdipGetImageHeight( image, height ) );
+        return height;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Image_GetPalette( Image image, ColorPalette* palette, int size )
+    {
+        return SetStatus( GdipGetImagePalette( image, palette, size ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Image_GetPaletteSize( Image image )
+    {
+        int size = 0;
+        SetStatus( GdipGetImagePaletteSize( image, size ) );
+        return size;
+    }
+
+/**************************************************************************
+
+    Gdi+ ImageAttributes Wrap Interface
+
+**************************************************************************/
+
+    static ImageAttributes ImageAttributes_new()
+    {
+        ImageAttributes ImageAttr = null;
+        Gdip.lastResult = GdipCreateImageAttributes( ImageAttr );
+        return ImageAttr;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void ImageAttributes_delete( ImageAttributes attrib )
+    {
+        GdipDisposeImageAttributes( attrib );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status ImageAttributes_SetWrapMode( ImageAttributes attrib,
+                                               WrapMode wrap,
+                                               ARGB color = Gdip.Black,
+                                               bool clamp = false )
+    {
+        return SetStatus(GdipSetImageAttributesWrapMode(
+                           attrib, wrap, color, clamp));
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status ImageAttributes_SetColorMatrix( ImageAttributes attrib,
+                                                  ref ColorMatrix matrix,
+                                               ColorMatrixFlag mode = Gdip.ColorMatrixFlagsDefault,
+                                               ColorAdjustType type = Gdip.ColorAdjustTypeDefault  )
+    {
+        return SetStatus( GdipSetImageAttributesColorMatrix(
+                                            attrib,
+                                            type,
+                                            true,
+                                            &matrix,
+                                            null,
+                                            mode));
+    }
+
+
+/**************************************************************************
+
+    Gdi+ Brush Wrap Interface
+
+**************************************************************************/
+
+    static Brush Brush_Clone( Brush brush )
+    {
+        Brush cloneBrush;
+        SetStatus( GdipCloneBrush( brush, cloneBrush ) );
+        return cloneBrush;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static BrushType Brush_GetType( Brush brush )
+    {
+        BrushType brushType = -1;
+        SetStatus( GdipGetBrushType( brush, brushType ) );
+        return brushType;
+    }
+
+/**************************************************************************
+
+    Gdi+ HatchedBrush Wrap Interface
+
+**************************************************************************/
+
+    static void HatchBrush_delete( HatchBrush brush )
+    {
+        GdipDeleteBrush(brush);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static HatchBrush HatchBrush_new( HatchStyle hatchStyle,
+                                      ARGB foreColor, ARGB backColor )
+    {
+        HatchBrush brush = null;
+
+        Gdip.lastResult = GdipCreateHatchBrush( hatchStyle,
+                                                foreColor,
+                                                backColor,
+                                                brush );
+        return brush;
+    }
+
+/**************************************************************************
+
+    Gdi+ LinearGradientBrush Wrap Interface
+
+**************************************************************************/
+
+    static LinearGradientBrush LinearGradientBrush_new( ref PointF point1, ref PointF point2,
+                                                        ARGB color1, ARGB color2 )
+    {
+        LinearGradientBrush brush = null;
+
+        lastResult = GdipCreateLineBrush(point1, point2,
+                                         color1, color2,
+                                         WrapModeTile, brush);
+        return brush;
+
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void LinearGradientBrush_delete( LinearGradientBrush brush )
+    {
+        GdipDeleteBrush(brush);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status LinearGradientBrush_SetInterpolationColors( LinearGradientBrush brush,
+                              ARGB* presetColors, float* blendPositions, int count )
+    {
+        if ((count <= 0) || presetColors is null)
+            return SetStatus(Status.InvalidParameter);
+
+        return SetStatus(GdipSetLinePresetBlend(brush, presetColors,
+                                                       blendPositions,
+                                                       count ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status LinearGradientBrush_SetWrapMode( LinearGradientBrush brush, WrapMode wrapMode )
+    {
+        return SetStatus(GdipSetLineWrapMode( brush, wrapMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status LinearGradientBrush_ResetTransform(LinearGradientBrush brush )
+    {
+        return SetStatus(GdipResetLineTransform(brush));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int LinearGradientBrush_ScaleTransform( LinearGradientBrush brush,
+                                                   float sx, float sy,
+                                                   MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus(GdipScaleLineTransform(brush, sx, sy, order));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int LinearGradientBrush_TranslateTransform( LinearGradientBrush brush,
+                                                       float dx, float dy,
+                                                       MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus(GdipTranslateLineTransform(brush, dx, dy, order));
+    }
+
+
+/**************************************************************************
+
+    GDI+ TextureBrush Wrap Interface
+
+**************************************************************************/
+
+    static TextureBrush TextureBrush_new( Image image, WrapMode wrapMode,
+                                          float dstX, float dstY,
+                                          float dstWidth, float dstHeight )
+    {
+        TextureBrush brush = null;
+
+        Gdip.lastResult = GdipCreateTexture2( image,
+                                              wrapMode,
+                                              dstX, dstY,
+                                              dstWidth, dstHeight,
+                                              brush  );
+        return brush;
+
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void TextureBrush_delete( TextureBrush brush )
+    {
+        GdipDeleteBrush( brush );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status TextureBrush_SetTransform( TextureBrush brush, Matrix matrix )
+    {
+        return SetStatus(GdipSetTextureTransform(brush, matrix));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status TextureBrush_ResetTransform( TextureBrush brush )
+    {
+                return SetStatus(GdipResetTextureTransform(brush));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status TextureBrush_ScaleTransform( TextureBrush brush,
+                                               float sx, float sy,
+                                               MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus(GdipScaleTextureTransform(brush, sx, sy, order));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status TextureBrush_TranslateTransform( TextureBrush brush,
+                                                   float dx, float dy,
+                                                   MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus(GdipTranslateTextureTransform(brush, dx, dy, order));
+    }
+
+
+/**************************************************************************
+
+    GDI+ Pen Wrap Interface
+
+**************************************************************************/
+
+    static SolidBrush SolidBrush_new( ARGB color )
+    {
+        SolidBrush brush = null;
+
+        Gdip.lastResult = GdipCreateSolidFill( color, brush );
+
+        return brush;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void SolidBrush_delete( SolidBrush brush )
+    {
+        GdipDeleteBrush(brush);
+    }
+
+/**************************************************************************
+
+    GDI+ Pen Wrap Interface
+
+**************************************************************************/
+
+    static Pen Pen_new( Brush brush, float width )
+    {
+        Unit unit = UnitWorld;
+        Pen pen = null;
+        Gdip.lastResult = GdipCreatePen2(brush, width, unit, pen);
+        return pen;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Pen_delete( Pen pen )
+    {
+        GdipDeletePen(pen);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static PenType Pen_GetPenType( Pen pen )
+    {
+       PenType type;
+       SetStatus(GdipGetPenFillType( pen, type ));
+       return type;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Brush Pen_GetBrush( Pen pen )
+    {
+        Brush brush;
+        SetStatus(GdipGetPenBrushFill(pen, brush));
+        return brush;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetBrush( Pen pen, Brush brush )
+    {
+        return SetStatus(GdipSetPenBrushFill(pen, brush));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetDashOffset( Pen pen, float dashOffset )
+    {
+        return SetStatus(GdipSetPenDashOffset(pen, dashOffset));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetDashPattern( Pen pen, float* dashArray, int count )
+    {
+        return SetStatus(GdipSetPenDashArray(pen, dashArray, count));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetDashStyle( Pen pen, DashStyle dashStyle )
+    {
+        return SetStatus(GdipSetPenDashStyle(pen, dashStyle));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetLineCap( Pen pen, LineCap startCap, LineCap endCap, DashCap dashCap )
+    {
+        return SetStatus(GdipSetPenLineCap197819(pen, startCap, endCap, dashCap));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetLineJoin( Pen pen, LineJoin lineJoin )
+    {
+        return SetStatus(GdipSetPenLineJoin(pen, lineJoin));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetMiterLimit( Pen pen, float miterLimit )
+    {
+        return SetStatus(GdipSetPenMiterLimit(pen, miterLimit));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Pen_SetWidth( Pen pen, float width )
+    {
+        return SetStatus(GdipSetPenWidth(pen, width));
+    }
+
+
+/**************************************************************************
+
+    GDI+ Color Wrap Interface
+
+**************************************************************************/
+
+    // The following two color functions appear to serve little use
+    // and should probably be replaced with an actual ARGB type assignment
+    // wherever they are used.
+
+    // I'm guessing they are being used in case of future adoption of the
+    // gdi+ Color class functionality in Swt.
+
+    static void Color_delete( ARGB color )
+    {
+        // no op
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static ARGB Color_new( ARGB color )
+    {
+        return color;
+    }
+
+/**************************************************************************
+
+    GDI+ FontFamily Wrap Interface
+
+**************************************************************************/
+
+    static int FontFamily_GetFamilyName( FontFamily family, wchar* name, int language )
+    {
+        return SetStatus( GdipGetFamilyName( family, name, language ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    // CAUTION:  Next two methods need to be tested - JJR
+
+    static void FontFamily_delete( FontFamily family )
+    {
+        if (family !is null)
+            GdipDeleteFontFamily( family );
+    }
+
+    /**************************************************************************
+
+        FontFamily_new() returns a null because flat Gdi+ FontFamily is
+        internally assigned a null until it is associated with a font
+        (see gdi+ C++ wrapper for details).
+
+    **************************************************************************/
+
+    static FontFamily FontFamily_new()
+    {
+        return null;
+    }
+
+/**************************************************************************
+
+    GDI+ Font Wrap Interface
+
+**************************************************************************/
+
+
+    static int Font_GetFamily( Font font, ref FontFamily family )
+    {
+        return SetStatus( GdipGetFamily( font, family ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static float Font_GetSize( Font font )
+    {
+        float  size;
+        SetStatus( GdipGetFontSize( font, size ) );
+        return size;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Font_GetStyle( Font font )
+    {
+        int style;
+        SetStatus( GdipGetFontStyle( font, style ) );
+        return style;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static bool Font_IsAvailable( Font font )
+    {
+        return (font !is null);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Font_delete( Font font )
+    {
+        GdipDeleteFont( font );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Font Font_new( HDC hdc, HFONT hfont )
+    {
+        Font font = null;
+
+        if (hfont is null) {
+            Gdip.lastResult = GdipCreateFontFromDC( hdc, font );
+        } else {
+            LOGFONTA logfont;
+            if (GetObjectA( hfont, LOGFONTA.sizeof, &logfont ))
+                Gdip.lastResult = GdipCreateFontFromLogfontA(hdc, logfont, font);
+            else
+                Gdip.lastResult = GdipCreateFontFromDC(hdc, font);
+        }
+
+        return font;
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Font Font_new( wchar* familyName, float emSize, int style, uint unit,
+                          FontCollection fontCollection  )
+    {
+        Font        nativeFont = null;
+        FontFamily  nativeFamily = null;
+
+        Gdip.lastResult = GdipCreateFontFamilyFromName( familyName, fontCollection, nativeFamily );
+
+        if (Gdip.lastResult != Status.OK)
+        {
+            if (GenericSansSerifFontFamily != null)
+            {
+                nativeFamily = GenericSansSerifFontFamily;
+            }
+            //TODO: access buffer via "ptr" property?
+            GenericSansSerifFontFamily = cast(FontFamily) GenericSansSerifFontFamilyBuffer;
+            Gdip.lastResult = GdipGetGenericFontFamilySansSerif( GenericSansSerifFontFamily );
+
+            nativeFamily = GenericSansSerifFontFamily;
+
+            if (Gdip.lastResult != Status.OK)
+                return null;
+        }
+
+        Gdip.lastResult = GdipCreateFont( nativeFamily, emSize, style, unit, nativeFont );
+
+        if (Gdip.lastResult != Status.OK)
+        {
+            if (GenericSansSerifFontFamily != null)
+            {
+                nativeFamily = GenericSansSerifFontFamily;
+            }
+
+            GenericSansSerifFontFamily = cast(FontFamily) GenericSansSerifFontFamilyBuffer;
+            Gdip.lastResult = GdipGetGenericFontFamilySansSerif( GenericSansSerifFontFamily );
+
+            nativeFamily = GenericSansSerifFontFamily;
+
+            if (Gdip.lastResult != Status.OK)
+                return null;
+
+            Gdip.lastResult = GdipCreateFont( nativeFamily, emSize, style,
+                                              unit, nativeFont  );
+        }
+
+        return nativeFont;
+    }
+
+/**************************************************************************
+
+    GDI+ Startup and Shutdown Wrap Interface
+
+**************************************************************************/
+
+    alias .GdiplusShutdown GdiplusShutdown;
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    alias .GdiplusStartup GdiplusStartup;
+
+
+/**************************************************************************
+
+    GDI+ Graphics Path Wrap Interface
+
+**************************************************************************/
+
+    static Path GraphicsPath_new( FillMode fillMode = FillModeAlternate )
+    {
+        Path path = null;
+        lastResult = GdipCreatePath(fillMode, path);
+        return path;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Path GraphicsPath_new( Point* points, ubyte* types, int count,
+                                  FillMode fillMode = FillModeAlternate )
+    {
+        Path path = null;
+        lastResult = GdipCreatePath2I(points, types, count, fillMode, path);
+        return path;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void GraphicsPath_delete( Path path )
+    {
+        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,
+                                           float width, float height,
+                                           float startAngle, float sweepAngle )
+    {
+        return SetStatus( GdipAddPathArc( path, x, y, width,
+                                          height, startAngle, sweepAngle) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddArc( Path path, int x, int y,
+                                                  int width, int height,
+                                                  float startAngle, float sweepAngle )
+    {
+        return SetStatus(GdipAddPathArcI(   path,
+                                            x,
+                                            y,
+                                            width,
+                                            height,
+                                            startAngle,
+                                            sweepAngle));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddBezier( Path path, float x1, float y1,
+                                                     float x2, float y2,
+                                                     float x3, float y3,
+                                                     float x4, float y4 )
+    {
+        return SetStatus( GdipAddPathBezier( path, x1, y1, x2, y2,
+                                                   x3, y3, x4, y4 ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddLine( Path path, float x1, float y1,
+                                                   float x2, float y2 )
+    {
+        return SetStatus( GdipAddPathLine( path, x1, y1, x2, y2 ) );
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddPath( Path path, Path addingPath, bool connect )
+    {
+        return SetStatus( GdipAddPathPath( path, addingPath, connect ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddRectangle( Path path, RectF rect )
+    {
+        return SetStatus( GdipAddPathRectangle( path,
+                                                rect.X,
+                                                rect.Y,
+                                                rect.Width,
+                                                rect.Height ) );
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_AddString( Path path, wchar* string,
+                                          int length, FontFamily family,
+                                          int style, float emSize,
+                                          ref PointF origin, StringFormat format )
+    {
+        RectF rect = { origin.X, origin.Y, 0.0f, 0.0f };
+
+        return SetStatus( GdipAddPathString( path, string, length, family,
+                                             style, emSize, rect, format ) );
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_CloseFigure( Path path )
+    {
+        return SetStatus( GdipClosePathFigure(path) );
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_Flatten( Path path, Matrix matrix, float flatness )
+    {
+        return SetStatus( GdipFlattenPath( path, matrix, flatness ) );
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_GetBounds( Path path, ref RectF bounds,
+                                          Matrix matrix, Pen pen )
+    {
+
+        return SetStatus( GdipGetPathWorldBounds( path, bounds,
+                                                  matrix, pen ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_GetLastPoint( Path path, out PointF lastPoint )
+    {
+        return SetStatus( GdipGetPathLastPoint( path, lastPoint) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_GetPathTypes( Path path, byte* types, int count )
+    {
+        return SetStatus( GdipGetPathTypes( path, types, count) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status GraphicsPath_GetPathPoints( Path path, PointF* points, int count)
+    {
+        return SetStatus(GdipGetPathPoints(path, points, count));
+    }
+
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int GraphicsPath_GetPointCount( Path path )
+    {
+        int count = 0;
+
+        SetStatus(GdipGetPointCount(path, count));
+
+        return count;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static bool GraphicsPath_IsOutlineVisible( Path path,
+                                float x, float y, Pen pen, Graphics g = null )
+    {
+        int booln = false;
+        SetStatus( GdipIsOutlineVisiblePathPoint( path, x, y,
+                                                  pen, g,
+                                                  booln )  );
+        return (booln == true);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static bool GraphicsPath_IsVisible( Path path, float x, float y, Graphics graphics )
+    {
+        int booln = false;
+
+        SetStatus(GdipIsVisiblePathPoint(path, x, y, graphics, booln));
+
+        return (booln == true);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int GraphicsPath_SetFillMode( Path path, FillMode fillmode )
+    {
+        return SetStatus( GdipSetPathFillMode(path, fillmode) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int GraphicsPath_StartFigure( Path path )
+    {
+        return SetStatus(GdipStartPathFigure(path));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int GraphicsPath_Transform( Path path, Matrix matrix )
+    {
+        if(matrix)
+            return SetStatus( GdipTransformPath(path, matrix));
+        else
+            return Status.OK;
+
+    }
+
+
+/**************************************************************************
+
+    GDI+ Graphics Wrap Interface
+
+**************************************************************************/
+
+    static Graphics Graphics_new( HDC hdc )
+    {
+
+        Graphics graphics = null;
+
+        Gdip.lastResult = GdipCreateFromHDC(hdc, graphics);
+
+        return graphics;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Graphics_delete( Graphics graphics)
+    {
+        GdipDeleteGraphics(graphics);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawArc( Graphics graphics, Pen pen,
+                                    int x, int y, int width, int height,
+                                    float startAngle, float sweepAngle )
+    {
+        return SetStatus(GdipDrawArcI(graphics, pen,
+                                      x, y, width, height,
+                                      startAngle, sweepAngle));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawEllipse(Graphics graphics, Pen pen,
+                                       int x, int y,
+                                       int width, int height)
+    {
+        return SetStatus(GdipDrawEllipseI(graphics, pen,
+                                          x, y, width, height));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawImage(Graphics graphics, Image image, int x, int y)
+    {
+        return SetStatus(GdipDrawImageI(graphics,image, x, y));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawImage( Graphics graphics, Image image, ref Rect destRect,
+                                        int srcx, int srcy, int srcwidth, int srcheight,
+                                        Unit srcUnit, ImageAttributes imageAttributes = null,
+                                        DrawImageAbort callback = null, void* callbackData = null )
+    {
+        return SetStatus(GdipDrawImageRectRectI(graphics, image,
+                                                destRect.X, destRect.Y,
+                                                destRect.Width, destRect.Height,
+                                                srcx, srcy,
+                                                srcwidth, srcheight,
+                                                srcUnit, imageAttributes,
+                                                callback, callbackData));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawLine( Graphics graphics, Pen pen,
+                                     int x1, int y1, int x2, int y2 )
+    {
+        return SetStatus(GdipDrawLineI(graphics, pen, x1, y1, x2, y2));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawLines( Graphics graphics, Pen pen, Point* points, uint count )
+    {
+        return SetStatus(GdipDrawLinesI(graphics, pen, points, count));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawPath( Graphics graphics, Pen pen, Path path )
+    {
+        return SetStatus(GdipDrawPath(graphics, pen, path));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawPolygon(Graphics graphics, Pen pen, Point* points, uint count )
+    {
+        return SetStatus(GdipDrawPolygonI(graphics, pen, points, count));
+
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawRectangle( Graphics graphics, Pen pen, int x, int y,
+                                                             int width, int height )
+    {
+        return SetStatus(GdipDrawRectangleI(graphics, pen, x, y, width, height));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawString( Graphics graphics, wchar* string, int length,
+                                       Font font, ref PointF origin, Brush brush  )
+    {
+        RectF rect = {origin.X, origin.Y, 0.0f, 0.0f};
+
+        return SetStatus(GdipDrawString(graphics,string,length, font, rect, null, brush));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_DrawString( Graphics graphics, wchar* string, int length,
+                                       Font font, ref PointF origin,
+                                       StringFormat format, Brush brush )
+    {
+        RectF rect = { origin.X, origin.Y, 0.0f, 0.0f };
+
+        return SetStatus(GdipDrawString(graphics, string, length, font, rect, format, brush));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_FillEllipse( Graphics graphics, Brush brush,
+                                        int x, int y,
+                                        int width, int height )
+    {
+        return SetStatus(GdipFillEllipseI(graphics, brush, x,y, width, height));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_FillPath( Graphics graphics, Brush brush, Path path )
+    {
+        return SetStatus(GdipFillPath(graphics,brush,path));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Graphics_Flush( Graphics graphics, FlushIntention intention = FlushIntentionFlush )
+    {
+        GdipFlush(graphics, intention);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_FillPie( Graphics graphics, Brush brush,
+                                    int x, int y,
+                                    int width, int height,
+                                    float startAngle, float sweepAngle )
+    {
+        return SetStatus(GdipFillPieI(graphics, brush,
+                                      x, y, width, height,
+                                      startAngle, sweepAngle));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_FillPolygon( Graphics graphics, Brush brush,
+                                        Point* points, int count, FillMode fillMode )
+    {
+        return SetStatus(GdipFillPolygonI(graphics, brush, points, count, fillMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_FillRectangle( Graphics graphics, Brush brush,
+                                          int x, int y,
+                                          int width, int height )
+    {
+        return SetStatus(GdipFillRectangleI(graphics, brush,
+                                            x, y,
+                                            width, height));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_GetClipBounds( Graphics graphics, out RectF rect )
+    {
+        return SetStatus(GdipGetClipBounds(graphics, rect));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_GetClipBounds( Graphics graphics, out Rect rect )
+    {
+        return SetStatus(GdipGetClipBoundsI(graphics, rect));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_GetClip( Graphics graphics, Region region )
+    {
+        return SetStatus(GdipGetClip(graphics, region));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static HDC Graphics_GetHDC(Graphics graphics)
+    {
+        HDC hdc = null;
+
+        SetStatus(GdipGetDC(graphics, hdc));
+
+        return hdc;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Graphics_ReleaseHDC(Graphics graphics, HDC hdc)
+    {
+        SetStatus(GdipReleaseDC(graphics, hdc));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static InterpolationMode Graphics_GetInterpolationMode( Graphics graphics )
+    {
+        InterpolationMode mode = InterpolationModeInvalid;
+
+        SetStatus(GdipGetInterpolationMode(graphics, mode));
+
+        return mode;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static SmoothingMode Graphics_GetSmoothingMode( Graphics graphics )
+    {
+        SmoothingMode smoothingMode = SmoothingModeInvalid;
+
+        SetStatus(GdipGetSmoothingMode(graphics, smoothingMode));
+
+        return smoothingMode;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static TextRenderingHint Graphics_GetTextRenderingHint( Graphics graphics )
+    {
+        TextRenderingHint hint;
+
+        SetStatus(GdipGetTextRenderingHint(graphics, hint));
+
+        return hint;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_GetTransform( Graphics graphics, Matrix matrix )
+    {
+        return SetStatus(GdipGetWorldTransform(graphics, matrix));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_GetVisibleClipBounds( Graphics graphics, out Rect rect )
+    {
+
+        return SetStatus(GdipGetVisibleClipBoundsI(graphics, rect));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_MeasureString( Graphics graphics, wchar* string, int length,
+                                          Font font, ref PointF origin,
+                                          ref RectF boundingBox )
+    {
+        RectF rect = {origin.X, origin.Y, 0.0f, 0.0f};
+
+        return SetStatus(GdipMeasureString(
+            graphics,
+            string,
+            length,
+            font,
+            rect,
+            null,
+            boundingBox,
+            null,
+            null
+        ));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_MeasureString( Graphics graphics, wchar* string, int length,
+                                          Font font, ref PointF origin,
+                                          StringFormat format, ref RectF boundingBox )
+    {
+        RectF rect = {origin.X, origin.Y, 0.0f, 0.0f};
+
+        return SetStatus(GdipMeasureString(
+            graphics,
+            string,
+            length,
+            font,
+            rect,
+            format,
+            boundingBox,
+            null,
+            null
+        ));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_ResetClip( Graphics graphics )
+    {
+        return SetStatus(GdipResetClip(graphics));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_Restore( Graphics graphics, GraphicsState gstate )
+    {
+        return SetStatus(GdipRestoreGraphics(graphics, gstate));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static GraphicsState Graphics_Save( Graphics graphics )
+    {
+        GraphicsState gstate;
+
+        SetStatus(GdipSaveGraphics(graphics, gstate));
+
+        return gstate;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_ScaleTransform( Graphics graphics, float sx, float sy,
+                                           MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus(GdipScaleWorldTransform(graphics, sx, sy, order));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetClip( Graphics graphics, HRGN hrgn,
+                                    CombineMode combineMode = CombineModeReplace )
+    {
+        return SetStatus(GdipSetClipHrgn(graphics, hrgn, combineMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetClipPath( Graphics graphics, Path path,
+                                    CombineMode combineMode = CombineModeReplace )
+    {
+        return SetStatus(GdipSetClipPath(graphics, path, combineMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetClip( Graphics graphics, ref Rect rect,
+                                    CombineMode combineMode = CombineModeReplace )
+    {
+       return SetStatus( GdipSetClipRectI( graphics,
+                                                      rect.X, rect.Y,
+                                                      rect.Width, rect.Height,
+                                                      combineMode));
+    }
+
+    //static Status Graphics_SetClipPath(Graphics graphics, GraphicsPath path ){
+    //    return SetStatus( SetClipPath( graphics, path ));
+    //}
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetCompositingQuality( Graphics graphics,
+                                                  CompositingQuality compositingQuality )
+    {
+        return SetStatus(GdipSetCompositingQuality(graphics, compositingQuality));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetPageUnit( Graphics graphics, Unit unit )
+    {
+        return SetStatus(GdipSetPageUnit(graphics, unit));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetPixelOffsetMode( Graphics graphics,
+                                               PixelOffsetMode pixelOffsetMode )
+    {
+        return SetStatus(GdipSetPixelOffsetMode(graphics, pixelOffsetMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetSmoothingMode( Graphics graphics,
+                                             SmoothingMode smoothingMode )
+    {
+        return SetStatus(GdipSetSmoothingMode(graphics, smoothingMode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetTransform( Graphics graphics, Matrix matrix )
+    {
+        return SetStatus(GdipSetWorldTransform(graphics, matrix));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetInterpolationMode( Graphics graphics,
+                                                 InterpolationMode mode )
+    {
+        return SetStatus(GdipSetInterpolationMode(graphics, mode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_SetTextRenderingHint( Graphics graphics, TextRenderingHint mode )
+    {
+        return SetStatus(GdipSetTextRenderingHint(graphics, mode));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Graphics_TranslateTransform( Graphics graphics, float dx, float dy,
+                                               MatrixOrder order = MatrixOrderPrepend )
+    {
+                return SetStatus(GdipTranslateWorldTransform(graphics, dx, dy, order));
+    }
+
+/**************************************************************************
+
+    Gdi+ Region Wrap Interface
+
+**************************************************************************/
+
+    static Region Region_new( HRGN hRgn )
+    {
+        Region region = null;
+
+        Gdip.lastResult = GdipCreateRegionHrgn( hRgn, region);
+
+        return region;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Region Region_new()
+    {
+        Region region = null;
+
+        Gdip.lastResult = GdipCreateRegion(region);
+
+        return region;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Region_delete( Region region )
+    {
+        GdipDeleteRegion(region);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static HRGN Region_GetHRGN( Region region, Graphics graphics )
+    {
+        HRGN hrgn;
+
+        SetStatus(GdipGetRegionHRgn(region, graphics, hrgn));
+
+        return hrgn;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Region_IsInfinite( Region region, Graphics graphics )
+    {
+        int booln = false;
+
+        SetStatus(GdipIsInfiniteRegion(region, graphics, booln));
+
+        return booln;
+    }
+
+/**************************************************************************
+
+    Gdi+ Matrix Wrap Interface
+
+**************************************************************************/
+
+    static Matrix Matrix_new(float m11, float m12, float m21, float m22, float dx, float dy)
+    {
+        Matrix matrix = null;
+
+        Gdip.lastResult = GdipCreateMatrix2(m11, m12, m21, m22, dx, dy, matrix);
+
+        return matrix;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static void Matrix_delete( Matrix matrix )
+    {
+        GdipDeleteMatrix( matrix );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_GetElements( Matrix matrix, float* m )
+    {
+        return SetStatus( GdipGetMatrixElements( matrix, m ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_Invert( Matrix matrix )
+    {
+        return SetStatus( GdipInvertMatrix( matrix ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int Matrix_IsIdentity( Matrix matrix )
+    {
+        int result = false;
+
+        SetStatus(GdipIsMatrixIdentity( matrix, result ) );
+
+        return result;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_Multiply( Matrix nativeMatrix, Matrix matrix,
+                                   MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus( GdipMultiplyMatrix( nativeMatrix, matrix, order) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int  Matrix_Rotate( Matrix matrix, float angle, MatrixOrder order = MatrixOrderPrepend )
+    {
+        return SetStatus( GdipRotateMatrix( matrix, angle, order ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_Scale( Matrix matrix, float scaleX , float scaleY,
+                                MatrixOrder order = MatrixOrderPrepend )
+    {
+        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));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_SetElements( Matrix matrix, float m11, float m12,
+                                                     float m21, float m22,
+                                                     float dx, float dy     )
+    {
+        return SetStatus( GdipSetMatrixElements( matrix, m11, m12, m21, m22, dx, dy ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_TransformPoints( Matrix matrix, PointF* pts, int count = 1 )
+    {
+        return SetStatus( GdipTransformMatrixPoints( matrix, pts, count ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static Status Matrix_Translate( Matrix matrix, float offsetX, float offsetY,
+                                    MatrixOrder order = MatrixOrderPrepend      )
+    {
+        return SetStatus( GdipTranslateMatrix( matrix, offsetX, offsetY, order ) );
+    }
+
+
+/**************************************************************************
+
+    Gdi+ StringFromat Wrap Interface
+
+**************************************************************************/
+
+    static void StringFormat_delete( StringFormat format )
+    {
+        GdipDeleteStringFormat( format );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static StringFormat StringFormat_Clone( StringFormat format )
+    {
+        StringFormat clonedStringFormat = null;
+
+        Gdip.lastResult = GdipCloneStringFormat( format, clonedStringFormat );
+
+        if (Gdip.lastResult == Status.OK)
+            return clonedStringFormat;
+        else
+            return null;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static StringFormat StringFormat_GenericDefault()
+    {
+        // TODO:  do we need to access buffer through "ptr" property?
+        StringFormat genericDefaultStringFormat =
+            cast(StringFormat) GenericDefaultStringFormatBuffer;
+
+        Gdip.lastResult = GdipStringFormatGetGenericDefault( genericDefaultStringFormat );
+
+        return genericDefaultStringFormat;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static StringFormat StringFormat_GenericTypographic()
+    {
+        // TODO:  do we need to access buffer through "ptr" property?
+        StringFormat genericTypographicStringFormat =
+            cast(StringFormat) GenericTypographicStringFormatBuffer;
+
+        Gdip.lastResult = GdipStringFormatGetGenericTypographic(
+            genericTypographicStringFormat );
+
+        return genericTypographicStringFormat;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    // TODO: StringFormat class in Gdi+ maintains it's own lastError status
+    // Right now all lastError and lastResult status for org.eclipse.swt's gdip objects
+    // are combined in one Gdip SetStatus method and lastResult member.
+    // Consider if there is a need to maintain per object lastResult
+    // monitoring.  For now, this /should/ work as is.
+
+    static int StringFormat_GetFormatFlags(StringFormat format)
+    {
+        int flags;
+        SetStatus( GdipGetStringFormatFlags(format, flags));
+        return flags;
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int StringFormat_SetHotkeyPrefix( StringFormat format, int hotkeyPrefix )
+    {
+       return SetStatus(GdipSetStringFormatHotkeyPrefix(format, hotkeyPrefix));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int StringFormat_SetFormatFlags( StringFormat format, int flags )
+    {
+       return SetStatus(GdipSetStringFormatFlags(format, flags));
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    static int StringFormat_SetTabStops( StringFormat format, float firstTabOffset,
+                                         int count, float* tabStops)
+    {
+        return SetStatus( GdipSetStringFormatTabStops( format, firstTabOffset,
+                                                       count, tabStops ) );
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/gdip/native.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1714 @@
+/******************************************************************************
+
+  module:
+
+  Based on D version created by John Chapman for the Juno Project
+    see: www.dsource.org/projects/juno
+
+  Changes and Additions for SWT:
+    John Reimer <terminal.node@gmail.com>
+
+******************************************************************************/
+
+module org.eclipse.swt.internal.gdip.native;
+
+import org.eclipse.swt.internal.win32.WINTYPES;
+import tango.sys.SharedLib : SharedLib;
+import java.lang.all;
+
+extern(Windows):
+
+/******************************************************************************
+
+
+******************************************************************************/
+
+enum DebugEventLevel {
+  Fatal,
+  Warning
+}
+
+alias void  function(DebugEventLevel level, char* message) DebugEventProc;
+
+alias int   function(out uint token)    NotificationHookProc;
+alias void  function(uint token)        NotificationUnhookProc;
+
+
+/******************************************************************************
+
+
+******************************************************************************/
+
+
+struct GdiplusStartupInput {
+  uint GdiplusVersion;
+  DebugEventProc DebugEventCallback;
+  int SuppressBackgroundThread;
+  int SuppressExternalCodecs;
+}
+
+struct GdiplusStartupOutput {
+  NotificationHookProc NotificationHook;
+  NotificationUnhookProc NotificationUnhook;
+}
+
+struct GpBitmapData {
+  int Width;
+  int Height;
+  int Stride;
+  int PixelFormat;
+  void* Scan0;
+  int Reserved;
+}
+
+struct GpColorMatrix {
+  float[5][5] m;
+}
+
+struct GpPropertyItem {
+  int id;
+  int length;
+  short type;
+  void* value;
+}
+
+struct GpColorPalette {
+  int Flags;
+  int Count;
+  int[1] Entries;
+}
+
+public struct GpRectF {
+    public float X;
+    public float Y;
+    public float Width;
+    public float Height;
+}
+
+public struct GpRect {
+    public int X;
+    public int Y;
+    public int Width;
+    public int Height;
+}
+public struct GpPoint {
+    public int X;
+    public int Y;
+}
+public struct GpPointF {
+    public float X;
+    public float Y;
+}
+
+alias int function(void*) GpDrawImageAbort;
+alias GpDrawImageAbort GpGetThumbnailImageAbort;
+
+/******************************************************************************
+
+
+******************************************************************************/
+
+enum Status {
+  OK,
+  GenericError,
+  InvalidParameter,
+  OutOfMemory,
+  ObjectBusy,
+  InsufficientBuffer,
+  NotImplemented,
+  Win32Error,
+  WrongState,
+  Aborted,
+  FileNotFound,
+  ValueOverflow,
+  AccessDenied,
+  UnknownImageFormat,
+  FontFamilyNotFound,
+  FontStyleNotFound,
+  NotTrueTypeFont,
+  UnsupportedGdiplusVersion,
+  GdiplusNotInitialized,
+  PropertyNotFound,
+  PropertyNotSupported
+}
+
+/**************************************************************************
+
+	Opaque types managed by Gdi+
+
+**************************************************************************/
+typedef GpImage  GpBitmap;
+
+// alias   uint   ARGB;
+typedef Handle GpFontFamily;
+typedef Handle GpImage;
+typedef Handle GpBrush;
+typedef Handle GpFont;
+typedef Handle GpFontCollection;
+typedef Handle GpGraphics;
+typedef Handle GpGraphicsPath;
+typedef Handle GpImageAttributes;
+typedef Handle GpHatchBrush;
+typedef Handle GpLinearGradientBrush;
+typedef Handle GpMatrix;
+typedef Handle GpPen;
+typedef Handle GpRegion;
+typedef Handle GpSolidBrush;
+typedef Handle GpStringFormat;
+typedef Handle GpTextureBrush;
+typedef Handle GpPath;
+
+alias void* Handle;
+
+alias int BrushType;
+alias int CombineMode;
+alias int FlushIntention;
+alias int MatrixOrder;
+alias int GraphicsUnit;
+alias int QualityMode;
+alias int SmoothingMode;
+alias int InterpolationMode;
+alias int CompositingMode;
+alias int CompositingQuality;
+alias int PixelOffsetMode;
+alias int PixelFormat;
+alias int RotateFlipType;
+alias int CoordinateSpace;
+alias int WarpMode;
+alias int WrapMode;
+alias int FillMode;
+alias int LineJoin;
+alias int LineCap;
+alias int DashCap;
+alias int DashStyle;
+alias int PenAlignment;
+alias int ColorMatrixFlag;
+alias int ColorAdjustType;
+alias int ColorChannelFlag;
+alias int ImageLockMode;
+alias int ImageCodecFlags;
+alias int EncoderParameterValueType;
+alias int GenericFontFamilies;
+alias int FontStyle;
+alias int HatchStyle;
+alias int StringFormatFlags;
+alias int StringAlignment;
+alias int StringTrimming;
+alias int TextRenderingHint;
+alias int PenType;
+alias int LinearGradientMode;
+alias int KnownColor;
+alias int Unit;
+
+alias uint GraphicsState;
+
+/******************************************************************************
+
+	Flat GDI+ Exports (C Interface)
+
+******************************************************************************/
+
+extern (Windows):
+
+version( STATIC_GDIPLUS ){
+Status GdiplusStartup( uint* token, GdiplusStartupInput* input, GdiplusStartupOutput* output);
+void   GdiplusShutdown(uint token);
+Status GdipCreateFromHDC(Handle hdc, out Handle graphics);
+Status GdipCreateFromHDC2(Handle hdc, Handle hDevice, out Handle graphics);
+Status GdipCreateFromHWND(Handle hwnd, out Handle graphics);
+Status GdipGetImageGraphicsContext(Handle image, out Handle graphics);
+Status GdipDeleteGraphics(Handle graphics);
+Status GdipGetDC(Handle graphics, out Handle hdc);
+Status GdipReleaseDC(Handle graphics, Handle hdc);
+Status GdipSetClipGraphics(Handle graphics, Handle srcgraphics, CombineMode combineMode);
+Status GdipSetClipRectI(Handle graphics, int x, int y, int width, int height, CombineMode combineMode);
+Status GdipSetClipRect(Handle graphics, float x, float y, float width, float height, CombineMode combineMode);
+Status GdipSetClipPath(Handle graphics, Handle path, CombineMode combineMode);
+Status GdipSetClipRegion(Handle graphics, Handle region, CombineMode combineMode);
+Status GdipSetClipHrgn(Handle graphics, HRGN hRgn, CombineMode combineMode);
+
+Status GdipGetClip(Handle graphics, out Handle region);
+Status GdipResetClip(Handle graphics);
+Status GdipSaveGraphics(Handle graphics, out uint state);
+Status GdipRestoreGraphics(Handle graphics, int state);
+Status GdipFlush(Handle graphics, FlushIntention intention);
+Status GdipScaleWorldTransform(Handle graphics, float sx, float sy, MatrixOrder order);
+Status GdipRotateWorldTransform(Handle graphics, float angle, MatrixOrder order);
+Status GdipTranslateWorldTransform(Handle graphics, float dx, float dy, MatrixOrder order);
+Status GdipMultiplyWorldTransform(Handle graphics, Handle matrix, MatrixOrder order);
+Status GdipResetWorldTransform(Handle graphics);
+Status GdipBeginContainer(Handle graphics, ref GpRectF dstrect, ref GpRectF srcrect, GraphicsUnit unit, out int state);
+Status GdipBeginContainerI(Handle graphics, ref GpRect dstrect, ref GpRect srcrect, GraphicsUnit unit, out int state);
+Status GdipBeginContainer2(Handle graphics, out int state);
+Status GdipEndContainer(Handle graphics, int state);
+Status GdipGetDpiX(Handle graphics, out float dpi);
+Status GdipGetDpiY(Handle graphics, out float dpi);
+Status GdipGetPageUnit(Handle graphics, out GraphicsUnit unit);
+Status GdipSetPageUnit(Handle graphics, GraphicsUnit unit);
+Status GdipGetPageScale(Handle graphics, out float scale);
+Status GdipSetPageScale(Handle graphics, float scale);
+Status GdipGetWorldTransform(Handle graphics, Handle matrix); // out not necessary?
+Status GdipSetWorldTransform(Handle graphics, Handle matrix);
+Status GdipGetCompositingMode(Handle graphics, out CompositingMode compositingMode);
+Status GdipSetCompositingMode(Handle graphics, CompositingMode compositingMode);
+Status GdipGetCompositingQuality(Handle graphics, out CompositingQuality compositingQuality);
+Status GdipSetCompositingQuality(Handle graphics, CompositingQuality compositingQuality);
+Status GdipGetInterpolationMode(Handle graphics, out InterpolationMode interpolationMode);
+Status GdipSetInterpolationMode(Handle graphics, InterpolationMode interpolationMode);
+Status GdipGetSmoothingMode(Handle graphics, out SmoothingMode smoothingMode);
+Status GdipSetSmoothingMode(Handle graphics, SmoothingMode smoothingMode);
+Status GdipGetPixelOffsetMode(Handle graphics, out PixelOffsetMode pixelOffsetMode);
+Status GdipSetPixelOffsetMode(Handle graphics, PixelOffsetMode pixelOffsetMode);
+Status GdipGetTextContrast(Handle graphics, out uint textContrast);
+Status GdipSetTextContrast(Handle graphics, uint textContrast);
+Status GdipGraphicsClear(Handle graphics, int color);
+Status GdipDrawLine(Handle graphics, Handle pen, float x1, float y1, float x2, float y2);
+Status GdipDrawLines(Handle graphics, Handle pen, GpPointF* points, int count);
+Status GdipDrawLineI(Handle graphics, Handle pen, int x1, int y1, int x2, int y2);
+Status GdipDrawLinesI(Handle graphics, Handle pen, GpPoint* points, int count);
+Status GdipDrawArc(Handle graphics, Handle pen, float x, float y, float width, float height, float startAngle, float sweepAngle);
+Status GdipDrawArcI(Handle graphics, Handle pen, int x, int y, int width, int height, float startAngle, float sweepAngle);
+Status GdipDrawBezier(Handle graphics, Handle pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+Status GdipDrawBeziers(Handle graphics, Handle pen, GpPointF* points, int count);
+Status GdipDrawBezierI(Handle graphics, Handle pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
+Status GdipDrawBeziersI(Handle graphics, Handle pen, GpPoint* points, int count);
+Status GdipDrawRectangle(Handle graphics, Handle pen, float x, float y, float width, float height);
+Status GdipDrawRectangles(Handle graphics, Handle pen, GpRectF* rects, int count);
+Status GdipDrawRectangleI(Handle graphics, Handle pen, int x, int y, int width, int height);
+Status GdipDrawRectanglesI(Handle graphics, Handle pen, GpRect* rects, int count);
+Status GdipDrawEllipse(Handle graphics, Handle pen, float x, float y, float width, float height);
+Status GdipDrawEllipseI(Handle graphics, Handle pen, int x, int y, int width, int height);
+Status GdipDrawPie(Handle graphics, Handle pen, float x, float y, float width, float height, float startAngle, float sweepAngle);
+Status GdipDrawPieI(Handle graphics, Handle pen, int x, int y, int width, int height, float startAngle, float sweepAngle);
+Status GdipDrawPolygon(Handle graphics, Handle pen, GpPointF* points, int count);
+Status GdipDrawPolygonI(Handle graphics, Handle pen, GpPoint* points, int count);
+Status GdipDrawCurve(Handle graphics, Handle pen, GpPointF* points, int count);
+Status GdipDrawCurve2(Handle graphics, Handle pen, GpPointF* points, int count, float tension);
+Status GdipDrawCurve3(Handle graphics, Handle pen, GpPointF* points, int count, int offset, int numberOfSegments, float tension);
+Status GdipDrawCurveI(Handle graphics, Handle pen, GpPoint* points, int count);
+Status GdipDrawCurve2I(Handle graphics, Handle pen, GpPoint* points, int count, float tension);
+Status GdipDrawCurve3I(Handle graphics, Handle pen, GpPoint* points, int count, int offset, int numberOfSegments, float tension);
+Status GdipDrawClosedCurve(Handle graphics, Handle pen, GpPointF* points, int count);
+Status GdipDrawClosedCurve2(Handle graphics, Handle pen, GpPointF* points, int count, float tension);
+Status GdipDrawClosedCurveI(Handle graphics, Handle pen, GpPoint* points, int count);
+Status GdipDrawClosedCurve2I(Handle graphics, Handle pen, GpPoint* points, int count, float tension);
+Status GdipFillRectangleI(Handle graphics, Handle brush, int x, int y, int width, int height);
+Status GdipFillRectangle(Handle graphics, Handle brush, float x, float y, float width, float height);
+Status GdipFillRectanglesI(Handle graphics, Handle brush, GpRect* rects, int count);
+Status GdipFillRectangles(Handle graphics, Handle brush, GpRectF* rects, int count);
+Status GdipFillPolygon(Handle graphics, Handle brush, GpPointF* rects, int count, FillMode fillMode);
+Status GdipFillPolygonI(Handle graphics, Handle brush, GpPoint* rects, int count, FillMode fillMode);
+Status GdipFillEllipse(Handle graphics, Handle brush, float x, float y, float width, float height);
+Status GdipFillEllipseI(Handle graphics, Handle brush, int x, int y, int width, int height);
+Status GdipFillPie(Handle graphics, Handle brush, float x, float y, float width, float height, float startAngle, float sweepAngle);
+Status GdipFillPieI(Handle graphics, Handle brush, int x, int y, int width, int height, float startAngle, float sweepAngle);
+Status GdipFillPath(Handle graphics, Handle brush, Handle path);
+Status GdipFillClosedCurve(Handle graphics, Handle brush, GpPointF* points, int count);
+Status GdipFillClosedCurveI(Handle graphics, Handle brush, GpPoint* points, int count);
+Status GdipFillClosedCurve2(Handle graphics, Handle brush, GpPointF* points, int count, FillMode fillMode, float tension);
+Status GdipFillClosedCurve2I(Handle graphics, Handle brush, GpPoint* points, int count, FillMode fillMode, float tension);
+Status GdipFillRegion(Handle graphics, Handle brush, Handle region);
+Status GdipDrawString(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, Handle brush);
+Status GdipMeasureString(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, ref GpRectF boundingBox, int* codepointsFitted, int* linesFitted);
+Status GdipGetStringFormatMeasurableCharacterRangeCount(Handle format, out int count);
+Status GdipCloneStringFormat(Handle format, out Handle newFormat);
+
+Status GdipMeasureCharacterRanges(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, int regionCount, Handle* regions);
+Status GdipDrawImage(Handle graphics, Handle image, float x, float y);
+Status GdipDrawImageI(Handle graphics, Handle image, int x, int y);
+Status GdipDrawImageRect(Handle graphics, Handle image, float x, float y, float width, float height);
+Status GdipDrawImageRectI(Handle graphics, Handle image, int x, int y, int width, int height);
+Status GdipDrawImagePointRect(Handle graphics, Handle image, float x, float y, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit);
+Status GdipDrawImagePointRectI(Handle graphics, Handle image, int x, int y, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit);
+Status GdipDrawImageRectRect(Handle graphics, Handle image, float dstx, float dsty, float dstwidth, float dstheight, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData);
+Status GdipDrawImageRectRectI(Handle graphics, Handle image, int dstx, int dsty, int dstwidth, int dstheight, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData);
+Status GdipDrawImagePoints(Handle graphics, Handle image, GpPointF* dstpoints, int count);
+Status GdipDrawImagePointsI(Handle graphics, Handle image, GpPoint* dstpoints, int count);
+Status GdipDrawImagePointsRect(Handle graphics, Handle image, GpPointF* dstpoints, int count, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData);
+Status GdipDrawImagePointsRectI(Handle graphics, Handle image, GpPoint* dstpoints, int count, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData);
+Status GdipIsVisiblePoint(Handle graphics, float x, float y, out int result);
+Status GdipIsVisiblePointI(Handle graphics, int x, int y, out int result);
+Status GdipIsVisibleRect(Handle graphics, float x, float y, float width, float height, out int result);
+Status GdipIsVisibleRectI(Handle graphics, int x, int y, int width, int height, out int result);
+Status GdipGetTextRenderingHint(Handle graphics, out TextRenderingHint mode);
+Status GdipSetTextRenderingHint(Handle graphics, TextRenderingHint mode);
+Status GdipGetClipBounds(Handle graphics, out GpRectF rect);
+Status GdipGetClipBoundsI(Handle graphics, out GpRect rect);
+Status GdipGetVisibleClipBounds(Handle graphics, out GpRectF rect);
+Status GdipGetVisibleClipBoundsI(Handle graphics, out GpRect rect);
+Status GdipIsClipEmpty(Handle graphics, out int result);
+Status GdipIsVisibleClipEmpty(Handle graphics, out int result);
+Status GdipGetRenderingOrigin(Handle graphics, out int x, out int y);
+Status GdipSetRenderingOrigin(Handle graphics, int x, int y);
+Status GdipGetNearestColor(Handle graphics, ref int argb);
+Status GdipComment(Handle graphics, uint sizeData, ubyte* data);
+Status GdipTransformPoints(Handle graphics, CoordinateSpace destSpace, CoordinateSpace srcSpace, GpPointF* points, int count);
+Status GdipTransformPointsI(Handle graphics, CoordinateSpace destSpace, CoordinateSpace srcSpace, GpPoint* points, int count);
+
+Status GdipCreateMatrix(out Handle matrix);
+Status GdipCreateMatrix2(float m11, float m12, float m21, float m22, float dx, float dy, out Handle matrix);
+Status GdipCreateMatrix3(ref GpRectF rect, GpPointF* dstplg, out Handle matrix);
+Status GdipCreateMatrix3I(ref GpRect rect, GpPoint* dstplg, out Handle matrix);
+Status GdipDeleteMatrix(Handle matrix);
+Status GdipCloneMatrix(Handle matrix, out Handle cloneMatrix);
+Status GdipGetMatrixElements(Handle matrix, float* matrixOut);
+Status GdipSetMatrixElements(Handle matrix, float m11, float m12, float m21, float m22, float xy, float dy);
+Status GdipInvertMatrix(Handle matrix);
+Status GdipMultiplyMatrix(Handle matrix, Handle matrix2, MatrixOrder order);
+Status GdipScaleMatrix(Handle matrix, float scaleX, float scaleY, MatrixOrder order);
+Status GdipShearMatrix(Handle matrix, float shearX, float shearY, MatrixOrder order);
+Status GdipRotateMatrix(Handle matrix, float angle, MatrixOrder order);
+Status GdipTranslateMatrix(Handle matrix, float offsetX, float offsetY, MatrixOrder order);
+Status GdipIsMatrixIdentity(Handle matrix, out int result);
+Status GdipIsMatrixInvertible(Handle matrix, out int result);
+Status GdipTransformMatrixPoints(Handle matrix, GpPointF *pts, int count);
+
+Status GdipGetBrushType(Handle brush, out BrushType type );
+Status GdipCloneBrush(Handle brush, out Handle cloneBrush);
+Status GdipDeleteBrush(Handle brush);
+
+Status GdipCreateSolidFill(int color, out Handle brush);
+Status GdipGetSolidFillColor(Handle brush, out int color);
+Status GdipSetSolidFillColor(Handle brush, int color);
+
+Status GdipCreateTexture(Handle image, WrapMode wrapMode, out Handle texture);
+Status GdipCreateTexture2(Handle image, WrapMode wrapMode, float x, float y, float width, float height, out Handle texture);
+Status GdipCreateTexture2I(Handle image, WrapMode wrapMode, int x, int y, int width, int height, out Handle texture);
+Status GdipGetTextureImage(Handle brush, out Handle image);
+Status GdipGetTextureTransform(Handle brush, out Handle matrix);
+Status GdipSetTextureTransform(Handle brush, Handle matrix);
+Status GdipGetTextureWrapMode(Handle brush, out WrapMode wrapmode);
+Status GdipSetTextureWrapMode(Handle brush, WrapMode wrapmode);
+
+Status GdipCreateHatchBrush(HatchStyle hatchstyle, int forecol, int backcol, out Handle brush);
+Status GdipGetHatchStyle(Handle brush, out HatchStyle hatchstyle);
+Status GdipGetHatchForegroundColor(Handle brush, out int forecol);
+Status GdipGetHatchBackgroundColor(Handle brush, out int backcol);
+
+Status GdipCreateLineBrushI(ref GpPoint point1, ref GpPoint point2, int color1, int color2, WrapMode wrapMode, out Handle lineGradient);
+Status GdipCreateLineBrush(ref GpPointF point1, ref GpPointF point2, int color1, int color2, WrapMode wrapMode, out Handle lineGradient);
+Status GdipCreateLineBrushFromRectI(ref GpRect rect, int color1, int color2, LinearGradientMode mode, WrapMode wrapMode, out Handle lineGradient);
+Status GdipCreateLineBrushFromRect(ref GpRectF rect, int color1, int color2, LinearGradientMode mode, WrapMode wrapMode, out Handle lineGradient);
+Status GdipCreateLineBrushFromRectWithAngleI(ref GpRect rect, int color1, int color2, float angle, int isAngleScalable, WrapMode wrapMode, out Handle lineGradient);
+Status GdipCreateLineBrushFromRectWithAngle(ref GpRectF rect, int color1, int color2, float angle, int isAngleScalable, WrapMode wrapMode, out Handle lineGradient);
+Status GdipGetLineBlendCount(Handle brush, out int count);
+Status GdipGetLineBlend(Handle brush, float* blend, float* positions, int count);
+Status GdipSetLineBlend(Handle brush, float* blend, float* positions, int count);
+Status GdipGetLinePresetBlendCount(Handle brush, out int count);
+Status GdipGetLinePresetBlend(Handle brush, uint* blend, float* positions, int count);
+Status GdipSetLinePresetBlend(Handle brush, uint* blend, float* positions, int count);
+Status GdipGetLineWrapMode(Handle brush, out WrapMode wrapmode);
+Status GdipSetLineWrapMode(Handle brush, WrapMode wrapmode);
+Status GdipGetLineRect(Handle brush, out GpRectF rect);
+Status GdipGetLineColors(Handle brush, int* colors);
+Status GdipSetLineColors(Handle brush, int color1, int color2);
+Status GdipGetLineGammaCorrection(Handle brush, out int useGammaCorrection);
+Status GdipSetLineGammaCorrection(Handle brush, int useGammaCorrection);
+Status GdipSetLineSigmaBlend(Handle brush, float focus, float scale);
+Status GdipSetLineLinearBlend(Handle brush, float focus, float scale);
+Status GdipGetLineTransform(Handle brush, out Handle matrix);
+Status GdipSetLineTransform(Handle brush, Handle matrix);
+Status GdipResetLineTransform(Handle brush);
+Status GdipMultiplyLineTransform(Handle brush, Handle matrix, MatrixOrder order);
+Status GdipTranslateLineTransform(Handle brush, float dx, float dy, MatrixOrder order);
+Status GdipScaleLineTransform(Handle brush, float sx, float sy, MatrixOrder order);
+Status GdipRotateLineTransform(Handle brush, float angle, MatrixOrder order);
+
+Status GdipCreatePen1(int argb, float width, GraphicsUnit unit, out Handle pen);
+Status GdipCreatePen2(Handle brush, float width, GraphicsUnit unit, out Handle pen);
+Status GdipDeletePen(Handle pen);
+Status GdipClonePen(Handle pen, out Handle clonepen);
+Status GdipSetPenLineCap197819(Handle pen, LineCap startCap, LineCap endCap, DashCap dashCap);
+Status GdipGetPenStartCap(Handle pen, out LineCap startCap);
+Status GdipSetPenStartCap(Handle pen, LineCap startCap);
+Status GdipGetPenEndCap(Handle pen, out LineCap endCap);
+Status GdipSetPenEndCap(Handle pen, LineCap endCap);
+Status GdipGetPenDashCap197819(Handle pen, out DashCap endCap);
+Status GdipSetPenDashCap197819(Handle pen, DashCap endCap);
+Status GdipGetPenLineJoin(Handle pen, out LineJoin lineJoin);
+Status GdipSetPenLineJoin(Handle pen, LineJoin lineJoin);
+Status GdipGetPenMiterLimit(Handle pen, out float miterLimit);
+Status GdipSetPenMiterLimit(Handle pen, float miterLimit);
+Status GdipGetPenMode(Handle pen, out PenAlignment penMode);
+Status GdipSetPenMode(Handle pen, PenAlignment penMode);
+Status GdipGetPenTransform(Handle pen, out Handle matrix);
+Status GdipSetPenTransform(Handle pen, Handle matrix);
+Status GdipResetPenTransform(Handle pen);
+Status GdipMultiplyPenTransform(Handle pen, Handle matrix, MatrixOrder order);
+Status GdipTranslatePenTransform(Handle pen, float dx, float dy, MatrixOrder order);
+Status GdipScalePenTransform(Handle pen, float sx, float sy, MatrixOrder order);
+Status GdipRotatePenTransform(Handle pen, float angle, MatrixOrder order);
+Status GdipGetPenColor(Handle pen, out int argb);
+Status GdipSetPenColor(Handle pen, int argb);
+Status GdipGetPenWidth(Handle pen, out float width);
+Status GdipSetPenWidth(Handle pen, float width);
+Status GdipGetPenFillType(Handle pen, out PenType type);
+Status GdipGetPenBrushFill(Handle pen, out Handle brush);
+Status GdipSetPenBrushFill(Handle pen, Handle brush);
+Status GdipGetPenDashStyle(Handle pen, out DashStyle dashstyle);
+Status GdipSetPenDashStyle(Handle pen, DashStyle dashstyle);
+Status GdipGetPenDashOffset(Handle pen, out float offset);
+Status GdipSetPenDashOffset(Handle pen, float offset);
+Status GdipGetPenDashCount(Handle pen, out int count);
+Status GdipGetPenDashArray(Handle pen, float* dash, int count);
+Status GdipSetPenDashArray(Handle pen, float* dash, int count);
+Status GdipGetPenCompoundCount(Handle pen, out int count);
+Status GdipGetPenCompoundArray(Handle pen, float* dash, int count);
+Status GdipSetPenCompoundArray(Handle pen, float* dash, int count);
+
+Status GdipCreateRegion(out Handle region);
+Status GdipCreateRegionRect(ref GpRectF rect, out Handle region);
+Status GdipCreateRegionRectI(ref GpRect rect, out Handle region);
+Status GdipCreateRegionPath(Handle path, out Handle region);
+Status GdipCreateRegionHrgn(Handle hRgn, out Handle region);
+Status GdipDeleteRegion(Handle region);
+Status GdipSetInfinite(Handle region);
+Status GdipSetEmpty(Handle region);
+Status GdipCombineRegionRect(Handle region, ref GpRectF rect, CombineMode combineMode);
+Status GdipCombineRegionRectI(Handle region, ref GpRect rect, CombineMode combineMode);
+Status GdipCombineRegionPath(Handle region, Handle path, CombineMode combineMode);
+Status GdipCombineRegionRegion(Handle region, Handle region, CombineMode combineMode);
+Status GdipTranslateRegion(Handle region, float dx, float dy);
+Status GdipTranslateRegionI(Handle region, int dx, int dy);
+Status GdipTransformRegion(Handle region, Handle matrix);
+Status GdipGetRegionBounds(Handle region, Handle graphics, out GpRectF rect);
+Status GdipGetRegionHRgn(Handle region, Handle graphics, out Handle hRgn);
+Status GdipIsEmptyRegion(Handle region, Handle graphics, out int result);
+Status GdipIsInfiniteRegion(Handle region, Handle graphics, out int result);
+Status GdipIsEqualRegion(Handle region1, Handle region2, Handle graphics, out int result);
+Status GdipIsVisibleRegionPoint(Handle region, float x, float y, Handle graphics, out int result);
+Status GdipIsVisibleRegionRect(Handle region, float x, float y, float width, float height, Handle graphics, out int result);
+Status GdipIsVisibleRegionPointI(Handle region, int x, int y, Handle graphics, out int result);
+Status GdipIsVisibleRegionRectI(Handle region, int x, int y, int width, int height, Handle graphics, out int result);
+Status GdipGetRegionScansCount(Handle region, out int count, Handle matrix);
+Status GdipGetRegionScans(Handle region, GpRectF* rects, out int count, Handle matrix);
+
+Status GdipDisposeImage(Handle image);
+Status GdipImageForceValidation(Handle image);
+Status GdipLoadImageFromFileICM(wchar* filename, out Handle image);
+Status GdipLoadImageFromFile(wchar* filename, out Handle image);
+// Status GdipLoadImageFromStreamICM(IStream stream, out Handle image);
+// Status GdipLoadImageFromStream(IStream stream, out Handle image);
+// Status GdipGetImageRawFormat(Handle image, out GUID format);
+Status GdipGetImageEncodersSize(out int numEncoders, out int size);
+// Status GdipGetImageEncoders(int numEncoders, int size, GpImageCodecInfo* encoders);
+// Status GdipSaveImageToFile(Handle image, wchar* filename, ref GUID clsidEncoder, GpEncoderParameters* encoderParams);
+// Status GdipSaveImageToStream(Handle image, IStream stream, ref GUID clsidEncoder, GpEncoderParameters* encoderParams);
+// Status GdipSaveAdd(Handle image, GpEncoderParameters* encoderParams);
+// Status GdipSaveAddImage(Handle image, Handle newImage, GpEncoderParameters* encoderParams);
+Status GdipCloneImage(Handle image, out Handle cloneImage);
+Status GdipGetImageType(Handle image, out int type);
+Status GdipGetImageFlags(Handle image, out uint flags);
+Status GdipGetImageWidth(Handle image, out uint width);
+Status GdipGetImageHeight(Handle image, out uint height);
+Status GdipGetImageHorizontalResolution(Handle image, out float resolution);
+Status GdipGetImageVerticalResolution(Handle image, out float resolution);
+Status GdipGetPropertyCount(Handle image, out int numOfProperty);
+Status GdipGetPropertyIdList(Handle image, int numOfProperty, int* list);
+Status GdipGetImagePixelFormat(Handle image, out PixelFormat format);
+Status GdipGetImageDimension(Handle image, out float width, out float height);
+Status GdipGetImageThumbnail(Handle image, int thumbWidth, int thumbHeight, out Handle thumbImage, GpGetThumbnailImageAbort callback, void* callbackData);
+// Status GdipImageGetFrameCount(Handle image, ref GUID dimensionID, out int count);
+// Status GdipImageSelectActiveFrame(Handle image, ref GUID dimensionID, int frameCount);
+Status GdipImageGetFrameDimensionsCount(Handle image, out int count);
+// Status GdipImageGetFrameDimensionsList(Handle image, GUID* dimensionIDs, int count);
+Status GdipImageRotateFlip(Handle image, RotateFlipType rotateFlipType);
+Status GdipGetPropertyItemSize(Handle image, int propId, out uint propSize);
+Status GdipGetPropertyItem(Handle image, int propId, uint propSize, GpPropertyItem* buffer);
+Status GdipSetPropertyItem(Handle image, ref GpPropertyItem buffer);
+Status GdipRemovePropertyItem(Handle image, int propId);
+Status GdipGetPropertySize(Handle image, out uint totalBufferSize, ref int numProperties);
+Status GdipGetAllPropertyItems(Handle image, uint totalBufferSize, int numProperties, GpPropertyItem* allItems);
+Status GdipGetImageBounds(Handle image, out GpRectF srcRect, out GraphicsUnit srcUnit);
+// Status GdipGetEncoderParameterListSize(Handle image, ref GUID clsidEncoder, out uint size);
+// Status GdipGetEncoderParameterList(Handle image, ref GUID clsidEncoder, uint size, GpEncoderParameters* buffer);
+Status GdipGetImagePaletteSize(Handle image, out int size);
+Status GdipGetImagePalette(Handle image, GpColorPalette* palette, int size);
+Status GdipSetImagePalette(Handle image, GpColorPalette* palette);
+
+Status GdipCreateBitmapFromScan0(int width, int height, int stride, PixelFormat format, ubyte* scan0, out Handle bitmap);
+Status GdipCreateBitmapFromHBITMAP(Handle hbitmap, Handle hpalette, out Handle bitmap);
+Status GdipCreateBitmapFromHICON(Handle hicon, out Handle bitmap);
+Status GdipCreateBitmapFromFileICM(wchar* fileName, out Handle bitmap);
+Status GdipCreateBitmapFromFile(wchar* fileName, out Handle bitmap);
+// Status GdipCreateBitmapFromStreamICM(IStream stream, out Handle bitmap);
+// Status GdipCreateBitmapFromStream(IStream stream, out Handle bitmap);
+Status GdipCreateBitmapFromGraphics(int width, int height, Handle graphics, out Handle bitmap);
+Status GdipCloneBitmapArea(float x, float y, float width, float height, PixelFormat format, Handle srcbitmap, out Handle dstbitmap);
+Status GdipCloneBitmapAreaI(int x, int y, int width, int height, PixelFormat format, Handle srcbitmap, out Handle dstbitmap);
+Status GdipBitmapGetPixel(Handle bitmap, int x, int y, out int color);
+Status GdipBitmapSetPixel(Handle bitmap, int x, int y, int color);
+Status GdipBitmapLockBits(Handle bitmap, GpRect* rect, ImageLockMode flags, PixelFormat format, GpBitmapData* lockedBitmapData);
+Status GdipBitmapUnlockBits(Handle bitmap, GpBitmapData* lockedBitmapData);
+Status GdipBitmapSetResolution(Handle bitmap, float xdpi, float ydpi);
+Status GdipCreateHICONFromBitmap(Handle bitmap, out Handle hbmReturn);
+Status GdipCreateHBITMAPFromBitmap(Handle bitmap, out Handle hbmReturn, int background);
+
+Status GdipCreateImageAttributes(out Handle imageattr);
+Status GdipDisposeImageAttributes(Handle imageattr);
+Status GdipSetImageAttributesColorMatrix(Handle imageattr, ColorAdjustType type, int enableFlag, GpColorMatrix* colorMatrix, GpColorMatrix* grayMatrix, ColorMatrixFlag flags);
+Status GdipSetImageAttributesThreshold(Handle imageattr, ColorAdjustType type, int enableFlag, float threshold);
+Status GdipSetImageAttributesGamma(Handle imageattr, ColorAdjustType type, int enableFlag, float gamma);
+Status GdipSetImageAttributesNoOp(Handle imageattr, ColorAdjustType type, int enableFlag);
+Status GdipSetImageAttributesColorKeys(Handle imageattr, ColorAdjustType type, int enableFlag, int colorLow, int colorHigh);
+Status GdipSetImageAttributesOutputChannel(Handle imageattr, ColorAdjustType type, int enableFlag, ColorChannelFlag flags);
+Status GdipSetImageAttributesOutputChannelColorProfile(Handle imageattr, ColorAdjustType type, int enableFlag, wchar* colorProfileFilename);
+Status GdipSetImageAttributesWrapMode(Handle imageattr, WrapMode wrap, int argb, int clamp);
+
+Status GdipNewInstalledFontCollection(out Handle fontCollection);
+Status GdipNewPrivateFontCollection(out Handle fontCollection);
+Status GdipDeletePrivateFontCollection(Handle fontCollection);
+Status GdipPrivateAddFontFile(Handle fontCollection, wchar* filename);
+Status GdipPrivateAddMemoryFont(Handle fontCollection, void* memory, int length);
+Status GdipGetFontCollectionFamilyCount(Handle fontCollection, out int numFound);
+Status GdipGetFontCollectionFamilyList(Handle fontCollection, int numSought, Handle* gpfamilies, out int numFound);
+
+Status GdipCreateFontFamilyFromName(wchar* name, Handle fontCollection, out Handle FontFamily);
+Status GdipDeleteFontFamily(Handle FontFamily);
+Status GdipCloneFontFamily(Handle FontFamily, out Handle clonedFontFamily);
+Status GdipGetFamilyName(Handle family, wchar* name, int language);
+Status GdipGetGenericFontFamilyMonospace(out Handle nativeFamily);
+Status GdipGetGenericFontFamilySerif(out Handle nativeFamily);
+Status GdipGetGenericFontFamilySansSerif(out Handle nativeFamily);
+Status GdipGetEmHeight(Handle family, FontStyle style, out short EmHeight);
+Status GdipGetCellAscent(Handle family, FontStyle style, out short CellAscent);
+Status GdipGetCellDescent(Handle family, FontStyle style, out short CellDescent);
+Status GdipGetLineSpacing(Handle family, FontStyle style, out short LineSpacing);
+Status GdipIsStyleAvailable(Handle family, FontStyle style, out int IsStyleAvailable);
+
+Status GdipCreateFont(Handle fontFamily, float emSize, int style, int unit, out Handle font);
+Status GdipCreateFontFromDC(Handle hdc, out Handle font);
+Status GdipDeleteFont(Handle font);
+Status GdipCloneFont(Handle font, out Handle cloneFont);
+Status GdipGetFontSize(Handle font, out float size);
+Status GdipGetFontHeight(Handle font, Handle graphics, out float height);
+Status GdipGetFontHeightGivenDPI(Handle font, float dpi, out float height);
+Status GdipGetFontStyle(Handle font, out FontStyle style);
+Status GdipGetFontUnit(Handle font, out GraphicsUnit unit);
+Status GdipGetFamily(Handle font, out Handle family);
+Status GdipCreateFontFromLogfontW( Handle hdc, ref LOGFONTW logfont, out Handle font);
+Status GdipCreateFontFromLogfontA( Handle hdc, ref LOGFONTA logfont, out Handle font );
+
+Status GdipGetLogFontW(Handle font, Handle graphics, out LOGFONTW logfontW);
+alias GdipGetLogFontW GdipGetLogFont;
+
+Status GdipCreateStringFormat(StringFormatFlags formatAttributes, int language, out Handle format);
+Status GdipDeleteStringFormat(Handle format);
+Status GdipGetStringFormatFlags(Handle format, out StringFormatFlags flags);
+Status GdipSetStringFormatFlags(Handle format, StringFormatFlags flags);
+Status GdipGetStringFormatAlign(Handle format, out StringAlignment alignment);
+Status GdipSetStringFormatAlign(Handle format, StringAlignment alignment);
+Status GdipGetStringFormatLineAlign(Handle format, out StringAlignment alignment);
+Status GdipSetStringFormatLineAlign(Handle format, StringAlignment alignment);
+Status GdipGetStringFormatTrimming(Handle format, out StringTrimming trimming);
+Status GdipSetStringFormatTrimming(Handle format, StringTrimming trimming);
+
+Status GdipCreatePath(FillMode brushMode, out Handle path);
+Status GdipCreatePath2(GpPointF*, ubyte*, int, FillMode, out Handle);
+Status GdipCreatePath2I(GpPoint*, ubyte*, int, FillMode, out Handle);
+Status GdipDeletePath(Handle path);
+Status GdipClonePath(Handle path, out Handle clonepath);
+Status GdipResetPath(Handle path);
+Status GdipGetPathFillMode(Handle path, out FillMode fillmode);
+Status GdipSetPathFillMode(Handle path, FillMode fillmode);
+Status GdipStartPathFigure(Handle path);
+Status GdipClosePathFigure(Handle path);
+Status GdipClosePathFigures(Handle path);
+Status GdipSetPathMarker(Handle path);
+Status GdipClearPathMarkers(Handle path);
+Status GdipReversePath(Handle path);
+Status GdipGetPathLastPoint(Handle path, out GpPointF lastPoint);
+Status GdipAddPathLine(Handle path, float x1, float y1, float x2, float y2);
+Status GdipAddPathLineI(Handle path, int x1, int y1, int x2, int y2);
+Status GdipAddPathLine2(Handle path, GpPointF* points, int count);
+Status GdipAddPathLine2I(Handle path, GpPoint* points, int count);
+Status GdipAddPathArc(Handle path, float x, float y, float width, float height, float startAngle, float sweepAngle);
+Status GdipAddPathArcI(Handle path, int x, int y, int width, int height, float startAngle, float sweepAngle);
+Status GdipAddPathBezier(Handle path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
+Status GdipAddPathBezierI(Handle path, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
+Status GdipAddPathBeziers(Handle path, GpPointF* points, int count);
+Status GdipAddPathBeziersI(Handle path, GpPoint* points, int count);
+Status GdipAddPathCurve(Handle path, GpPointF* points, int count);
+Status GdipAddPathCurveI(Handle path, GpPoint* points, int count);
+Status GdipAddPathCurve2(Handle path, GpPointF* points, int count, float tension);
+Status GdipAddPathCurve2I(Handle path, GpPoint* points, int count, float tension);
+Status GdipAddPathCurve3(Handle path, GpPointF* points, int count, int offset, int numberOfSegments, float tension);
+Status GdipAddPathCurve3I(Handle path, GpPoint* points, int count, int offset, int numberOfSegments, float tension);
+Status GdipAddPathClosedCurve(Handle path, GpPointF* points, int count);
+Status GdipAddPathClosedCurveI(Handle path, GpPoint* points, int count);
+Status GdipAddPathClosedCurve2(Handle path, GpPointF* points, int count, float tension);
+Status GdipAddPathClosedCurve2I(Handle path, GpPoint* points, int count, float tension);
+Status GdipAddPathRectangle(Handle path, float x, float y, float width, float height);
+Status GdipAddPathRectangleI(Handle path, int x, int y, int width, int height);
+Status GdipAddPathRectangles(Handle path, GpRectF* rects, int count);
+Status GdipAddPathRectanglesI(Handle path, GpRect* rects, int count);
+Status GdipAddPathEllipse(Handle path, float x, float y, float width, float height);
+Status GdipAddPathEllipseI(Handle path, int x, int y, int width, int height);
+Status GdipAddPathPie(Handle path, float x, float y, float width, float height, float startAngle, float sweepAngle);
+Status GdipAddPathPieI(Handle path, int x, int y, int width, int height, float startAngle, float sweepAngle);
+Status GdipAddPathPolygon(Handle path, GpPointF* points, int count);
+Status GdipAddPathPolygonI(Handle path, GpPoint* points, int count);
+Status GdipAddPathPath(Handle path, Handle addingPath, int connect);
+Status GdipAddPathString(Handle path, wchar* string, int length, Handle family, FontStyle style, float emSize, ref GpRectF layoutRect, Handle format);
+Status GdipAddPathStringI(Handle path, wchar* string, int length, Handle family, FontStyle style, float emSize, ref GpRect layoutRect, Handle format);
+Status GdipTransformPath(Handle path, Handle matrix);
+Status GdipGetPathWorldBounds(Handle path, out GpRectF bounds, Handle matrix, Handle pen);
+Status GdipFlattenPath(Handle path, Handle matrix, float flatness);
+Status GdipWidenPath(Handle path, Handle pen, Handle matrix, float flatness);
+Status GdipWindingModeOutline(Handle path, Handle matrix, float flatness);
+Status GdipWarpPath(Handle path, Handle matrix, GpPointF* points, int count, float srcx, float srcy, float srcwidth, float srcwidth, WarpMode warpMode, float flatness);
+Status GdipGetPointCount(Handle path, out int count);
+Status GdipGetPathTypes(Handle path, byte* types, int count);
+Status GdipGetPathPoints(Handle path, GpPointF* points, int count);
+Status GdipIsVisiblePathPoint(Handle path, float x, float y, Handle graphics, out int result);
+Status GdipIsVisiblePathPointI(Handle path, int x, int y, Handle graphics, out int result);
+Status GdipIsOutlineVisiblePathPoint(Handle path, float x, float y, Handle pen, Handle graphics, out int result);
+Status GdipIsOutlineVisiblePathPointI(Handle path, int x, int y, Handle pen, Handle graphics, out int result);
+Status GdipDrawPath(Handle graphics, Handle pen, Handle path);
+
+
+Status GdipCreatePathIter(out Handle iterator, Handle path);
+Status GdipDeletePathIter(Handle iterator);
+Status GdipPathIterNextSubpath(Handle iterator, out int resultCount, out int startIndex, out int endIndex, out int isClosed);
+Status GdipPathIterNextSubpathPath(Handle iterator, out int resultCount, Handle path, out int isClosed);
+Status GdipPathIterNextPathType(Handle iterator, out int resultCount, out ubyte pathType, out int startIndex, out int endIndex);
+Status GdipPathIterNextMarker(Handle iterator, out int resultCount, out int startIndex, out int endIndex);
+Status GdipPathIterNextMarkerPath(Handle iterator, out int resultCount, Handle path);
+Status GdipPathIterGetCount(Handle iterator, out int count);
+Status GdipPathIterGetSubpathCount(Handle iterator, out int count);
+Status GdipPathIterHasCurve(Handle iterator, out int hasCurve);
+Status GdipPathIterRewind(Handle iterator);
+Status GdipPathIterEnumerate(Handle iterator, out int resultCount, GpPointF* points, ubyte* types, int count);
+Status GdipPathIterCopyData(Handle iterator, out int resultCount, GpPointF* points, ubyte* types, int startIndex, int endIndex);
+
+Status GdipCreatePathGradient(GpPointF* points, int count, WrapMode wrapMode, out Handle polyGradient);
+Status GdipCreatePathGradientI(GpPoint* points, int count, WrapMode wrapMode, out Handle polyGradient);
+Status GdipCreatePathGradientFromPath(Handle path, out Handle polyGradient);
+Status GdipGetPathGradientCenterColor(Handle brush, out int colors);
+Status GdipSetPathGradientCenterColor(Handle brush, int colors);
+Status GdipGetPathGradientSurroundColorCount(Handle brush, out int count);
+Status GdipGetPathGradientSurroundColorsWithCount(Handle brush, int* color, ref int count);
+Status GdipSetPathGradientSurroundColorsWithCount(Handle brush, int* color, ref int count);
+Status GdipGetPathGradientCenterPoint(Handle brush, ref GpPointF point);
+Status GdipSetPathGradientCenterPoint(Handle brush, ref GpPointF point);
+Status GdipGetPathGradientRect(Handle brush, ref GpRectF rect);
+Status GdipGetPathGradientBlendCount(Handle brush, out int count);
+Status GdipGetPathGradientBlend(Handle brush, float* blend, float* positions, int count);
+Status GdipSetPathGradientBlend(Handle brush, float* blend, float* positions, int count);
+Status GdipGetPathGradientPresetBlendCount(Handle brush, out int count);
+Status GdipGetPathGradientPresetBlend(Handle brush, int* blend, float* positions, int count);
+Status GdipSetPathGradientPresetBlend(Handle brush, int* blend, float* positions, int count);
+Status GdipSetPathGradientSigmaBlend(Handle brush, float focus, float scale);
+Status GdipSetPathGradientLinearBlend(Handle brush, float focus, float scale);
+Status GdipGetPathGradientTransform(Handle brush, out Handle matrix);
+Status GdipSetPathGradientTransform(Handle brush, Handle matrix);
+Status GdipResetPathGradientTransform(Handle brush);
+Status GdipMultiplyPathGradientTransform(Handle brush, Handle matrix, MatrixOrder order);
+Status GdipRotatePathGradientTransform(Handle brush, float angle, MatrixOrder order);
+Status GdipTranslatePathGradientTransform(Handle brush, float dx, float dy, MatrixOrder order);
+Status GdipScalePathGradientTransform(Handle brush, float sx, float sy, MatrixOrder order);
+Status GdipGetPathGradientFocusScales(Handle brush, out float xScale, out float yScale);
+Status GdipSetPathGradientFocusScales(Handle brush, float xScale, float yScale);
+Status GdipGetPathGradientWrapMode(Handle brush, out WrapMode wrapMode);
+Status GdipSetPathGradientWrapMode(Handle brush, WrapMode wrapMode);
+
+//added
+
+Status GdipResetTextureTransform( Handle brush );
+Status GdipScaleTextureTransform( Handle brush, float sx, float sy, MatrixOrder order );
+Status GdipTranslateTextureTransform( Handle brush, float dx, float dy, MatrixOrder order);
+Status GdipStringFormatGetGenericDefault(out Handle format);
+Status GdipStringFormatGetGenericTypographic(out Handle format);
+Status GdipSetStringFormatHotkeyPrefix(Handle format, int hotkeyPrefix);
+Status GdipSetStringFormatTabStops( Handle format, float firstTabOffset, int count, float* tabStops);
+
+void loadLib_Gdip(){
+    // do nothing in this version
+}
+
+}
+else{ // version(!STATIC_GDIPLUS)
+Status function( uint* token, GdiplusStartupInput* input, GdiplusStartupOutput* output) GdiplusStartup;
+void   function(uint token) GdiplusShutdown;
+Status function(Handle hdc, out Handle graphics) GdipCreateFromHDC;
+Status function(Handle hdc, Handle hDevice, out Handle graphics) GdipCreateFromHDC2;
+Status function(Handle hwnd, out Handle graphics) GdipCreateFromHWND;
+Status function(Handle image, out Handle graphics) GdipGetImageGraphicsContext;
+Status function(Handle graphics) GdipDeleteGraphics;
+Status function(Handle graphics, out Handle hdc) GdipGetDC;
+Status function(Handle graphics, Handle hdc) GdipReleaseDC;
+Status function(Handle graphics, Handle srcgraphics, CombineMode combineMode) GdipSetClipGraphics;
+Status function(Handle graphics, int x, int y, int width, int height, CombineMode combineMode) GdipSetClipRectI;
+Status function(Handle graphics, float x, float y, float width, float height, CombineMode combineMode) GdipSetClipRect;
+Status function(Handle graphics, Handle path, CombineMode combineMode) GdipSetClipPath;
+Status function(Handle graphics, Handle region, CombineMode combineMode) GdipSetClipRegion;
+Status function(Handle graphics, HRGN hRgn, CombineMode combineMode) GdipSetClipHrgn;
+Status function(Handle graphics, out Handle region) GdipGetClip;
+Status function(Handle graphics) GdipResetClip;
+Status function(Handle graphics, out uint state) GdipSaveGraphics;
+Status function(Handle graphics, int state) GdipRestoreGraphics;
+Status function(Handle graphics, FlushIntention intention) GdipFlush;
+Status function(Handle graphics, float sx, float sy, MatrixOrder order) GdipScaleWorldTransform;
+Status function(Handle graphics, float angle, MatrixOrder order) GdipRotateWorldTransform;
+Status function(Handle graphics, float dx, float dy, MatrixOrder order) GdipTranslateWorldTransform;
+Status function(Handle graphics, Handle matrix, MatrixOrder order) GdipMultiplyWorldTransform;
+Status function(Handle graphics) GdipResetWorldTransform;
+Status function(Handle graphics, ref GpRectF dstrect, ref GpRectF srcrect, GraphicsUnit unit, out int state) GdipBeginContainer;
+Status function(Handle graphics, ref GpRect dstrect, ref GpRect srcrect, GraphicsUnit unit, out int state) GdipBeginContainerI;
+Status function(Handle graphics, out int state) GdipBeginContainer2;
+Status function(Handle graphics, int state) GdipEndContainer;
+Status function(Handle graphics, out float dpi) GdipGetDpiX;
+Status function(Handle graphics, out float dpi) GdipGetDpiY;
+Status function(Handle graphics, out GraphicsUnit unit) GdipGetPageUnit;
+Status function(Handle graphics, GraphicsUnit unit) GdipSetPageUnit;
+Status function(Handle graphics, out float scale) GdipGetPageScale;
+Status function(Handle graphics, float scale) GdipSetPageScale;
+Status function(Handle graphics, Handle matrix) GdipGetWorldTransform;
+Status function(Handle graphics, Handle matrix) GdipSetWorldTransform;
+Status function(Handle graphics, out CompositingMode compositingMode) GdipGetCompositingMode;
+Status function(Handle graphics, CompositingMode compositingMode) GdipSetCompositingMode;
+Status function(Handle graphics, out CompositingQuality compositingQuality) GdipGetCompositingQuality;
+Status function(Handle graphics, CompositingQuality compositingQuality) GdipSetCompositingQuality;
+Status function(Handle graphics, out InterpolationMode interpolationMode) GdipGetInterpolationMode;
+Status function(Handle graphics, InterpolationMode interpolationMode) GdipSetInterpolationMode;
+Status function(Handle graphics, out SmoothingMode smoothingMode) GdipGetSmoothingMode;
+Status function(Handle graphics, SmoothingMode smoothingMode) GdipSetSmoothingMode;
+Status function(Handle graphics, out PixelOffsetMode pixelOffsetMode) GdipGetPixelOffsetMode;
+Status function(Handle graphics, PixelOffsetMode pixelOffsetMode) GdipSetPixelOffsetMode;
+Status function(Handle graphics, out uint textContrast) GdipGetTextContrast;
+Status function(Handle graphics, uint textContrast) GdipSetTextContrast;
+Status function(Handle graphics, int color) GdipGraphicsClear;
+Status function(Handle graphics, Handle pen, float x1, float y1, float x2, float y2) GdipDrawLine;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count) GdipDrawLines;
+Status function(Handle graphics, Handle pen, int x1, int y1, int x2, int y2) GdipDrawLineI;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count) GdipDrawLinesI;
+Status function(Handle graphics, Handle pen, float x, float y, float width, float height, float startAngle, float sweepAngle) GdipDrawArc;
+Status function(Handle graphics, Handle pen, int x, int y, int width, int height, float startAngle, float sweepAngle) GdipDrawArcI;
+Status function(Handle graphics, Handle pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) GdipDrawBezier;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count) GdipDrawBeziers;
+Status function(Handle graphics, Handle pen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) GdipDrawBezierI;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count) GdipDrawBeziersI;
+Status function(Handle graphics, Handle pen, float x, float y, float width, float height) GdipDrawRectangle;
+Status function(Handle graphics, Handle pen, GpRectF* rects, int count) GdipDrawRectangles;
+Status function(Handle graphics, Handle pen, int x, int y, int width, int height) GdipDrawRectangleI;
+Status function(Handle graphics, Handle pen, GpRect* rects, int count) GdipDrawRectanglesI;
+Status function(Handle graphics, Handle pen, float x, float y, float width, float height) GdipDrawEllipse;
+Status function(Handle graphics, Handle pen, int x, int y, int width, int height) GdipDrawEllipseI;
+Status function(Handle graphics, Handle pen, float x, float y, float width, float height, float startAngle, float sweepAngle) GdipDrawPie;
+Status function(Handle graphics, Handle pen, int x, int y, int width, int height, float startAngle, float sweepAngle) GdipDrawPieI;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count) GdipDrawPolygon;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count) GdipDrawPolygonI;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count) GdipDrawCurve;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count, float tension) GdipDrawCurve2;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count, int offset, int numberOfSegments, float tension) GdipDrawCurve3;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count) GdipDrawCurveI;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count, float tension) GdipDrawCurve2I;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count, int offset, int numberOfSegments, float tension) GdipDrawCurve3I;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count) GdipDrawClosedCurve;
+Status function(Handle graphics, Handle pen, GpPointF* points, int count, float tension) GdipDrawClosedCurve2;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count) GdipDrawClosedCurveI;
+Status function(Handle graphics, Handle pen, GpPoint* points, int count, float tension) GdipDrawClosedCurve2I;
+Status function(Handle graphics, Handle brush, int x, int y, int width, int height) GdipFillRectangleI;
+Status function(Handle graphics, Handle brush, float x, float y, float width, float height) GdipFillRectangle;
+Status function(Handle graphics, Handle brush, GpRect* rects, int count) GdipFillRectanglesI;
+Status function(Handle graphics, Handle brush, GpRectF* rects, int count) GdipFillRectangles;
+Status function(Handle graphics, Handle brush, GpPointF* rects, int count, FillMode fillMode) GdipFillPolygon;
+Status function(Handle graphics, Handle brush, GpPoint* rects, int count, FillMode fillMode) GdipFillPolygonI;
+Status function(Handle graphics, Handle brush, float x, float y, float width, float height) GdipFillEllipse;
+Status function(Handle graphics, Handle brush, int x, int y, int width, int height) GdipFillEllipseI;
+Status function(Handle graphics, Handle brush, float x, float y, float width, float height, float startAngle, float sweepAngle) GdipFillPie;
+Status function(Handle graphics, Handle brush, int x, int y, int width, int height, float startAngle, float sweepAngle) GdipFillPieI;
+Status function(Handle graphics, Handle brush, Handle path) GdipFillPath;
+Status function(Handle graphics, Handle brush, GpPointF* points, int count) GdipFillClosedCurve;
+Status function(Handle graphics, Handle brush, GpPoint* points, int count) GdipFillClosedCurveI;
+Status function(Handle graphics, Handle brush, GpPointF* points, int count, FillMode fillMode, float tension) GdipFillClosedCurve2;
+Status function(Handle graphics, Handle brush, GpPoint* points, int count, FillMode fillMode, float tension) GdipFillClosedCurve2I;
+Status function(Handle graphics, Handle brush, Handle region) GdipFillRegion;
+Status function(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, Handle brush) GdipDrawString;
+Status function(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, ref GpRectF boundingBox, int* codepointsFitted, int* linesFitted) GdipMeasureString;
+Status function(Handle format, out int count) GdipGetStringFormatMeasurableCharacterRangeCount;
+Status function(Handle format, out Handle newFormat) GdipCloneStringFormat;
+Status function(Handle graphics, wchar* string, int length, Handle font, ref GpRectF layoutRect, Handle stringFormat, int regionCount, Handle* regions) GdipMeasureCharacterRanges;
+Status function(Handle graphics, Handle image, float x, float y) GdipDrawImage;
+Status function(Handle graphics, Handle image, int x, int y) GdipDrawImageI;
+Status function(Handle graphics, Handle image, float x, float y, float width, float height) GdipDrawImageRect;
+Status function(Handle graphics, Handle image, int x, int y, int width, int height) GdipDrawImageRectI;
+Status function(Handle graphics, Handle image, float x, float y, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit) GdipDrawImagePointRect;
+Status function(Handle graphics, Handle image, int x, int y, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit) GdipDrawImagePointRectI;
+Status function(Handle graphics, Handle image, float dstx, float dsty, float dstwidth, float dstheight, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData) GdipDrawImageRectRect;
+Status function(Handle graphics, Handle image, int dstx, int dsty, int dstwidth, int dstheight, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData) GdipDrawImageRectRectI;
+Status function(Handle graphics, Handle image, GpPointF* dstpoints, int count) GdipDrawImagePoints;
+Status function(Handle graphics, Handle image, GpPoint* dstpoints, int count) GdipDrawImagePointsI;
+Status function(Handle graphics, Handle image, GpPointF* dstpoints, int count, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData) GdipDrawImagePointsRect;
+Status function(Handle graphics, Handle image, GpPoint* dstpoints, int count, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcUnit, Handle imageAttributes, GpDrawImageAbort callback, void* callbakcData) GdipDrawImagePointsRectI;
+Status function(Handle graphics, float x, float y, out int result) GdipIsVisiblePoint;
+Status function(Handle graphics, int x, int y, out int result) GdipIsVisiblePointI;
+Status function(Handle graphics, float x, float y, float width, float height, out int result) GdipIsVisibleRect;
+Status function(Handle graphics, int x, int y, int width, int height, out int result) GdipIsVisibleRectI;
+Status function(Handle graphics, out TextRenderingHint mode) GdipGetTextRenderingHint;
+Status function(Handle graphics, TextRenderingHint mode) GdipSetTextRenderingHint;
+Status function(Handle graphics, out GpRectF rect) GdipGetClipBounds;
+Status function(Handle graphics, out GpRect rect) GdipGetClipBoundsI;
+Status function(Handle graphics, out GpRectF rect) GdipGetVisibleClipBounds;
+Status function(Handle graphics, out GpRect rect) GdipGetVisibleClipBoundsI;
+Status function(Handle graphics, out int result) GdipIsClipEmpty;
+Status function(Handle graphics, out int result) GdipIsVisibleClipEmpty;
+Status function(Handle graphics, out int x, out int y) GdipGetRenderingOrigin;
+Status function(Handle graphics, int x, int y) GdipSetRenderingOrigin;
+Status function(Handle graphics, ref int argb) GdipGetNearestColor;
+Status function(Handle graphics, uint sizeData, ubyte* data) GdipComment;
+Status function(Handle graphics, CoordinateSpace destSpace, CoordinateSpace srcSpace, GpPointF* points, int count) GdipTransformPoints;
+Status function(Handle graphics, CoordinateSpace destSpace, CoordinateSpace srcSpace, GpPoint* points, int count) GdipTransformPointsI;
+Status function(out Handle matrix) GdipCreateMatrix;
+Status function(float m11, float m12, float m21, float m22, float dx, float dy, out Handle matrix) GdipCreateMatrix2;
+Status function(ref GpRectF rect, GpPointF* dstplg, out Handle matrix) GdipCreateMatrix3;
+Status function(ref GpRect rect, GpPoint* dstplg, out Handle matrix) GdipCreateMatrix3I;
+Status function(Handle matrix) GdipDeleteMatrix;
+Status function(Handle matrix, out Handle cloneMatrix) GdipCloneMatrix;
+Status function(Handle matrix, float* matrixOut) GdipGetMatrixElements;
+Status function(Handle matrix, float m11, float m12, float m21, float m22, float xy, float dy) GdipSetMatrixElements;
+Status function(Handle matrix) GdipInvertMatrix;
+Status function(Handle matrix, Handle matrix2, MatrixOrder order) GdipMultiplyMatrix;
+Status function(Handle matrix, float scaleX, float scaleY, MatrixOrder order) GdipScaleMatrix;
+Status function(Handle matrix, float shearX, float shearY, MatrixOrder order) GdipShearMatrix;
+Status function(Handle matrix, float angle, MatrixOrder order) GdipRotateMatrix;
+Status function(Handle matrix, float offsetX, float offsetY, MatrixOrder order) GdipTranslateMatrix;
+Status function(Handle matrix, out int result) GdipIsMatrixIdentity;
+Status function(Handle matrix, out int result) GdipIsMatrixInvertible;
+Status function(Handle matrix, GpPointF *pts, int count) GdipTransformMatrixPoints;
+Status function(Handle brush, out BrushType type ) GdipGetBrushType;
+Status function(Handle brush, out Handle cloneBrush) GdipCloneBrush;
+Status function(Handle brush) GdipDeleteBrush;
+Status function(int color, out Handle brush) GdipCreateSolidFill;
+Status function(Handle brush, out int color) GdipGetSolidFillColor;
+Status function(Handle brush, int color) GdipSetSolidFillColor;
+Status function(Handle image, WrapMode wrapMode, out Handle texture) GdipCreateTexture;
+Status function(Handle image, WrapMode wrapMode, float x, float y, float width, float height, out Handle texture) GdipCreateTexture2;
+Status function(Handle image, WrapMode wrapMode, int x, int y, int width, int height, out Handle texture) GdipCreateTexture2I;
+Status function(Handle brush, out Handle image) GdipGetTextureImage;
+Status function(Handle brush, out Handle matrix) GdipGetTextureTransform;
+Status function(Handle brush, Handle matrix) GdipSetTextureTransform;
+Status function(Handle brush, out WrapMode wrapmode) GdipGetTextureWrapMode;
+Status function(Handle brush, WrapMode wrapmode) GdipSetTextureWrapMode;
+Status function(HatchStyle hatchstyle, int forecol, int backcol, out Handle brush) GdipCreateHatchBrush;
+Status function(Handle brush, out HatchStyle hatchstyle) GdipGetHatchStyle;
+Status function(Handle brush, out int forecol) GdipGetHatchForegroundColor;
+Status function(Handle brush, out int backcol) GdipGetHatchBackgroundColor;
+Status function(ref GpPoint point1, ref GpPoint point2, int color1, int color2, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrushI;
+Status function(ref GpPointF point1, ref GpPointF point2, int color1, int color2, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrush;
+Status function(ref GpRect rect, int color1, int color2, LinearGradientMode mode, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrushFromRectI;
+Status function(ref GpRectF rect, int color1, int color2, LinearGradientMode mode, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrushFromRect;
+Status function(ref GpRect rect, int color1, int color2, float angle, int isAngleScalable, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrushFromRectWithAngleI;
+Status function(ref GpRectF rect, int color1, int color2, float angle, int isAngleScalable, WrapMode wrapMode, out Handle lineGradient) GdipCreateLineBrushFromRectWithAngle;
+Status function(Handle brush, out int count) GdipGetLineBlendCount;
+Status function(Handle brush, float* blend, float* positions, int count) GdipGetLineBlend;
+Status function(Handle brush, float* blend, float* positions, int count) GdipSetLineBlend;
+Status function(Handle brush, out int count) GdipGetLinePresetBlendCount;
+Status function(Handle brush, uint* blend, float* positions, int count) GdipGetLinePresetBlend;
+Status function(Handle brush, uint* blend, float* positions, int count) GdipSetLinePresetBlend;
+Status function(Handle brush, out WrapMode wrapmode) GdipGetLineWrapMode;
+Status function(Handle brush, WrapMode wrapmode) GdipSetLineWrapMode;
+Status function(Handle brush, out GpRectF rect) GdipGetLineRect;
+Status function(Handle brush, int* colors) GdipGetLineColors;
+Status function(Handle brush, int color1, int color2) GdipSetLineColors;
+Status function(Handle brush, out int useGammaCorrection) GdipGetLineGammaCorrection;
+Status function(Handle brush, int useGammaCorrection) GdipSetLineGammaCorrection;
+Status function(Handle brush, float focus, float scale) GdipSetLineSigmaBlend;
+Status function(Handle brush, float focus, float scale) GdipSetLineLinearBlend;
+Status function(Handle brush, out Handle matrix) GdipGetLineTransform;
+Status function(Handle brush, Handle matrix) GdipSetLineTransform;
+Status function(Handle brush) GdipResetLineTransform;
+Status function(Handle brush, Handle matrix, MatrixOrder order) GdipMultiplyLineTransform;
+Status function(Handle brush, float dx, float dy, MatrixOrder order) GdipTranslateLineTransform;
+Status function(Handle brush, float sx, float sy, MatrixOrder order) GdipScaleLineTransform;
+Status function(Handle brush, float angle, MatrixOrder order) GdipRotateLineTransform;
+Status function(int argb, float width, GraphicsUnit unit, out Handle pen) GdipCreatePen1;
+Status function(Handle brush, float width, GraphicsUnit unit, out Handle pen) GdipCreatePen2;
+Status function(Handle pen) GdipDeletePen;
+Status function(Handle pen, out Handle clonepen) GdipClonePen;
+Status function(Handle pen, LineCap startCap, LineCap endCap, DashCap dashCap) GdipSetPenLineCap197819;
+Status function(Handle pen, out LineCap startCap) GdipGetPenStartCap;
+Status function(Handle pen, LineCap startCap) GdipSetPenStartCap;
+Status function(Handle pen, out LineCap endCap) GdipGetPenEndCap;
+Status function(Handle pen, LineCap endCap) GdipSetPenEndCap;
+Status function(Handle pen, out DashCap endCap) GdipGetPenDashCap197819;
+Status function(Handle pen, DashCap endCap) GdipSetPenDashCap197819;
+Status function(Handle pen, out LineJoin lineJoin) GdipGetPenLineJoin;
+Status function(Handle pen, LineJoin lineJoin) GdipSetPenLineJoin;
+Status function(Handle pen, out float miterLimit) GdipGetPenMiterLimit;
+Status function(Handle pen, float miterLimit) GdipSetPenMiterLimit;
+Status function(Handle pen, out PenAlignment penMode) GdipGetPenMode;
+Status function(Handle pen, PenAlignment penMode) GdipSetPenMode;
+Status function(Handle pen, out Handle matrix) GdipGetPenTransform;
+Status function(Handle pen, Handle matrix) GdipSetPenTransform;
+Status function(Handle pen) GdipResetPenTransform;
+Status function(Handle pen, Handle matrix, MatrixOrder order) GdipMultiplyPenTransform;
+Status function(Handle pen, float dx, float dy, MatrixOrder order) GdipTranslatePenTransform;
+Status function(Handle pen, float sx, float sy, MatrixOrder order) GdipScalePenTransform;
+Status function(Handle pen, float angle, MatrixOrder order) GdipRotatePenTransform;
+Status function(Handle pen, out int argb) GdipGetPenColor;
+Status function(Handle pen, int argb) GdipSetPenColor;
+Status function(Handle pen, out float width) GdipGetPenWidth;
+Status function(Handle pen, float width) GdipSetPenWidth;
+Status function(Handle pen, out PenType type) GdipGetPenFillType;
+Status function(Handle pen, out Handle brush) GdipGetPenBrushFill;
+Status function(Handle pen, Handle brush) GdipSetPenBrushFill;
+Status function(Handle pen, out DashStyle dashstyle) GdipGetPenDashStyle;
+Status function(Handle pen, DashStyle dashstyle) GdipSetPenDashStyle;
+Status function(Handle pen, out float offset) GdipGetPenDashOffset;
+Status function(Handle pen, float offset) GdipSetPenDashOffset;
+Status function(Handle pen, out int count) GdipGetPenDashCount;
+Status function(Handle pen, float* dash, int count) GdipGetPenDashArray;
+Status function(Handle pen, float* dash, int count) GdipSetPenDashArray;
+Status function(Handle pen, out int count) GdipGetPenCompoundCount;
+Status function(Handle pen, float* dash, int count) GdipGetPenCompoundArray;
+Status function(Handle pen, float* dash, int count) GdipSetPenCompoundArray;
+Status function(out Handle region) GdipCreateRegion;
+Status function(ref GpRectF rect, out Handle region) GdipCreateRegionRect;
+Status function(ref GpRect rect, out Handle region) GdipCreateRegionRectI;
+Status function(Handle path, out Handle region) GdipCreateRegionPath;
+Status function(Handle hRgn, out Handle region) GdipCreateRegionHrgn;
+Status function(Handle region) GdipDeleteRegion;
+Status function(Handle region) GdipSetInfinite;
+Status function(Handle region) GdipSetEmpty;
+Status function(Handle region, ref GpRectF rect, CombineMode combineMode) GdipCombineRegionRect;
+Status function(Handle region, ref GpRect rect, CombineMode combineMode) GdipCombineRegionRectI;
+Status function(Handle region, Handle path, CombineMode combineMode) GdipCombineRegionPath;
+Status function(Handle region, Handle region, CombineMode combineMode) GdipCombineRegionRegion;
+Status function(Handle region, float dx, float dy) GdipTranslateRegion;
+Status function(Handle region, int dx, int dy) GdipTranslateRegionI;
+Status function(Handle region, Handle matrix) GdipTransformRegion;
+Status function(Handle region, Handle graphics, out GpRectF rect) GdipGetRegionBounds;
+Status function(Handle region, Handle graphics, out Handle hRgn) GdipGetRegionHRgn;
+Status function(Handle region, Handle graphics, out int result) GdipIsEmptyRegion;
+Status function(Handle region, Handle graphics, out int result) GdipIsInfiniteRegion;
+Status function(Handle region1, Handle region2, Handle graphics, out int result) GdipIsEqualRegion;
+Status function(Handle region, float x, float y, Handle graphics, out int result) GdipIsVisibleRegionPoint;
+Status function(Handle region, float x, float y, float width, float height, Handle graphics, out int result) GdipIsVisibleRegionRect;
+Status function(Handle region, int x, int y, Handle graphics, out int result) GdipIsVisibleRegionPointI;
+Status function(Handle region, int x, int y, int width, int height, Handle graphics, out int result) GdipIsVisibleRegionRectI;
+Status function(Handle region, out int count, Handle matrix) GdipGetRegionScansCount;
+Status function(Handle region, GpRectF* rects, out int count, Handle matrix) GdipGetRegionScans;
+Status function(Handle image) GdipDisposeImage;
+Status function(Handle image) GdipImageForceValidation;
+Status function(wchar* filename, out Handle image) GdipLoadImageFromFileICM;
+Status function(wchar* filename, out Handle image) GdipLoadImageFromFile;
+Status function(out int numEncoders, out int size) GdipGetImageEncodersSize;
+Status function(Handle image, out Handle cloneImage) GdipCloneImage;
+Status function(Handle image, out int type) GdipGetImageType;
+Status function(Handle image, out uint flags) GdipGetImageFlags;
+Status function(Handle image, out uint width) GdipGetImageWidth;
+Status function(Handle image, out uint height) GdipGetImageHeight;
+Status function(Handle image, out float resolution) GdipGetImageHorizontalResolution;
+Status function(Handle image, out float resolution) GdipGetImageVerticalResolution;
+Status function(Handle image, out int numOfProperty) GdipGetPropertyCount;
+Status function(Handle image, int numOfProperty, int* list) GdipGetPropertyIdList;
+Status function(Handle image, out PixelFormat format) GdipGetImagePixelFormat;
+Status function(Handle image, out float width, out float height) GdipGetImageDimension;
+Status function(Handle image, int thumbWidth, int thumbHeight, out Handle thumbImage, GpGetThumbnailImageAbort callback, void* callbackData) GdipGetImageThumbnail;
+Status function(Handle image, out int count) GdipImageGetFrameDimensionsCount;
+Status function(Handle image, RotateFlipType rotateFlipType) GdipImageRotateFlip;
+Status function(Handle image, int propId, out uint propSize) GdipGetPropertyItemSize;
+Status function(Handle image, int propId, uint propSize, GpPropertyItem* buffer) GdipGetPropertyItem;
+Status function(Handle image, ref GpPropertyItem buffer) GdipSetPropertyItem;
+Status function(Handle image, int propId) GdipRemovePropertyItem;
+Status function(Handle image, out uint totalBufferSize, ref int numProperties) GdipGetPropertySize;
+Status function(Handle image, uint totalBufferSize, int numProperties, GpPropertyItem* allItems) GdipGetAllPropertyItems;
+Status function(Handle image, out GpRectF srcRect, out GraphicsUnit srcUnit) GdipGetImageBounds;
+Status function(Handle image, out int size) GdipGetImagePaletteSize;
+Status function(Handle image, GpColorPalette* palette, int size) GdipGetImagePalette;
+Status function(Handle image, GpColorPalette* palette) GdipSetImagePalette;
+Status function(int width, int height, int stride, PixelFormat format, ubyte* scan0, out Handle bitmap) GdipCreateBitmapFromScan0;
+Status function(Handle hbitmap, Handle hpalette, out Handle bitmap) GdipCreateBitmapFromHBITMAP;
+Status function(Handle hicon, out Handle bitmap) GdipCreateBitmapFromHICON;
+Status function(wchar* fileName, out Handle bitmap) GdipCreateBitmapFromFileICM;
+Status function(wchar* fileName, out Handle bitmap) GdipCreateBitmapFromFile;
+Status function(int width, int height, Handle graphics, out Handle bitmap) GdipCreateBitmapFromGraphics;
+Status function(float x, float y, float width, float height, PixelFormat format, Handle srcbitmap, out Handle dstbitmap) GdipCloneBitmapArea;
+Status function(int x, int y, int width, int height, PixelFormat format, Handle srcbitmap, out Handle dstbitmap) GdipCloneBitmapAreaI;
+Status function(Handle bitmap, int x, int y, out int color) GdipBitmapGetPixel;
+Status function(Handle bitmap, int x, int y, int color) GdipBitmapSetPixel;
+Status function(Handle bitmap, GpRect* rect, ImageLockMode flags, PixelFormat format, GpBitmapData* lockedBitmapData) GdipBitmapLockBits;
+Status function(Handle bitmap, GpBitmapData* lockedBitmapData) GdipBitmapUnlockBits;
+Status function(Handle bitmap, float xdpi, float ydpi) GdipBitmapSetResolution;
+Status function(Handle bitmap, out Handle hbmReturn) GdipCreateHICONFromBitmap;
+Status function(Handle bitmap, out Handle hbmReturn, int background) GdipCreateHBITMAPFromBitmap;
+Status function(out Handle imageattr) GdipCreateImageAttributes;
+Status function(Handle imageattr) GdipDisposeImageAttributes;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, GpColorMatrix* colorMatrix, GpColorMatrix* grayMatrix, ColorMatrixFlag flags) GdipSetImageAttributesColorMatrix;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, float threshold) GdipSetImageAttributesThreshold;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, float gamma) GdipSetImageAttributesGamma;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag) GdipSetImageAttributesNoOp;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, int colorLow, int colorHigh) GdipSetImageAttributesColorKeys;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, ColorChannelFlag flags) GdipSetImageAttributesOutputChannel;
+Status function(Handle imageattr, ColorAdjustType type, int enableFlag, wchar* colorProfileFilename) GdipSetImageAttributesOutputChannelColorProfile;
+Status function(Handle imageattr, WrapMode wrap, int argb, int clamp) GdipSetImageAttributesWrapMode;
+Status function(out Handle fontCollection) GdipNewInstalledFontCollection;
+Status function(out Handle fontCollection) GdipNewPrivateFontCollection;
+Status function(Handle fontCollection) GdipDeletePrivateFontCollection;
+Status function(Handle fontCollection, wchar* filename) GdipPrivateAddFontFile;
+Status function(Handle fontCollection, void* memory, int length) GdipPrivateAddMemoryFont;
+Status function(Handle fontCollection, out int numFound) GdipGetFontCollectionFamilyCount;
+Status function(Handle fontCollection, int numSought, Handle* gpfamilies, out int numFound) GdipGetFontCollectionFamilyList;
+Status function(wchar* name, Handle fontCollection, out Handle FontFamily) GdipCreateFontFamilyFromName;
+Status function(Handle FontFamily) GdipDeleteFontFamily;
+Status function(Handle FontFamily, out Handle clonedFontFamily) GdipCloneFontFamily;
+Status function(Handle family, wchar* name, int language) GdipGetFamilyName;
+Status function(out Handle nativeFamily) GdipGetGenericFontFamilyMonospace;
+Status function(out Handle nativeFamily) GdipGetGenericFontFamilySerif;
+Status function(out Handle nativeFamily) GdipGetGenericFontFamilySansSerif;
+Status function(Handle family, FontStyle style, out short EmHeight) GdipGetEmHeight;
+Status function(Handle family, FontStyle style, out short CellAscent) GdipGetCellAscent;
+Status function(Handle family, FontStyle style, out short CellDescent) GdipGetCellDescent;
+Status function(Handle family, FontStyle style, out short LineSpacing) GdipGetLineSpacing;
+Status function(Handle family, FontStyle style, out int IsStyleAvailable) GdipIsStyleAvailable;
+Status function(Handle fontFamily, float emSize, int style, int unit, out Handle font) GdipCreateFont;
+Status function(Handle hdc, out Handle font) GdipCreateFontFromDC;
+Status function(Handle font) GdipDeleteFont;
+Status function(Handle font, out Handle cloneFont) GdipCloneFont;
+Status function(Handle font, out float size) GdipGetFontSize;
+Status function(Handle font, Handle graphics, out float height) GdipGetFontHeight;
+Status function(Handle font, float dpi, out float height) GdipGetFontHeightGivenDPI;
+Status function(Handle font, out FontStyle style) GdipGetFontStyle;
+Status function(Handle font, out GraphicsUnit unit) GdipGetFontUnit;
+Status function(Handle font, out Handle family) GdipGetFamily;
+Status function( Handle hdc, ref LOGFONTW logfont, out Handle font) GdipCreateFontFromLogfontW;
+Status function( Handle hdc, ref LOGFONTA logfont, out Handle font ) GdipCreateFontFromLogfontA;
+Status function(Handle font, Handle graphics, out LOGFONTW logfontW) GdipGetLogFontW;
+Status function(StringFormatFlags formatAttributes, int language, out Handle format) GdipCreateStringFormat;
+Status function(Handle format) GdipDeleteStringFormat;
+Status function(Handle format, out StringFormatFlags flags) GdipGetStringFormatFlags;
+Status function(Handle format, StringFormatFlags flags) GdipSetStringFormatFlags;
+Status function(Handle format, out StringAlignment alignment) GdipGetStringFormatAlign;
+Status function(Handle format, StringAlignment alignment) GdipSetStringFormatAlign;
+Status function(Handle format, out StringAlignment alignment) GdipGetStringFormatLineAlign;
+Status function(Handle format, StringAlignment alignment) GdipSetStringFormatLineAlign;
+Status function(Handle format, out StringTrimming trimming) GdipGetStringFormatTrimming;
+Status function(Handle format, StringTrimming trimming) GdipSetStringFormatTrimming;
+Status function(FillMode brushMode, out Handle path) GdipCreatePath;
+Status function(GpPointF*, ubyte*, int, FillMode, out Handle) GdipCreatePath2;
+Status function(GpPoint*, ubyte*, int, FillMode, out Handle) GdipCreatePath2I;
+Status function(Handle path) GdipDeletePath;
+Status function(Handle path, out Handle clonepath) GdipClonePath;
+Status function(Handle path) GdipResetPath;
+Status function(Handle path, out FillMode fillmode) GdipGetPathFillMode;
+Status function(Handle path, FillMode fillmode) GdipSetPathFillMode;
+Status function(Handle path) GdipStartPathFigure;
+Status function(Handle path) GdipClosePathFigure;
+Status function(Handle path) GdipClosePathFigures;
+Status function(Handle path) GdipSetPathMarker;
+Status function(Handle path) GdipClearPathMarkers;
+Status function(Handle path) GdipReversePath;
+Status function(Handle path, out GpPointF lastPoint) GdipGetPathLastPoint;
+Status function(Handle path, float x1, float y1, float x2, float y2) GdipAddPathLine;
+Status function(Handle path, int x1, int y1, int x2, int y2) GdipAddPathLineI;
+Status function(Handle path, GpPointF* points, int count) GdipAddPathLine2;
+Status function(Handle path, GpPoint* points, int count) GdipAddPathLine2I;
+Status function(Handle path, float x, float y, float width, float height, float startAngle, float sweepAngle) GdipAddPathArc;
+Status function(Handle path, int x, int y, int width, int height, float startAngle, float sweepAngle) GdipAddPathArcI;
+Status function(Handle path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) GdipAddPathBezier;
+Status function(Handle path, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) GdipAddPathBezierI;
+Status function(Handle path, GpPointF* points, int count) GdipAddPathBeziers;
+Status function(Handle path, GpPoint* points, int count) GdipAddPathBeziersI;
+Status function(Handle path, GpPointF* points, int count) GdipAddPathCurve;
+Status function(Handle path, GpPoint* points, int count) GdipAddPathCurveI;
+Status function(Handle path, GpPointF* points, int count, float tension) GdipAddPathCurve2;
+Status function(Handle path, GpPoint* points, int count, float tension) GdipAddPathCurve2I;
+Status function(Handle path, GpPointF* points, int count, int offset, int numberOfSegments, float tension) GdipAddPathCurve3;
+Status function(Handle path, GpPoint* points, int count, int offset, int numberOfSegments, float tension) GdipAddPathCurve3I;
+Status function(Handle path, GpPointF* points, int count) GdipAddPathClosedCurve;
+Status function(Handle path, GpPoint* points, int count) GdipAddPathClosedCurveI;
+Status function(Handle path, GpPointF* points, int count, float tension) GdipAddPathClosedCurve2;
+Status function(Handle path, GpPoint* points, int count, float tension) GdipAddPathClosedCurve2I;
+Status function(Handle path, float x, float y, float width, float height) GdipAddPathRectangle;
+Status function(Handle path, int x, int y, int width, int height) GdipAddPathRectangleI;
+Status function(Handle path, GpRectF* rects, int count) GdipAddPathRectangles;
+Status function(Handle path, GpRect* rects, int count) GdipAddPathRectanglesI;
+Status function(Handle path, float x, float y, float width, float height) GdipAddPathEllipse;
+Status function(Handle path, int x, int y, int width, int height) GdipAddPathEllipseI;
+Status function(Handle path, float x, float y, float width, float height, float startAngle, float sweepAngle) GdipAddPathPie;
+Status function(Handle path, int x, int y, int width, int height, float startAngle, float sweepAngle) GdipAddPathPieI;
+Status function(Handle path, GpPointF* points, int count) GdipAddPathPolygon;
+Status function(Handle path, GpPoint* points, int count) GdipAddPathPolygonI;
+Status function(Handle path, Handle addingPath, int connect) GdipAddPathPath;
+Status function(Handle path, wchar* string, int length, Handle family, FontStyle style, float emSize, ref GpRectF layoutRect, Handle format) GdipAddPathString;
+Status function(Handle path, wchar* string, int length, Handle family, FontStyle style, float emSize, ref GpRect layoutRect, Handle format) GdipAddPathStringI;
+Status function(Handle path, Handle matrix) GdipTransformPath;
+Status function(Handle path, out GpRectF bounds, Handle matrix, Handle pen) GdipGetPathWorldBounds;
+Status function(Handle path, Handle matrix, float flatness) GdipFlattenPath;
+Status function(Handle path, Handle pen, Handle matrix, float flatness) GdipWidenPath;
+Status function(Handle path, Handle matrix, float flatness) GdipWindingModeOutline;
+Status function(Handle path, Handle matrix, GpPointF* points, int count, float srcx, float srcy, float srcwidth, float srcwidth, WarpMode warpMode, float flatness) GdipWarpPath;
+Status function(Handle path, out int count) GdipGetPointCount;
+Status function(Handle path, byte* types, int count) GdipGetPathTypes;
+Status function(Handle path, GpPointF* points, int count) GdipGetPathPoints;
+Status function(Handle path, float x, float y, Handle graphics, out int result) GdipIsVisiblePathPoint;
+Status function(Handle path, int x, int y, Handle graphics, out int result) GdipIsVisiblePathPointI;
+Status function(Handle path, float x, float y, Handle pen, Handle graphics, out int result) GdipIsOutlineVisiblePathPoint;
+Status function(Handle path, int x, int y, Handle pen, Handle graphics, out int result) GdipIsOutlineVisiblePathPointI;
+Status function(Handle graphics, Handle pen, Handle path) GdipDrawPath;
+Status function(out Handle iterator, Handle path) GdipCreatePathIter;
+Status function(Handle iterator) GdipDeletePathIter;
+Status function(Handle iterator, out int resultCount, out int startIndex, out int endIndex, out int isClosed) GdipPathIterNextSubpath;
+Status function(Handle iterator, out int resultCount, Handle path, out int isClosed) GdipPathIterNextSubpathPath;
+Status function(Handle iterator, out int resultCount, out ubyte pathType, out int startIndex, out int endIndex) GdipPathIterNextPathType;
+Status function(Handle iterator, out int resultCount, out int startIndex, out int endIndex) GdipPathIterNextMarker;
+Status function(Handle iterator, out int resultCount, Handle path) GdipPathIterNextMarkerPath;
+Status function(Handle iterator, out int count) GdipPathIterGetCount;
+Status function(Handle iterator, out int count) GdipPathIterGetSubpathCount;
+Status function(Handle iterator, out int hasCurve) GdipPathIterHasCurve;
+Status function(Handle iterator) GdipPathIterRewind;
+Status function(Handle iterator, out int resultCount, GpPointF* points, ubyte* types, int count) GdipPathIterEnumerate;
+Status function(Handle iterator, out int resultCount, GpPointF* points, ubyte* types, int startIndex, int endIndex) GdipPathIterCopyData;
+Status function(GpPointF* points, int count, WrapMode wrapMode, out Handle polyGradient) GdipCreatePathGradient;
+Status function(GpPoint* points, int count, WrapMode wrapMode, out Handle polyGradient) GdipCreatePathGradientI;
+Status function(Handle path, out Handle polyGradient) GdipCreatePathGradientFromPath;
+Status function(Handle brush, out int colors) GdipGetPathGradientCenterColor;
+Status function(Handle brush, int colors) GdipSetPathGradientCenterColor;
+Status function(Handle brush, out int count) GdipGetPathGradientSurroundColorCount;
+Status function(Handle brush, int* color, ref int count) GdipGetPathGradientSurroundColorsWithCount;
+Status function(Handle brush, int* color, ref int count) GdipSetPathGradientSurroundColorsWithCount;
+Status function(Handle brush, ref GpPointF point) GdipGetPathGradientCenterPoint;
+Status function(Handle brush, ref GpPointF point) GdipSetPathGradientCenterPoint;
+Status function(Handle brush, ref GpRectF rect) GdipGetPathGradientRect;
+Status function(Handle brush, out int count) GdipGetPathGradientBlendCount;
+Status function(Handle brush, float* blend, float* positions, int count) GdipGetPathGradientBlend;
+Status function(Handle brush, float* blend, float* positions, int count) GdipSetPathGradientBlend;
+Status function(Handle brush, out int count) GdipGetPathGradientPresetBlendCount;
+Status function(Handle brush, int* blend, float* positions, int count) GdipGetPathGradientPresetBlend;
+Status function(Handle brush, int* blend, float* positions, int count) GdipSetPathGradientPresetBlend;
+Status function(Handle brush, float focus, float scale) GdipSetPathGradientSigmaBlend;
+Status function(Handle brush, float focus, float scale) GdipSetPathGradientLinearBlend;
+Status function(Handle brush, out Handle matrix) GdipGetPathGradientTransform;
+Status function(Handle brush, Handle matrix) GdipSetPathGradientTransform;
+Status function(Handle brush) GdipResetPathGradientTransform;
+Status function(Handle brush, Handle matrix, MatrixOrder order) GdipMultiplyPathGradientTransform;
+Status function(Handle brush, float angle, MatrixOrder order) GdipRotatePathGradientTransform;
+Status function(Handle brush, float dx, float dy, MatrixOrder order) GdipTranslatePathGradientTransform;
+Status function(Handle brush, float sx, float sy, MatrixOrder order) GdipScalePathGradientTransform;
+Status function(Handle brush, out float xScale, out float yScale) GdipGetPathGradientFocusScales;
+Status function(Handle brush, float xScale, float yScale) GdipSetPathGradientFocusScales;
+Status function(Handle brush, out WrapMode wrapMode) GdipGetPathGradientWrapMode;
+Status function(Handle brush, WrapMode wrapMode) GdipSetPathGradientWrapMode;
+Status function( Handle brush ) GdipResetTextureTransform;
+Status function( Handle brush, float sx, float sy, MatrixOrder order ) GdipScaleTextureTransform;
+Status function( Handle brush, float dx, float dy, MatrixOrder order) GdipTranslateTextureTransform;
+Status function(out Handle format) GdipStringFormatGetGenericDefault;
+Status function(out Handle format) GdipStringFormatGetGenericTypographic;
+Status function(Handle format, int hotkeyPrefix) GdipSetStringFormatHotkeyPrefix;
+Status function( Handle format, float firstTabOffset, int count, float* tabStops) GdipSetStringFormatTabStops;
+
+struct Symbol {
+    char[] name;
+    void** symbol;
+}
+
+Symbol[] symbols = [
+    { "GdiplusStartup", cast(void**)& GdiplusStartup },
+    { "GdiplusShutdown", cast(void**)& GdiplusShutdown },
+    { "GdipCreateFromHDC", cast(void**)& GdipCreateFromHDC },
+    { "GdipCreateFromHDC2", cast(void**)& GdipCreateFromHDC2 },
+    { "GdipCreateFromHWND", cast(void**)& GdipCreateFromHWND },
+    { "GdipGetImageGraphicsContext", cast(void**)& GdipGetImageGraphicsContext },
+    { "GdipDeleteGraphics", cast(void**)& GdipDeleteGraphics },
+    { "GdipGetDC", cast(void**)& GdipGetDC },
+    { "GdipReleaseDC", cast(void**)& GdipReleaseDC },
+    { "GdipSetClipGraphics", cast(void**)& GdipSetClipGraphics },
+    { "GdipSetClipRectI", cast(void**)& GdipSetClipRectI },
+    { "GdipSetClipRect", cast(void**)& GdipSetClipRect },
+    { "GdipSetClipPath", cast(void**)& GdipSetClipPath },
+    { "GdipSetClipRegion", cast(void**)& GdipSetClipRegion },
+    { "GdipSetClipHrgn", cast(void**)& GdipSetClipHrgn },
+    { "GdipGetClip", cast(void**)& GdipGetClip },
+    { "GdipResetClip", cast(void**)& GdipResetClip },
+    { "GdipSaveGraphics", cast(void**)& GdipSaveGraphics },
+    { "GdipRestoreGraphics", cast(void**)& GdipRestoreGraphics },
+    { "GdipFlush", cast(void**)& GdipFlush },
+    { "GdipScaleWorldTransform", cast(void**)& GdipScaleWorldTransform },
+    { "GdipRotateWorldTransform", cast(void**)& GdipRotateWorldTransform },
+    { "GdipTranslateWorldTransform", cast(void**)& GdipTranslateWorldTransform },
+    { "GdipMultiplyWorldTransform", cast(void**)& GdipMultiplyWorldTransform },
+    { "GdipResetWorldTransform", cast(void**)& GdipResetWorldTransform },
+    { "GdipBeginContainer", cast(void**)& GdipBeginContainer },
+    { "GdipBeginContainerI", cast(void**)& GdipBeginContainerI },
+    { "GdipBeginContainer2", cast(void**)& GdipBeginContainer2 },
+    { "GdipEndContainer", cast(void**)& GdipEndContainer },
+    { "GdipGetDpiX", cast(void**)& GdipGetDpiX },
+    { "GdipGetDpiY", cast(void**)& GdipGetDpiY },
+    { "GdipGetPageUnit", cast(void**)& GdipGetPageUnit },
+    { "GdipSetPageUnit", cast(void**)& GdipSetPageUnit },
+    { "GdipGetPageScale", cast(void**)& GdipGetPageScale },
+    { "GdipSetPageScale", cast(void**)& GdipSetPageScale },
+    { "GdipGetWorldTransform", cast(void**)& GdipGetWorldTransform },
+    { "GdipSetWorldTransform", cast(void**)& GdipSetWorldTransform },
+    { "GdipGetCompositingMode", cast(void**)& GdipGetCompositingMode },
+    { "GdipSetCompositingMode", cast(void**)& GdipSetCompositingMode },
+    { "GdipGetCompositingQuality", cast(void**)& GdipGetCompositingQuality },
+    { "GdipSetCompositingQuality", cast(void**)& GdipSetCompositingQuality },
+    { "GdipGetInterpolationMode", cast(void**)& GdipGetInterpolationMode },
+    { "GdipSetInterpolationMode", cast(void**)& GdipSetInterpolationMode },
+    { "GdipGetSmoothingMode", cast(void**)& GdipGetSmoothingMode },
+    { "GdipSetSmoothingMode", cast(void**)& GdipSetSmoothingMode },
+    { "GdipGetPixelOffsetMode", cast(void**)& GdipGetPixelOffsetMode },
+    { "GdipSetPixelOffsetMode", cast(void**)& GdipSetPixelOffsetMode },
+    { "GdipGetTextContrast", cast(void**)& GdipGetTextContrast },
+    { "GdipSetTextContrast", cast(void**)& GdipSetTextContrast },
+    { "GdipGraphicsClear", cast(void**)& GdipGraphicsClear },
+    { "GdipDrawLine", cast(void**)& GdipDrawLine },
+    { "GdipDrawLines", cast(void**)& GdipDrawLines },
+    { "GdipDrawLineI", cast(void**)& GdipDrawLineI },
+    { "GdipDrawLinesI", cast(void**)& GdipDrawLinesI },
+    { "GdipDrawArc", cast(void**)& GdipDrawArc },
+    { "GdipDrawArcI", cast(void**)& GdipDrawArcI },
+    { "GdipDrawBezier", cast(void**)& GdipDrawBezier },
+    { "GdipDrawBeziers", cast(void**)& GdipDrawBeziers },
+    { "GdipDrawBezierI", cast(void**)& GdipDrawBezierI },
+    { "GdipDrawBeziersI", cast(void**)& GdipDrawBeziersI },
+    { "GdipDrawRectangle", cast(void**)& GdipDrawRectangle },
+    { "GdipDrawRectangles", cast(void**)& GdipDrawRectangles },
+    { "GdipDrawRectangleI", cast(void**)& GdipDrawRectangleI },
+    { "GdipDrawRectanglesI", cast(void**)& GdipDrawRectanglesI },
+    { "GdipDrawEllipse", cast(void**)& GdipDrawEllipse },
+    { "GdipDrawEllipseI", cast(void**)& GdipDrawEllipseI },
+    { "GdipDrawPie", cast(void**)& GdipDrawPie },
+    { "GdipDrawPieI", cast(void**)& GdipDrawPieI },
+    { "GdipDrawPolygon", cast(void**)& GdipDrawPolygon },
+    { "GdipDrawPolygonI", cast(void**)& GdipDrawPolygonI },
+    { "GdipDrawCurve", cast(void**)& GdipDrawCurve },
+    { "GdipDrawCurve2", cast(void**)& GdipDrawCurve2 },
+    { "GdipDrawCurve3", cast(void**)& GdipDrawCurve3 },
+    { "GdipDrawCurveI", cast(void**)& GdipDrawCurveI },
+    { "GdipDrawCurve2I", cast(void**)& GdipDrawCurve2I },
+    { "GdipDrawCurve3I", cast(void**)& GdipDrawCurve3I },
+    { "GdipDrawClosedCurve", cast(void**)& GdipDrawClosedCurve },
+    { "GdipDrawClosedCurve2", cast(void**)& GdipDrawClosedCurve2 },
+    { "GdipDrawClosedCurveI", cast(void**)& GdipDrawClosedCurveI },
+    { "GdipDrawClosedCurve2I", cast(void**)& GdipDrawClosedCurve2I },
+    { "GdipFillRectangleI", cast(void**)& GdipFillRectangleI },
+    { "GdipFillRectangle", cast(void**)& GdipFillRectangle },
+    { "GdipFillRectanglesI", cast(void**)& GdipFillRectanglesI },
+    { "GdipFillRectangles", cast(void**)& GdipFillRectangles },
+    { "GdipFillPolygon", cast(void**)& GdipFillPolygon },
+    { "GdipFillPolygonI", cast(void**)& GdipFillPolygonI },
+    { "GdipFillEllipse", cast(void**)& GdipFillEllipse },
+    { "GdipFillEllipseI", cast(void**)& GdipFillEllipseI },
+    { "GdipFillPie", cast(void**)& GdipFillPie },
+    { "GdipFillPieI", cast(void**)& GdipFillPieI },
+    { "GdipFillPath", cast(void**)& GdipFillPath },
+    { "GdipFillClosedCurve", cast(void**)& GdipFillClosedCurve },
+    { "GdipFillClosedCurveI", cast(void**)& GdipFillClosedCurveI },
+    { "GdipFillClosedCurve2", cast(void**)& GdipFillClosedCurve2 },
+    { "GdipFillClosedCurve2I", cast(void**)& GdipFillClosedCurve2I },
+    { "GdipFillRegion", cast(void**)& GdipFillRegion },
+    { "GdipDrawString", cast(void**)& GdipDrawString },
+    { "GdipMeasureString", cast(void**)& GdipMeasureString },
+    { "GdipGetStringFormatMeasurableCharacterRangeCount", cast(void**)& GdipGetStringFormatMeasurableCharacterRangeCount },
+    { "GdipCloneStringFormat", cast(void**)& GdipCloneStringFormat },
+    { "GdipMeasureCharacterRanges", cast(void**)& GdipMeasureCharacterRanges },
+    { "GdipDrawImage", cast(void**)& GdipDrawImage },
+    { "GdipDrawImageI", cast(void**)& GdipDrawImageI },
+    { "GdipDrawImageRect", cast(void**)& GdipDrawImageRect },
+    { "GdipDrawImageRectI", cast(void**)& GdipDrawImageRectI },
+    { "GdipDrawImagePointRect", cast(void**)& GdipDrawImagePointRect },
+    { "GdipDrawImagePointRectI", cast(void**)& GdipDrawImagePointRectI },
+    { "GdipDrawImageRectRect", cast(void**)& GdipDrawImageRectRect },
+    { "GdipDrawImageRectRectI", cast(void**)& GdipDrawImageRectRectI },
+    { "GdipDrawImagePoints", cast(void**)& GdipDrawImagePoints },
+    { "GdipDrawImagePointsI", cast(void**)& GdipDrawImagePointsI },
+    { "GdipDrawImagePointsRect", cast(void**)& GdipDrawImagePointsRect },
+    { "GdipDrawImagePointsRectI", cast(void**)& GdipDrawImagePointsRectI },
+    { "GdipIsVisiblePoint", cast(void**)& GdipIsVisiblePoint },
+    { "GdipIsVisiblePointI", cast(void**)& GdipIsVisiblePointI },
+    { "GdipIsVisibleRect", cast(void**)& GdipIsVisibleRect },
+    { "GdipIsVisibleRectI", cast(void**)& GdipIsVisibleRectI },
+    { "GdipGetTextRenderingHint", cast(void**)& GdipGetTextRenderingHint },
+    { "GdipSetTextRenderingHint", cast(void**)& GdipSetTextRenderingHint },
+    { "GdipGetClipBounds", cast(void**)& GdipGetClipBounds },
+    { "GdipGetClipBoundsI", cast(void**)& GdipGetClipBoundsI },
+    { "GdipGetVisibleClipBounds", cast(void**)& GdipGetVisibleClipBounds },
+    { "GdipGetVisibleClipBoundsI", cast(void**)& GdipGetVisibleClipBoundsI },
+    { "GdipIsClipEmpty", cast(void**)& GdipIsClipEmpty },
+    { "GdipIsVisibleClipEmpty", cast(void**)& GdipIsVisibleClipEmpty },
+    { "GdipGetRenderingOrigin", cast(void**)& GdipGetRenderingOrigin },
+    { "GdipSetRenderingOrigin", cast(void**)& GdipSetRenderingOrigin },
+    { "GdipGetNearestColor", cast(void**)& GdipGetNearestColor },
+    { "GdipComment", cast(void**)& GdipComment },
+    { "GdipTransformPoints", cast(void**)& GdipTransformPoints },
+    { "GdipTransformPointsI", cast(void**)& GdipTransformPointsI },
+    { "GdipCreateMatrix", cast(void**)& GdipCreateMatrix },
+    { "GdipCreateMatrix2", cast(void**)& GdipCreateMatrix2 },
+    { "GdipCreateMatrix3", cast(void**)& GdipCreateMatrix3 },
+    { "GdipCreateMatrix3I", cast(void**)& GdipCreateMatrix3I },
+    { "GdipDeleteMatrix", cast(void**)& GdipDeleteMatrix },
+    { "GdipCloneMatrix", cast(void**)& GdipCloneMatrix },
+    { "GdipGetMatrixElements", cast(void**)& GdipGetMatrixElements },
+    { "GdipSetMatrixElements", cast(void**)& GdipSetMatrixElements },
+    { "GdipInvertMatrix", cast(void**)& GdipInvertMatrix },
+    { "GdipMultiplyMatrix", cast(void**)& GdipMultiplyMatrix },
+    { "GdipScaleMatrix", cast(void**)& GdipScaleMatrix },
+    { "GdipShearMatrix", cast(void**)& GdipShearMatrix },
+    { "GdipRotateMatrix", cast(void**)& GdipRotateMatrix },
+    { "GdipTranslateMatrix", cast(void**)& GdipTranslateMatrix },
+    { "GdipIsMatrixIdentity", cast(void**)& GdipIsMatrixIdentity },
+    { "GdipIsMatrixInvertible", cast(void**)& GdipIsMatrixInvertible },
+    { "GdipTransformMatrixPoints", cast(void**)& GdipTransformMatrixPoints },
+    { "GdipGetBrushType", cast(void**)& GdipGetBrushType },
+    { "GdipCloneBrush", cast(void**)& GdipCloneBrush },
+    { "GdipDeleteBrush", cast(void**)& GdipDeleteBrush },
+    { "GdipCreateSolidFill", cast(void**)& GdipCreateSolidFill },
+    { "GdipGetSolidFillColor", cast(void**)& GdipGetSolidFillColor },
+    { "GdipSetSolidFillColor", cast(void**)& GdipSetSolidFillColor },
+    { "GdipCreateTexture", cast(void**)& GdipCreateTexture },
+    { "GdipCreateTexture2", cast(void**)& GdipCreateTexture2 },
+    { "GdipCreateTexture2I", cast(void**)& GdipCreateTexture2I },
+    { "GdipGetTextureImage", cast(void**)& GdipGetTextureImage },
+    { "GdipGetTextureTransform", cast(void**)& GdipGetTextureTransform },
+    { "GdipSetTextureTransform", cast(void**)& GdipSetTextureTransform },
+    { "GdipGetTextureWrapMode", cast(void**)& GdipGetTextureWrapMode },
+    { "GdipSetTextureWrapMode", cast(void**)& GdipSetTextureWrapMode },
+    { "GdipCreateHatchBrush", cast(void**)& GdipCreateHatchBrush },
+    { "GdipGetHatchStyle", cast(void**)& GdipGetHatchStyle },
+    { "GdipGetHatchForegroundColor", cast(void**)& GdipGetHatchForegroundColor },
+    { "GdipGetHatchBackgroundColor", cast(void**)& GdipGetHatchBackgroundColor },
+    { "GdipCreateLineBrushI", cast(void**)& GdipCreateLineBrushI },
+    { "GdipCreateLineBrush", cast(void**)& GdipCreateLineBrush },
+    { "GdipCreateLineBrushFromRectI", cast(void**)& GdipCreateLineBrushFromRectI },
+    { "GdipCreateLineBrushFromRect", cast(void**)& GdipCreateLineBrushFromRect },
+    { "GdipCreateLineBrushFromRectWithAngleI", cast(void**)& GdipCreateLineBrushFromRectWithAngleI },
+    { "GdipCreateLineBrushFromRectWithAngle", cast(void**)& GdipCreateLineBrushFromRectWithAngle },
+    { "GdipGetLineBlendCount", cast(void**)& GdipGetLineBlendCount },
+    { "GdipGetLineBlend", cast(void**)& GdipGetLineBlend },
+    { "GdipSetLineBlend", cast(void**)& GdipSetLineBlend },
+    { "GdipGetLinePresetBlendCount", cast(void**)& GdipGetLinePresetBlendCount },
+    { "GdipGetLinePresetBlend", cast(void**)& GdipGetLinePresetBlend },
+    { "GdipSetLinePresetBlend", cast(void**)& GdipSetLinePresetBlend },
+    { "GdipGetLineWrapMode", cast(void**)& GdipGetLineWrapMode },
+    { "GdipSetLineWrapMode", cast(void**)& GdipSetLineWrapMode },
+    { "GdipGetLineRect", cast(void**)& GdipGetLineRect },
+    { "GdipGetLineColors", cast(void**)& GdipGetLineColors },
+    { "GdipSetLineColors", cast(void**)& GdipSetLineColors },
+    { "GdipGetLineGammaCorrection", cast(void**)& GdipGetLineGammaCorrection },
+    { "GdipSetLineGammaCorrection", cast(void**)& GdipSetLineGammaCorrection },
+    { "GdipSetLineSigmaBlend", cast(void**)& GdipSetLineSigmaBlend },
+    { "GdipSetLineLinearBlend", cast(void**)& GdipSetLineLinearBlend },
+    { "GdipGetLineTransform", cast(void**)& GdipGetLineTransform },
+    { "GdipSetLineTransform", cast(void**)& GdipSetLineTransform },
+    { "GdipResetLineTransform", cast(void**)& GdipResetLineTransform },
+    { "GdipMultiplyLineTransform", cast(void**)& GdipMultiplyLineTransform },
+    { "GdipTranslateLineTransform", cast(void**)& GdipTranslateLineTransform },
+    { "GdipScaleLineTransform", cast(void**)& GdipScaleLineTransform },
+    { "GdipRotateLineTransform", cast(void**)& GdipRotateLineTransform },
+    { "GdipCreatePen1", cast(void**)& GdipCreatePen1 },
+    { "GdipCreatePen2", cast(void**)& GdipCreatePen2 },
+    { "GdipDeletePen", cast(void**)& GdipDeletePen },
+    { "GdipClonePen", cast(void**)& GdipClonePen },
+    { "GdipSetPenLineCap197819", cast(void**)& GdipSetPenLineCap197819 },
+    { "GdipGetPenStartCap", cast(void**)& GdipGetPenStartCap },
+    { "GdipSetPenStartCap", cast(void**)& GdipSetPenStartCap },
+    { "GdipGetPenEndCap", cast(void**)& GdipGetPenEndCap },
+    { "GdipSetPenEndCap", cast(void**)& GdipSetPenEndCap },
+    { "GdipGetPenDashCap197819", cast(void**)& GdipGetPenDashCap197819 },
+    { "GdipSetPenDashCap197819", cast(void**)& GdipSetPenDashCap197819 },
+    { "GdipGetPenLineJoin", cast(void**)& GdipGetPenLineJoin },
+    { "GdipSetPenLineJoin", cast(void**)& GdipSetPenLineJoin },
+    { "GdipGetPenMiterLimit", cast(void**)& GdipGetPenMiterLimit },
+    { "GdipSetPenMiterLimit", cast(void**)& GdipSetPenMiterLimit },
+    { "GdipGetPenMode", cast(void**)& GdipGetPenMode },
+    { "GdipSetPenMode", cast(void**)& GdipSetPenMode },
+    { "GdipGetPenTransform", cast(void**)& GdipGetPenTransform },
+    { "GdipSetPenTransform", cast(void**)& GdipSetPenTransform },
+    { "GdipResetPenTransform", cast(void**)& GdipResetPenTransform },
+    { "GdipMultiplyPenTransform", cast(void**)& GdipMultiplyPenTransform },
+    { "GdipTranslatePenTransform", cast(void**)& GdipTranslatePenTransform },
+    { "GdipScalePenTransform", cast(void**)& GdipScalePenTransform },
+    { "GdipRotatePenTransform", cast(void**)& GdipRotatePenTransform },
+    { "GdipGetPenColor", cast(void**)& GdipGetPenColor },
+    { "GdipSetPenColor", cast(void**)& GdipSetPenColor },
+    { "GdipGetPenWidth", cast(void**)& GdipGetPenWidth },
+    { "GdipSetPenWidth", cast(void**)& GdipSetPenWidth },
+    { "GdipGetPenFillType", cast(void**)& GdipGetPenFillType },
+    { "GdipGetPenBrushFill", cast(void**)& GdipGetPenBrushFill },
+    { "GdipSetPenBrushFill", cast(void**)& GdipSetPenBrushFill },
+    { "GdipGetPenDashStyle", cast(void**)& GdipGetPenDashStyle },
+    { "GdipSetPenDashStyle", cast(void**)& GdipSetPenDashStyle },
+    { "GdipGetPenDashOffset", cast(void**)& GdipGetPenDashOffset },
+    { "GdipSetPenDashOffset", cast(void**)& GdipSetPenDashOffset },
+    { "GdipGetPenDashCount", cast(void**)& GdipGetPenDashCount },
+    { "GdipGetPenDashArray", cast(void**)& GdipGetPenDashArray },
+    { "GdipSetPenDashArray", cast(void**)& GdipSetPenDashArray },
+    { "GdipGetPenCompoundCount", cast(void**)& GdipGetPenCompoundCount },
+    { "GdipGetPenCompoundArray", cast(void**)& GdipGetPenCompoundArray },
+    { "GdipSetPenCompoundArray", cast(void**)& GdipSetPenCompoundArray },
+    { "GdipCreateRegion", cast(void**)& GdipCreateRegion },
+    { "GdipCreateRegionRect", cast(void**)& GdipCreateRegionRect },
+    { "GdipCreateRegionRectI", cast(void**)& GdipCreateRegionRectI },
+    { "GdipCreateRegionPath", cast(void**)& GdipCreateRegionPath },
+    { "GdipCreateRegionHrgn", cast(void**)& GdipCreateRegionHrgn },
+    { "GdipDeleteRegion", cast(void**)& GdipDeleteRegion },
+    { "GdipSetInfinite", cast(void**)& GdipSetInfinite },
+    { "GdipSetEmpty", cast(void**)& GdipSetEmpty },
+    { "GdipCombineRegionRect", cast(void**)& GdipCombineRegionRect },
+    { "GdipCombineRegionRectI", cast(void**)& GdipCombineRegionRectI },
+    { "GdipCombineRegionPath", cast(void**)& GdipCombineRegionPath },
+    { "GdipCombineRegionRegion", cast(void**)& GdipCombineRegionRegion },
+    { "GdipTranslateRegion", cast(void**)& GdipTranslateRegion },
+    { "GdipTranslateRegionI", cast(void**)& GdipTranslateRegionI },
+    { "GdipTransformRegion", cast(void**)& GdipTransformRegion },
+    { "GdipGetRegionBounds", cast(void**)& GdipGetRegionBounds },
+    { "GdipGetRegionHRgn", cast(void**)& GdipGetRegionHRgn },
+    { "GdipIsEmptyRegion", cast(void**)& GdipIsEmptyRegion },
+    { "GdipIsInfiniteRegion", cast(void**)& GdipIsInfiniteRegion },
+    { "GdipIsEqualRegion", cast(void**)& GdipIsEqualRegion },
+    { "GdipIsVisibleRegionPoint", cast(void**)& GdipIsVisibleRegionPoint },
+    { "GdipIsVisibleRegionRect", cast(void**)& GdipIsVisibleRegionRect },
+    { "GdipIsVisibleRegionPointI", cast(void**)& GdipIsVisibleRegionPointI },
+    { "GdipIsVisibleRegionRectI", cast(void**)& GdipIsVisibleRegionRectI },
+    { "GdipGetRegionScansCount", cast(void**)& GdipGetRegionScansCount },
+    { "GdipGetRegionScans", cast(void**)& GdipGetRegionScans },
+    { "GdipDisposeImage", cast(void**)& GdipDisposeImage },
+    { "GdipImageForceValidation", cast(void**)& GdipImageForceValidation },
+    { "GdipLoadImageFromFileICM", cast(void**)& GdipLoadImageFromFileICM },
+    { "GdipLoadImageFromFile", cast(void**)& GdipLoadImageFromFile },
+    { "GdipGetImageEncodersSize", cast(void**)& GdipGetImageEncodersSize },
+    { "GdipCloneImage", cast(void**)& GdipCloneImage },
+    { "GdipGetImageType", cast(void**)& GdipGetImageType },
+    { "GdipGetImageFlags", cast(void**)& GdipGetImageFlags },
+    { "GdipGetImageWidth", cast(void**)& GdipGetImageWidth },
+    { "GdipGetImageHeight", cast(void**)& GdipGetImageHeight },
+    { "GdipGetImageHorizontalResolution", cast(void**)& GdipGetImageHorizontalResolution },
+    { "GdipGetImageVerticalResolution", cast(void**)& GdipGetImageVerticalResolution },
+    { "GdipGetPropertyCount", cast(void**)& GdipGetPropertyCount },
+    { "GdipGetPropertyIdList", cast(void**)& GdipGetPropertyIdList },
+    { "GdipGetImagePixelFormat", cast(void**)& GdipGetImagePixelFormat },
+    { "GdipGetImageDimension", cast(void**)& GdipGetImageDimension },
+    { "GdipGetImageThumbnail", cast(void**)& GdipGetImageThumbnail },
+    { "GdipImageGetFrameDimensionsCount", cast(void**)& GdipImageGetFrameDimensionsCount },
+    { "GdipImageRotateFlip", cast(void**)& GdipImageRotateFlip },
+    { "GdipGetPropertyItemSize", cast(void**)& GdipGetPropertyItemSize },
+    { "GdipGetPropertyItem", cast(void**)& GdipGetPropertyItem },
+    { "GdipSetPropertyItem", cast(void**)& GdipSetPropertyItem },
+    { "GdipRemovePropertyItem", cast(void**)& GdipRemovePropertyItem },
+    { "GdipGetPropertySize", cast(void**)& GdipGetPropertySize },
+    { "GdipGetAllPropertyItems", cast(void**)& GdipGetAllPropertyItems },
+    { "GdipGetImageBounds", cast(void**)& GdipGetImageBounds },
+    { "GdipGetImagePaletteSize", cast(void**)& GdipGetImagePaletteSize },
+    { "GdipGetImagePalette", cast(void**)& GdipGetImagePalette },
+    { "GdipSetImagePalette", cast(void**)& GdipSetImagePalette },
+    { "GdipCreateBitmapFromScan0", cast(void**)& GdipCreateBitmapFromScan0 },
+    { "GdipCreateBitmapFromHBITMAP", cast(void**)& GdipCreateBitmapFromHBITMAP },
+    { "GdipCreateBitmapFromHICON", cast(void**)& GdipCreateBitmapFromHICON },
+    { "GdipCreateBitmapFromFileICM", cast(void**)& GdipCreateBitmapFromFileICM },
+    { "GdipCreateBitmapFromFile", cast(void**)& GdipCreateBitmapFromFile },
+    { "GdipCreateBitmapFromGraphics", cast(void**)& GdipCreateBitmapFromGraphics },
+    { "GdipCloneBitmapArea", cast(void**)& GdipCloneBitmapArea },
+    { "GdipCloneBitmapAreaI", cast(void**)& GdipCloneBitmapAreaI },
+    { "GdipBitmapGetPixel", cast(void**)& GdipBitmapGetPixel },
+    { "GdipBitmapSetPixel", cast(void**)& GdipBitmapSetPixel },
+    { "GdipBitmapLockBits", cast(void**)& GdipBitmapLockBits },
+    { "GdipBitmapUnlockBits", cast(void**)& GdipBitmapUnlockBits },
+    { "GdipBitmapSetResolution", cast(void**)& GdipBitmapSetResolution },
+    { "GdipCreateHICONFromBitmap", cast(void**)& GdipCreateHICONFromBitmap },
+    { "GdipCreateHBITMAPFromBitmap", cast(void**)& GdipCreateHBITMAPFromBitmap },
+    { "GdipCreateImageAttributes", cast(void**)& GdipCreateImageAttributes },
+    { "GdipDisposeImageAttributes", cast(void**)& GdipDisposeImageAttributes },
+    { "GdipSetImageAttributesColorMatrix", cast(void**)& GdipSetImageAttributesColorMatrix },
+    { "GdipSetImageAttributesThreshold", cast(void**)& GdipSetImageAttributesThreshold },
+    { "GdipSetImageAttributesGamma", cast(void**)& GdipSetImageAttributesGamma },
+    { "GdipSetImageAttributesNoOp", cast(void**)& GdipSetImageAttributesNoOp },
+    { "GdipSetImageAttributesColorKeys", cast(void**)& GdipSetImageAttributesColorKeys },
+    { "GdipSetImageAttributesOutputChannel", cast(void**)& GdipSetImageAttributesOutputChannel },
+    { "GdipSetImageAttributesOutputChannelColorProfile", cast(void**)& GdipSetImageAttributesOutputChannelColorProfile },
+    { "GdipSetImageAttributesWrapMode", cast(void**)& GdipSetImageAttributesWrapMode },
+    { "GdipNewInstalledFontCollection", cast(void**)& GdipNewInstalledFontCollection },
+    { "GdipNewPrivateFontCollection", cast(void**)& GdipNewPrivateFontCollection },
+    { "GdipDeletePrivateFontCollection", cast(void**)& GdipDeletePrivateFontCollection },
+    { "GdipPrivateAddFontFile", cast(void**)& GdipPrivateAddFontFile },
+    { "GdipPrivateAddMemoryFont", cast(void**)& GdipPrivateAddMemoryFont },
+    { "GdipGetFontCollectionFamilyCount", cast(void**)& GdipGetFontCollectionFamilyCount },
+    { "GdipGetFontCollectionFamilyList", cast(void**)& GdipGetFontCollectionFamilyList },
+    { "GdipCreateFontFamilyFromName", cast(void**)& GdipCreateFontFamilyFromName },
+    { "GdipDeleteFontFamily", cast(void**)& GdipDeleteFontFamily },
+    { "GdipCloneFontFamily", cast(void**)& GdipCloneFontFamily },
+    { "GdipGetFamilyName", cast(void**)& GdipGetFamilyName },
+    { "GdipGetGenericFontFamilyMonospace", cast(void**)& GdipGetGenericFontFamilyMonospace },
+    { "GdipGetGenericFontFamilySerif", cast(void**)& GdipGetGenericFontFamilySerif },
+    { "GdipGetGenericFontFamilySansSerif", cast(void**)& GdipGetGenericFontFamilySansSerif },
+    { "GdipGetEmHeight", cast(void**)& GdipGetEmHeight },
+    { "GdipGetCellAscent", cast(void**)& GdipGetCellAscent },
+    { "GdipGetCellDescent", cast(void**)& GdipGetCellDescent },
+    { "GdipGetLineSpacing", cast(void**)& GdipGetLineSpacing },
+    { "GdipIsStyleAvailable", cast(void**)& GdipIsStyleAvailable },
+    { "GdipCreateFont", cast(void**)& GdipCreateFont },
+    { "GdipCreateFontFromDC", cast(void**)& GdipCreateFontFromDC },
+    { "GdipDeleteFont", cast(void**)& GdipDeleteFont },
+    { "GdipCloneFont", cast(void**)& GdipCloneFont },
+    { "GdipGetFontSize", cast(void**)& GdipGetFontSize },
+    { "GdipGetFontHeight", cast(void**)& GdipGetFontHeight },
+    { "GdipGetFontHeightGivenDPI", cast(void**)& GdipGetFontHeightGivenDPI },
+    { "GdipGetFontStyle", cast(void**)& GdipGetFontStyle },
+    { "GdipGetFontUnit", cast(void**)& GdipGetFontUnit },
+    { "GdipGetFamily", cast(void**)& GdipGetFamily },
+    { "GdipCreateFontFromLogfontW", cast(void**)& GdipCreateFontFromLogfontW },
+    { "GdipCreateFontFromLogfontA", cast(void**)& GdipCreateFontFromLogfontA },
+    { "GdipGetLogFontW", cast(void**)& GdipGetLogFontW },
+    { "GdipCreateStringFormat", cast(void**)& GdipCreateStringFormat },
+    { "GdipDeleteStringFormat", cast(void**)& GdipDeleteStringFormat },
+    { "GdipGetStringFormatFlags", cast(void**)& GdipGetStringFormatFlags },
+    { "GdipSetStringFormatFlags", cast(void**)& GdipSetStringFormatFlags },
+    { "GdipGetStringFormatAlign", cast(void**)& GdipGetStringFormatAlign },
+    { "GdipSetStringFormatAlign", cast(void**)& GdipSetStringFormatAlign },
+    { "GdipGetStringFormatLineAlign", cast(void**)& GdipGetStringFormatLineAlign },
+    { "GdipSetStringFormatLineAlign", cast(void**)& GdipSetStringFormatLineAlign },
+    { "GdipGetStringFormatTrimming", cast(void**)& GdipGetStringFormatTrimming },
+    { "GdipSetStringFormatTrimming", cast(void**)& GdipSetStringFormatTrimming },
+    { "GdipCreatePath", cast(void**)& GdipCreatePath },
+    { "GdipCreatePath2", cast(void**)& GdipCreatePath2 },
+    { "GdipCreatePath2I", cast(void**)& GdipCreatePath2I },
+    { "GdipDeletePath", cast(void**)& GdipDeletePath },
+    { "GdipClonePath", cast(void**)& GdipClonePath },
+    { "GdipResetPath", cast(void**)& GdipResetPath },
+    { "GdipGetPathFillMode", cast(void**)& GdipGetPathFillMode },
+    { "GdipSetPathFillMode", cast(void**)& GdipSetPathFillMode },
+    { "GdipStartPathFigure", cast(void**)& GdipStartPathFigure },
+    { "GdipClosePathFigure", cast(void**)& GdipClosePathFigure },
+    { "GdipClosePathFigures", cast(void**)& GdipClosePathFigures },
+    { "GdipSetPathMarker", cast(void**)& GdipSetPathMarker },
+    { "GdipClearPathMarkers", cast(void**)& GdipClearPathMarkers },
+    { "GdipReversePath", cast(void**)& GdipReversePath },
+    { "GdipGetPathLastPoint", cast(void**)& GdipGetPathLastPoint },
+    { "GdipAddPathLine", cast(void**)& GdipAddPathLine },
+    { "GdipAddPathLineI", cast(void**)& GdipAddPathLineI },
+    { "GdipAddPathLine2", cast(void**)& GdipAddPathLine2 },
+    { "GdipAddPathLine2I", cast(void**)& GdipAddPathLine2I },
+    { "GdipAddPathArc", cast(void**)& GdipAddPathArc },
+    { "GdipAddPathArcI", cast(void**)& GdipAddPathArcI },
+    { "GdipAddPathBezier", cast(void**)& GdipAddPathBezier },
+    { "GdipAddPathBezierI", cast(void**)& GdipAddPathBezierI },
+    { "GdipAddPathBeziers", cast(void**)& GdipAddPathBeziers },
+    { "GdipAddPathBeziersI", cast(void**)& GdipAddPathBeziersI },
+    { "GdipAddPathCurve", cast(void**)& GdipAddPathCurve },
+    { "GdipAddPathCurveI", cast(void**)& GdipAddPathCurveI },
+    { "GdipAddPathCurve2", cast(void**)& GdipAddPathCurve2 },
+    { "GdipAddPathCurve2I", cast(void**)& GdipAddPathCurve2I },
+    { "GdipAddPathCurve3", cast(void**)& GdipAddPathCurve3 },
+    { "GdipAddPathCurve3I", cast(void**)& GdipAddPathCurve3I },
+    { "GdipAddPathClosedCurve", cast(void**)& GdipAddPathClosedCurve },
+    { "GdipAddPathClosedCurveI", cast(void**)& GdipAddPathClosedCurveI },
+    { "GdipAddPathClosedCurve2", cast(void**)& GdipAddPathClosedCurve2 },
+    { "GdipAddPathClosedCurve2I", cast(void**)& GdipAddPathClosedCurve2I },
+    { "GdipAddPathRectangle", cast(void**)& GdipAddPathRectangle },
+    { "GdipAddPathRectangleI", cast(void**)& GdipAddPathRectangleI },
+    { "GdipAddPathRectangles", cast(void**)& GdipAddPathRectangles },
+    { "GdipAddPathRectanglesI", cast(void**)& GdipAddPathRectanglesI },
+    { "GdipAddPathEllipse", cast(void**)& GdipAddPathEllipse },
+    { "GdipAddPathEllipseI", cast(void**)& GdipAddPathEllipseI },
+    { "GdipAddPathPie", cast(void**)& GdipAddPathPie },
+    { "GdipAddPathPieI", cast(void**)& GdipAddPathPieI },
+    { "GdipAddPathPolygon", cast(void**)& GdipAddPathPolygon },
+    { "GdipAddPathPolygonI", cast(void**)& GdipAddPathPolygonI },
+    { "GdipAddPathPath", cast(void**)& GdipAddPathPath },
+    { "GdipAddPathString", cast(void**)& GdipAddPathString },
+    { "GdipAddPathStringI", cast(void**)& GdipAddPathStringI },
+    { "GdipTransformPath", cast(void**)& GdipTransformPath },
+    { "GdipGetPathWorldBounds", cast(void**)& GdipGetPathWorldBounds },
+    { "GdipFlattenPath", cast(void**)& GdipFlattenPath },
+    { "GdipWidenPath", cast(void**)& GdipWidenPath },
+    { "GdipWindingModeOutline", cast(void**)& GdipWindingModeOutline },
+    { "GdipWarpPath", cast(void**)& GdipWarpPath },
+    { "GdipGetPointCount", cast(void**)& GdipGetPointCount },
+    { "GdipGetPathTypes", cast(void**)& GdipGetPathTypes },
+    { "GdipGetPathPoints", cast(void**)& GdipGetPathPoints },
+    { "GdipIsVisiblePathPoint", cast(void**)& GdipIsVisiblePathPoint },
+    { "GdipIsVisiblePathPointI", cast(void**)& GdipIsVisiblePathPointI },
+    { "GdipIsOutlineVisiblePathPoint", cast(void**)& GdipIsOutlineVisiblePathPoint },
+    { "GdipIsOutlineVisiblePathPointI", cast(void**)& GdipIsOutlineVisiblePathPointI },
+    { "GdipDrawPath", cast(void**)& GdipDrawPath },
+    { "GdipCreatePathIter", cast(void**)& GdipCreatePathIter },
+    { "GdipDeletePathIter", cast(void**)& GdipDeletePathIter },
+    { "GdipPathIterNextSubpath", cast(void**)& GdipPathIterNextSubpath },
+    { "GdipPathIterNextSubpathPath", cast(void**)& GdipPathIterNextSubpathPath },
+    { "GdipPathIterNextPathType", cast(void**)& GdipPathIterNextPathType },
+    { "GdipPathIterNextMarker", cast(void**)& GdipPathIterNextMarker },
+    { "GdipPathIterNextMarkerPath", cast(void**)& GdipPathIterNextMarkerPath },
+    { "GdipPathIterGetCount", cast(void**)& GdipPathIterGetCount },
+    { "GdipPathIterGetSubpathCount", cast(void**)& GdipPathIterGetSubpathCount },
+    { "GdipPathIterHasCurve", cast(void**)& GdipPathIterHasCurve },
+    { "GdipPathIterRewind", cast(void**)& GdipPathIterRewind },
+    { "GdipPathIterEnumerate", cast(void**)& GdipPathIterEnumerate },
+    { "GdipPathIterCopyData", cast(void**)& GdipPathIterCopyData },
+    { "GdipCreatePathGradient", cast(void**)& GdipCreatePathGradient },
+    { "GdipCreatePathGradientI", cast(void**)& GdipCreatePathGradientI },
+    { "GdipCreatePathGradientFromPath", cast(void**)& GdipCreatePathGradientFromPath },
+    { "GdipGetPathGradientCenterColor", cast(void**)& GdipGetPathGradientCenterColor },
+    { "GdipSetPathGradientCenterColor", cast(void**)& GdipSetPathGradientCenterColor },
+    { "GdipGetPathGradientSurroundColorCount", cast(void**)& GdipGetPathGradientSurroundColorCount },
+    { "GdipGetPathGradientSurroundColorsWithCount", cast(void**)& GdipGetPathGradientSurroundColorsWithCount },
+    { "GdipSetPathGradientSurroundColorsWithCount", cast(void**)& GdipSetPathGradientSurroundColorsWithCount },
+    { "GdipGetPathGradientCenterPoint", cast(void**)& GdipGetPathGradientCenterPoint },
+    { "GdipSetPathGradientCenterPoint", cast(void**)& GdipSetPathGradientCenterPoint },
+    { "GdipGetPathGradientRect", cast(void**)& GdipGetPathGradientRect },
+    { "GdipGetPathGradientBlendCount", cast(void**)& GdipGetPathGradientBlendCount },
+    { "GdipGetPathGradientBlend", cast(void**)& GdipGetPathGradientBlend },
+    { "GdipSetPathGradientBlend", cast(void**)& GdipSetPathGradientBlend },
+    { "GdipGetPathGradientPresetBlendCount", cast(void**)& GdipGetPathGradientPresetBlendCount },
+    { "GdipGetPathGradientPresetBlend", cast(void**)& GdipGetPathGradientPresetBlend },
+    { "GdipSetPathGradientPresetBlend", cast(void**)& GdipSetPathGradientPresetBlend },
+    { "GdipSetPathGradientSigmaBlend", cast(void**)& GdipSetPathGradientSigmaBlend },
+    { "GdipSetPathGradientLinearBlend", cast(void**)& GdipSetPathGradientLinearBlend },
+    { "GdipGetPathGradientTransform", cast(void**)& GdipGetPathGradientTransform },
+    { "GdipSetPathGradientTransform", cast(void**)& GdipSetPathGradientTransform },
+    { "GdipResetPathGradientTransform", cast(void**)& GdipResetPathGradientTransform },
+    { "GdipMultiplyPathGradientTransform", cast(void**)& GdipMultiplyPathGradientTransform },
+    { "GdipRotatePathGradientTransform", cast(void**)& GdipRotatePathGradientTransform },
+    { "GdipTranslatePathGradientTransform", cast(void**)& GdipTranslatePathGradientTransform },
+    { "GdipScalePathGradientTransform", cast(void**)& GdipScalePathGradientTransform },
+    { "GdipGetPathGradientFocusScales", cast(void**)& GdipGetPathGradientFocusScales },
+    { "GdipSetPathGradientFocusScales", cast(void**)& GdipSetPathGradientFocusScales },
+    { "GdipGetPathGradientWrapMode", cast(void**)& GdipGetPathGradientWrapMode },
+    { "GdipSetPathGradientWrapMode", cast(void**)& GdipSetPathGradientWrapMode },
+    { "GdipResetTextureTransform", cast(void**)& GdipResetTextureTransform },
+    { "GdipScaleTextureTransform", cast(void**)& GdipScaleTextureTransform },
+    { "GdipTranslateTextureTransform", cast(void**)& GdipTranslateTextureTransform },
+    { "GdipStringFormatGetGenericDefault", cast(void**)& GdipStringFormatGetGenericDefault },
+    { "GdipStringFormatGetGenericTypographic", cast(void**)& GdipStringFormatGetGenericTypographic },
+    { "GdipSetStringFormatHotkeyPrefix", cast(void**)& GdipSetStringFormatHotkeyPrefix },
+    { "GdipSetStringFormatTabStops", cast(void**)& GdipSetStringFormatTabStops },
+];
+
+
+void loadLib_Gdip(){
+    if (auto lib = SharedLib.load(`gdiplus.dll`)) {
+        foreach( inout s; symbols ){
+            *s.symbol = lib.getSymbol( s.name.ptr );
+            if( s.symbol is null ){
+                getDwtLogger.error("gdiplus.dll: Symbol '{}' not found", s.name );
+            }
+        }
+    } else {
+        getDwtLogger.error("Could not load the library gdiplus.dll");
+    }
+}
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+/+
+private uint initToken;
+private bool isShutdown;
+
+public int startup() {
+  static GdiplusStartupInput input = { 1, null, 0, 0 };
+  static GdiplusStartupOutput output;
+
+  return GdiplusStartup(initToken, input, output);
+}
+
+public void shutdown() {
+  // GC.collect();
+  isShutdown = true;
+
+  GdiplusShutdown(initToken);
+}
++/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/FileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.FileFormat;
+
+import java.lang.all;
+
+public import org.eclipse.swt.graphics.ImageLoader;
+public import org.eclipse.swt.graphics.ImageData;
+public import org.eclipse.swt.internal.image.LEDataInputStream;
+public import org.eclipse.swt.internal.image.LEDataOutputStream;
+
+import org.eclipse.swt.SWT;
+
+public import java.io.InputStream;
+public import java.io.OutputStream;
+
+import org.eclipse.swt.internal.image.GIFFileFormat;
+import org.eclipse.swt.internal.image.WinBMPFileFormat;
+import org.eclipse.swt.internal.image.WinICOFileFormat;
+import org.eclipse.swt.internal.image.TIFFFileFormat;
+import org.eclipse.swt.internal.image.OS2BMPFileFormat;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.PNGFileFormat;
+
+import tango.core.Exception;
+import tango.core.Tuple;
+
+/**
+ * Abstract factory class for loading/unloading images from files or streams
+ * in various image file formats.
+ *
+ */
+public abstract class FileFormat {
+    static const String FORMAT_PACKAGE = "org.eclipse.swt.internal.image"; //$NON-NLS-1$
+    static const String FORMAT_SUFFIX = "FileFormat"; //$NON-NLS-1$
+    static const String[] FORMATS = [ "WinBMP"[], "WinBMP", "GIF", "WinICO", "JPEG", "PNG", "TIFF", "OS2BMP" ]; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$//$NON-NLS-5$ //$NON-NLS-6$//$NON-NLS-7$//$NON-NLS-8$
+    alias Tuple!( WinBMPFileFormat, WinBMPFileFormat, GIFFileFormat, WinICOFileFormat, JPEGFileFormat, PNGFileFormat, TIFFFileFormat, OS2BMPFileFormat ) TFormats;
+    LEDataInputStream inputStream;
+    LEDataOutputStream outputStream;
+    ImageLoader loader;
+    int compression;
+
+/**
+ * Return whether or not the specified input stream
+ * represents a supported file format.
+ */
+abstract bool isFileFormat(LEDataInputStream stream);
+
+abstract ImageData[] loadFromByteStream();
+
+/**
+ * Read the specified input stream, and return the
+ * device independent image array represented by the stream.
+ */
+public ImageData[] loadFromStream(LEDataInputStream stream) {
+    try {
+        inputStream = stream;
+        return loadFromByteStream();
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+        return null;
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE, e);
+        return null;
+    }
+}
+
+/**
+ * Read the specified input stream using the specified loader, and
+ * return the device independent image array represented by the stream.
+ */
+public static ImageData[] load(InputStream istr, ImageLoader loader) {
+    FileFormat fileFormat = null;
+    LEDataInputStream stream = new LEDataInputStream(istr);
+    bool isSupported = false;    
+    foreach( TFormat; TFormats ){
+        try{
+            fileFormat = new TFormat();
+            if (fileFormat.isFileFormat(stream)) {
+                isSupported = true;
+                break;
+            }
+        } catch (Exception e) {
+        }
+    }
+    if (!isSupported) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+    fileFormat.loader = loader;
+    return fileFormat.loadFromStream(stream);
+}
+
+/**
+ * Write the device independent image array stored in the specified loader
+ * to the specified output stream using the specified file format.
+ */
+public static void save(OutputStream os, int format, ImageLoader loader) {
+    if (format < 0 || format >= FORMATS.length) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+    if (FORMATS[format] is null) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+    if (loader.data is null || loader.data.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+
+    LEDataOutputStream stream = new LEDataOutputStream(os);
+    FileFormat fileFormat = null;
+    try {
+        foreach( idx, TFormat; TFormats ){
+            if( idx is format ){
+                fileFormat = new TFormat();
+            }
+        }
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+    }
+    if (format is SWT.IMAGE_BMP_RLE) {
+        switch (loader.data[0].depth) {
+            case 8: fileFormat.compression = 1; break;
+            case 4: fileFormat.compression = 2; break;
+            default:
+        }
+    }
+    fileFormat.unloadIntoStream(loader, stream);
+}
+
+abstract void unloadIntoByteStream(ImageLoader loader);
+
+/**
+ * Write the device independent image array stored in the specified loader
+ * to the specified output stream.
+ */
+public void unloadIntoStream(ImageLoader loader, LEDataOutputStream stream) {
+    try {
+        outputStream = stream;
+        unloadIntoByteStream(loader);
+        outputStream.flush();
+    } catch (Exception e) {
+        try {outputStream.flush();} catch (Exception f) {}
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/GIFFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,632 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.GIFFileFormat;
+
+public import org.eclipse.swt.internal.image.FileFormat;
+public import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.LZWCodec;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoaderEvent;
+import org.eclipse.swt.graphics.ImageLoader;
+import tango.core.Exception;
+import java.lang.all;
+
+
+final class GIFFileFormat : FileFormat {
+    String signature;
+    int screenWidth, screenHeight, backgroundPixel, bitsPerPixel, defaultDepth;
+    int disposalMethod = 0;
+    int delayTime = 0;
+    int transparentPixel = -1;
+    int repeatCount = 1;
+
+    static final int GIF_APPLICATION_EXTENSION_BLOCK_ID = 0xFF;
+    static final int GIF_GRAPHICS_CONTROL_BLOCK_ID = 0xF9;
+    static final int GIF_PLAIN_TEXT_BLOCK_ID = 0x01;
+    static final int GIF_COMMENT_BLOCK_ID = 0xFE;
+    static final int GIF_EXTENSION_BLOCK_ID = 0x21;
+    static final int GIF_IMAGE_BLOCK_ID = 0x2C;
+    static final int GIF_TRAILER_ID = 0x3B;
+    static final byte[] GIF89a = cast(byte[])"GIF89a";
+    static final byte[] NETSCAPE2_0 = cast(byte[])"NETSCAPE2.0";
+
+    /**
+     * Answer a palette containing numGrays
+     * shades of gray, ranging from black to white.
+     */
+    static PaletteData grayRamp(int numGrays) {
+        int n = numGrays - 1;
+        RGB[] colors = new RGB[numGrays];
+        for (int i = 0; i < numGrays; i++) {
+            int intensity = cast(byte)((i * 3) * 256 / n);
+            colors[i] = new RGB(intensity, intensity, intensity);
+        }
+        return new PaletteData(colors);
+    }
+
+    override bool isFileFormat(LEDataInputStream stream) {
+        try {
+            byte[3] signature;
+            stream.read(signature);
+            stream.unread(signature);
+            return signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F';
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * Load the GIF image(s) stored in the input stream.
+     * Return an array of ImageData representing the image(s).
+     */
+    override ImageData[] loadFromByteStream() {
+        byte[3] signature;
+        byte[3] versionBytes;
+        byte[7] block;
+        try {
+            inputStream.read(signature);
+            if (!(signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F'))
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+            inputStream.read(versionBytes);
+
+            inputStream.read(block);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        screenWidth = (block[0] & 0xFF) | ((block[1] & 0xFF) << 8);
+        loader.logicalScreenWidth = screenWidth;
+        screenHeight = (block[2] & 0xFF) | ((block[3] & 0xFF) << 8);
+        loader.logicalScreenHeight = screenHeight;
+        byte bitField = block[4];
+        backgroundPixel = block[5] & 0xFF;
+        //aspect = block[6] & 0xFF;
+        bitsPerPixel = ((bitField >> 4) & 0x07) + 1;
+        defaultDepth = (bitField & 0x7) + 1;
+        PaletteData palette = null;
+        if ((bitField & 0x80) !is 0) {
+            // Global palette.
+            //sorted = (bitField & 0x8) !is 0;
+            palette = readPalette(1 << defaultDepth);
+        } else {
+            // No global palette.
+            //sorted = false;
+            backgroundPixel = -1;
+            defaultDepth = bitsPerPixel;
+        }
+        loader.backgroundPixel = backgroundPixel;
+
+        getExtensions();
+        int id = readID();
+        ImageData[] images = new ImageData[0];
+        while (id is GIF_IMAGE_BLOCK_ID) {
+            ImageData image = readImageBlock(palette);
+            if (loader.hasListeners()) {
+                loader.notifyListeners(new ImageLoaderEvent(loader, image, 3, true));
+            }
+            ImageData[] oldImages = images;
+            images = new ImageData[oldImages.length + 1];
+            System.arraycopy(oldImages, 0, images, 0, oldImages.length);
+            images[images.length - 1] = image;
+            //images ~= image;
+            try {
+                /* Read the 0-byte terminator at the end of the image. */
+                id = inputStream.read();
+                if (id > 0) {
+                    /* We read the terminator earlier. */
+                    byte[1] arr;
+                    arr[0] = id;
+                    inputStream.unread( arr );
+                }
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+            getExtensions();
+            id = readID();
+        }
+        return images;
+    }
+
+    /**
+     * Read and return the next block or extension identifier from the file.
+     */
+    int readID() {
+        try {
+            return inputStream.read();
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        return -1;
+    }
+
+    /**
+     * Read extensions until an image descriptor appears.
+     * In the future, if we care about the extensions, they
+     * should be properly grouped with the image data before
+     * which they appeared. Right now, the interesting parts
+     * of some extensions are kept, but the rest is discarded.
+     * Throw an error if an error occurs.
+     */
+    void getExtensions() {
+        int id = readID();
+        while (id !is GIF_IMAGE_BLOCK_ID && id !is GIF_TRAILER_ID && id > 0) {
+            if (id is GIF_EXTENSION_BLOCK_ID) {
+                readExtension();
+            } else {
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            }
+            id = readID();
+        }
+        if (id is GIF_IMAGE_BLOCK_ID || id is GIF_TRAILER_ID) {
+            try {
+                byte[1] arr;
+                arr[0] = id;
+                inputStream.unread(arr);
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+        }
+    }
+
+    /**
+     * Read a control extension.
+     * Return the extension block data.
+     */
+    byte[] readExtension() {
+        int extensionID = readID();
+        if (extensionID is GIF_COMMENT_BLOCK_ID)
+            return readCommentExtension();
+        if (extensionID is GIF_PLAIN_TEXT_BLOCK_ID)
+            return readPlainTextExtension();
+        if (extensionID is GIF_GRAPHICS_CONTROL_BLOCK_ID)
+            return readGraphicsControlExtension();
+        if (extensionID is GIF_APPLICATION_EXTENSION_BLOCK_ID)
+            return readApplicationExtension();
+        // Otherwise, we don't recognize the block. If the
+        // field size is correct, we can just skip over
+        // the block contents.
+        try {
+            int extSize = inputStream.read();
+            if (extSize < 0) {
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            }
+            byte[] ext = new byte[extSize];
+            inputStream.read(ext, 0, extSize);
+            return ext;
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+
+    /**
+     * We have just read the Comment extension identifier
+     * from the input stream. Read in the rest of the comment
+     * and return it. GIF comment blocks are variable size.
+     */
+    byte[] readCommentExtension() {
+        try {
+            byte[] comment = new byte[0];
+            byte[] block = new byte[255];
+            int size = inputStream.read();
+            while ((size > 0) && (inputStream.read(block, 0, size) !is -1)) {
+                byte[] oldComment = comment;
+                comment = new byte[oldComment.length + size];
+                System.arraycopy(oldComment, 0, comment, 0, oldComment.length);
+                System.arraycopy(block, 0, comment, oldComment.length, size);
+                //comment ~= block[ 0 .. size ];
+                size = inputStream.read();
+            }
+            return comment;
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+
+    /**
+     * We have just read the PlainText extension identifier
+     * from the input stream. Read in the plain text info and text,
+     * and return the text. GIF plain text blocks are variable size.
+     */
+    byte[] readPlainTextExtension() {
+        try {
+            // Read size of block = 0x0C.
+            inputStream.read();
+            // Read the text information (x, y, width, height, colors).
+            byte[] info = new byte[12];
+            inputStream.read(info);
+            // Read the text.
+            byte[] text = new byte[0];
+            byte[] block = new byte[255];
+            int size = inputStream.read();
+            while ((size > 0) && (inputStream.read(block, 0, size) !is -1)) {
+                byte[] oldText = text;
+                text = new byte[oldText.length + size];
+                System.arraycopy(oldText, 0, text, 0, oldText.length);
+                System.arraycopy(block, 0, text, oldText.length, size);
+                //text ~= block[ 0 .. size ];
+                size = inputStream.read();
+            }
+            return text;
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+
+    /**
+     * We have just read the GraphicsControl extension identifier
+     * from the input stream. Read in the control information, store
+     * it, and return it.
+     */
+    byte[] readGraphicsControlExtension() {
+        try {
+            // Read size of block = 0x04.
+            inputStream.read();
+            // Read the control block.
+            byte[] controlBlock = new byte[4];
+            inputStream.read(controlBlock);
+            byte bitField = controlBlock[0];
+            // Store the user input field.
+            //userInput = (bitField & 0x02) !is 0;
+            // Store the disposal method.
+            disposalMethod = (bitField >> 2) & 0x07;
+            // Store the delay time.
+            delayTime = (controlBlock[1] & 0xFF) | ((controlBlock[2] & 0xFF) << 8);
+            // Store the transparent color.
+            if ((bitField & 0x01) !is 0) {
+                transparentPixel = controlBlock[3] & 0xFF;
+            } else {
+                transparentPixel = -1;
+            }
+            // Read block terminator.
+            inputStream.read();
+            return controlBlock;
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+
+    /**
+     * We have just read the Application extension identifier
+     * from the input stream.  Read in the rest of the extension,
+     * look for and store 'number of repeats', and return the data.
+     */
+    byte[] readApplicationExtension() {
+        try {
+            // Read size of block = 0x0B.
+            inputStream.read();
+            // Read application identifier.
+            byte[] application = new byte[8];
+            inputStream.read(application);
+            // Read authentication code.
+            byte[] authentication = new byte[3];
+            inputStream.read(authentication);
+            // Read application data.
+            byte[] data = new byte[0];
+            byte[] block = new byte[255];
+            int size = inputStream.read();
+            while ((size > 0) && (inputStream.read(block, 0, size) !is -1)) {
+                byte[] oldData = data;
+                data = new byte[oldData.length + size];
+                System.arraycopy(oldData, 0, data, 0, oldData.length);
+                System.arraycopy(block, 0, data, oldData.length, size);
+                //data ~= block[ 0 .. size ];
+                size = inputStream.read();
+            }
+            // Look for the NETSCAPE 'repeat count' field for an animated GIF.
+            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;
+            }
+            return data;
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+
+    /**
+     * Return a DeviceIndependentImage representing the
+     * image block at the current position in the input stream.
+     * Throw an error if an error occurs.
+     */
+    ImageData readImageBlock(PaletteData defaultPalette) {
+        int depth;
+        PaletteData palette;
+        byte[] block = new byte[9];
+        try {
+            inputStream.read(block);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        int left = (block[0] & 0xFF) | ((block[1] & 0xFF) << 8);
+        int top = (block[2] & 0xFF) | ((block[3] & 0xFF) << 8);
+        int width = (block[4] & 0xFF) | ((block[5] & 0xFF) << 8);
+        int height = (block[6] & 0xFF) | ((block[7] & 0xFF) << 8);
+        byte bitField = block[8];
+        bool interlaced = (bitField & 0x40) !is 0;
+        //bool sorted = (bitField & 0x20) !is 0;
+        if ((bitField & 0x80) !is 0) {
+            // Local palette.
+            depth = (bitField & 0x7) + 1;
+            palette = readPalette(1 << depth);
+        } else {
+            // No local palette.
+            depth = defaultDepth;
+            palette = defaultPalette;
+        }
+        /* Work around: Ignore the case where a GIF specifies an
+         * invalid index for the transparent pixel that is larger
+         * than the number of entries in the palette. */
+        if (transparentPixel > 1 << depth) {
+            transparentPixel = -1;
+        }
+        // Promote depth to next highest supported value.
+        if (!(depth is 1 || depth is 4 || depth is 8)) {
+            if (depth < 4)
+                depth = 4;
+            else
+                depth = 8;
+        }
+        if (palette is null) {
+            palette = grayRamp(1 << depth);
+        }
+        int initialCodeSize = -1;
+        try {
+            initialCodeSize = inputStream.read();
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        if (initialCodeSize < 0) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        ImageData image = ImageData.internal_new(
+            width,
+            height,
+            depth,
+            palette,
+            4,
+            null,
+            0,
+            null,
+            null,
+            -1,
+            transparentPixel,
+            SWT.IMAGE_GIF,
+            left,
+            top,
+            disposalMethod,
+            delayTime);
+        LZWCodec codec = new LZWCodec();
+        codec.decode(inputStream, loader, image, interlaced, initialCodeSize);
+        return image;
+    }
+
+    /**
+     * Read a palette from the input stream.
+     */
+    PaletteData readPalette(int numColors) {
+        byte[] bytes = new byte[numColors * 3];
+        try {
+            if (inputStream.read(bytes) !is bytes.length)
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        RGB[] colors = new RGB[numColors];
+        for (int i = 0; i < numColors; i++)
+            colors[i] = new RGB(bytes[i*3] & 0xFF,
+                bytes[i*3+1] & 0xFF, bytes[i*3+2] & 0xFF);
+        return new PaletteData(colors);
+    }
+
+    override void unloadIntoByteStream(ImageLoader loader) {
+
+        /* Step 1: Acquire GIF parameters. */
+        ImageData[] data = loader.data;
+        int frameCount = data.length;
+        bool multi = frameCount > 1;
+        ImageData firstImage = data[0];
+        int logicalScreenWidth = multi ? loader.logicalScreenWidth : firstImage.width;
+        int logicalScreenHeight = multi ? loader.logicalScreenHeight : firstImage.height;
+        int backgroundPixel = loader.backgroundPixel;
+        int depth = firstImage.depth;
+        PaletteData palette = firstImage.palette;
+        RGB[] colors = palette.getRGBs();
+        short globalTable = 1;
+
+        /* Step 2: Check for validity and global/local color map. */
+        if (!(depth is 1 || depth is 4 || depth is 8)) {
+            SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+        }
+        for (int i=0; i<frameCount; i++) {
+            if (data[i].palette.isDirect) {
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            }
+            if (multi) {
+                if (!(data[i].height <= logicalScreenHeight && data[i].width <= logicalScreenWidth && data[i].depth is depth)) {
+                    SWT.error(SWT.ERROR_INVALID_IMAGE);
+                }
+                if (globalTable is 1) {
+                    RGB rgbs[] = data[i].palette.getRGBs();
+                    if (rgbs.length !is colors.length) {
+                        globalTable = 0;
+                    } else {
+                        for (int j=0; j<colors.length; j++) {
+                            if (!(rgbs[j].red is colors[j].red &&
+                                rgbs[j].green is colors[j].green &&
+                                rgbs[j].blue is colors[j].blue))
+                                    globalTable = 0;
+                        }
+                    }
+                }
+            }
+        }
+
+        try {
+            /* Step 3: Write the GIF89a Header and Logical Screen Descriptor. */
+            outputStream.write(GIF89a);
+            int bitField = globalTable*128 + (depth-1)*16 + depth-1;
+            outputStream.writeShort(cast(short)logicalScreenWidth);
+            outputStream.writeShort(cast(short)logicalScreenHeight);
+            outputStream.write(bitField);
+            outputStream.write(backgroundPixel);
+            outputStream.write(0); // Aspect ratio is 1:1
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+
+        /* Step 4: Write Global Color Table if applicable. */
+        if (globalTable is 1) {
+            writePalette(palette, depth);
+        }
+
+        /* Step 5: Write Application Extension if applicable. */
+        if (multi) {
+            int repeatCount = loader.repeatCount;
+            try {
+                outputStream.write(GIF_EXTENSION_BLOCK_ID);
+                outputStream.write(GIF_APPLICATION_EXTENSION_BLOCK_ID);
+                outputStream.write(NETSCAPE2_0.length);
+                outputStream.write(NETSCAPE2_0);
+                outputStream.write(3); // Three bytes follow
+                outputStream.write(1); // Extension type
+                outputStream.writeShort(cast(short) repeatCount);
+                outputStream.write(0); // Block terminator
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+        }
+
+        for (int frame=0; frame<frameCount; frame++) {
+
+            /* Step 6: Write Graphics Control Block for each frame if applicable. */
+            if (multi || data[frame].transparentPixel !is -1) {
+                writeGraphicsControlBlock(data[frame]);
+            }
+
+            /* Step 7: Write Image Header for each frame. */
+            int x = data[frame].x;
+            int y = data[frame].y;
+            int width = data[frame].width;
+            int height = data[frame].height;
+            try {
+                outputStream.write(GIF_IMAGE_BLOCK_ID);
+                byte[] block = new byte[9];
+                block[0] = cast(byte)(x & 0xFF);
+                block[1] = cast(byte)((x >> 8) & 0xFF);
+                block[2] = cast(byte)(y & 0xFF);
+                block[3] = cast(byte)((y >> 8) & 0xFF);
+                block[4] = cast(byte)(width & 0xFF);
+                block[5] = cast(byte)((width >> 8) & 0xFF);
+                block[6] = cast(byte)(height & 0xFF);
+                block[7] = cast(byte)((height >> 8) & 0xFF);
+                block[8] = cast(byte)(globalTable is 0 ? (depth-1) | 0x80 : 0x00);
+                outputStream.write(block);
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+
+            /* Step 8: Write Local Color Table for each frame if applicable. */
+            if (globalTable is 0) {
+                writePalette(data[frame].palette, depth);
+            }
+
+            /* Step 9: Write the actual data for each frame. */
+            try {
+                outputStream.write(depth); // Minimum LZW Code size
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+            (new LZWCodec()).encode(outputStream, data[frame]);
+        }
+
+        /* Step 10: Write GIF terminator. */
+        try {
+            outputStream.write(0x3B);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+
+    /**
+     * Write out a GraphicsControlBlock to describe
+     * the specified device independent image.
+     */
+    void writeGraphicsControlBlock(ImageData image) {
+        try {
+            outputStream.write(GIF_EXTENSION_BLOCK_ID);
+            outputStream.write(GIF_GRAPHICS_CONTROL_BLOCK_ID);
+            byte[] gcBlock = new byte[4];
+            gcBlock[0] = 0;
+            gcBlock[1] = 0;
+            gcBlock[2] = 0;
+            gcBlock[3] = 0;
+            if (image.transparentPixel !is -1) {
+                gcBlock[0] = cast(byte)0x01;
+                gcBlock[3] = cast(byte)image.transparentPixel;
+            }
+            if (image.disposalMethod !is 0) {
+                gcBlock[0] |= cast(byte)((image.disposalMethod & 0x07) << 2);
+            }
+            if (image.delayTime !is 0) {
+                gcBlock[1] = cast(byte)(image.delayTime & 0xFF);
+                gcBlock[2] = cast(byte)((image.delayTime >> 8) & 0xFF);
+            }
+            outputStream.write(cast(byte)gcBlock.length);
+            outputStream.write(gcBlock);
+            outputStream.write(0); // Block terminator
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+
+    /**
+     * Write the specified palette to the output stream.
+     */
+    void writePalette(PaletteData palette, int depth) {
+        byte[] bytes = new byte[(1 << depth) * 3];
+        int offset = 0;
+        for (int i = 0; i < palette.colors.length; i++) {
+            RGB color = palette.colors[i];
+            bytes[offset] = cast(byte)color.red;
+            bytes[offset + 1] = cast(byte)color.green;
+            bytes[offset + 2] = cast(byte)color.blue;
+            offset += 3;
+        }
+        try {
+            outputStream.write(bytes);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGAppn.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGAppn;
+
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+final class JPEGAppn : JPEGVariableSizeSegment {
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+    }
+
+    public override bool verify() {
+        int marker = getSegmentMarker();
+        return marker >= JPEGFileFormat.APP0 && marker <= JPEGFileFormat.APP15;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGArithmeticConditioningTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGArithmeticConditioningTable;
+
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+final class JPEGArithmeticConditioningTable : JPEGVariableSizeSegment {
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+    }
+
+    public override int signature() {
+        return JPEGFileFormat.DAC;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGComment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGComment;
+
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+final class JPEGComment : JPEGVariableSizeSegment {
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+    }
+
+    public override int signature() {
+        return JPEGFileFormat.COM;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGDecoder.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,6395 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGDecoder;
+
+import org.eclipse.swt.SWT;
+import java.io.InputStream;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.ImageLoaderEvent;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import java.lang.all;
+
+import tango.core.Exception;
+import tango.util.Convert;
+import Math = tango.math.Math;
+
+public class JPEGDecoder {
+
+    static const int DCTSIZE = 8;
+    static const int DCTSIZE2 = 64;
+    static const int NUM_QUANT_TBLS = 4;
+    static const int NUM_HUFF_TBLS = 4;
+    static const int NUM_ARITH_TBLS = 16;
+    static const int MAX_COMPS_IN_SCAN = 4;
+    static const int MAX_COMPONENTS = 10;
+    static const int MAX_SAMP_FACTOR = 4;
+    static const int D_MAX_BLOCKS_IN_MCU = 10;
+    static const int HUFF_LOOKAHEAD = 8;
+    static const int MAX_Q_COMPS = 4;
+    static const int IFAST_SCALE_BITS = 2;
+    static const int MAXJSAMPLE = 255;
+    static const int CENTERJSAMPLE = 128;
+    static const int MIN_GET_BITS = 32-7;
+    static const int INPUT_BUFFER_SIZE = 4096;
+
+    static const int SCALEBITS = 16;    /* speediest right-shift on some machines */
+    static const int ONE_HALF = 1 << (SCALEBITS-1);
+
+    static const int RGB_RED = 2;   /* Offset of Red in an RGB scanline element */
+    static const int RGB_GREEN = 1; /* Offset of Green */
+    static const int RGB_BLUE = 0;  /* Offset of Blue */
+    static const int RGB_PIXELSIZE = 3;
+
+    static const int JBUF_PASS_THRU = 0;
+    static const int JBUF_SAVE_SOURCE = 1;  /* Run source subobject only, save output */
+    static const int JBUF_CRANK_DEST = 2;   /* Run dest subobject only, using saved data */
+    static const int JBUF_SAVE_AND_PASS = 3;
+
+    static const int JPEG_MAX_DIMENSION = 65500;
+    static const int BITS_IN_JSAMPLE = 8;
+
+    static const int JDITHER_NONE = 0;      /* no dithering */
+    static const int JDITHER_ORDERED = 1;   /* simple ordered dither */
+    static const int JDITHER_FS = 2;
+
+    static const int JDCT_ISLOW = 0;    /* slow but accurate integer algorithm */
+    static const int JDCT_IFAST = 1;    /* faster, less accurate integer method */
+    static const int JDCT_FLOAT = 2;    /* floating-point: accurate, fast on fast HW */
+    static const int JDCT_DEFAULT = JDCT_ISLOW;
+
+    static const int JCS_UNKNOWN = 0;       /* error/unspecified */
+    static const int JCS_GRAYSCALE = 1;     /* monochrome */
+    static const int JCS_RGB = 2;       /* red/green/blue */
+    static const int JCS_YCbCr = 3;     /* Y/Cb/Cr (also known as YUV) */
+    static const int JCS_CMYK = 4;      /* C/M/Y/K */
+    static const int JCS_YCCK = 5;      /* Y/Cb/Cr/K */
+
+    static const int SAVED_COEFS = 6;
+    static const int Q01_POS = 1;
+    static const int Q10_POS = 8;
+    static const int Q20_POS = 16;
+    static const int Q11_POS = 9;
+    static const int Q02_POS = 2;
+
+    static const int CTX_PREPARE_FOR_IMCU = 0;  /* need to prepare for MCU row */
+    static const int CTX_PROCESS_IMCU = 1;  /* feeding iMCU to postprocessor */
+    static const int CTX_POSTPONED_ROW = 2; /* feeding postponed row group */
+
+    static const int APP0_DATA_LEN = 14;    /* Length of interesting data in APP0 */
+    static const int APP14_DATA_LEN = 12;   /* Length of interesting data in APP14 */
+    static const int APPN_DATA_LEN = 14;    /* Must be the largest of the above!! */
+
+    /* markers */
+    static const int M_SOF0 = 0xc0;
+    static const int M_SOF1 = 0xc1;
+    static const int M_SOF2 = 0xc2;
+    static const int M_SOF3 = 0xc3;
+    static const int M_SOF5 = 0xc5;
+    static const int M_SOF6 = 0xc6;
+    static const int M_SOF7 = 0xc7;
+    static const int M_JPG = 0xc8;
+    static const int M_SOF9 = 0xc9;
+    static const int M_SOF10 = 0xca;
+    static const int M_SOF11 = 0xcb;
+    static const int M_SOF13 = 0xcd;
+    static const int M_SOF14 = 0xce;
+    static const int M_SOF15 = 0xcf;
+    static const int M_DHT = 0xc4;
+    static const int M_DAC = 0xcc;
+    static const int M_RST0 = 0xd0;
+    static const int M_RST1 = 0xd1;
+    static const int M_RST2 = 0xd2;
+    static const int M_RST3 = 0xd3;
+    static const int M_RST4 = 0xd4;
+    static const int M_RST5 = 0xd5;
+    static const int M_RST6 = 0xd6;
+    static const int M_RST7 = 0xd7;
+    static const int M_SOI = 0xd8;
+    static const int M_EOI = 0xd9;
+    static const int M_SOS = 0xda;
+    static const int M_DQT = 0xdb;
+    static const int M_DNL = 0xdc;
+    static const int M_DRI = 0xdd;
+    static const int M_DHP = 0xde;
+    static const int M_EXP = 0xdf;
+    static const int M_APP0 = 0xe0;
+    static const int M_APP1 = 0xe1;
+    static const int M_APP2 = 0xe2;
+    static const int M_APP3 = 0xe3;
+    static const int M_APP4 = 0xe4;
+    static const int M_APP5 = 0xe5;
+    static const int M_APP6 = 0xe6;
+    static const int M_APP7 = 0xe7;
+    static const int M_APP8 = 0xe8;
+    static const int M_APP9 = 0xe9;
+    static const int M_APP10 = 0xea;
+    static const int M_APP11 = 0xeb;
+    static const int M_APP12 = 0xec;
+    static const int M_APP13 = 0xed;
+    static const int M_APP14 = 0xee;
+    static const int M_APP15 = 0xef;
+    static const int M_JPG0 = 0xf0;
+    static const int M_JPG13 = 0xfd;
+    static const int M_COM = 0xfe;
+    static const int M_TEM = 0x01;
+    static const int M_ERROR = 0x100;
+
+    /* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+    static const int CSTATE_START = 100;    /* after create_compress */
+    static const int CSTATE_SCANNING = 101; /* start_compress done, write_scanlines OK */
+    static const int CSTATE_RAW_OK = 102;   /* start_compress done, write_raw_data OK */
+    static const int CSTATE_WRCOEFS = 103;  /* jpeg_write_coefficients done */
+    static const int DSTATE_START = 200;    /* after create_decompress */
+    static const int DSTATE_INHEADER = 201; /* reading header markers, no SOS yet */
+    static const int DSTATE_READY = 202;    /* found SOS, ready for start_decompress */
+    static const int DSTATE_PRELOAD = 203;  /* reading multiscan file in start_decompress*/
+    static const int DSTATE_PRESCAN = 204;  /* performing dummy pass for 2-pass quant */
+    static const int DSTATE_SCANNING = 205; /* start_decompress done, read_scanlines OK */
+    static const int DSTATE_RAW_OK = 206;   /* start_decompress done, read_raw_data OK */
+    static const int DSTATE_BUFIMAGE = 207; /* expecting jpeg_start_output */
+    static const int DSTATE_BUFPOST = 208;  /* looking for SOS/EOI in jpeg_finish_output */
+    static const int DSTATE_RDCOEFS = 209;  /* reading file in jpeg_read_coefficients */
+    static const int DSTATE_STOPPING = 210; /* looking for EOI in jpeg_finish_decompress */
+
+    static const int JPEG_REACHED_SOS = 1; /* Reached start of new scan */
+    static const int JPEG_REACHED_EOI = 2; /* Reached end of image */
+    static const int JPEG_ROW_COMPLETED = 3; /* Completed one iMCU row */
+    static const int JPEG_SCAN_COMPLETED = 4; /* Completed last iMCU row of a scan */
+
+    static const int JPEG_SUSPENDED = 0; /* Suspended due to lack of input data */
+    static const int JPEG_HEADER_OK = 1; /* Found valid image datastream */
+    static const int JPEG_HEADER_TABLES_ONLY = 2; /* Found valid table-specs-only datastream */
+
+    /* Function pointers */
+    static const int DECOMPRESS_DATA = 0;
+    static const int DECOMPRESS_SMOOTH_DATA = 1;
+    static const int DECOMPRESS_ONEPASS = 2;
+
+    static const int CONSUME_DATA = 0;
+    static const int DUMMY_CONSUME_DATA = 1;
+
+    static const int PROCESS_DATA_SIMPLE_MAIN = 0;
+    static const int PROCESS_DATA_CONTEXT_MAIN = 1;
+    static const int PROCESS_DATA_CRANK_POST = 2;
+
+    static const int POST_PROCESS_1PASS = 0;
+    static const int POST_PROCESS_DATA_UPSAMPLE = 1;
+
+    static const int NULL_CONVERT = 0;
+    static const int GRAYSCALE_CONVERT = 1;
+    static const int YCC_RGB_CONVERT = 2;
+    static const int GRAY_RGB_CONVERT = 3;
+    static const int YCCK_CMYK_CONVERT = 4;
+
+    static const int NOOP_UPSAMPLE = 0;
+    static const int FULLSIZE_UPSAMPLE = 1;
+    static const int H2V1_FANCY_UPSAMPLE = 2;
+    static const int H2V1_UPSAMPLE = 3;
+    static const int H2V2_FANCY_UPSAMPLE = 4;
+    static const int H2V2_UPSAMPLE = 5;
+    static const int INT_UPSAMPLE = 6;
+
+    static const int INPUT_CONSUME_INPUT = 0;
+    static const int COEF_CONSUME_INPUT = 1;
+
+    static int extend_test[] =   /* entry n is 2**(n-1) */
+    [
+        0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+        0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
+    ];
+
+    static int extend_offset[] = /* entry n is (-1 << n) + 1 */
+    [
+        0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+        ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+        ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+        ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1
+    ];
+
+    static int jpeg_natural_order[] = [
+        0,  1,  8, 16,  9,  2,  3, 10,
+        17, 24, 32, 25, 18, 11, 4,  5,
+        12, 19, 26, 33, 40, 48, 41, 34,
+        27, 20, 13, 6,  7, 14, 21, 28,
+        35, 42, 49, 56, 57, 50, 43, 36,
+        29, 22, 15, 23, 30, 37, 44, 51,
+        58, 59, 52, 45, 38, 31, 39, 46,
+        53, 60, 61, 54, 47, 55, 62, 63,
+        63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
+        63, 63, 63, 63, 63, 63, 63, 63
+    ];
+
+    static final class JQUANT_TBL {
+        /* This array gives the coefficient quantizers in natural array order
+         * (not the zigzag order in which they are stored in a JPEG DQT marker).
+         * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+         */
+        short[DCTSIZE2] quantval;// = new short[DCTSIZE2];  /* quantization step for each coefficient */
+        /* This field is used only during compression.  It's initialized false when
+         * the table is created, and set true when it's been output to the file.
+         * You could suppress output of a table by setting this to true.
+         * (See jpeg_suppress_tables for an example.)
+         */
+        bool sent_table;     /* true when table has been output */
+    }
+
+    static final class JHUFF_TBL {
+        /* These two fields directly represent the contents of a JPEG DHT marker */
+        byte[17] bits;// = new byte[17]; /* bits[k] = # of symbols with codes of */
+                                    /* length k bits; bits[0] is unused */
+        byte[256] huffval;// = new byte[256];       /* The symbols, in order of incr code length */
+        /* This field is used only during compression.  It's initialized false when
+         * the table is created, and set true when it's been output to the file.
+         * You could suppress output of a table by setting this to true.
+         * (See jpeg_suppress_tables for an example.)
+         */
+        bool sent_table;     /* true when table has been output */
+    }
+
+    static final class bitread_perm_state {     /* Bitreading state saved across MCUs */
+        int get_buffer; /* current bit-extraction buffer */
+        int bits_left;      /* # of unused bits in it */
+    }
+
+    static final class bitread_working_state {      /* Bitreading working state within an MCU */
+        /* Current data source location */
+        /* We need a copy, rather than munging the original, in case of suspension */
+        byte[] buffer; /* => next byte to read from source */
+        int bytes_offset;
+        int bytes_in_buffer;    /* # of bytes remaining in source buffer */
+        /* Bit input buffer --- note these values are kept in register variables,
+         * not in this struct, inside the inner loops.
+         */
+        int get_buffer; /* current bit-extraction buffer */
+        int bits_left;      /* # of unused bits in it */
+        /* Pointer needed by jpeg_fill_bit_buffer. */
+        jpeg_decompress_struct cinfo;   /* back link to decompress master record */
+    }
+
+    static final class savable_state {
+        int EOBRUN; //Note that this is only used in the progressive case
+        int[MAX_COMPS_IN_SCAN] last_dc_val;// = new int[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+    }
+
+    static final class d_derived_tbl {
+        /* Basic tables: (element [0] of each array is unused) */
+        int[18] maxcode;// = new int[18];       /* largest code of length k (-1 if none) */
+        /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+        int[17] valoffset;// = new int[17];     /* huffval[] offset for codes of length k */
+        /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
+         * the smallest code of length k; so given a code of length k, the
+         * corresponding symbol is huffval[code + valoffset[k]]
+         */
+
+        /* Link to public Huffman table (needed only in jpeg_huff_decode) */
+        JHUFF_TBL pub;
+
+        /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
+         * the input data stream.   If the next Huffman code is no more
+         * than HUFF_LOOKAHEAD bits long, we can obtain its length and
+         * the corresponding symbol directly from these tables.
+         */
+        int[1<<HUFF_LOOKAHEAD] look_nbits;// = new int[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+        byte[1<<HUFF_LOOKAHEAD] look_sym;// = new byte[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
+    }
+
+    static final class jpeg_d_coef_controller {
+        int consume_data;
+        int decompress_data;
+
+        /* Pointer to array of coefficient virtual arrays, or null if none */
+        short[][][] coef_arrays;
+
+        /* These variables keep track of the current location of the input side. */
+        /* cinfo.input_iMCU_row is also used for this. */
+        int MCU_ctr;        /* counts MCUs processed in current row */
+        int MCU_vert_offset;        /* counts MCU rows within iMCU row */
+        int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+        /* The output side's location is represented by cinfo.output_iMCU_row. */
+
+        /* In single-pass modes, it's sufficient to buffer just one MCU.
+         * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
+         * and let the entropy decoder write into that workspace each time.
+         * (On 80x86, the workspace is FAR even though it's not really very big;
+         * this is to keep the module interfaces unchanged when a large coefficient
+         * buffer is necessary.)
+         * In multi-pass modes, this array points to the current MCU's blocks
+         * within the virtual arrays; it is used only by the input side.
+         */
+        short[][D_MAX_BLOCKS_IN_MCU] MCU_buffer;// = new short[D_MAX_BLOCKS_IN_MCU][];
+
+        /* In multi-pass modes, we need a virtual block array for each component. */
+        short[][][][MAX_COMPONENTS] whole_image;// = new short[MAX_COMPONENTS][][][];
+
+        /* When doing block smoothing, we latch coefficient Al values here */
+        int[] coef_bits_latch;
+
+        short[] workspace;
+
+        void start_input_pass (jpeg_decompress_struct cinfo) {
+            cinfo.input_iMCU_row = 0;
+            start_iMCU_row(cinfo);
+        }
+
+        /* Reset within-iMCU-row counters for a new row (input side) */
+        void start_iMCU_row (jpeg_decompress_struct cinfo) {
+            jpeg_d_coef_controller coef = cinfo.coef;
+
+            /* In an interleaved scan, an MCU row is the same as an iMCU row.
+             * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+             * But at the bottom of the image, process only what's left.
+             */
+            if (cinfo.comps_in_scan > 1) {
+                coef.MCU_rows_per_iMCU_row = 1;
+            } else {
+                if (cinfo.input_iMCU_row < (cinfo.total_iMCU_rows-1))
+                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].v_samp_factor;
+                else
+                    coef.MCU_rows_per_iMCU_row = cinfo.cur_comp_info[0].last_row_height;
+            }
+
+            coef.MCU_ctr = 0;
+            coef.MCU_vert_offset = 0;
+        }
+
+    }
+
+    static abstract class jpeg_entropy_decoder {
+        abstract void start_pass (jpeg_decompress_struct cinfo);
+        abstract bool decode_mcu (jpeg_decompress_struct cinfo, short[][] MCU_data);
+
+        /* This is here to share code between baseline and progressive decoders; */
+        /* other modules probably should not use it */
+        bool insufficient_data;  /* set true after emitting warning */
+
+        bitread_working_state br_state_local;
+        savable_state state_local;
+        public this(){
+            br_state_local = new bitread_working_state();
+            state_local = new savable_state();
+        }
+    }
+
+    static final class huff_entropy_decoder : jpeg_entropy_decoder {
+        bitread_perm_state bitstate;// = new bitread_perm_state();  /* Bit buffer at start of MCU */
+        savable_state saved;// = new savable_state();       /* Other state at start of MCU */
+
+        /* These fields are NOT loaded into local working state. */
+        int restarts_to_go; /* MCUs left in this restart interval */
+
+        /* Pointers to derived tables (these workspaces have image lifespan) */
+        d_derived_tbl[NUM_HUFF_TBLS] dc_derived_tbls;// = new d_derived_tbl[NUM_HUFF_TBLS];
+        d_derived_tbl[NUM_HUFF_TBLS] ac_derived_tbls;// = new d_derived_tbl[NUM_HUFF_TBLS];
+
+        /* Precalculated info set up by start_pass for use in decode_mcu: */
+
+        /* Pointers to derived tables to be used for each block within an MCU */
+        d_derived_tbl[D_MAX_BLOCKS_IN_MCU] dc_cur_tbls;// = new d_derived_tbl[D_MAX_BLOCKS_IN_MCU];
+        d_derived_tbl[D_MAX_BLOCKS_IN_MCU] ac_cur_tbls;// = new d_derived_tbl[D_MAX_BLOCKS_IN_MCU];
+        /* Whether we care about the DC and AC coefficient values for each block */
+        bool[D_MAX_BLOCKS_IN_MCU] dc_needed;// = new bool[D_MAX_BLOCKS_IN_MCU];
+        bool[D_MAX_BLOCKS_IN_MCU] ac_needed;// = new bool[D_MAX_BLOCKS_IN_MCU];
+
+        public this(){
+            bitstate = new bitread_perm_state(); /* Bit buffer at start of MCU */
+            saved = new savable_state();      /* Other state at start of MCU */
+        }
+
+        override void start_pass (jpeg_decompress_struct cinfo) {
+            start_pass_huff_decoder(cinfo);
+        }
+
+        override bool decode_mcu (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+            huff_entropy_decoder entropy = this;
+            int blkn;
+//          BITREAD_STATE_VARS;
+            int get_buffer;
+            int bits_left;
+//          bitread_working_state br_state = new bitread_working_state();
+//          savable_state state = new savable_state();
+            bitread_working_state br_state = br_state_local;
+            savable_state state = state_local;
+
+                /* Process restart marker if needed; may have to suspend */
+            if (cinfo.restart_interval !is 0) {
+                if (entropy.restarts_to_go is 0)
+                    if (! process_restart(cinfo))
+                        return false;
+            }
+
+            /* If we've run out of data, just leave the MCU set to zeroes.
+             * This way, we return uniform gray for the remainder of the segment.
+             */
+            if (! entropy.insufficient_data) {
+
+                /* Load up working state */
+//              BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
+                br_state.cinfo = cinfo;
+                br_state.buffer = cinfo.buffer;
+                br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
+                br_state.bytes_offset = cinfo.bytes_offset;
+                get_buffer = entropy.bitstate.get_buffer;
+                bits_left = entropy.bitstate.bits_left;
+
+//              ASSIGN_STATE(state, entropy.saved);
+                state.last_dc_val[0] = entropy.saved.last_dc_val[0];
+                state.last_dc_val[1] = entropy.saved.last_dc_val[1];
+                state.last_dc_val[2] = entropy.saved.last_dc_val[2];
+                state.last_dc_val[3] = entropy.saved.last_dc_val[3];
+
+                /* Outer loop handles each block in the MCU */
+
+                for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
+                    short[] block = MCU_data[blkn];
+                    d_derived_tbl dctbl = entropy.dc_cur_tbls[blkn];
+                    d_derived_tbl actbl = entropy.ac_cur_tbls[blkn];
+                    int s = 0, k, r;
+
+                    /* Decode a single block's worth of coefficients */
+
+                    /* Section F.2.2.1: decode the DC coefficient difference */
+//                  HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
+                    {
+                    int nb = 0, look;
+                    if (bits_left < HUFF_LOOKAHEAD) {
+                        if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+                            return false;
+                        }
+                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        if (bits_left < HUFF_LOOKAHEAD) {
+                            nb = 1;
+//                          goto slowlabel;
+                            if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,dctbl,nb)) < 0) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                    }
+//                  look = PEEK_BITS(HUFF_LOOKAHEAD);
+                    if (nb !is 1) {
+                        look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                        if ((nb = dctbl.look_nbits[look]) !is 0) {
+//                          DROP_BITS(nb);
+                            bits_left -= nb;
+                            s = dctbl.look_sym[look] & 0xFF;
+                        } else {
+                            nb = HUFF_LOOKAHEAD+1;
+//                          slowlabel:
+                            if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,dctbl,nb)) < 0) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                    }
+                    }
+
+                    if (s !is 0) {
+//                      CHECK_BIT_BUFFER(br_state, s, return FALSE);
+                        {
+                        if (bits_left < (s)) {
+                            if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                        }
+//                      r = GET_BITS(s);
+                        r = (( (get_buffer >> (bits_left -= (s)))) & ((1<<(s))-1));
+//                      s = HUFF_EXTEND(r, s);
+                        s = ((r) < extend_test[s] ? (r) + extend_offset[s] : (r));
+                    }
+
+                    if (entropy.dc_needed[blkn]) {
+                        /* Convert DC difference to actual value, update last_dc_val */
+                        int ci = cinfo.MCU_membership[blkn];
+                        s += state.last_dc_val[ci];
+                        state.last_dc_val[ci] = s;
+                        /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
+                        block[0] = cast(short) s;
+                    }
+
+                    if (entropy.ac_needed[blkn]) {
+
+                        /* Section F.2.2.2: decode the AC coefficients */
+                        /* Since zeroes are skipped, output area must be cleared beforehand */
+                        for (k = 1; k < DCTSIZE2; k++) {
+//                          HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
+                            {
+                            int nb = 0, look;
+                            if (bits_left < HUFF_LOOKAHEAD) {
+                                if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                if (bits_left < HUFF_LOOKAHEAD) {
+                                    nb = 1;
+//                                  goto slowlabel;
+                                    if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb)) < 0) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                            }
+                            if (nb !is 1) {
+//                              look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                if ((nb = actbl.look_nbits[look]) !is 0) {
+//                                  DROP_BITS(nb);
+                                    bits_left -= (nb);
+                                    s = actbl.look_sym[look] & 0xFF;
+                                } else {
+                                    nb = HUFF_LOOKAHEAD+1;
+//                                  slowlabel:
+                                    if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb)) < 0) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                            }
+                            }
+                            r = s >> 4;
+                            s &= 15;
+
+                            if (s !is 0) {
+                                k += r;
+//                              CHECK_BIT_BUFFER(br_state, s, return FALSE);
+                                {
+                                if (bits_left < (s)) {
+                                    if (!jpeg_fill_bit_buffer(br_state, get_buffer, bits_left, s)) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer;
+                                    bits_left = br_state.bits_left;
+                                }
+                                }
+//                              r = GET_BITS(s);
+                                r = (((get_buffer >> (bits_left -= (s)))) & ((1 << (s)) - 1));
+//                              s = HUFF_EXTEND(r, s);
+                                s = ((r) < extend_test[s] ? (r) + extend_offset[s] : (r));
+                                /*
+                                 * Output coefficient in natural (dezigzagged)
+                                 * order. Note: the extra entries in
+                                 * jpeg_natural_order[] will save us if k >=
+                                 * DCTSIZE2, which could happen if the data is
+                                 * corrupted.
+                                 */
+                                block[jpeg_natural_order[k]] = cast(short) s;
+                            } else {
+                                if (r !is 15)
+                                    break;
+                                k += 15;
+                            }
+                        }
+
+                    } else {
+
+                        /* Section F.2.2.2: decode the AC coefficients */
+                        /* In this path we just discard the values */
+                        for (k = 1; k < DCTSIZE2; k++) {
+//                          HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
+                            {
+                            int nb = 0, look;
+                            if (bits_left < HUFF_LOOKAHEAD) {
+                                if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                if (bits_left < HUFF_LOOKAHEAD) {
+                                    nb = 1;
+//                                  goto slowlabel;
+                                    if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb)) < 0) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                            }
+                            if (nb !is 1) {
+//                              look = PEEK_BITS(HUFF_LOOKAHEAD);
+                                look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                                if ((nb = actbl.look_nbits[look]) !is 0) {
+//                                  DROP_BITS(nb);
+                                    bits_left -= (nb);
+                                    s = actbl.look_sym[look] & 0xFF;
+                                } else {
+                                    nb = HUFF_LOOKAHEAD+1;
+//                                  slowlabel:
+                                    if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb)) < 0) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                            }
+                            }
+                            r = s >> 4;
+                            s &= 15;
+
+                            if (s !is 0) {
+                                k += r;
+//                              CHECK_BIT_BUFFER(br_state, s, return FALSE);
+                                {
+                                if (bits_left < (s)) {
+                                    if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) {
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                    }
+                                }
+//                              DROP_BITS(s);
+                                bits_left -= s;
+                            } else {
+                                if (r !is 15)
+                                    break;
+                                k += 15;
+                            }
+                        }
+
+                    }
+                }
+
+                /* Completed MCU, so update state */
+//              BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
+                cinfo.buffer = br_state.buffer;
+                cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
+                cinfo.bytes_offset = br_state.bytes_offset;
+                entropy.bitstate.get_buffer = get_buffer;
+                entropy.bitstate.bits_left = bits_left;
+//              ASSIGN_STATE(entropy.saved, state);
+                entropy.saved.last_dc_val[0] = state.last_dc_val[0];
+                entropy.saved.last_dc_val[1] = state.last_dc_val[1];
+                entropy.saved.last_dc_val[2] = state.last_dc_val[2];
+                entropy.saved.last_dc_val[3] = state.last_dc_val[3];
+            }
+
+            /* Account for restart interval (no-op if not using restarts) */
+            entropy.restarts_to_go--;
+
+            return true;
+        }
+
+        void start_pass_huff_decoder (jpeg_decompress_struct cinfo) {
+            huff_entropy_decoder entropy = this;
+            int ci, blkn, dctbl, actbl;
+            jpeg_component_info compptr;
+
+            /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+             * This ought to be an error condition, but we make it a warning because
+             * there are some baseline files out there with all zeroes in these bytes.
+             */
+            if (cinfo.Ss !is 0 || cinfo.Se !is DCTSIZE2-1 || cinfo.Ah !is 0 || cinfo.Al !is 0) {
+//              WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+            }
+
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+                compptr = cinfo.cur_comp_info[ci];
+                dctbl = compptr.dc_tbl_no;
+                actbl = compptr.ac_tbl_no;
+                /* Compute derived values for Huffman tables */
+                /* We may do this more than once for a table, but it's not expensive */
+                jpeg_make_d_derived_tbl(cinfo, true, dctbl, entropy.dc_derived_tbls[dctbl] = new d_derived_tbl());
+                jpeg_make_d_derived_tbl(cinfo, false, actbl, entropy.ac_derived_tbls[actbl] = new d_derived_tbl());
+                /* Initialize DC predictions to 0 */
+                entropy.saved.last_dc_val[ci] = 0;
+            }
+
+            /* Precalculate decoding info for each block in an MCU of this scan */
+            for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
+                ci = cinfo.MCU_membership[blkn];
+                compptr = cinfo.cur_comp_info[ci];
+                /* Precalculate which table to use for each block */
+                entropy.dc_cur_tbls[blkn] = entropy.dc_derived_tbls[compptr.dc_tbl_no];
+                entropy.ac_cur_tbls[blkn] = entropy.ac_derived_tbls[compptr.ac_tbl_no];
+                /* Decide whether we really care about the coefficient values */
+                if (compptr.component_needed) {
+                    entropy.dc_needed[blkn] = true;
+                    /* we don't need the ACs if producing a 1/8th-size image */
+                    entropy.ac_needed[blkn] = (compptr.DCT_scaled_size > 1);
+                } else {
+                    entropy.dc_needed[blkn] = entropy.ac_needed[blkn] = false;
+                }
+            }
+
+            /* Initialize bitread state variables */
+            entropy.bitstate.bits_left = 0;
+            entropy.bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+            entropy.insufficient_data = false;
+
+            /* Initialize restart counter */
+            entropy.restarts_to_go = cinfo.restart_interval;
+        }
+
+        bool process_restart (jpeg_decompress_struct cinfo) {
+            huff_entropy_decoder entropy = this;
+            int ci;
+
+            /* Throw away any unused bits remaining in bit buffer; */
+            /* include any full bytes in next_marker's count of discarded bytes */
+            cinfo.marker.discarded_bytes += entropy.bitstate.bits_left / 8;
+            entropy.bitstate.bits_left = 0;
+
+            /* Advance past the RSTn marker */
+            if (! read_restart_marker (cinfo))
+                return false;
+
+            /* Re-initialize DC predictions to 0 */
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++)
+                entropy.saved.last_dc_val[ci] = 0;
+
+            /* Reset restart counter */
+            entropy.restarts_to_go = cinfo.restart_interval;
+
+            /* Reset out-of-data flag, unless read_restart_marker left us smack up
+             * against a marker.    In that case we will end up treating the next data
+             * segment as empty, and we can avoid producing bogus output pixels by
+             * leaving the flag set.
+             */
+            if (cinfo.unread_marker is 0)
+                entropy.insufficient_data = false;
+
+            return true;
+        }
+    }
+
+    static final class phuff_entropy_decoder : jpeg_entropy_decoder {
+
+        /* These fields are loaded into local variables at start of each MCU.
+         * In case of suspension, we exit WITHOUT updating them.
+         */
+        bitread_perm_state bitstate;// = new bitread_perm_state();  /* Bit buffer at start of MCU */
+        savable_state saved;// = new savable_state();       /* Other state at start of MCU */
+
+        /* These fields are NOT loaded into local working state. */
+        int restarts_to_go; /* MCUs left in this restart interval */
+
+        /* Pointers to derived tables (these workspaces have image lifespan) */
+        d_derived_tbl[NUM_HUFF_TBLS] derived_tbls;// = new d_derived_tbl[NUM_HUFF_TBLS];
+
+        d_derived_tbl ac_derived_tbl; /* active table during an AC scan */
+
+        int[DCTSIZE2] newnz_pos;// = new int[DCTSIZE2];
+
+        public this(){
+            bitstate = new bitread_perm_state(); /* Bit buffer at start of MCU */
+            saved = new savable_state();      /* Other state at start of MCU */
+        }
+
+        override void start_pass (jpeg_decompress_struct cinfo) {
+            start_pass_phuff_decoder(cinfo);
+        }
+
+        override bool decode_mcu (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+            bool is_DC_band = (cinfo.Ss is 0);
+            if (cinfo.Ah is 0) {
+                if (is_DC_band)
+                    return decode_mcu_DC_first(cinfo, MCU_data);
+                else
+                    return decode_mcu_AC_first(cinfo, MCU_data);
+            } else {
+                if (is_DC_band)
+                    return decode_mcu_DC_refine(cinfo, MCU_data);
+                else
+                    return decode_mcu_AC_refine(cinfo, MCU_data);
+            }
+        }
+
+        bool decode_mcu_DC_refine (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+            phuff_entropy_decoder entropy = this;
+            int p1 = 1 << cinfo.Al; /* 1 in the bit position being coded */
+            int blkn;
+            short[] block;
+//          BITREAD_STATE_VARS;
+            int get_buffer;
+            int bits_left;
+//          bitread_working_state br_state = new bitread_working_state();
+            bitread_working_state br_state = br_state_local;
+
+            /* Process restart marker if needed; may have to suspend */
+            if (cinfo.restart_interval !is 0) {
+                if (entropy.restarts_to_go is 0)
+                    if (! process_restart(cinfo))
+                        return false;
+            }
+
+            /* Not worth the cycles to check insufficient_data here,
+             * since we will not change the data anyway if we read zeroes.
+             */
+
+            /* Load up working state */
+//          BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
+            br_state.cinfo = cinfo;
+            br_state.buffer = cinfo.buffer;
+            br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
+            br_state.bytes_offset = cinfo.bytes_offset;
+            get_buffer = entropy.bitstate.get_buffer;
+            bits_left = entropy.bitstate.bits_left;
+
+            /* Outer loop handles each block in the MCU */
+
+            for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
+                block = MCU_data[blkn];
+
+                /* Encoded data is simply the next bit of the two's-complement DC value */
+//              CHECK_BIT_BUFFER(br_state, 1, return FALSE);
+                {
+                if (bits_left < (1)) {
+                    if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) {
+                         return false;
+                    }
+                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                }
+                }
+//              if (GET_BITS(1))
+                if ((( (get_buffer >> (bits_left -= (1)))) & ((1<<(1))-1)) !is 0)
+                    block[0] |= p1;
+                    /* Note: since we use |=, repeating the assignment later is safe */
+            }
+
+            /* Completed MCU, so update state */
+//          BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
+            cinfo.buffer = br_state.buffer;
+            cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
+            cinfo.bytes_offset = br_state.bytes_offset;
+            entropy.bitstate.get_buffer = get_buffer;
+            entropy.bitstate.bits_left = bits_left;
+
+            /* Account for restart interval (no-op if not using restarts) */
+            entropy.restarts_to_go--;
+
+            return true;
+
+        }
+
+        bool decode_mcu_AC_refine (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+            phuff_entropy_decoder entropy = this;
+            int Se = cinfo.Se;
+            int p1 = 1 << cinfo.Al; /* 1 in the bit position being coded */
+            int m1 = (-1) << cinfo.Al;  /* -1 in the bit position being coded */
+            int s = 0, k, r;
+            int EOBRUN;
+            short[] block;
+            short[] thiscoef;
+//          BITREAD_STATE_VARS;
+            int get_buffer;
+            int bits_left;
+//          bitread_working_state br_state = new bitread_working_state();
+            bitread_working_state br_state = br_state_local;
+
+            d_derived_tbl tbl;
+            int num_newnz;
+            int[] newnz_pos = entropy.newnz_pos;
+
+                /* Process restart marker if needed; may have to suspend */
+            if (cinfo.restart_interval !is 0) {
+                if (entropy.restarts_to_go is 0)
+                    if (! process_restart(cinfo))
+                        return false;
+            }
+
+            /* If we've run out of data, don't modify the MCU.
+             */
+            if (! entropy.insufficient_data) {
+
+                /* Load up working state */
+//              BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
+                br_state.cinfo = cinfo;
+                br_state.buffer = cinfo.buffer;
+                br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
+                br_state.bytes_offset = cinfo.bytes_offset;
+                get_buffer = entropy.bitstate.get_buffer;
+                bits_left = entropy.bitstate.bits_left;
+
+                EOBRUN = entropy.saved.EOBRUN; /* only part of saved state we need */
+
+                /* There is always only one block per MCU */
+                block = MCU_data[0];
+                tbl = entropy.ac_derived_tbl;
+
+                /* If we are forced to suspend, we must undo the assignments to any newly
+                 * nonzero coefficients in the block, because otherwise we'd get confused
+                 * next time about which coefficients were already nonzero.
+                 * But we need not undo addition of bits to already-nonzero coefficients;
+                 * instead, we can test the current bit to see if we already did it.
+                 */
+                num_newnz = 0;
+
+                /* initialize coefficient loop counter to start of band */
+                k = cinfo.Ss;
+
+                if (EOBRUN is 0) {
+                    for (; k <= Se; k++) {
+//                      HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
+                        {
+                        int nb = 0, look;
+                        if (bits_left < HUFF_LOOKAHEAD) {
+                            if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+//                              failaction;
+                                while (num_newnz > 0)
+                                    block[newnz_pos[--num_newnz]] = 0;
+
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            if (bits_left < HUFF_LOOKAHEAD) {
+                                nb = 1;
+//                              goto slowlabel;
+                                if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+//                                  failaction;
+                                    while (num_newnz > 0)
+                                        block[newnz_pos[--num_newnz]] = 0;
+
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                        }
+                        if (nb !is 1) {
+//                          look = PEEK_BITS(HUFF_LOOKAHEAD);
+                            look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+                            if ((nb = tbl.look_nbits[look]) !is 0) {
+//                              DROP_BITS(nb);
+                                bits_left -= nb;
+                                s = tbl.look_sym[look] & 0xFF;
+                            } else {
+                                nb = HUFF_LOOKAHEAD+1;
+//                              slowlabel:
+                                if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+//                                  failaction;
+                                    while (num_newnz > 0)
+                                        block[newnz_pos[--num_newnz]] = 0;
+
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                        }
+                        }
+                        r = s >> 4;
+                        s &= 15;
+                        if (s !is 0) {
+                            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);
+                            {
+                            if (bits_left < (1)) {
+                                if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) {
+//                                  failaction;
+                                    while (num_newnz > 0)
+                                        block[newnz_pos[--num_newnz]] = 0;
+
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                            }
+//                          if (GET_BITS(1))
+                            if ((( (get_buffer >> (bits_left -= (1)))) & ((1<<(1))-1)) !is 0)
+                                s = p1;     /* newly nonzero coef is positive */
+                            else
+                                s = m1;     /* newly nonzero coef is negative */
+                        } else {
+                            if (r !is 15) {
+                                EOBRUN = 1 << r;    /* EOBr, run length is 2^r + appended bits */
+                                if (r !is 0) {
+//                                  CHECK_BIT_BUFFER(br_state, r, goto undoit);
+                                    {
+                                    if (bits_left < (r)) {
+                                        if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,r)) {
+//                                          failaction;
+                                            while (num_newnz > 0)
+                                                block[newnz_pos[--num_newnz]] = 0;
+
+                                            return false;
+                                        }
+                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                    }
+                                    }
+//                                  r = GET_BITS(r);
+                                    r = (( (get_buffer >> (bits_left -= (r)))) & ((1<<(r))-1));
+                                    EOBRUN += r;
+                                }
+                                break;      /* rest of block is handled by EOB logic */
+                            }
+                            /* note s = 0 for processing ZRL */
+                        }
+                        /* Advance over already-nonzero coefs and r still-zero coefs,
+                         * appending correction bits to the nonzeroes.  A correction bit is 1
+                         * if the absolute value of the coefficient must be increased.
+                         */
+                        do {
+                            thiscoef = block;
+                            int thiscoef_offset = jpeg_natural_order[k];
+                            if (thiscoef[thiscoef_offset] !is 0) {
+//                              CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+                                {
+                                if (bits_left < (1)) {
+                                    if (!jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) {
+//                                      failaction;
+                                        while (num_newnz > 0)
+                                            block[newnz_pos[--num_newnz]] = 0;
+
+                                        return false;
+                                    }
+                                    get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                }
+                                }
+//                              if (GET_BITS(1)) {
+                                if ((( (get_buffer >> (bits_left -= (1)))) & ((1<<(1))-1)) !is 0) {
+                                    if ((thiscoef[thiscoef_offset] & p1) is 0) { /* do nothing if already set it */
+                                        if (thiscoef[thiscoef_offset] >= 0)
+                                            thiscoef[thiscoef_offset] += p1;
+                                        else
+                                            thiscoef[thiscoef_offset] += m1;
+                                    }
+                                }
+                            } else {
+                                if (--r < 0)
+                                    break;      /* reached target zero coefficient */
+                            }
+                            k++;
+                        } while (k <= Se);
+                        if (s !is 0) {
+                            int pos = jpeg_natural_order[k];
+                            /* Output newly nonzero coefficient */
+                            block[pos] = cast(short) s;
+                            /* Remember its position in case we have to suspend */
+                            newnz_pos[num_newnz++] = pos;
+                        }
+                    }
+                }
+
+                if (EOBRUN > 0) {
+                    /* Scan any remaining coefficient positions after the end-of-band
+                     * (the last newly nonzero coefficient, if any).    Append a correction
+                     * bit to each already-nonzero coefficient. A correction bit is 1
+                     * if the absolute value of the coefficient must be increased.
+                     */
+                    for (; k <= Se; k++) {
+                        thiscoef = block;
+                        int thiscoef_offset = jpeg_natural_order[k];
+                        if (thiscoef[thiscoef_offset] !is 0) {
+//                          CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+                            {
+                            if (bits_left < (1)) {
+                                if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) {
+//                                  failaction;
+                                    while (num_newnz > 0)
+                                        block[newnz_pos[--num_newnz]] = 0;
+
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                            }
+//                          if (GET_BITS(1)) {
+                            if ((( (get_buffer >> (bits_left -= (1)))) & ((1<<(1))-1)) !is 0) {
+                                if ((thiscoef[thiscoef_offset] & p1) is 0) { /* do nothing if already changed it */
+                                    if (thiscoef[thiscoef_offset] >= 0)
+                                        thiscoef[thiscoef_offset] += p1;
+                                    else
+                                        thiscoef[thiscoef_offset] += m1;
+                                }
+                            }
+                        }
+                    }
+                        /* Count one block completed in EOB run */
+                    EOBRUN--;
+                }
+
+                /* Completed MCU, so update state */
+//              BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
+                cinfo.buffer = br_state.buffer;
+                cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
+                cinfo.bytes_offset = br_state.bytes_offset;
+                entropy.bitstate.get_buffer = get_buffer;
+                entropy.bitstate.bits_left = bits_left;
+
+                entropy.saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+            }
+
+            /* Account for restart interval (no-op if not using restarts) */
+            entropy.restarts_to_go--;
+
+            return true;
+
+//          undoit:
+//              /* Re-zero any output coefficients that we made newly nonzero */
+//              while (num_newnz > 0)
+//                  (*block)[newnz_pos[--num_newnz]] = 0;
+//
+//              return false;
+
+        }
+
+        bool decode_mcu_AC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+            phuff_entropy_decoder entropy = this;
+            int Se = cinfo.Se;
+            int Al = cinfo.Al;
+            int s = 0, k, r;
+            int EOBRUN;
+            short[] block;
+//          BITREAD_STATE_VARS;
+            int get_buffer;
+            int bits_left;
+//          bitread_working_state br_state = new bitread_working_state();
+            bitread_working_state br_state = br_state_local;
+
+            d_derived_tbl tbl;
+
+            /* Process restart marker if needed; may have to suspend */
+            if (cinfo.restart_interval !is 0) {
+                if (entropy.restarts_to_go is 0)
+                    if (! process_restart(cinfo))
+                        return false;
+            }
+
+            /* If we've run out of data, just leave the MCU set to zeroes.
+             * This way, we return uniform gray for the remainder of the segment.
+             */
+            if (! entropy.insufficient_data) {
+
+                /* Load up working state.
+                 * We can avoid loading/saving bitread state if in an EOB run.
+                 */
+                EOBRUN = entropy.saved.EOBRUN;  /* only part of saved state we need */
+
+                /* There is always only one block per MCU */
+
+                if (EOBRUN > 0)     /* if it's a band of zeroes... */
+                    EOBRUN--;           /* ...process it now (we do nothing) */
+                else {
+//                  BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
+                    br_state.cinfo = cinfo;
+                    br_state.buffer = cinfo.buffer;
+                    br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
+                    br_state.bytes_offset = cinfo.bytes_offset;
+                    get_buffer = entropy.bitstate.get_buffer;
+                    bits_left = entropy.bitstate.bits_left;
+
+                    block = MCU_data[0];
+                    tbl = entropy.ac_derived_tbl;
+
+                    for (k = cinfo.Ss; k <= Se; k++) {
+//                      HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
+                        {
+                        int nb = 0, look;
+                        if (bits_left < HUFF_LOOKAHEAD) {
+                            if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            if (bits_left < HUFF_LOOKAHEAD) {
+                                nb = 1;
+//                              goto slowlabel;
+                                if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                        }
+                        if (nb !is 1) {
+//                          look = PEEK_BITS(HUFF_LOOKAHEAD);
+                            look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+
+                            if ((nb = tbl.look_nbits[look]) !is 0) {
+//                              DROP_BITS(nb);
+                                bits_left -= nb;
+                                s = tbl.look_sym[look] & 0xFF;
+                            } else {
+                                nb = HUFF_LOOKAHEAD+1;
+//                              slowlabel:
+                                if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                        }
+                        }
+                        r = s >> 4;
+                        s &= 15;
+                        if (s !is 0) {
+                            k += r;
+//                          CHECK_BIT_BUFFER(br_state, s, return FALSE);
+                            {
+                            if (bits_left < (s)) {
+                                if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) {
+                                    return false;
+                                }
+                                get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                            }
+                            }
+//                          r = GET_BITS(s);
+                            r = (( (get_buffer >> (bits_left -= (s)))) & ((1<<(s))-1));
+//                          s = HUFF_EXTEND(r, s);
+                            s = ((r) < extend_test[s] ? (r) + extend_offset[s] : (r));
+                            /* Scale and output coefficient in natural (dezigzagged) order */
+                            block[jpeg_natural_order[k]] = cast(short) (s << Al);
+                        } else {
+                            if (r is 15) {  /* ZRL */
+                                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 */
+//                                  CHECK_BIT_BUFFER(br_state, r, return FALSE);
+                                    {
+                                    if (bits_left < (r)) {
+                                        if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,r)) {
+                                            return false;
+                                        }
+                                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                                    }
+                                    }
+//                                  r = GET_BITS(r);
+                                    r = (( (get_buffer >> (bits_left -= (r)))) & ((1<<(r))-1));
+                                    EOBRUN += r;
+                                }
+                                EOBRUN--;       /* this band is processed at this moment */
+                                break;      /* force end-of-band */
+                            }
+                        }
+                    }
+
+//                  BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
+                    cinfo.buffer = br_state.buffer;
+                    cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
+                    cinfo.bytes_offset = br_state.bytes_offset;
+                    entropy.bitstate.get_buffer = get_buffer;
+                    entropy.bitstate.bits_left = bits_left;
+                }
+
+                /* Completed MCU, so update state */
+                entropy.saved.EOBRUN = EOBRUN;  /* only part of saved state we need */
+            }
+
+            /* Account for restart interval (no-op if not using restarts) */
+            entropy.restarts_to_go--;
+
+            return true;
+        }
+
+        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;
+            int blkn, ci;
+            short[] block;
+//          BITREAD_STATE_VARS;
+            int get_buffer;
+            int bits_left;
+//          bitread_working_state br_state = new bitread_working_state();
+            bitread_working_state br_state = br_state_local;
+
+//          savable_state state = new savable_state();
+            savable_state state = state_local;
+            d_derived_tbl tbl;
+            jpeg_component_info compptr;
+
+            /* Process restart marker if needed; may have to suspend */
+            if (cinfo.restart_interval !is 0) {
+                if (entropy.restarts_to_go is 0)
+                    if (! process_restart(cinfo))
+                        return false;
+            }
+
+            /* If we've run out of data, just leave the MCU set to zeroes.
+             * This way, we return uniform gray for the remainder of the segment.
+             */
+            if (! entropy.insufficient_data) {
+
+                /* Load up working state */
+//              BITREAD_LOAD_STATE(cinfo,entropy.bitstate);
+                br_state.cinfo = cinfo;
+                br_state.buffer = cinfo.buffer;
+                br_state.bytes_in_buffer = cinfo.bytes_in_buffer;
+                br_state.bytes_offset = cinfo.bytes_offset;
+                get_buffer = entropy.bitstate.get_buffer;
+                bits_left = entropy.bitstate.bits_left;
+
+//              ASSIGN_STATE(state, entropy.saved);
+                state.EOBRUN = entropy.saved.EOBRUN;
+                state.last_dc_val[0] = entropy.saved.last_dc_val[0];
+                state.last_dc_val[1] = entropy.saved.last_dc_val[1];
+                state.last_dc_val[2] = entropy.saved.last_dc_val[2];
+                state.last_dc_val[3] = entropy.saved.last_dc_val[3];
+
+                /* Outer loop handles each block in the MCU */
+
+                for (blkn = 0; blkn < cinfo.blocks_in_MCU; blkn++) {
+                    block = MCU_data[blkn];
+                    ci = cinfo.MCU_membership[blkn];
+                    compptr = cinfo.cur_comp_info[ci];
+                    tbl = entropy.derived_tbls[compptr.dc_tbl_no];
+
+                    /* Decode a single block's worth of coefficients */
+
+                    /* Section F.2.2.1: decode the DC coefficient difference */
+//                  HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
+                    {
+                    int nb = 0, look;
+                    if (bits_left < HUFF_LOOKAHEAD) {
+                        if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) {
+                            return false;
+                        }
+                        get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        if (bits_left < HUFF_LOOKAHEAD) {
+                            nb = 1;
+//                          goto slowlabel;
+                            if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                    }
+                    if (nb !is 1) {
+//                      look = PEEK_BITS(HUFF_LOOKAHEAD);
+                        look = (( (get_buffer >> (bits_left -   (HUFF_LOOKAHEAD)))) & ((1<<(HUFF_LOOKAHEAD))-1));
+
+                        if ((nb = tbl.look_nbits[look]) !is 0) {
+//                          DROP_BITS(nb);
+                            bits_left -= nb;
+                            s = tbl.look_sym[look] & 0xFF;
+                        } else {
+                            nb = HUFF_LOOKAHEAD+1;
+//                          slowlabel:
+                            if ((s=jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb)) < 0) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                    }
+                    }
+                    if (s !is 0) {
+//                      CHECK_BIT_BUFFER(br_state, s, return FALSE);
+                        {
+                        if (bits_left < (s)) {
+                            if (! jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) {
+                                return false;
+                            }
+                            get_buffer = br_state.get_buffer; bits_left = br_state.bits_left;
+                        }
+                        }
+//                      r = GET_BITS(s);
+                        r = (( (get_buffer >> (bits_left -= (s)))) & ((1<<(s))-1));
+//                      s = HUFF_EXTEND(r, s);
+                        s = ((r) < extend_test[s] ? (r) + extend_offset[s] : (r));
+                    }
+
+                        /* Convert DC difference to actual value, update last_dc_val */
+                    s += state.last_dc_val[ci];
+                    state.last_dc_val[ci] = s;
+                    /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
+                    block[0] = cast(short) (s << Al);
+                }
+
+                /* Completed MCU, so update state */
+//              BITREAD_SAVE_STATE(cinfo,entropy.bitstate);
+                cinfo.buffer = br_state.buffer;
+                cinfo.bytes_in_buffer = br_state.bytes_in_buffer;
+                cinfo.bytes_offset = br_state.bytes_offset;
+                entropy.bitstate.get_buffer = get_buffer;
+                entropy.bitstate.bits_left = bits_left;
+//              ASSIGN_STATE(entropy.saved, state);
+                entropy.saved.EOBRUN = state.EOBRUN;
+                entropy.saved.last_dc_val[0] = state.last_dc_val[0];
+                entropy.saved.last_dc_val[1] = state.last_dc_val[1];
+                entropy.saved.last_dc_val[2] = state.last_dc_val[2];
+                entropy.saved.last_dc_val[3] = state.last_dc_val[3];
+            }
+
+            /* Account for restart interval (no-op if not using restarts) */
+            entropy.restarts_to_go--;
+
+            return true;
+        }
+
+        bool process_restart (jpeg_decompress_struct cinfo) {
+            phuff_entropy_decoder entropy = this;
+            int ci;
+
+            /* Throw away any unused bits remaining in bit buffer; */
+            /* include any full bytes in next_marker's count of discarded bytes */
+            cinfo.marker.discarded_bytes += entropy.bitstate.bits_left / 8;
+            entropy.bitstate.bits_left = 0;
+
+            /* Advance past the RSTn marker */
+            if (! read_restart_marker (cinfo))
+                return false;
+
+            /* Re-initialize DC predictions to 0 */
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++)
+                entropy.saved.last_dc_val[ci] = 0;
+                /* Re-init EOB run count, too */
+            entropy.saved.EOBRUN = 0;
+
+            /* Reset restart counter */
+            entropy.restarts_to_go = cinfo.restart_interval;
+
+            /* Reset out-of-data flag, unless read_restart_marker left us smack up
+             * against a marker.    In that case we will end up treating the next data
+             * segment as empty, and we can avoid producing bogus output pixels by
+             * leaving the flag set.
+             */
+            if (cinfo.unread_marker is 0)
+                entropy.insufficient_data = false;
+
+            return true;
+        }
+
+        void start_pass_phuff_decoder (jpeg_decompress_struct cinfo) {
+            phuff_entropy_decoder entropy = this;
+            bool is_DC_band, bad;
+            int ci, coefi, tbl;
+            int[] coef_bit_ptr;
+            jpeg_component_info compptr;
+
+            is_DC_band = (cinfo.Ss is 0);
+
+            /* Validate scan parameters */
+            bad = false;
+            if (is_DC_band) {
+                if (cinfo.Se !is 0)
+                    bad = true;
+            } else {
+                /* need not check Ss/Se < 0 since they came from unsigned bytes */
+                if (cinfo.Ss > cinfo.Se || cinfo.Se >= DCTSIZE2)
+                    bad = true;
+                /* AC scans may have only one component */
+                if (cinfo.comps_in_scan !is 1)
+                    bad = true;
+            }
+            if (cinfo.Ah !is 0) {
+                /* Successive approximation refinement scan: must have Al = Ah-1. */
+                if (cinfo.Al !is cinfo.Ah-1)
+                    bad = true;
+            }
+            if (cinfo.Al > 13)      /* need not check for < 0 */
+                bad = true;
+            /* Arguably the maximum Al value should be less than 13 for 8-bit precision,
+             * but the spec doesn't say so, and we try to be liberal about what we
+             * accept.  Note: large Al values could result in out-of-range DC
+             * coefficients during early scans, leading to bizarre displays due to
+             * overflows in the IDCT math.  But we won't crash.
+             */
+            if (bad)
+                error();
+//              ERREXIT4(cinfo, JERR_BAD_PROGRESSION, cinfo.Ss, cinfo.Se, cinfo.Ah, cinfo.Al);
+            /* Update progression status, and verify that scan order is legal.
+             * Note that inter-scan inconsistencies are treated as warnings
+             * not fatal errors ... not clear if this is right way to behave.
+             */
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+                int cindex = cinfo.cur_comp_info[ci].component_index;
+                coef_bit_ptr = cinfo.coef_bits[cindex];
+                if (!is_DC_band && coef_bit_ptr[0] < 0) {/* AC without prior DC scan */
+//                  WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+                }
+                for (coefi = cinfo.Ss; coefi <= cinfo.Se; coefi++) {
+                    int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+                    if (cinfo.Ah !is expected) {
+//                      WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+                    }
+                    coef_bit_ptr[coefi] = cinfo.Al;
+                }
+            }
+
+            /* Select MCU decoding routine */
+//          if (cinfo.Ah is 0) {
+//              if (is_DC_band)
+//                  entropy.pub.decode_mcu = decode_mcu_DC_first;
+//              else
+//                  entropy.pub.decode_mcu = decode_mcu_AC_first;
+//          } else {
+//              if (is_DC_band)
+//                  entropy.pub.decode_mcu = decode_mcu_DC_refine;
+//              else
+//                  entropy.pub.decode_mcu = decode_mcu_AC_refine;
+//          }
+
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+                compptr = cinfo.cur_comp_info[ci];
+                /* Make sure requested tables are present, and compute derived tables.
+                 * We may build same derived table more than once, but it's not expensive.
+                 */
+                if (is_DC_band) {
+                    if (cinfo.Ah is 0) {    /* DC refinement needs no table */
+                        tbl = compptr.dc_tbl_no;
+                        jpeg_make_d_derived_tbl(cinfo, true, tbl, entropy.derived_tbls[tbl] = new d_derived_tbl());
+                    }
+                } else {
+                    tbl = compptr.ac_tbl_no;
+                    jpeg_make_d_derived_tbl(cinfo, false, tbl, entropy.derived_tbls[tbl] = new d_derived_tbl());
+                    /* remember the single active table */
+                    entropy.ac_derived_tbl = entropy.derived_tbls[tbl];
+                }
+                /* Initialize DC predictions to 0 */
+                entropy.saved.last_dc_val[ci] = 0;
+            }
+
+            /* Initialize bitread state variables */
+            entropy.bitstate.bits_left = 0;
+            entropy.bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+            entropy.insufficient_data = false;
+
+            /* Initialize private state variables */
+            entropy.saved.EOBRUN = 0;
+
+            /* Initialize restart counter */
+            entropy.restarts_to_go = cinfo.restart_interval;
+        }
+
+    }
+
+    static final class jpeg_component_info {
+        /* These values are fixed over the whole image. */
+        /* For compression, they must be supplied by parameter setup; */
+        /* for decompression, they are read from the SOF marker. */
+        int component_id;       /* identifier for this component (0..255) */
+        int component_index;        /* its index in SOF or cinfo.comp_info[] */
+        int h_samp_factor;      /* horizontal sampling factor (1..4) */
+        int v_samp_factor;      /* vertical sampling factor (1..4) */
+        int quant_tbl_no;       /* quantization table selector (0..3) */
+        /* These values may vary between scans. */
+        /* For compression, they must be supplied by parameter setup; */
+        /* for decompression, they are read from the SOS marker. */
+        /* The decompressor output side may not use these variables. */
+        int dc_tbl_no;      /* DC entropy table selector (0..3) */
+        int ac_tbl_no;      /* AC entropy table selector (0..3) */
+
+        /* Remaining fields should be treated as private by applications. */
+
+        /* These values are computed during compression or decompression startup: */
+        /* Component's size in DCT blocks.
+         * Any dummy blocks added to complete an MCU are not counted; therefore
+         * these values do not depend on whether a scan is interleaved or not.
+         */
+        int width_in_blocks;
+        int height_in_blocks;
+        /* Size of a DCT block in samples.  Always DCTSIZE for compression.
+         * For decompression this is the size of the output from one DCT block,
+         * reflecting any scaling we choose to apply during the IDCT step.
+         * Values of 1,2,4,8 are likely to be supported.    Note that different
+         * components may receive different IDCT scalings.
+         */
+        int DCT_scaled_size;
+        /* The downsampled dimensions are the component's actual, unpadded number
+         * of samples at the main buffer (preprocessing/compression interface), thus
+         * downsampled_width = ceil(image_width * Hi/Hmax)
+         * and similarly for height.    For decompression, IDCT scaling is included, so
+         * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)
+         */
+        int downsampled_width;   /* actual width in samples */
+        int downsampled_height; /* actual height in samples */
+        /* This flag is used only for decompression.    In cases where some of the
+         * components will be ignored (eg grayscale output from YCbCr image),
+         * we can skip most computations for the unused components.
+         */
+        bool component_needed;   /* do we need the value of this component? */
+
+        /* These values are computed before starting a scan of the component. */
+        /* The decompressor output side may not use these variables. */
+        int MCU_width;      /* number of blocks per MCU, horizontally */
+        int MCU_height;     /* number of blocks per MCU, vertically */
+        int MCU_blocks;     /* MCU_width * MCU_height */
+        int MCU_sample_width;       /* MCU width in samples, MCU_width*DCT_scaled_size */
+        int last_col_width;     /* # of non-dummy blocks across in last MCU */
+        int last_row_height;        /* # of non-dummy blocks down in last MCU */
+
+        /* Saved quantization table for component; null if none yet saved.
+         * See jdinput.c comments about the need for this information.
+         * This field is currently used only for decompression.
+         */
+        JQUANT_TBL quant_table;
+
+        /* Private per-component storage for DCT or IDCT subsystem. */
+        int[] dct_table;
+    }
+
+    static final class jpeg_color_quantizer {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo, bool is_pre_scan));
+//      JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+//                   JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+//                   int num_rows));
+//      JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+//      JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+
+        /* Initially allocated colormap is saved here */
+        int[][] sv_colormap;    /* The color map as a 2-D pixel array */
+        int sv_actual;      /* number of entries in use */
+
+        int[][] colorindex; /* Precomputed mapping for speed */
+        /* colorindex[i][j] = index of color closest to pixel value j in component i,
+         * premultiplied as described above.    Since colormap indexes must fit into
+         * JSAMPLEs, the entries of this array will too.
+         */
+        bool is_padded;      /* is the colorindex padded for odither? */
+
+        int[MAX_Q_COMPS] Ncolors;// = new int [MAX_Q_COMPS];    /* # of values alloced to each component */
+
+        /* Variables for ordered dithering */
+        int row_index;      /* cur row's vertical index in dither matrix */
+//          ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
+
+        /* Variables for Floyd-Steinberg dithering */
+//          FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
+        bool on_odd_row; 
+
+        void start_pass (jpeg_decompress_struct cinfo, bool is_pre_scan) {
+            error();
+        }
+    }
+
+    static final class jpeg_upsampler {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+//      JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+//                   JSAMPIMAGE input_buf,
+//                   JDIMENSION *in_row_group_ctr,
+//                   JDIMENSION in_row_groups_avail,
+//                   JSAMPARRAY output_buf,
+//                   JDIMENSION *out_row_ctr,
+//                   JDIMENSION out_rows_avail));
+
+        bool need_context_rows;  /* TRUE if need rows above & below */
+
+        /* Color conversion buffer. When using separate upsampling and color
+         * conversion steps, this buffer holds one upsampled row group until it
+         * has been color converted and output.
+         * Note: we do not allocate any storage for component(s) which are full-size,
+         * ie do not need rescaling.    The corresponding entry of color_buf[] is
+         * simply set to point to the input data array, thereby avoiding copying.
+         */
+        byte[][][MAX_COMPONENTS] color_buf;// = new byte[MAX_COMPONENTS][][];
+        int[MAX_COMPONENTS] color_buf_offset;// = new int[MAX_COMPONENTS];
+
+        /* Per-component upsampling method pointers */
+        int[MAX_COMPONENTS] methods;// = new int[MAX_COMPONENTS];
+
+        int next_row_out;       /* counts rows emitted from color_buf */
+        int rows_to_go; /* counts rows remaining in image */
+
+        /* Height of an input row group for each component. */
+        int[MAX_COMPONENTS] rowgroup_height;// = new int[MAX_COMPONENTS];
+
+        /* These arrays save pixel expansion factors so that int_expand need not
+         * recompute them each time.    They are unused for other upsampling methods.
+         */
+        byte[MAX_COMPONENTS] h_expand;// = new byte[MAX_COMPONENTS];
+        byte[MAX_COMPONENTS] v_expand;// = new byte[MAX_COMPONENTS];
+
+        void start_pass (jpeg_decompress_struct cinfo) {
+            jpeg_upsampler upsample = cinfo.upsample;
+
+            /* Mark the conversion buffer empty */
+            upsample.next_row_out = cinfo.max_v_samp_factor;
+            /* Initialize total-height counter for detecting bottom of image */
+            upsample.rows_to_go = cinfo.output_height;
+        }
+
+    }
+
+    static final class jpeg_marker_reader {
+        /* Read a restart marker --- exported for use by entropy decoder only */
+//      jpeg_marker_parser_method read_restart_marker;
+
+        /* State of marker reader --- nominally internal, but applications
+         * supplying COM or APPn handlers might like to know the state.
+         */
+        bool saw_SOI;        /* found SOI? */
+        bool saw_SOF;        /* found SOF? */
+        int next_restart_num;       /* next restart number expected (0-7) */
+        int discarded_bytes;    /* # of bytes skipped looking for a marker */
+
+        /* Application-overridable marker processing methods */
+//      jpeg_marker_parser_method process_COM;
+//      jpeg_marker_parser_method process_APPn[16];
+
+        /* Limit on marker data length to save for each marker type */
+        int length_limit_COM;
+        int[16] length_limit_APPn;// = new int[16];
+
+        /* Status of COM/APPn marker saving */
+//      jpeg_marker_reader cur_marker;  /* null if not processing a marker */
+//      int bytes_read;     /* data bytes read so far in marker */
+        /* Note: cur_marker is not linked into marker_list until it's all read. */
+    }
+
+
+    static final class jpeg_d_main_controller {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+        int process_data;
+
+         /* Pointer to allocated workspace (M or M+2 row groups). */
+        byte[][][MAX_COMPONENTS] buffer;// = new byte[MAX_COMPONENTS][][];
+        int[MAX_COMPONENTS] buffer_offset;// = new int[MAX_COMPONENTS];
+
+        bool buffer_full;        /* Have we gotten an iMCU row from decoder? */
+        int[1] rowgroup_ctr;// = new int[1];    /* counts row groups output to postprocessor */
+
+        /* Remaining fields are only used in the context case. */
+
+        /* These are the master pointers to the funny-order pointer lists. */
+        byte[][][][2] xbuffer;// = new byte[2][][][];   /* pointers to weird pointer lists */
+        int[][2] xbuffer_offset;// = new int[2][];
+
+        int whichptr;           /* indicates which pointer set is now in use */
+        int context_state;      /* process_data state machine status */
+        int rowgroups_avail;    /* row groups available to postprocessor */
+        int iMCU_row_ctr;   /* counts iMCU rows to detect image top/bot */
+
+        void start_pass (jpeg_decompress_struct cinfo, int pass_mode) {
+            jpeg_d_main_controller main = cinfo.main;
+
+            switch (pass_mode) {
+                case JBUF_PASS_THRU:
+                    if (cinfo.upsample.need_context_rows) {
+                        main.process_data = PROCESS_DATA_CONTEXT_MAIN;
+                        make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
+                        main.whichptr = 0;  /* Read first iMCU row into xbuffer[0] */
+                        main.context_state = CTX_PREPARE_FOR_IMCU;
+                        main.iMCU_row_ctr = 0;
+                    } else {
+                        /* Simple case with no context needed */
+                        main.process_data = PROCESS_DATA_SIMPLE_MAIN;
+                    }
+                    main.buffer_full = false;   /* Mark buffer empty */
+                    main.rowgroup_ctr[0] = 0;
+                    break;
+//              #ifdef QUANT_2PASS_SUPPORTED
+//              case JBUF_CRANK_DEST:
+//                  /* For last pass of 2-pass quantization, just crank the postprocessor */
+//                  main.process_data = PROCESS_DATA_CRANK_POST;
+//                  break;
+//              #endif
+                default:
+                    error();
+//                  ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+                    break;
+            }
+        }
+
+    }
+
+    static final class jpeg_decomp_master {
+//      JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+//      JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+        /* State variables made visible to other modules */
+        bool is_dummy_pass;
+
+        int pass_number;        /* # of passes completed */
+
+        bool using_merged_upsample; /* true if using merged upsample/cconvert */
+
+        /* Saved references to initialized quantizer modules,
+         * in case we need to switch modes.
+         */
+        jpeg_color_quantizer quantizer_1pass;
+        jpeg_color_quantizer quantizer_2pass;
+    }
+
+    static final class jpeg_inverse_dct {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+//      /* It is useful to allow each component to have a separate IDCT method. */
+//      inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+        int[MAX_COMPONENTS] cur_method;// = new int[MAX_COMPONENTS];
+
+        void start_pass (jpeg_decompress_struct cinfo) {
+            jpeg_inverse_dct idct = cinfo.idct;
+            int ci, i;
+            jpeg_component_info compptr;
+            int method = 0;
+//          inverse_DCT_method_ptr method_ptr = NULL;
+            JQUANT_TBL qtbl;
+
+            for (ci = 0; ci < cinfo.num_components; ci++) {
+                compptr = cinfo.comp_info[ci];
+                /* Select the proper IDCT routine for this component's scaling */
+                switch (compptr.DCT_scaled_size) {
+//                  #ifdef IDCT_SCALING_SUPPORTED
+//                  case 1:
+//                      method_ptr = jpeg_idct_1x1;
+//                      method = JDCT_ISLOW;    /* jidctred uses islow-style table */
+//                      break;
+//                  case 2:
+//                      method_ptr = jpeg_idct_2x2;
+//                      method = JDCT_ISLOW;    /* jidctred uses islow-style table */
+//                      break;
+//                  case 4:
+//                      method_ptr = jpeg_idct_4x4;
+//                      method = JDCT_ISLOW;    /* jidctred uses islow-style table */
+//                      break;
+//                  #endif
+                    case DCTSIZE:
+                        switch (cinfo.dct_method) {
+//                          #ifdef DCT_ISLOW_SUPPORTED
+                            case JDCT_ISLOW:
+//                              method_ptr = jpeg_idct_islow;
+                                method = JDCT_ISLOW;
+                                break;
+//                          #endif
+//                          #ifdef DCT_IFAST_SUPPORTED
+//                          case JDCT_IFAST:
+//                              method_ptr = jpeg_idct_ifast;
+//                              method = JDCT_IFAST;
+//                              break;
+//                          #endif
+//                          #ifdef DCT_FLOAT_SUPPORTED
+//                          case JDCT_FLOAT:
+//                              method_ptr = jpeg_idct_float;
+//                              method = JDCT_FLOAT;
+//                              break;
+//                          #endif
+                            default:
+                                error();
+//                              ERREXIT(cinfo, JERR_NOT_COMPILED);
+                                break;
+                        }
+                        break;
+                    default:
+                        error();
+//                      ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr.DCT_scaled_size);
+                        break;
+                    }
+//                  idct.inverse_DCT[ci] = method_ptr;
+                    /* Create multiplier table from quant table.
+                     * However, we can skip this if the component is uninteresting
+                     * or if we already built the table.    Also, if no quant table
+                     * has yet been saved for the component, we leave the
+                     * multiplier table all-zero; we'll be reading zeroes from the
+                     * coefficient controller's buffer anyway.
+                     */
+                    if (! compptr.component_needed || idct.cur_method[ci] is method)
+                        continue;
+                    qtbl = compptr.quant_table;
+                    if (qtbl is null)       /* happens if no data yet for component */
+                        continue;
+                    idct.cur_method[ci] = method;
+                    switch (method) {
+//                      #ifdef PROVIDE_ISLOW_TABLES
+                        case JDCT_ISLOW:
+                        {
+                            /* For LL&M IDCT method, multipliers are equal to raw quantization
+                             * coefficients, but are stored as ints to ensure access efficiency.
+                             */
+                            int[] ismtbl = compptr.dct_table;
+                            for (i = 0; i < DCTSIZE2; i++) {
+                                ismtbl[i] = qtbl.quantval[i];
+                            }
+                        }
+                        break;
+//                      #endif
+//                      #ifdef DCT_IFAST_SUPPORTED
+//                      case JDCT_IFAST:
+//                      {
+//                          /* For AA&N IDCT method, multipliers are equal to quantization
+//                           * coefficients scaled by scalefactor[row]*scalefactor[col], where
+//                           *   scalefactor[0] = 1
+//                           *   scalefactor[k] = cos(k*PI/16) * sqrt(2)        for k=1..7
+//                           * For integer operation, the multiplier table is to be scaled by
+//                           * IFAST_SCALE_BITS.
+//                           */
+//                          int[] ifmtbl = compptr.dct_table;
+//                          short aanscales[] = {
+//                              /* precomputed values scaled up by 14 bits */
+//                              16384, 22725, 21407, 19266, 16384, 12873,   8867,   4520,
+//                              22725, 31521, 29692, 26722, 22725, 17855, 12299,    6270,
+//                              21407, 29692, 27969, 25172, 21407, 16819, 11585,    5906,
+//                              19266, 26722, 25172, 22654, 19266, 15137, 10426,    5315,
+//                              16384, 22725, 21407, 19266, 16384, 12873,   8867,   4520,
+//                              12873, 17855, 16819, 15137, 12873, 10114,   6967,   3552,
+//                              8867, 12299, 11585, 10426,  8867,   6967,   4799,   2446,
+//                              4520,   6270,   5906,   5315,   4520,   3552,   2446,   1247
+//                          };
+//                          SHIFT_TEMPS
+//
+//                          for (i = 0; i < DCTSIZE2; i++) {
+//                              ifmtbl[i] = DESCALE(MULTIPLY16V16( qtbl.quantval[i], aanscales[i]), CONST_BITS-IFAST_SCALE_BITS);
+//                          }
+//                      }
+//                      break;
+//                      #endif
+//                      #ifdef DCT_FLOAT_SUPPORTED
+//                      case JDCT_FLOAT:
+//                      {
+//                          /* For float AA&N IDCT method, multipliers are equal to quantization
+//                           * coefficients scaled by scalefactor[row]*scalefactor[col], where
+//                           *   scalefactor[0] = 1
+//                           *   scalefactor[k] = cos(k*PI/16) * sqrt(2)        for k=1..7
+//                           */
+//                          FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr.dct_table;
+//                          int row, col;
+//                          static const double aanscalefactor[DCTSIZE] = {
+//                              1.0, 1.387039845, 1.306562965, 1.175875602,
+//                              1.0, 0.785694958, 0.541196100, 0.275899379
+//                          };
+//
+//                          i = 0;
+//                          for (row = 0; row < DCTSIZE; row++) {
+//                              for (col = 0; col < DCTSIZE; col++) {
+//                                  fmtbl[i] = (FLOAT_MULT_TYPE)
+//                                      ((double) qtbl.quantval[i] *
+//                                   aanscalefactor[row] * aanscalefactor[col]);
+//                                  i++;
+//                              }
+//                          }
+//                      }
+//                      break;
+//                      #endif
+                    default:
+                        error();
+//                      ERREXIT(cinfo, JERR_NOT_COMPILED);
+                        break;
+                }
+            }
+        }
+    }
+
+    static final class jpeg_input_controller {
+        int consume_input;
+        bool has_multiple_scans; /* True if file has multiple scans */
+        bool eoi_reached;
+
+        bool inheaders;      /* true until first SOS is reached */
+    }
+
+    static final class  jpeg_color_deconverter {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+        int color_convert;
+
+        /* Private state for YCC.RGB conversion */
+        int[] Cr_r_tab;     /* => table for Cr to R conversion */
+        int[] Cb_b_tab;     /* => table for Cb to B conversion */
+        int[] Cr_g_tab;     /* => table for Cr to G conversion */
+        int[] Cb_g_tab;     /* => table for Cb to G conversion */
+
+        void start_pass (jpeg_decompress_struct cinfo) {
+            /* no work needed */
+        }
+
+    }
+
+    static final class jpeg_d_post_controller {
+//      JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+        int post_process_data;
+
+        /* Color quantization source buffer: this holds output data from
+         * the upsample/color conversion step to be passed to the quantizer.
+         * For two-pass color quantization, we need a full-image buffer;
+         * for one-pass operation, a strip buffer is sufficient.
+         */
+        int[] whole_image;  /* virtual array, or NULL if one-pass */
+        int[][] buffer;     /* strip buffer, or current strip of virtual */
+        int strip_height;   /* buffer size in rows */
+        /* for two-pass mode only: */
+        int starting_row;   /* row # of first row in current strip */
+        int next_row;       /* index of next row to fill/empty in strip */
+
+        void start_pass (jpeg_decompress_struct cinfo, int pass_mode) {
+            jpeg_d_post_controller post = cinfo.post;
+
+            switch (pass_mode) {
+                case JBUF_PASS_THRU:
+                    if (cinfo.quantize_colors) {
+                        error(SWT.ERROR_NOT_IMPLEMENTED);
+//                      /* Single-pass processing with color quantization. */
+//                      post.post_process_data = POST_PROCESS_1PASS;
+//                      /* We could be doing buffered-image output before starting a 2-pass
+//                       * color quantization; in that case, jinit_d_post_controller did not
+//                       * allocate a strip buffer. Use the virtual-array buffer as workspace.
+//                       */
+//                      if (post.buffer is null) {
+//                          post.buffer = (*cinfo.mem.access_virt_sarray)
+//                              ((j_common_ptr) cinfo, post.whole_image,
+//                              (JDIMENSION) 0, post.strip_height, TRUE);
+//                      }
+                    } else {
+                        /* For single-pass processing without color quantization,
+                         * I have no work to do; just call the upsampler directly.
+                         */
+                        post.post_process_data = POST_PROCESS_DATA_UPSAMPLE;
+                    }
+                    break;
+//              #ifdef QUANT_2PASS_SUPPORTED
+//              case JBUF_SAVE_AND_PASS:
+//                  /* First pass of 2-pass quantization */
+//                  if (post.whole_image is NULL)
+//                      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+//                  post.pub.post_process_data = post_process_prepass;
+//                  break;
+//              case JBUF_CRANK_DEST:
+//                  /* Second pass of 2-pass quantization */
+//                  if (post.whole_image is NULL)
+//                      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+//                  post.pub.post_process_data = post_process_2pass;
+//                  break;
+//              #endif /* QUANT_2PASS_SUPPORTED */
+                    default:
+                        error();
+//                      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+                        break;
+            }
+            post.starting_row = post.next_row = 0;
+        }
+
+    }
+
+    static final class jpeg_decompress_struct {
+//      jpeg_error_mgr * err;   /* Error handler module */\
+//      struct jpeg_memory_mgr * mem;   /* Memory manager module */\
+//      struct jpeg_progress_mgr * progress; /* Progress monitor, or null if none */\
+//      void * client_data;     /* Available for use by application */\
+        bool is_decompressor;    /* So common code can tell which is which */
+        int global_state;       /* For checking call sequence validity */
+
+//      /* Source of compressed data */
+//      struct jpeg_source_mgr * src;
+        InputStream inputStream;
+        byte[] buffer;
+        int bytes_in_buffer;
+        int bytes_offset;
+        bool start_of_file;
+
+        /* Basic description of image --- filled in by jpeg_read_header(). */
+        /* Application may inspect these values to decide how to process image. */
+
+        int image_width;    /* nominal image width (from SOF marker) */
+        int image_height;   /* nominal image height */
+        int num_components;     /* # of color components in JPEG image */
+        int jpeg_color_space; /* colorspace of JPEG image */
+
+        /* Decompression processing parameters --- these fields must be set before
+         * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
+         * them to default values.
+         */
+
+        int out_color_space; /* colorspace for output */
+
+        int scale_num, scale_denom; /* fraction by which to scale image */
+
+        double output_gamma;        /* image gamma wanted in output */
+
+        bool buffered_image; /* true=multiple output passes */
+        bool raw_data_out;       /* true=downsampled data wanted */
+
+        int dct_method; /* IDCT algorithm selector */
+        bool do_fancy_upsampling;    /* true=apply fancy upsampling */
+        bool do_block_smoothing; /* true=apply interblock smoothing */
+
+        bool quantize_colors;    /* true=colormapped output wanted */
+        /* the following are ignored if not quantize_colors: */
+        int dither_mode;    /* type of color dithering to use */
+        bool two_pass_quantize;  /* true=use two-pass color quantization */
+        int desired_number_of_colors;   /* max # colors to use in created colormap */
+        /* these are significant only in buffered-image mode: */
+        bool enable_1pass_quant; /* enable future use of 1-pass quantizer */
+        bool enable_external_quant;/* enable future use of external colormap */
+        bool enable_2pass_quant; /* enable future use of 2-pass quantizer */
+
+        /* Description of actual output image that will be returned to application.
+         * These fields are computed by jpeg_start_decompress().
+         * You can also use jpeg_calc_output_dimensions() to determine these values
+         * in advance of calling jpeg_start_decompress().
+         */
+
+        int output_width;   /* scaled image width */
+        int output_height;  /* scaled image height */
+        int out_color_components;   /* # of color components in out_color_space */
+        int output_components;  /* # of color components returned */
+        /* output_components is 1 (a colormap index) when quantizing colors;
+         * otherwise it equals out_color_components.
+         */
+        int rec_outbuf_height;  /* min recommended height of scanline buffer */
+        /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+         * high, space and time will be wasted due to unnecessary data copying.
+         * Usually rec_outbuf_height will be 1 or 2, at most 4.
+         */
+
+        /* When quantizing colors, the output colormap is described by these fields.
+         * The application can supply a colormap by setting colormap non-null before
+         * calling jpeg_start_decompress; otherwise a colormap is created during
+         * jpeg_start_decompress or jpeg_start_output.
+         * The map has out_color_components rows and actual_number_of_colors columns.
+         */
+        int actual_number_of_colors;    /* number of entries in use */
+        int[] colormap;     /* The color map as a 2-D pixel array */
+
+        /* State variables: these variables indicate the progress of decompression.
+         * The application may examine these but must not modify them.
+         */
+
+        /* Row index of next scanline to be read from jpeg_read_scanlines().
+         * Application may use this to control its processing loop, e.g.,
+         * "while (output_scanline < output_height)".
+         */
+        int output_scanline;    /* 0 .. output_height-1 */
+
+        /* Current input scan number and number of iMCU rows completed in scan.
+         * These indicate the progress of the decompressor input side.
+         */
+        int input_scan_number;  /* Number of SOS markers seen so far */
+        int input_iMCU_row; /* Number of iMCU rows completed */
+
+        /* The "output scan number" is the notional scan being displayed by the
+         * output side. The decompressor will not allow output scan/row number
+         * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+         */
+        int output_scan_number; /* Nominal scan number being displayed */
+        int output_iMCU_row;    /* Number of iMCU rows read */
+
+        /* Current progression status.  coef_bits[c][i] indicates the precision
+         * with which component c's DCT coefficient i (in zigzag order) is known.
+         * It is -1 when no data has yet been received, otherwise it is the point
+         * transform (shift) value for the most recent scan of the coefficient
+         * (thus, 0 at completion of the progression).
+         * This pointer is null when reading a non-progressive file.
+         */
+        int[][] coef_bits;  /* -1 or current Al value for each coef */
+
+        /* Internal JPEG parameters --- the application usually need not look at
+         * these fields.    Note that the decompressor output side may not use
+         * any parameters that can change between scans.
+         */
+
+        /* Quantization and Huffman tables are carried forward across input
+         * datastreams when processing abbreviated JPEG datastreams.
+         */
+
+        JQUANT_TBL[NUM_QUANT_TBLS] quant_tbl_ptrs;// = new JQUANT_TBL[NUM_QUANT_TBLS];
+        /* ptrs to coefficient quantization tables, or null if not defined */
+
+        JHUFF_TBL[NUM_HUFF_TBLS] dc_huff_tbl_ptrs;// = new JHUFF_TBL[NUM_HUFF_TBLS];
+        JHUFF_TBL[NUM_HUFF_TBLS] ac_huff_tbl_ptrs;// = new JHUFF_TBL[NUM_HUFF_TBLS];
+        /* ptrs to Huffman coding tables, or null if not defined */
+
+        /* These parameters are never carried across datastreams, since they
+         * are given in SOF/SOS markers or defined to be reset by SOI.
+         */
+
+        int data_precision;     /* bits of precision in image data */
+
+        jpeg_component_info[] comp_info;
+        /* comp_info[i] describes component that appears i'th in SOF */
+
+        bool progressive_mode;   /* true if SOFn specifies progressive mode */
+        bool arith_code;     /* true=arithmetic coding, false=Huffman */
+
+        byte[NUM_ARITH_TBLS] arith_dc_L;// = new byte[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+        byte[NUM_ARITH_TBLS] arith_dc_U;// = new byte[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+        byte[NUM_ARITH_TBLS] arith_ac_K;// = new byte[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+        int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+        /* These fields record data obtained from optional markers recognized by
+         * the JPEG library.
+         */
+        bool saw_JFIF_marker;    /* true iff a JFIF APP0 marker was found */
+        /* Data copied from JFIF marker; only valid if saw_JFIF_marker is true: */
+        byte JFIF_major_version;    /* JFIF version number */
+        byte JFIF_minor_version;
+        byte density_unit;      /* JFIF code for pixel size units */
+        short X_density;        /* Horizontal pixel density */
+        short Y_density;        /* Vertical pixel density */
+        bool saw_Adobe_marker;   /* true iff an Adobe APP14 marker was found */
+        byte Adobe_transform;   /* Color transform code from Adobe marker */
+
+        bool CCIR601_sampling;   /* true=first samples are cosited */
+
+        /* Aside from the specific data retained from APPn markers known to the
+         * library, the uninterpreted contents of any or all APPn and COM markers
+         * can be saved in a list for examination by the application.
+         */
+        jpeg_marker_reader marker_list; /* Head of list of saved markers */
+
+        /* Remaining fields are known throughout decompressor, but generally
+         * should not be touched by a surrounding application.
+         */
+
+        /*
+         * These fields are computed during decompression startup
+         */
+        int max_h_samp_factor;  /* largest h_samp_factor */
+        int max_v_samp_factor;  /* largest v_samp_factor */
+
+        int min_DCT_scaled_size;    /* smallest DCT_scaled_size of any component */
+
+        int total_iMCU_rows;    /* # of iMCU rows in image */
+        /* The coefficient controller's input and output progress is measured in
+         * units of "iMCU" (interleaved MCU) rows.  These are the same as MCU rows
+         * in fully interleaved JPEG scans, but are used whether the scan is
+         * interleaved or not.  We define an iMCU row as v_samp_factor DCT block
+         * rows of each component.  Therefore, the IDCT output contains
+         * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.
+         */
+
+        byte[] sample_range_limit; /* table for fast range-limiting */
+        int sample_range_limit_offset;
+
+        /*
+         * These fields are valid during any one scan.
+         * They describe the components and MCUs actually appearing in the scan.
+         * Note that the decompressor output side must not use these fields.
+         */
+        int comps_in_scan;      /* # of JPEG components in this scan */
+        jpeg_component_info[MAX_COMPS_IN_SCAN] cur_comp_info;// = new jpeg_component_info[MAX_COMPS_IN_SCAN];
+        /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+        int MCUs_per_row;   /* # of MCUs across the image */
+        int MCU_rows_in_scan;   /* # of MCU rows in the image */
+
+        int blocks_in_MCU;      /* # of DCT blocks per MCU */
+        int[D_MAX_BLOCKS_IN_MCU] MCU_membership;// = new int[D_MAX_BLOCKS_IN_MCU];
+        /* MCU_membership[i] is index in cur_comp_info of component owning */
+        /* i'th block in an MCU */
+
+        int Ss, Se, Ah, Al;     /* progressive JPEG parameters for scan */
+
+        /* This field is shared between entropy decoder and marker parser.
+         * It is either zero or the code of a JPEG marker that has been
+         * read from the data source, but has not yet been processed.
+         */
+        int unread_marker;
+
+        int[DCTSIZE2] workspace;// = new int[DCTSIZE2];
+        int[1] row_ctr;// = new int[1];
+
+        /*
+         * Links to decompression subobjects (methods, private variables of modules)
+         */
+        jpeg_decomp_master master;
+        jpeg_d_main_controller main;
+        jpeg_d_coef_controller coef;
+        jpeg_d_post_controller post;
+        jpeg_input_controller inputctl;
+        jpeg_marker_reader marker;
+        jpeg_entropy_decoder entropy;
+        jpeg_inverse_dct idct;
+        jpeg_upsampler upsample;
+        jpeg_color_deconverter cconvert;
+        jpeg_color_quantizer cquantize;
+    }
+
+static void error() {
+    SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+static void error(int code) {
+    SWT.error(code);
+}
+
+static void error(String msg) {
+    SWT.error(SWT.ERROR_INVALID_IMAGE, null, msg);
+}
+
+static void jinit_marker_reader (jpeg_decompress_struct cinfo) {
+    jpeg_marker_reader marker = cinfo.marker = new jpeg_marker_reader();
+//  int i;
+
+    /* Initialize COM/APPn processing.
+     * By default, we examine and then discard APP0 and APP14,
+     * but simply discard COM and all other APPn.
+     */
+//  marker.process_COM = skip_variable;
+    marker.length_limit_COM = 0;
+//  for (i = 0; i < 16; i++) {
+//      marker.process_APPn[i] = skip_variable;
+//      marker.length_limit_APPn[i] = 0;
+//  }
+//  marker.process_APPn[0] = get_interesting_appn;
+//  marker.process_APPn[14] = get_interesting_appn;
+    /* Reset marker processing state */
+    reset_marker_reader(cinfo);
+}
+
+static void jinit_d_coef_controller (jpeg_decompress_struct cinfo, bool need_full_buffer) {
+    jpeg_d_coef_controller coef = new jpeg_d_coef_controller();
+    cinfo.coef = coef;
+//  coef.pub.start_input_pass = start_input_pass;
+//  coef.pub.start_output_pass = start_output_pass;
+    coef.coef_bits_latch = null;
+
+    /* Create the coefficient buffer. */
+    if (need_full_buffer) {
+//#ifdef D_MULTISCAN_FILES_SUPPORTED
+        /* Allocate a full-image virtual array for each component, */
+        /* padded to a multiple of samp_factor DCT blocks in each direction. */
+        /* Note we ask for a pre-zeroed array. */
+        int ci, access_rows;
+        jpeg_component_info compptr;
+
+        for (ci = 0; ci < cinfo.num_components; ci++) {
+            compptr = cinfo.comp_info[ci];
+            access_rows = compptr.v_samp_factor;
+//#ifdef BLOCK_SMOOTHING_SUPPORTED
+            /* If block smoothing could be used, need a bigger window */
+            if (cinfo.progressive_mode)
+                access_rows *= 3;
+//#endif
+            coef.whole_image[ci] =
+                new short[][][](
+                    cast(int)jround_up( compptr.height_in_blocks, compptr.v_samp_factor),
+                    cast(int)jround_up( compptr.width_in_blocks, compptr.h_samp_factor),
+                    DCTSIZE2
+                    );
+        }
+//      coef.consume_data = consume_data;
+        coef.decompress_data = DECOMPRESS_DATA;
+        coef.coef_arrays = coef.whole_image[0]; /* link to virtual arrays */
+//      #else
+//              ERREXIT(cinfo, JERR_NOT_COMPILED);
+//      #endif
+    } else {
+        /* We only need a single-MCU buffer. */
+        foreach( inout el; coef.MCU_buffer ){
+            el = new short[](DCTSIZE2);
+        }
+//      coef.consume_data = dummy_consume_data;
+        coef.decompress_data = DECOMPRESS_ONEPASS;
+        coef.coef_arrays = null; /* flag for no virtual arrays */
+    }
+}
+
+static void start_output_pass (jpeg_decompress_struct cinfo) {
+//#ifdef BLOCK_SMOOTHING_SUPPORTED
+    jpeg_d_coef_controller coef = cinfo.coef;
+
+    /* If multipass, check to see whether to use block smoothing on this pass */
+    if (coef.coef_arrays !is null) {
+        if (cinfo.do_block_smoothing && smoothing_ok(cinfo))
+            coef.decompress_data = DECOMPRESS_SMOOTH_DATA;
+        else
+            coef.decompress_data = DECOMPRESS_DATA;
+    }
+//#endif
+    cinfo.output_iMCU_row = 0;
+}
+
+static void jpeg_create_decompress(jpeg_decompress_struct cinfo) {
+    cinfo.is_decompressor = true;
+
+
+    /* Initialize marker processor so application can override methods
+     * for COM, APPn markers before calling jpeg_read_header.
+     */
+    cinfo.marker_list = null;
+    jinit_marker_reader(cinfo);
+
+    /* And initialize the overall input controller. */
+    jinit_input_controller(cinfo);
+
+    /* OK, I'm ready */
+    cinfo.global_state = DSTATE_START;
+}
+
+static void jpeg_calc_output_dimensions (jpeg_decompress_struct cinfo)
+/* Do computations that are needed before master selection phase */
+{
+//#ifdef IDCT_SCALING_SUPPORTED
+//  int ci;
+//  jpeg_component_info compptr;
+//#endif
+
+    /* Prevent application from calling me at wrong times */
+    if (cinfo.global_state !is DSTATE_READY)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+
+//#ifdef IDCT_SCALING_SUPPORTED
+//
+//  /* Compute actual output image dimensions and DCT scaling choices. */
+//  if (cinfo.scale_num * 8 <= cinfo.scale_denom) {
+//      /* Provide 1/8 scaling */
+//      cinfo.output_width = cast(int)
+//          jdiv_round_up(cinfo.image_width, 8L);
+//      cinfo.output_height = cast(int)
+//          jdiv_round_up(cinfo.image_height, 8L);
+//      cinfo.min_DCT_scaled_size = 1;
+//  } else if (cinfo.scale_num * 4 <= cinfo.scale_denom) {
+//      /* Provide 1/4 scaling */
+//      cinfo.output_width = cast(int)
+//          jdiv_round_up(cinfo.image_width, 4L);
+//      cinfo.output_height = cast(int)
+//          jdiv_round_up(cinfo.image_height, 4L);
+//      cinfo.min_DCT_scaled_size = 2;
+//  } else if (cinfo.scale_num * 2 <= cinfo.scale_denom) {
+//      /* Provide 1/2 scaling */
+//      cinfo.output_width = cast(int)
+//          jdiv_round_up(cinfo.image_width, 2L);
+//      cinfo.output_height = cast(int)
+//          jdiv_round_up(cinfo.image_height, 2L);
+//      cinfo.min_DCT_scaled_size = 4;
+//  } else {
+//      /* Provide 1/1 scaling */
+//      cinfo.output_width = cinfo.image_width;
+//      cinfo.output_height = cinfo.image_height;
+//      cinfo.min_DCT_scaled_size = DCTSIZE;
+//  }
+//  /* In selecting the actual DCT scaling for each component, we try to
+//   * scale up the chroma components via IDCT scaling rather than upsampling.
+//   * This saves time if the upsampler gets to use 1:1 scaling.
+//   * Note this code assumes that the supported DCT scalings are powers of 2.
+//   */
+//  for (ci = 0; ci < cinfo.num_components; ci++) {
+//      compptr = cinfo.comp_info[ci];
+//      int ssize = cinfo.min_DCT_scaled_size;
+//      while (ssize < DCTSIZE &&
+//          (compptr.h_samp_factor * ssize * 2 <= cinfo.max_h_samp_factor * cinfo.min_DCT_scaled_size) &&
+//          (compptr.v_samp_factor * ssize * 2 <= cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size))
+//      {
+//          ssize = ssize * 2;
+//      }
+//      compptr.DCT_scaled_size = ssize;
+//  }
+//
+//  /* Recompute downsampled dimensions of components;
+//   * application needs to know these if using raw downsampled data.
+//   */
+//  for (ci = 0; ci < cinfo.num_components; ci++) {
+//      compptr = cinfo.comp_info[ci];
+//      /* Size in samples, after IDCT scaling */
+//      compptr.downsampled_width = cast(int)
+//          jdiv_round_up(cast(long) cinfo.image_width * cast(long) (compptr.h_samp_factor * compptr.DCT_scaled_size),
+//              (cinfo.max_h_samp_factor * DCTSIZE));
+//      compptr.downsampled_height = cast(int)
+//          jdiv_round_up(cast(long) cinfo.image_height * cast(long) (compptr.v_samp_factor * compptr.DCT_scaled_size),
+//              (cinfo.max_v_samp_factor * DCTSIZE));
+//  }
+//
+//#else /* !IDCT_SCALING_SUPPORTED */
+
+    /* Hardwire it to "no scaling" */
+    cinfo.output_width = cinfo.image_width;
+    cinfo.output_height = cinfo.image_height;
+    /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
+     * and has computed unscaled downsampled_width and downsampled_height.
+     */
+
+//#endif /* IDCT_SCALING_SUPPORTED */
+
+    /* Report number of components in selected colorspace. */
+    /* Probably this should be in the color conversion module... */
+    switch (cinfo.out_color_space) {
+        case JCS_GRAYSCALE:
+            cinfo.out_color_components = 1;
+            break;
+        case JCS_RGB:
+            if (RGB_PIXELSIZE !is 3) {
+                cinfo.out_color_components = RGB_PIXELSIZE;
+                break;
+            }
+            //FALLTHROUGH
+        case JCS_YCbCr:
+            cinfo.out_color_components = 3;
+            break;
+        case JCS_CMYK:
+        case JCS_YCCK:
+            cinfo.out_color_components = 4;
+            break;
+        default:            /* else must be same colorspace as in file */
+            cinfo.out_color_components = cinfo.num_components;
+            break;
+    }
+    cinfo.output_components = (cinfo.quantize_colors ? 1 : cinfo.out_color_components);
+
+    /* See if upsampler will want to emit more than one row at a time */
+    if (use_merged_upsample(cinfo))
+        cinfo.rec_outbuf_height = cinfo.max_v_samp_factor;
+    else
+        cinfo.rec_outbuf_height = 1;
+}
+
+static bool use_merged_upsample (jpeg_decompress_struct cinfo) {
+//#ifdef UPSAMPLE_MERGING_SUPPORTED
+    /* Merging is the equivalent of plain box-filter upsampling */
+    if (cinfo.do_fancy_upsampling || cinfo.CCIR601_sampling)
+        return false;
+    /* jdmerge.c only supports YCC=>RGB color conversion */
+    if (cinfo.jpeg_color_space !is JCS_YCbCr || cinfo.num_components !is 3 ||
+            cinfo.out_color_space !is JCS_RGB ||
+            cinfo.out_color_components !is RGB_PIXELSIZE)
+        return false;
+    /* and it only handles 2h1v or 2h2v sampling ratios */
+    if (cinfo.comp_info[0].h_samp_factor !is 2 ||
+            cinfo.comp_info[1].h_samp_factor !is 1 ||
+            cinfo.comp_info[2].h_samp_factor !is 1 ||
+            cinfo.comp_info[0].v_samp_factor >  2 ||
+            cinfo.comp_info[1].v_samp_factor !is 1 ||
+            cinfo.comp_info[2].v_samp_factor !is 1)
+        return false;
+    /* furthermore, it doesn't work if we've scaled the IDCTs differently */
+    if (cinfo.comp_info[0].DCT_scaled_size !is cinfo.min_DCT_scaled_size ||
+            cinfo.comp_info[1].DCT_scaled_size !is cinfo.min_DCT_scaled_size ||
+            cinfo.comp_info[2].DCT_scaled_size !is cinfo.min_DCT_scaled_size)
+        return false;
+    /* ??? also need to test for upsample-time rescaling, when & if supported */
+    return true;            /* by golly, it'll work... */
+//#else
+//  return false;
+//#endif
+}
+
+static void prepare_range_limit_table (jpeg_decompress_struct cinfo)
+/* Allocate and fill in the sample_range_limit table */
+{
+    byte[] table;
+    int i;
+
+    table = new byte[5 * (MAXJSAMPLE+1) + CENTERJSAMPLE];
+    int offset = (MAXJSAMPLE+1);    /* allow negative subscripts of simple table */
+    cinfo.sample_range_limit_offset = offset;
+    cinfo.sample_range_limit = table;
+    /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+    /* Main part of "simple" table: limit[x] = x */
+    for (i = 0; i <= MAXJSAMPLE; i++)
+        table[i + offset] = cast(byte)i;
+    offset += CENTERJSAMPLE;    /* Point to where post-IDCT table starts */
+    /* End of simple table, rest of first half of post-IDCT table */
+    for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+        table[i+offset] = cast(byte)MAXJSAMPLE;
+    /* Second half of post-IDCT table */
+    System.arraycopy(cinfo.sample_range_limit, cinfo.sample_range_limit_offset, table, offset + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), CENTERJSAMPLE);
+}
+
+static void build_ycc_rgb_table (jpeg_decompress_struct cinfo) {
+    jpeg_color_deconverter cconvert = cinfo.cconvert;
+    int i;
+    int x;
+//  SHIFT_TEMPS
+
+    cconvert.Cr_r_tab = new int[MAXJSAMPLE+1];
+    cconvert.Cb_b_tab = new int[MAXJSAMPLE+1];
+    cconvert.Cr_g_tab = new int[MAXJSAMPLE+1];
+    cconvert.Cb_g_tab = new int[MAXJSAMPLE+1];
+
+    for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+        /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+        /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+        /* Cr=>R value is nearest int to 1.40200 * x */
+        cconvert.Cr_r_tab[i] = (cast(int)(1.40200f * (1<<SCALEBITS) + 0.5f) * x + ONE_HALF) >> SCALEBITS;
+        /* Cb=>B value is nearest int to 1.77200 * x */
+        cconvert.Cb_b_tab[i] = (cast(int)(1.77200f * (1<<SCALEBITS) + 0.5f) * x + ONE_HALF) >> SCALEBITS;
+        /* Cr=>G value is scaled-up -0.71414 * x */
+        cconvert.Cr_g_tab[i] = (cast(int)(- (0.71414f * (1<<SCALEBITS) + 0.5f)) * x);
+        /* Cb=>G value is scaled-up -0.34414 * x */
+        /* We also add in ONE_HALF so that need not do it in inner loop */
+        cconvert.Cb_g_tab[i] = (cast(int)(- (0.34414f* (1<<SCALEBITS) + 0.5f)) * x + ONE_HALF);
+    }
+}
+
+static void jinit_color_deconverter (jpeg_decompress_struct cinfo) {
+    jpeg_color_deconverter cconvert = cinfo.cconvert = new jpeg_color_deconverter();
+//  cconvert.start_pass = start_pass_dcolor;
+
+    /* Make sure num_components agrees with jpeg_color_space */
+    switch (cinfo.jpeg_color_space) {
+        case JCS_GRAYSCALE:
+            if (cinfo.num_components !is 1)
+                error();
+//              ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+            break;
+
+        case JCS_RGB:
+        case JCS_YCbCr:
+            if (cinfo.num_components !is 3)
+                error();
+//              ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+            break;
+
+        case JCS_CMYK:
+        case JCS_YCCK:
+            if (cinfo.num_components !is 4)
+                error();
+//              ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+            break;
+
+        default:            /* JCS_UNKNOWN can be anything */
+            if (cinfo.num_components < 1)
+                error();
+//              ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+            break;
+    }
+
+    /* Set out_color_components and conversion method based on requested space.
+     * Also clear the component_needed flags for any unused components,
+     * so that earlier pipeline stages can avoid useless computation.
+     */
+
+    int ci;
+    switch (cinfo.out_color_space) {
+        case JCS_GRAYSCALE:
+            cinfo.out_color_components = 1;
+            if (cinfo.jpeg_color_space is JCS_GRAYSCALE || cinfo.jpeg_color_space is JCS_YCbCr) {
+                cconvert.color_convert = GRAYSCALE_CONVERT;
+                /* For color.grayscale conversion, only the Y (0) component is needed */
+                for (ci = 1; ci < cinfo.num_components; ci++)
+                    cinfo.comp_info[ci].component_needed = false;
+            } else
+                error();
+//              ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+            break;
+
+        case JCS_RGB:
+            cinfo.out_color_components = RGB_PIXELSIZE;
+            if (cinfo.jpeg_color_space is JCS_YCbCr) {
+                cconvert.color_convert = YCC_RGB_CONVERT;
+                build_ycc_rgb_table(cinfo);
+            } else if (cinfo.jpeg_color_space is JCS_GRAYSCALE) {
+                cconvert.color_convert = GRAY_RGB_CONVERT;
+            } else if (cinfo.jpeg_color_space is JCS_RGB && RGB_PIXELSIZE is 3) {
+                cconvert.color_convert = NULL_CONVERT;
+            } else
+                error();
+//              ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+                break;
+
+        case JCS_CMYK:
+            cinfo.out_color_components = 4;
+            if (cinfo.jpeg_color_space is JCS_YCCK) {
+                cconvert.color_convert = YCCK_CMYK_CONVERT;
+                build_ycc_rgb_table(cinfo);
+            } else if (cinfo.jpeg_color_space is JCS_CMYK) {
+                cconvert.color_convert = NULL_CONVERT;
+            } else
+                error();
+//              ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+            break;
+
+        default:
+            /* Permit null conversion to same output space */
+            if (cinfo.out_color_space is cinfo.jpeg_color_space) {
+                cinfo.out_color_components = cinfo.num_components;
+                cconvert.color_convert = NULL_CONVERT;
+            } else  /* unsupported non-null conversion */
+                error();
+//              ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+            break;
+    }
+
+    if (cinfo.quantize_colors)
+        cinfo.output_components = 1; /* single colormapped output component */
+    else
+        cinfo.output_components = cinfo.out_color_components;
+}
+
+static void jinit_d_post_controller (jpeg_decompress_struct cinfo, bool need_full_buffer) {
+    jpeg_d_post_controller post = cinfo.post = new jpeg_d_post_controller();
+//  post.pub.start_pass = start_pass_dpost;
+    post.whole_image = null;    /* flag for no virtual arrays */
+    post.buffer = null;     /* flag for no strip buffer */
+
+    /* Create the quantization buffer, if needed */
+    if (cinfo.quantize_colors) {
+        error(SWT.ERROR_NOT_IMPLEMENTED);
+//      /* The buffer strip height is max_v_samp_factor, which is typically
+//       * an efficient number of rows for upsampling to return.
+//       * (In the presence of output rescaling, we might want to be smarter?)
+//       */
+//      post.strip_height = cinfo.max_v_samp_factor;
+//      if (need_full_buffer) {
+//          /* Two-pass color quantization: need full-image storage. */
+//          /* We round up the number of rows to a multiple of the strip height. */
+//#ifdef QUANT_2PASS_SUPPORTED
+//          post.whole_image = (*cinfo.mem.request_virt_sarray)
+//              ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+//              cinfo.output_width * cinfo.out_color_components,
+//              (JDIMENSION) jround_up(cast(long) cinfo.output_height,
+//              cast(long) post.strip_height),
+//   post.strip_height);
+//#else
+//          ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+//#endif /* QUANT_2PASS_SUPPORTED */
+//      } else {
+//          /* One-pass color quantization: just make a strip buffer. */
+//          post.buffer = (*cinfo.mem.alloc_sarray)
+//              ((j_common_ptr) cinfo, JPOOL_IMAGE,
+//              cinfo.output_width * cinfo.out_color_components,
+//              post.strip_height);
+//      }
+    }
+}
+
+static void make_funny_pointers (jpeg_decompress_struct cinfo)
+/* Create the funny pointer lists discussed in the comments above.
+ * The actual workspace is already allocated (in main.buffer),
+ * and the space for the pointer lists is allocated too.
+ * This routine just fills in the curiously ordered lists.
+ * This will be repeated at the beginning of each pass.
+ */
+{
+    jpeg_d_main_controller main = cinfo.main;
+    int ci, i, rgroup;
+    int M = cinfo.min_DCT_scaled_size;
+    jpeg_component_info compptr;
+    byte[][] buf, xbuf0, xbuf1;
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size) /
+            cinfo.min_DCT_scaled_size; /* height of a row group of component */
+        xbuf0 = main.xbuffer[0][ci];
+        int xbuf0_offset = main.xbuffer_offset[0][ci];
+        xbuf1 = main.xbuffer[1][ci];
+        int xbuf1_offset = main.xbuffer_offset[1][ci];
+        /* First copy the workspace pointers as-is */
+        buf = main.buffer[ci];
+        for (i = 0; i < rgroup * (M + 2); i++) {
+            xbuf0[i + xbuf0_offset] = xbuf1[i + xbuf1_offset] = buf[i];
+        }
+        /* In the second list, put the last four row groups in swapped order */
+        for (i = 0; i < rgroup * 2; i++) {
+            xbuf1[rgroup*(M-2) + i + xbuf1_offset] = buf[rgroup*M + i];
+            xbuf1[rgroup*M + i + xbuf1_offset] = buf[rgroup*(M-2) + i];
+        }
+        /* The wraparound pointers at top and bottom will be filled later
+         * (see set_wraparound_pointers, below).    Initially we want the "above"
+         * pointers to duplicate the first actual data line.    This only needs
+         * to happen in xbuffer[0].
+         */
+        for (i = 0; i < rgroup; i++) {
+            xbuf0[i - rgroup + xbuf0_offset] = xbuf0[0 + xbuf0_offset];
+        }
+    }
+}
+
+static void alloc_funny_pointers (jpeg_decompress_struct cinfo)
+/* Allocate space for the funny pointer lists.
+ * This is done only once, not once per pass.
+ */
+{
+    jpeg_d_main_controller main = cinfo.main;
+    int ci, rgroup;
+    int M = cinfo.min_DCT_scaled_size;
+    jpeg_component_info compptr;
+    byte[][] xbuf;
+
+    /* Get top-level space for component array pointers.
+     * We alloc both arrays with one call to save a few cycles.
+     */
+    main.xbuffer[0] = new byte[][][](cinfo.num_components);
+    main.xbuffer[1] = new byte[][][](cinfo.num_components);
+    main.xbuffer_offset[0] = new int[](cinfo.num_components);
+    main.xbuffer_offset[1] = new int[](cinfo.num_components);
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size; /* height of a row group of component */
+        /* Get space for pointer lists --- M+4 row groups in each list.
+         * We alloc both pointer lists with one call to save a few cycles.
+         */
+        xbuf = new byte[][](2 * (rgroup * (M + 4)));
+        int offset = rgroup;
+        main.xbuffer_offset[0][ci] = offset;
+        main.xbuffer[0][ci] = xbuf;
+        offset += rgroup * (M + 4);
+        main.xbuffer_offset[1][ci] = offset;
+        main.xbuffer[1][ci] = xbuf;
+    }
+}
+
+
+static void jinit_d_main_controller (jpeg_decompress_struct cinfo, bool need_full_buffer) {
+    int ci, rgroup, ngroups;
+    jpeg_component_info compptr;
+
+    jpeg_d_main_controller main = cinfo.main = new jpeg_d_main_controller();
+//  main.pub.start_pass = start_pass_main;
+
+    if (need_full_buffer)       /* shouldn't happen */
+        error();
+//      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+    /* Allocate the workspace.
+     * ngroups is the number of row groups we need.
+     */
+    if (cinfo.upsample.need_context_rows) {
+        if (cinfo.min_DCT_scaled_size < 2) /* unsupported, see comments above */
+            error();
+//          ERREXIT(cinfo, JERR_NOTIMPL);
+        alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
+        ngroups = cinfo.min_DCT_scaled_size + 2;
+    } else {
+        ngroups = cinfo.min_DCT_scaled_size;
+    }
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size; /* height of a row group of component */
+        main.buffer[ci] = new byte[][]( rgroup * ngroups, compptr.width_in_blocks * compptr.DCT_scaled_size );
+    }
+}
+
+static long jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+    a += b - 1L;
+    return a - (a % b);
+}
+
+static void jinit_upsampler (jpeg_decompress_struct cinfo) {
+    int ci;
+    jpeg_component_info compptr;
+    bool need_buffer, do_fancy;
+    int h_in_group, v_in_group, h_out_group, v_out_group;
+
+    jpeg_upsampler upsample = new jpeg_upsampler();
+    cinfo.upsample = upsample;
+//  upsample.start_pass = start_pass_upsample;
+//  upsample.upsample = sep_upsample;
+    upsample.need_context_rows = false; /* until we find out differently */
+
+    if (cinfo.CCIR601_sampling) /* this isn't supported */
+        error();
+//      ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+    /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
+     * so don't ask for it.
+     */
+    do_fancy = cinfo.do_fancy_upsampling && cinfo.min_DCT_scaled_size > 1;
+
+    /* Verify we can handle the sampling factors, select per-component methods,
+     * and create storage as needed.
+     */
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* Compute size of an "input group" after IDCT scaling. This many samples
+         * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
+         */
+        h_in_group = (compptr.h_samp_factor * compptr.DCT_scaled_size) /
+         cinfo.min_DCT_scaled_size;
+        v_in_group = (compptr.v_samp_factor * compptr.DCT_scaled_size) /
+         cinfo.min_DCT_scaled_size;
+        h_out_group = cinfo.max_h_samp_factor;
+        v_out_group = cinfo.max_v_samp_factor;
+        upsample.rowgroup_height[ci] = v_in_group; /* save for use later */
+        need_buffer = true;
+        if (! compptr.component_needed) {
+            /* Don't bother to upsample an uninteresting component. */
+            upsample.methods[ci] = NOOP_UPSAMPLE;
+            need_buffer = false;
+        } else if (h_in_group is h_out_group && v_in_group is v_out_group) {
+            /* Fullsize components can be processed without any work. */
+            upsample.methods[ci] = FULLSIZE_UPSAMPLE;
+            need_buffer = false;
+        } else if (h_in_group * 2 is h_out_group && v_in_group is v_out_group) {
+            /* Special cases for 2h1v upsampling */
+            if (do_fancy && compptr.downsampled_width > 2)
+                upsample.methods[ci] = H2V1_FANCY_UPSAMPLE;
+            else
+                upsample.methods[ci] = H2V1_UPSAMPLE;
+        } else if (h_in_group * 2 is h_out_group && v_in_group * 2 is v_out_group) {
+            /* Special cases for 2h2v upsampling */
+            if (do_fancy && compptr.downsampled_width > 2) {
+                upsample.methods[ci] = H2V2_FANCY_UPSAMPLE;
+                upsample.need_context_rows = true;
+            } else
+                upsample.methods[ci] = H2V2_UPSAMPLE;
+        } else if ((h_out_group % h_in_group) is 0 && (v_out_group % v_in_group) is 0) {
+            /* Generic integral-factors upsampling method */
+            upsample.methods[ci] = INT_UPSAMPLE;
+            upsample.h_expand[ci] = cast(byte) (h_out_group / h_in_group);
+            upsample.v_expand[ci] = cast(byte) (v_out_group / v_in_group);
+        } else
+            error();
+//          ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+        if (need_buffer) {
+            upsample.color_buf[ci] = new byte[][]( cinfo.max_v_samp_factor,
+                         cast(int) jround_up(cinfo.output_width, cinfo.max_h_samp_factor));
+        }
+    }
+}
+
+static void jinit_phuff_decoder (jpeg_decompress_struct cinfo) {
+    int[][] coef_bit_ptr;
+    int ci, i;
+
+    cinfo.entropy = new phuff_entropy_decoder();
+//  entropy.pub.start_pass = start_pass_phuff_decoder;
+
+    /* Create progression status table */
+    cinfo.coef_bits = new int[][]( cinfo.num_components, DCTSIZE2 );
+    coef_bit_ptr = cinfo.coef_bits;
+    for (ci = 0; ci < cinfo.num_components; ci++)
+        for (i = 0; i < DCTSIZE2; i++)
+            coef_bit_ptr[ci][i] = -1;
+}
+
+
+static void jinit_huff_decoder (jpeg_decompress_struct cinfo) {
+
+    cinfo.entropy = new huff_entropy_decoder();
+//  entropy.pub.start_pass = start_pass_huff_decoder;
+//  entropy.pub.decode_mcu = decode_mcu;
+
+}
+
+static void jinit_inverse_dct (jpeg_decompress_struct cinfo) {
+    int ci;
+    jpeg_component_info compptr;
+
+    jpeg_inverse_dct idct = cinfo.idct = new jpeg_inverse_dct();
+//  idct.pub.start_pass = start_pass;
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* Allocate and pre-zero a multiplier table for each component */
+        compptr.dct_table = new int[DCTSIZE2];
+        /* Mark multiplier table not yet set up for any method */
+        idct.cur_method[ci] = -1;
+    }
+}
+
+static final int CONST_BITS = 13;
+static final int PASS1_BITS = 2;
+static final int RANGE_MASK =(MAXJSAMPLE * 4 + 3);
+static void jpeg_idct_islow (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+    short[] coef_block,
+    byte[][] output_buf, int output_buf_offset, int output_col)
+{
+    int tmp0, tmp1, tmp2, tmp3;
+    int tmp10, tmp11, tmp12, tmp13;
+    int z1, z2, z3, z4, z5;
+    short[] inptr;
+    int[] quantptr;
+    int[] wsptr;
+    byte[] outptr;
+    byte[] range_limit = cinfo.sample_range_limit;
+    int range_limit_offset = cinfo.sample_range_limit_offset + CENTERJSAMPLE;
+    int ctr;
+    int[] workspace = cinfo.workspace;  /* buffers data between passes */
+//  SHIFT_TEMPS
+
+    /* Pass 1: process columns from input, store into work array. */
+    /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+    /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+    inptr = coef_block;
+    quantptr = compptr.dct_table;
+    wsptr = workspace;
+    int inptr_offset = 0, quantptr_offset = 0, wsptr_offset = 0;
+    for (ctr = DCTSIZE; ctr > 0; ctr--) {
+        /* Due to quantization, we will usually find that many of the input
+         * coefficients are zero, especially the AC terms.  We can exploit this
+         * by short-circuiting the IDCT calculation for any column in which all
+         * the AC terms are zero.   In that case each output is equal to the
+         * DC coefficient (with scale factor as needed).
+         * With typical images and quantization tables, half or more of the
+         * column DCT calculations can be simplified this way.
+         */
+
+        if (inptr[DCTSIZE*1+inptr_offset] is 0 && inptr[DCTSIZE*2+inptr_offset] is 0 &&
+            inptr[DCTSIZE*3+inptr_offset] is 0 && inptr[DCTSIZE*4+inptr_offset] is 0 &&
+            inptr[DCTSIZE*5+inptr_offset] is 0 && inptr[DCTSIZE*6+inptr_offset] is 0 &&
+            inptr[DCTSIZE*7+inptr_offset] is 0)
+        {
+            /* AC terms all zero */
+            int dcval = ((inptr[DCTSIZE*0+inptr_offset]) * quantptr[DCTSIZE*0+quantptr_offset]) << PASS1_BITS;
+
+            wsptr[DCTSIZE*0+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*1+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*2+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*3+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*4+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*5+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*6+wsptr_offset] = dcval;
+            wsptr[DCTSIZE*7+wsptr_offset] = dcval;
+
+            inptr_offset++;         /* advance pointers to next column */
+            quantptr_offset++;
+            wsptr_offset++;
+            continue;
+        }
+
+        /* Even part: reverse the even part of the forward DCT. */
+        /* The rotator is sqrt(2)*c(-6). */
+
+        z2 = ((inptr[DCTSIZE*2+inptr_offset]) * quantptr[DCTSIZE*2+quantptr_offset]);
+        z3 = ((inptr[DCTSIZE*6+inptr_offset]) * quantptr[DCTSIZE*6+quantptr_offset]);
+
+        z1 = ((z2 + z3) * 4433/*FIX_0_541196100*/);
+        tmp2 = z1 + (z3 * - 15137/*FIX_1_847759065*/);
+        tmp3 = z1 + (z2 * 6270/*FIX_0_765366865*/);
+
+        z2 = ((inptr[DCTSIZE*0+inptr_offset]) * quantptr[DCTSIZE*0+quantptr_offset]);
+        z3 = ((inptr[DCTSIZE*4+inptr_offset]) * quantptr[DCTSIZE*4+quantptr_offset]);
+
+        tmp0 = (z2 + z3) << CONST_BITS;
+        tmp1 = (z2 - z3) << CONST_BITS;
+
+        tmp10 = tmp0 + tmp3;
+        tmp13 = tmp0 - tmp3;
+        tmp11 = tmp1 + tmp2;
+        tmp12 = tmp1 - tmp2;
+
+        /* Odd part per figure 8; the matrix is unitary and hence its
+         * transpose is its inverse.    i0..i3 are y7,y5,y3,y1 respectively.
+         */
+
+        tmp0 = ((inptr[DCTSIZE*7+inptr_offset]) * quantptr[DCTSIZE*7+quantptr_offset]);
+        tmp1 = ((inptr[DCTSIZE*5+inptr_offset]) * quantptr[DCTSIZE*5+quantptr_offset]);
+        tmp2 = ((inptr[DCTSIZE*3+inptr_offset]) * quantptr[DCTSIZE*3+quantptr_offset]);
+        tmp3 = ((inptr[DCTSIZE*1+inptr_offset]) * quantptr[DCTSIZE*1+quantptr_offset]);
+
+        z1 = tmp0 + tmp3;
+        z2 = tmp1 + tmp2;
+        z3 = tmp0 + tmp2;
+        z4 = tmp1 + tmp3;
+        z5 = ((z3 + z4) * 9633/*FIX_1_175875602*/); /* sqrt(2) * c3 */
+
+        tmp0 = (tmp0 * 2446/*FIX_0_298631336*/); /* sqrt(2) * (-c1+c3+c5-c7) */
+        tmp1 = (tmp1 * 16819/*FIX_2_053119869*/); /* sqrt(2) * ( c1+c3-c5+c7) */
+        tmp2 = (tmp2 * 25172/*FIX_3_072711026*/); /* sqrt(2) * ( c1+c3+c5-c7) */
+        tmp3 = (tmp3 * 12299/*FIX_1_501321110*/); /* sqrt(2) * ( c1+c3-c5-c7) */
+        z1 = (z1 * - 7373/*FIX_0_899976223*/); /* sqrt(2) * (c7-c3) */
+        z2 = (z2 * - 20995/*FIX_2_562915447*/); /* sqrt(2) * (-c1-c3) */
+        z3 = (z3 * - 16069/*FIX_1_961570560*/); /* sqrt(2) * (-c3-c5) */
+        z4 = (z4 * - 3196/*FIX_0_390180644*/); /* sqrt(2) * (c5-c3) */
+
+        z3 += z5;
+        z4 += z5;
+
+        tmp0 += z1 + z3;
+        tmp1 += z2 + z4;
+        tmp2 += z2 + z3;
+        tmp3 += z1 + z4;
+
+        /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+//      #define DESCALE(x,n)    RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+        wsptr[DCTSIZE*0+wsptr_offset] = (((tmp10 + tmp3) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*7+wsptr_offset] = (((tmp10 - tmp3) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*1+wsptr_offset] = (((tmp11 + tmp2) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*6+wsptr_offset] = (((tmp11 - tmp2) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*2+wsptr_offset] = (((tmp12 + tmp1) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*5+wsptr_offset] = (((tmp12 - tmp1) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*3+wsptr_offset] = (((tmp13 + tmp0) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+        wsptr[DCTSIZE*4+wsptr_offset] = (((tmp13 - tmp0) + (1 << ((CONST_BITS-PASS1_BITS)-1))) >> (CONST_BITS-PASS1_BITS));
+
+        inptr_offset++;         /* advance pointers to next column */
+        quantptr_offset++;
+        wsptr_offset++;
+    }
+
+
+    /* Pass 2: process rows from work array, store into output array. */
+    /* Note that we must descale the results by a factor of 8 is 2**3, */
+    /* and also undo the PASS1_BITS scaling. */
+
+    int outptr_offset = 0;
+    wsptr = workspace;
+    wsptr_offset =0;
+    for (ctr = 0; ctr < DCTSIZE; ctr++) {
+        outptr = output_buf[ctr+output_buf_offset];
+        outptr_offset = output_col;
+        /* Rows of zeroes can be exploited in the same way as we did with columns.
+         * However, the column calculation has created many nonzero AC terms, so
+         * the simplification applies less often (typically 5% to 10% of the time).
+         * On machines with very fast multiplication, it's possible that the
+         * test takes more time than it's worth.    In that case this section
+         * may be commented out.
+         */
+
+//#ifndef NO_ZERO_ROW_TEST
+        if (wsptr[1+wsptr_offset] is 0 && wsptr[2+wsptr_offset] is 0 && wsptr[3+wsptr_offset] is 0 && wsptr[4+wsptr_offset] is 0 &&
+            wsptr[5+wsptr_offset] is 0 && wsptr[6+wsptr_offset] is 0 && wsptr[7+wsptr_offset] is 0)
+        {
+            /* AC terms all zero */
+//          #define DESCALE(x,n)    RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+            byte dcval = range_limit[range_limit_offset + ((((wsptr[0+wsptr_offset]) + (1 << ((PASS1_BITS+3)-1))) >> PASS1_BITS+3)
+                    & RANGE_MASK)];
+
+            outptr[0+outptr_offset] = dcval;
+            outptr[1+outptr_offset] = dcval;
+            outptr[2+outptr_offset] = dcval;
+            outptr[3+outptr_offset] = dcval;
+            outptr[4+outptr_offset] = dcval;
+            outptr[5+outptr_offset] = dcval;
+            outptr[6+outptr_offset] = dcval;
+            outptr[7+outptr_offset] = dcval;
+
+            wsptr_offset += DCTSIZE;        /* advance pointer to next row */
+            continue;
+        }
+//#endif
+
+        /* Even part: reverse the even part of the forward DCT. */
+        /* The rotator is sqrt(2)*c(-6). */
+
+        z2 = wsptr[2+wsptr_offset];
+        z3 = wsptr[6+wsptr_offset];
+
+        z1 = ((z2 + z3) * 4433/*FIX_0_541196100*/);
+        tmp2 = z1 + (z3 * - 15137/*FIX_1_847759065*/);
+        tmp3 = z1 + (z2 * 6270/*FIX_0_765366865*/);
+
+        tmp0 = (wsptr[0+wsptr_offset] + wsptr[4+wsptr_offset]) << CONST_BITS;
+        tmp1 = (wsptr[0+wsptr_offset] - wsptr[4+wsptr_offset]) << CONST_BITS;
+
+        tmp10 = tmp0 + tmp3;
+        tmp13 = tmp0 - tmp3;
+        tmp11 = tmp1 + tmp2;
+        tmp12 = tmp1 - tmp2;
+
+        /* Odd part per figure 8; the matrix is unitary and hence its
+         * transpose is its inverse.    i0..i3 are y7,y5,y3,y1 respectively.
+         */
+
+        tmp0 = wsptr[7+wsptr_offset];
+        tmp1 = wsptr[5+wsptr_offset];
+        tmp2 = wsptr[3+wsptr_offset];
+        tmp3 = wsptr[1+wsptr_offset];
+
+        z1 = tmp0 + tmp3;
+        z2 = tmp1 + tmp2;
+        z3 = tmp0 + tmp2;
+        z4 = tmp1 + tmp3;
+        z5 = ((z3 + z4) * 9633/*FIX_1_175875602*/); /* sqrt(2) * c3 */
+
+        tmp0 = (tmp0 * 2446/*FIX_0_298631336*/); /* sqrt(2) * (-c1+c3+c5-c7) */
+        tmp1 = (tmp1 * 16819/*FIX_2_053119869*/); /* sqrt(2) * ( c1+c3-c5+c7) */
+        tmp2 = (tmp2 * 25172/*FIX_3_072711026*/); /* sqrt(2) * ( c1+c3+c5-c7) */
+        tmp3 = (tmp3 * 12299/*FIX_1_501321110*/); /* sqrt(2) * ( c1+c3-c5-c7) */
+        z1 = (z1 * - 7373/*FIX_0_899976223*/); /* sqrt(2) * (c7-c3) */
+        z2 = (z2 * - 20995/*FIX_2_562915447*/); /* sqrt(2) * (-c1-c3) */
+        z3 = (z3 * - 16069/*FIX_1_961570560*/); /* sqrt(2) * (-c3-c5) */
+        z4 = (z4 * - 3196/*FIX_0_390180644*/); /* sqrt(2) * (c5-c3) */
+
+        z3 += z5;
+        z4 += z5;
+
+        tmp0 += z1 + z3;
+        tmp1 += z2 + z4;
+        tmp2 += z2 + z3;
+        tmp3 += z1 + z4;
+
+        /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+
+//      #define DESCALE(x,n)    RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+        outptr[0+outptr_offset] = range_limit[range_limit_offset + ((((tmp10 + tmp3) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                        CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[7+outptr_offset] = range_limit[range_limit_offset + ((((tmp10 - tmp3) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[1+outptr_offset] = range_limit[range_limit_offset + ((((tmp11 + tmp2) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[6+outptr_offset] = range_limit[range_limit_offset + ((((tmp11 - tmp2) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[2+outptr_offset] = range_limit[range_limit_offset + ((((tmp12 + tmp1) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[5+outptr_offset] = range_limit[range_limit_offset + ((((tmp12 - tmp1) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[3+outptr_offset] = range_limit[range_limit_offset + ((((tmp13 + tmp0) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+        outptr[4+outptr_offset] = range_limit[range_limit_offset + ((((tmp13 - tmp0) + (1 << ((CONST_BITS+PASS1_BITS+3)-1))) >>
+                                    CONST_BITS+PASS1_BITS+3)
+                    & RANGE_MASK)];
+
+        wsptr_offset += DCTSIZE;        /* advance pointer to next row */
+    }
+}
+
+static void upsample (jpeg_decompress_struct cinfo,
+    byte[][][] input_buf, int[] input_buf_offset, int[] in_row_group_ctr,
+    int in_row_groups_avail,
+    byte[][] output_buf, int[] out_row_ctr,
+    int out_rows_avail)
+{
+    sep_upsample(cinfo, input_buf, input_buf_offset, in_row_group_ctr, in_row_groups_avail, output_buf, out_row_ctr, out_rows_avail);
+}
+
+static bool smoothing_ok (jpeg_decompress_struct cinfo) {
+    jpeg_d_coef_controller coef = cinfo.coef;
+    bool smoothing_useful = false;
+    int ci, coefi;
+    jpeg_component_info compptr;
+    JQUANT_TBL qtable;
+    int[] coef_bits;
+    int[] coef_bits_latch;
+
+    if (! cinfo.progressive_mode || cinfo.coef_bits is null)
+        return false;
+
+    /* Allocate latch area if not already done */
+    if (coef.coef_bits_latch is null)
+        coef.coef_bits_latch = new int[cinfo.num_components * SAVED_COEFS];
+    coef_bits_latch = coef.coef_bits_latch;
+    int coef_bits_latch_offset = 0;
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* All components' quantization values must already be latched. */
+        if ((qtable = compptr.quant_table) is null)
+            return false;
+        /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+        if (qtable.quantval[0] is 0 ||
+            qtable.quantval[Q01_POS] is 0 ||
+            qtable.quantval[Q10_POS] is 0 ||
+            qtable.quantval[Q20_POS] is 0 ||
+            qtable.quantval[Q11_POS] is 0 ||
+            qtable.quantval[Q02_POS] is 0)
+                return false;
+        /* DC values must be at least partly known for all components. */
+        coef_bits = cinfo.coef_bits[ci];
+        if (coef_bits[0] < 0)
+            return false;
+        /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
+        for (coefi = 1; coefi <= 5; coefi++) {
+            coef_bits_latch[coefi+coef_bits_latch_offset] = coef_bits[coefi];
+            if (coef_bits[coefi] !is 0)
+                smoothing_useful = true;
+        }
+        coef_bits_latch_offset += SAVED_COEFS;
+    }
+
+    return smoothing_useful;
+}
+
+static void master_selection (jpeg_decompress_struct cinfo) {
+    jpeg_decomp_master master = cinfo.master;
+    bool use_c_buffer;
+    long samplesperrow;
+    int jd_samplesperrow;
+
+    /* Initialize dimensions and other stuff */
+    jpeg_calc_output_dimensions(cinfo);
+    prepare_range_limit_table(cinfo);
+
+    /* Width of an output scanline must be representable as JDIMENSION. */
+    samplesperrow = cast(long) cinfo.output_width * cast(long) cinfo.out_color_components;
+    jd_samplesperrow = cast(int) samplesperrow;
+    if ( jd_samplesperrow !is samplesperrow)
+        error();
+//      ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+    /* Initialize my private state */
+    master.pass_number = 0;
+    master.using_merged_upsample = use_merged_upsample(cinfo);
+
+    /* Color quantizer selection */
+    master.quantizer_1pass = null;
+    master.quantizer_2pass = null;
+    /* No mode changes if not using buffered-image mode. */
+    if (! cinfo.quantize_colors || ! cinfo.buffered_image) {
+        cinfo.enable_1pass_quant = false;
+        cinfo.enable_external_quant = false;
+        cinfo.enable_2pass_quant = false;
+    }
+    if (cinfo.quantize_colors) {
+        error(SWT.ERROR_NOT_IMPLEMENTED);
+//      if (cinfo.raw_data_out)
+//          ERREXIT(cinfo, JERR_NOTIMPL);
+//      /* 2-pass quantizer only works in 3-component color space. */
+//      if (cinfo.out_color_components !is 3) {
+//          cinfo.enable_1pass_quant = true;
+//          cinfo.enable_external_quant = false;
+//          cinfo.enable_2pass_quant = false;
+//          cinfo.colormap = null;
+//      } else if (cinfo.colormap !is null) {
+//          cinfo.enable_external_quant = true;
+//      } else if (cinfo.two_pass_quantize) {
+//          cinfo.enable_2pass_quant = true;
+//      } else {
+//          cinfo.enable_1pass_quant = true;
+//      }
+//
+//      if (cinfo.enable_1pass_quant) {
+//#ifdef QUANT_1PASS_SUPPORTED
+//          jinit_1pass_quantizer(cinfo);
+//          master.quantizer_1pass = cinfo.cquantize;
+//#else
+//          ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif
+//      }
+//
+//      /* We use the 2-pass code to map to external colormaps. */
+//      if (cinfo.enable_2pass_quant || cinfo.enable_external_quant) {
+//#ifdef QUANT_2PASS_SUPPORTED
+//          jinit_2pass_quantizer(cinfo);
+//          master.quantizer_2pass = cinfo.cquantize;
+//#else
+//          ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif
+//      }
+//      /* If both quantizers are initialized, the 2-pass one is left active;
+//       * this is necessary for starting with quantization to an external map.
+//       */
+    }
+
+    /* Post-processing: in particular, color conversion first */
+    if (! cinfo.raw_data_out) {
+        if (master.using_merged_upsample) {
+//#ifdef UPSAMPLE_MERGING_SUPPORTED
+//          jinit_merged_upsampler(cinfo); /* does color conversion too */
+//#else
+            error();
+//          ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif
+        } else {
+            jinit_color_deconverter(cinfo);
+            jinit_upsampler(cinfo);
+        }
+        jinit_d_post_controller(cinfo, cinfo.enable_2pass_quant);
+    }
+    /* Inverse DCT */
+    jinit_inverse_dct(cinfo);
+    /* Entropy decoding: either Huffman or arithmetic coding. */
+    if (cinfo.arith_code) {
+        error();
+//      ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+    } else {
+        if (cinfo.progressive_mode) {
+//#ifdef D_PROGRESSIVE_SUPPORTED
+            jinit_phuff_decoder(cinfo);
+//#else
+//          ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif
+        } else
+            jinit_huff_decoder(cinfo);
+    }
+
+    /* Initialize principal buffer controllers. */
+    use_c_buffer = cinfo.inputctl.has_multiple_scans || cinfo.buffered_image;
+    jinit_d_coef_controller(cinfo, use_c_buffer);
+
+    if (! cinfo.raw_data_out)
+        jinit_d_main_controller(cinfo, false /* never need full buffer here */);
+
+    /* Initialize input side of decompressor to consume first scan. */
+    start_input_pass (cinfo);
+
+//#ifdef D_MULTISCAN_FILES_SUPPORTED
+    /* If jpeg_start_decompress will read the whole file, initialize
+     * progress monitoring appropriately.   The input step is counted
+     * as one pass.
+     */
+//  if (cinfo.progress !is null && ! cinfo.buffered_image &&
+//          cinfo.inputctl.has_multiple_scans) {
+//      int nscans;
+//      /* Estimate number of scans to set pass_limit. */
+//      if (cinfo.progressive_mode) {
+//          /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+//          nscans = 2 + 3 * cinfo.num_components;
+//      } else {
+//          /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+//          nscans = cinfo.num_components;
+//      }
+//      cinfo.progress.pass_counter = 0L;
+//      cinfo.progress.pass_limit = cast(long) cinfo.total_iMCU_rows * nscans;
+//      cinfo.progress.completed_passes = 0;
+//      cinfo.progress.total_passes = (cinfo.enable_2pass_quant ? 3 : 2);
+//      /* Count the input pass as done */
+//      master.pass_number++;
+//  }
+//#endif /* D_MULTISCAN_FILES_SUPPORTED */
+}
+
+static void jinit_master_decompress (jpeg_decompress_struct cinfo) {
+    jpeg_decomp_master master = new jpeg_decomp_master();
+    cinfo.master = master;
+//  master.prepare_for_output_pass = prepare_for_output_pass;
+//  master.finish_output_pass = finish_output_pass;
+
+    master.is_dummy_pass = false;
+
+    master_selection(cinfo);
+}
+
+static void
+jcopy_sample_rows (byte[][] input_array, int source_row,
+           byte[][] output_array, int dest_row,
+           int num_rows, int num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas may overlap for duplication.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+  byte[] inptr, outptr;
+  int count = num_cols;
+  int row;
+
+  int input_array_offset = source_row;
+  int output_array_offset = dest_row;
+
+  for (row = num_rows; row > 0; row--) {
+    inptr = input_array[input_array_offset++];
+    outptr = output_array[output_array_offset++];
+    System.arraycopy(inptr, 0, outptr, 0, count);
+  }
+}
+
+static bool jpeg_start_decompress (jpeg_decompress_struct cinfo) {
+    if (cinfo.global_state is DSTATE_READY) {
+        /* First call: initialize master control, select active modules */
+        jinit_master_decompress(cinfo);
+        if (cinfo.buffered_image) {
+            /* No more work here; expecting jpeg_start_output next */
+            cinfo.global_state = DSTATE_BUFIMAGE;
+            return true;
+        }
+        cinfo.global_state = DSTATE_PRELOAD;
+    }
+    if (cinfo.global_state is DSTATE_PRELOAD) {
+        /* If file has multiple scans, absorb them all into the coef buffer */
+        if (cinfo.inputctl.has_multiple_scans) {
+//#ifdef D_MULTISCAN_FILES_SUPPORTED
+            for (;;) {
+                int retcode;
+                /* Call progress monitor hook if present */
+//              if (cinfo.progress !is null)
+//                  (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
+                /* Absorb some more input */
+                retcode = consume_input (cinfo);
+                if (retcode is JPEG_SUSPENDED)
+                    return false;
+                if (retcode is JPEG_REACHED_EOI)
+                    break;
+                /* Advance progress counter if appropriate */
+//              if (cinfo.progress !is null && (retcode is JPEG_ROW_COMPLETED || retcode is JPEG_REACHED_SOS)) {
+//                  if (++cinfo.progress.pass_counter >= cinfo.progress.pass_limit) {
+//                      /* jdmaster underestimated number of scans; ratchet up one scan */
+//                      cinfo.progress.pass_limit += cast(long) cinfo.total_iMCU_rows;
+//                  }
+//              }
+            }
+//#else
+//          ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif /* D_MULTISCAN_FILES_SUPPORTED */
+        }
+        cinfo.output_scan_number = cinfo.input_scan_number;
+    } else if (cinfo.global_state !is DSTATE_PRESCAN)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    /* Perform any dummy output passes, and set up for the final pass */
+    return output_pass_setup(cinfo);
+}
+
+static void prepare_for_output_pass (jpeg_decompress_struct cinfo) {
+    jpeg_decomp_master master = cinfo.master;
+
+    if (master.is_dummy_pass) {
+//#ifdef QUANT_2PASS_SUPPORTED
+//      /* Final pass of 2-pass quantization */
+//      master.pub.is_dummy_pass = FALSE;
+//      (*cinfo.cquantize.start_pass) (cinfo, FALSE);
+//      (*cinfo.post.start_pass) (cinfo, JBUF_CRANK_DEST);
+//      (*cinfo.main.start_pass) (cinfo, JBUF_CRANK_DEST);
+//#else
+        error(SWT.ERROR_NOT_IMPLEMENTED);
+//      ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif /* QUANT_2PASS_SUPPORTED */
+    } else {
+        if (cinfo.quantize_colors && cinfo.colormap is null) {
+            /* Select new quantization method */
+            if (cinfo.two_pass_quantize && cinfo.enable_2pass_quant) {
+                cinfo.cquantize = master.quantizer_2pass;
+                master.is_dummy_pass = true;
+            } else if (cinfo.enable_1pass_quant) {
+                cinfo.cquantize = master.quantizer_1pass;
+            } else {
+                error();
+//  ERREXIT(cinfo, JERR_MODE_CHANGE);
+            }
+        }
+        cinfo.idct.start_pass (cinfo);
+        start_output_pass (cinfo);
+        if (! cinfo.raw_data_out) {
+            if (! master.using_merged_upsample)
+                cinfo.cconvert.start_pass (cinfo);
+            cinfo.upsample.start_pass (cinfo);
+            if (cinfo.quantize_colors)
+                cinfo.cquantize.start_pass (cinfo, master.is_dummy_pass);
+            cinfo.post.start_pass (cinfo, (master.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+            cinfo.main.start_pass (cinfo, JBUF_PASS_THRU);
+        }
+    }
+
+//  /* Set up progress monitor's pass info if present */
+//  if (cinfo.progress !is NULL) {
+//      cinfo.progress.completed_passes = master.pass_number;
+//      cinfo.progress.total_passes = master.pass_number +
+//                      (master.pub.is_dummy_pass ? 2 : 1);
+//      /* In buffered-image mode, we assume one more output pass if EOI not
+//       * yet reached, but no more passes if EOI has been reached.
+//       */
+//      if (cinfo.buffered_image && ! cinfo.inputctl.eoi_reached) {
+//          cinfo.progress.total_passes += (cinfo.enable_2pass_quant ? 2 : 1);
+//      }
+//  }
+}
+
+
+static bool jpeg_resync_to_restart (jpeg_decompress_struct cinfo, int desired) {
+    int marker = cinfo.unread_marker;
+    int action = 1;
+
+    /* Always put up a warning. */
+//  WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
+
+    /* Outer loop handles repeated decision after scanning forward. */
+    for (;;) {
+        if (marker < M_SOF0)
+            action = 2;     /* invalid marker */
+        else if (marker < M_RST0 || marker > M_RST7)
+            action = 3;     /* valid non-restart marker */
+        else {
+            if (marker is (M_RST0 + ((desired+1) & 7)) || marker is ( M_RST0 + ((desired+2) & 7)))
+                action = 3;     /* one of the next two expected restarts */
+            else if (marker is (M_RST0 + ((desired-1) & 7)) || marker is ( M_RST0 + ((desired-2) & 7)))
+                action = 2;     /* a prior restart, so advance */
+            else
+                action = 1;     /* desired restart or too far away */
+        }
+//      TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
+        switch (action) {
+            case 1:
+                /* Discard marker and let entropy decoder resume processing. */
+                cinfo.unread_marker = 0;
+                return true;
+            case 2:
+                /* Scan to the next marker, and repeat the decision loop. */
+                if (! next_marker(cinfo))
+                    return false;
+                marker = cinfo.unread_marker;
+                break;
+            case 3:
+                /* Return without advancing past this marker. */
+                /* Entropy decoder will be forced to process an empty segment. */
+                return true;
+            default:
+        }
+    } /* end loop */
+}
+
+static bool read_restart_marker (jpeg_decompress_struct cinfo) {
+    /* Obtain a marker unless we already did. */
+    /* Note that next_marker will complain if it skips any data. */
+    if (cinfo.unread_marker is 0) {
+        if (! next_marker(cinfo))
+            return false;
+    }
+
+    if (cinfo.unread_marker is (M_RST0 + cinfo.marker.next_restart_num)) {
+        /* Normal case --- swallow the marker and let entropy decoder continue */
+//      TRACEMS1(cinfo, 3, JTRC_RST, cinfo.marker.next_restart_num);
+        cinfo.unread_marker = 0;
+    } else {
+        /* Uh-oh, the restart markers have been messed up. */
+        /* Let the data source manager determine how to resync. */
+        if (! jpeg_resync_to_restart (cinfo, cinfo.marker.next_restart_num))
+            return false;
+    }
+
+    /* Update next-restart state */
+    cinfo.marker.next_restart_num = (cinfo.marker.next_restart_num + 1) & 7;
+
+    return true;
+}
+
+static bool jpeg_fill_bit_buffer (bitread_working_state state, int get_buffer, int bits_left, int nbits)
+/* Load up the bit buffer to a depth of at least nbits */
+{
+    /* Copy heavily used state fields into locals (hopefully registers) */
+    byte[] buffer = state.buffer;
+    int bytes_in_buffer = state.bytes_in_buffer;
+    int bytes_offset = state.bytes_offset;
+    jpeg_decompress_struct cinfo = state.cinfo;
+
+    /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
+    /* (It is assumed that no request will be for more than that many bits.) */
+    /* We fail to do so only if we hit a marker or are forced to suspend. */
+
+    if (cinfo.unread_marker is 0) { /* cannot advance past a marker */
+        while (bits_left < MIN_GET_BITS) {
+            int c;
+
+            /* Attempt to read a byte */
+            if (bytes_offset is bytes_in_buffer) {
+                if (! fill_input_buffer (cinfo))
+                    return false;
+                buffer = cinfo.buffer;
+                bytes_in_buffer = cinfo.bytes_in_buffer;
+                bytes_offset = cinfo.bytes_offset;
+            }
+            c = buffer[bytes_offset++] & 0xFF;
+
+            /* If it's 0xFF, check and discard stuffed zero byte */
+            if (c is 0xFF) {
+                /* Loop here to discard any padding FF's on terminating marker,
+                 * so that we can save a valid unread_marker value. NOTE: we will
+                 * accept multiple FF's followed by a 0 as meaning a single FF data
+                 * byte.    This data pattern is not valid according to the standard.
+                 */
+                do {
+                    if (bytes_offset is bytes_in_buffer) {
+                        if (! fill_input_buffer (cinfo))
+                            return false;
+                        buffer = cinfo.buffer;
+                        bytes_in_buffer = cinfo.bytes_in_buffer;
+                        bytes_offset = cinfo.bytes_offset;
+                    }
+                    c = buffer[bytes_offset++] & 0xFF;
+                } while (c is 0xFF);
+
+                if (c is 0) {
+                    /* Found FF/00, which represents an FF data byte */
+                    c = 0xFF;
+                } else {
+                    /* Oops, it's actually a marker indicating end of compressed data.
+                     * Save the marker code for later use.
+                     * Fine point: it might appear that we should save the marker into
+                     * bitread working state, not straight into permanent state.    But
+                     * once we have hit a marker, we cannot need to suspend within the
+                     * current MCU, because we will read no more bytes from the data
+                     * source.  So it is OK to update permanent state right away.
+                     */
+                    cinfo.unread_marker = c;
+                    /* See if we need to insert some fake zero bits. */
+//                  goto no_more_bytes;
+                    if (nbits > bits_left) {
+                        /* Uh-oh.   Report corrupted data to user and stuff zeroes into
+                         * the data stream, so that we can produce some kind of image.
+                         * We use a nonvolatile flag to ensure that only one warning message
+                         * appears per data segment.
+                         */
+                        if (! cinfo.entropy.insufficient_data) {
+//                          WARNMS(cinfo, JWRN_HIT_MARKER);
+                            cinfo.entropy.insufficient_data = true;
+                        }
+                    /* Fill the buffer with zero bits */
+                        get_buffer <<= MIN_GET_BITS - bits_left;
+                        bits_left = MIN_GET_BITS;
+                    }
+
+                    /* Unload the local registers */
+                    state.buffer = buffer;
+                    state.bytes_in_buffer = bytes_in_buffer;
+                    state.bytes_offset = bytes_offset;
+                    state.get_buffer = get_buffer;
+                    state.bits_left = bits_left;
+
+                    return true;
+
+                }
+            }
+
+            /* OK, load c into get_buffer */
+            get_buffer = (get_buffer << 8) | c;
+            bits_left += 8;
+        } /* end while */
+    } else {
+//      no_more_bytes:
+        /* We get here if we've read the marker that terminates the compressed
+         * data segment.    There should be enough bits in the buffer register
+         * to satisfy the request; if so, no problem.
+         */
+        if (nbits > bits_left) {
+            /* Uh-oh.   Report corrupted data to user and stuff zeroes into
+             * the data stream, so that we can produce some kind of image.
+             * We use a nonvolatile flag to ensure that only one warning message
+             * appears per data segment.
+             */
+            if (! cinfo.entropy.insufficient_data) {
+//              WARNMS(cinfo, JWRN_HIT_MARKER);
+                cinfo.entropy.insufficient_data = true;
+            }
+            /* Fill the buffer with zero bits */
+            get_buffer <<= MIN_GET_BITS - bits_left;
+            bits_left = MIN_GET_BITS;
+        }
+    }
+
+    /* Unload the local registers */
+    state.buffer = buffer;
+    state.bytes_in_buffer = bytes_in_buffer;
+    state.bytes_offset = bytes_offset;
+    state.get_buffer = get_buffer;
+    state.bits_left = bits_left;
+
+    return true;
+}
+
+static int jpeg_huff_decode (bitread_working_state state, int get_buffer, int bits_left, d_derived_tbl htbl, int min_bits) {
+    int l = min_bits;
+    int code;
+
+    /* HUFF_DECODE has determined that the code is at least min_bits */
+    /* bits long, so fetch that many bits in one swoop. */
+
+//  CHECK_BIT_BUFFER(*state, l, return -1);
+    {
+    if (bits_left < (l)) {
+        if (! jpeg_fill_bit_buffer(state,get_buffer,bits_left,l)) {
+            return -1;
+        }
+        get_buffer = state.get_buffer; bits_left = state.bits_left;
+    }
+    }
+//  code = GET_BITS(l);
+    code = (( (get_buffer >> (bits_left -= (l)))) & ((1<<(l))-1));
+
+    /* Collect the rest of the Huffman code one bit at a time. */
+    /* This is per Figure F.16 in the JPEG spec. */
+
+    while (code > htbl.maxcode[l]) {
+        code <<= 1;
+//      CHECK_BIT_BUFFER(*state, 1, return -1);
+        {
+        if (bits_left < (1)) {
+            if (! jpeg_fill_bit_buffer(state,get_buffer,bits_left,1)) {
+                return -1;
+            }
+            get_buffer = state.get_buffer; bits_left = state.bits_left;
+        }
+        }
+//      code |= GET_BITS(1);
+        code |= (( (get_buffer >> (bits_left -= (1)))) & ((1<<(1))-1));
+        l++;
+    }
+
+    /* Unload the local registers */
+    state.get_buffer = get_buffer;
+    state.bits_left = bits_left;
+
+    /* With garbage input we may reach the sentinel value l = 17. */
+
+    if (l > 16) {
+//      WARNMS(state.cinfo, JWRN_HUFF_BAD_CODE);
+        return 0;           /* fake a zero as the safest result */
+    }
+
+    return htbl.pub.huffval[ (code + htbl.valoffset[l]) ] & 0xFF;
+}
+
+static int decompress_onepass (jpeg_decompress_struct cinfo, byte[][][] output_buf, int[] output_buf_offset) {
+    jpeg_d_coef_controller coef = cinfo.coef;
+    int MCU_col_num;    /* index of current MCU within row */
+    int last_MCU_col = cinfo.MCUs_per_row - 1;
+    int last_iMCU_row = cinfo.total_iMCU_rows - 1;
+    int blkn, ci, xindex, yindex, yoffset, useful_width;
+    byte[][] output_ptr;
+    int start_col, output_col;
+    jpeg_component_info compptr;
+//  inverse_DCT_method_ptr inverse_DCT;
+
+    /* Loop to process as much as one whole iMCU row */
+    for (yoffset = coef.MCU_vert_offset; yoffset < coef.MCU_rows_per_iMCU_row; yoffset++) {
+        for (MCU_col_num = coef.MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) {
+            /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
+            for (int i = 0; i < cinfo.blocks_in_MCU; i++) {
+                short[] blk = coef.MCU_buffer[i];
+                for (int j = 0; j < blk.length; j++) {
+                    blk[j] = 0;
+                }
+            }
+            if (! cinfo.entropy.decode_mcu (cinfo, coef.MCU_buffer)) {
+                /* Suspension forced; update state counters and exit */
+                coef.MCU_vert_offset = yoffset;
+                coef.MCU_ctr = MCU_col_num;
+                return JPEG_SUSPENDED;
+            }
+            /* Determine where data should go in output_buf and do the IDCT thing.
+             * We skip dummy blocks at the right and bottom edges (but blkn gets
+             * incremented past them!). Note the inner loop relies on having
+             * allocated the MCU_buffer[] blocks sequentially.
+             */
+            blkn = 0;           /* index of current DCT block within MCU */
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+                compptr = cinfo.cur_comp_info[ci];
+                /* Don't bother to IDCT an uninteresting component. */
+                if (! compptr.component_needed) {
+                    blkn += compptr.MCU_blocks;
+                    continue;
+                }
+//              inverse_DCT = cinfo.idct.inverse_DCT[compptr.component_index];
+                useful_width = (MCU_col_num < last_MCU_col) ? compptr.MCU_width : compptr.last_col_width;
+                output_ptr = output_buf[compptr.component_index];
+                int output_ptr_offset = output_buf_offset[compptr.component_index] + yoffset * compptr.DCT_scaled_size;
+                start_col = MCU_col_num * compptr.MCU_sample_width;
+                for (yindex = 0; yindex < compptr.MCU_height; yindex++) {
+                    if (cinfo.input_iMCU_row < last_iMCU_row || yoffset+yindex < compptr.last_row_height) {
+                        output_col = start_col;
+                        for (xindex = 0; xindex < useful_width; xindex++) {
+                            jpeg_idct_islow(cinfo, compptr, coef.MCU_buffer[blkn+xindex], output_ptr, output_ptr_offset, output_col);
+                            output_col += compptr.DCT_scaled_size;
+                        }
+                    }
+                    blkn += compptr.MCU_width;
+                    output_ptr_offset += compptr.DCT_scaled_size;
+                }
+            }
+        }
+        /* Completed an MCU row, but perhaps not an iMCU row */
+        coef.MCU_ctr = 0;
+    }
+    /* Completed the iMCU row, advance counters for next one */
+    cinfo.output_iMCU_row++;
+    if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows) {
+        coef.start_iMCU_row(cinfo);
+        return JPEG_ROW_COMPLETED;
+    }
+    /* Completed the scan */
+    finish_input_pass (cinfo);
+    return JPEG_SCAN_COMPLETED;
+}
+
+static int decompress_smooth_data (jpeg_decompress_struct cinfo, byte[][][] output_buf, int[] output_buf_offset) {
+    jpeg_d_coef_controller coef = cinfo.coef;
+    int last_iMCU_row = cinfo.total_iMCU_rows - 1;
+    int block_num, last_block_column;
+    int ci, block_row, block_rows, access_rows;
+    short[][][] buffer;
+    short[][] buffer_ptr, prev_block_row, next_block_row;
+    byte[][] output_ptr;
+    int output_col;
+    jpeg_component_info compptr;
+//  inverse_DCT_method_ptr inverse_DCT;
+    bool first_row, last_row;
+    short[] workspace = coef.workspace;
+    if (workspace is null) workspace = coef.workspace = new short[DCTSIZE2];
+    int[] coef_bits;
+    JQUANT_TBL quanttbl;
+    int Q00,Q01,Q02,Q10,Q11,Q20, num;
+    int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+    int Al, pred;
+
+    /* Force some input to be done if we are getting ahead of the input. */
+    while (cinfo.input_scan_number <= cinfo.output_scan_number && ! cinfo.inputctl.eoi_reached) {
+        if (cinfo.input_scan_number is cinfo.output_scan_number) {
+            /* If input is working on current scan, we ordinarily want it to
+             * have completed the current row.  But if input scan is DC,
+             * we want it to keep one row ahead so that next block row's DC
+             * values are up to date.
+             */
+            int delta = (cinfo.Ss is 0) ? 1 : 0;
+            if (cinfo.input_iMCU_row > cinfo.output_iMCU_row+delta)
+                break;
+        }
+        if (consume_input(cinfo) is JPEG_SUSPENDED)
+            return JPEG_SUSPENDED;
+    }
+
+    /* OK, output from the virtual arrays. */
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* Don't bother to IDCT an uninteresting component. */
+        if (! compptr.component_needed)
+            continue;
+        /* Count non-dummy DCT block rows in this iMCU row. */
+        if (cinfo.output_iMCU_row < last_iMCU_row) {
+            block_rows = compptr.v_samp_factor;
+            access_rows = block_rows * 2; /* this and next iMCU row */
+            last_row = false;
+        } else {
+            /* NB: can't use last_row_height here; it is input-side-dependent! */
+            block_rows = (compptr.height_in_blocks % compptr.v_samp_factor);
+            if (block_rows is 0) block_rows = compptr.v_samp_factor;
+            access_rows = block_rows; /* this iMCU row only */
+            last_row = true;
+        }
+        /* Align the virtual buffer for this component. */
+        int buffer_offset;
+        if (cinfo.output_iMCU_row > 0) {
+            access_rows += compptr.v_samp_factor; /* prior iMCU row too */
+            buffer = coef.whole_image[ci];
+            buffer_offset = (cinfo.output_iMCU_row - 1) * compptr.v_samp_factor;
+            buffer_offset += compptr.v_samp_factor; /* point to current iMCU row */
+            first_row = false;
+        } else {
+            buffer = coef.whole_image[ci];
+            buffer_offset = 0;
+            first_row = true;
+        }
+        /* Fetch component-dependent info */
+        coef_bits = coef.coef_bits_latch;
+        int coef_offset = (ci * SAVED_COEFS);
+        quanttbl = compptr.quant_table;
+        Q00 = quanttbl.quantval[0];
+        Q01 = quanttbl.quantval[Q01_POS];
+        Q10 = quanttbl.quantval[Q10_POS];
+        Q20 = quanttbl.quantval[Q20_POS];
+        Q11 = quanttbl.quantval[Q11_POS];
+        Q02 = quanttbl.quantval[Q02_POS];
+//      inverse_DCT = cinfo.idct.inverse_DCT[ci];
+        output_ptr = output_buf[ci];
+        int output_ptr_offset = output_buf_offset[ci];
+        /* Loop over all DCT blocks to be processed. */
+        for (block_row = 0; block_row < block_rows; block_row++) {
+            buffer_ptr = buffer[block_row+buffer_offset];
+            int buffer_ptr_offset = 0, prev_block_row_offset = 0, next_block_row_offset = 0;
+            if (first_row && block_row is 0) {
+                prev_block_row = buffer_ptr;
+                prev_block_row_offset = buffer_ptr_offset;
+            } else {
+                prev_block_row = buffer[block_row-1+buffer_offset];
+                prev_block_row_offset = 0;
+            }
+            if (last_row && block_row is block_rows-1) {
+                next_block_row = buffer_ptr;
+                next_block_row_offset = buffer_ptr_offset;
+            } else {
+                next_block_row = buffer[block_row+1+buffer_offset];
+                next_block_row_offset = 0;
+            }
+            /* We fetch the surrounding DC values using a sliding-register approach.
+             * Initialize all nine here so as to do the right thing on narrow pics.
+             */
+            DC1 = DC2 = DC3 = prev_block_row[0+prev_block_row_offset][0];
+            DC4 = DC5 = DC6 = buffer_ptr[0+buffer_ptr_offset][0];
+            DC7 = DC8 = DC9 = next_block_row[0+next_block_row_offset][0];
+            output_col = 0;
+            last_block_column = compptr.width_in_blocks - 1;
+            for (block_num = 0; block_num <= last_block_column; block_num++) {
+                /* Fetch current DCT block into workspace so we can modify it. */
+//              jcopy_block_row(buffer_ptr, workspace, 1);
+                System.arraycopy(buffer_ptr[buffer_ptr_offset], 0, workspace, 0, workspace.length);
+                /* Update DC values */
+                if (block_num < last_block_column) {
+                    DC3 = prev_block_row[1+prev_block_row_offset][0];
+                    DC6 = buffer_ptr[1+buffer_ptr_offset][0];
+                    DC9 = next_block_row[1+next_block_row_offset][0];
+                }
+                /* Compute coefficient estimates per K.8.
+                 * An estimate is applied only if coefficient is still zero,
+                 * and is not known to be fully accurate.
+                 */
+                /* AC01 */
+                if ((Al=coef_bits[1+coef_offset]) !is 0 && workspace[1] is 0) {
+                    num = 36 * Q00 * (DC4 - DC6);
+                    if (num >= 0) {
+                        pred = (((Q01<<7) + num) / (Q01<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                    } else {
+                        pred = (((Q01<<7) - num) / (Q01<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                        pred = -pred;
+                    }
+                    workspace[1] = cast(short) pred;
+                }
+                /* AC10 */
+                if ((Al=coef_bits[2+coef_offset]) !is 0 && workspace[8] is 0) {
+                    num = 36 * Q00 * (DC2 - DC8);
+                    if (num >= 0) {
+                        pred = (((Q10<<7) + num) / (Q10<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                    } else {
+                        pred = (((Q10<<7) - num) / (Q10<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                        pred = -pred;
+                    }
+                    workspace[8] = cast(short) pred;
+                }
+                /* AC20 */
+                if ((Al=coef_bits[3+coef_offset]) !is 0 && workspace[16] is 0) {
+                    num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+                    if (num >= 0) {
+                        pred = (((Q20<<7) + num) / (Q20<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                    } else {
+                        pred = (((Q20<<7) - num) / (Q20<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                        pred = -pred;
+                    }
+                    workspace[16] = cast(short) pred;
+                }
+                /* AC11 */
+                if ((Al=coef_bits[4+coef_offset]) !is 0 && workspace[9] is 0) {
+                    num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
+                    if (num >= 0) {
+                        pred = (((Q11<<7) + num) / (Q11<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                    } else {
+                        pred = (((Q11<<7) - num) / (Q11<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                        pred = -pred;
+                    }
+                    workspace[9] = cast(short) pred;
+                }
+                /* AC02 */
+                if ((Al=coef_bits[5+coef_offset]) !is 0 && workspace[2] is 0) {
+                    num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+                    if (num >= 0) {
+                        pred = (((Q02<<7) + num) / (Q02<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                    } else {
+                        pred = (((Q02<<7) - num) / (Q02<<8));
+                        if (Al > 0 && pred >= (1<<Al))
+                            pred = (1<<Al)-1;
+                        pred = -pred;
+                    }
+                    workspace[2] = cast(short) pred;
+                }
+                /* OK, do the IDCT */
+                jpeg_idct_islow(cinfo, compptr, workspace, output_ptr, output_ptr_offset, output_col);
+                /* Advance for next column */
+                DC1 = DC2; DC2 = DC3;
+                DC4 = DC5; DC5 = DC6;
+                DC7 = DC8; DC8 = DC9;
+                buffer_ptr_offset++; prev_block_row_offset++; next_block_row_offset++;
+                output_col += compptr.DCT_scaled_size;
+            }
+            output_ptr_offset += compptr.DCT_scaled_size;
+        }
+    }
+
+    if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows)
+        return JPEG_ROW_COMPLETED;
+    return JPEG_SCAN_COMPLETED;
+}
+
+static int decompress_data (jpeg_decompress_struct cinfo, byte[][][] output_buf, int[] output_buf_offset) {
+    jpeg_d_coef_controller coef = cinfo.coef;
+    int last_iMCU_row = cinfo.total_iMCU_rows - 1;
+    int block_num;
+    int ci, block_row, block_rows;
+    short[][][] buffer;
+    short[][] buffer_ptr;
+    byte[][] output_ptr;
+    int output_col;
+    jpeg_component_info compptr;
+//  inverse_DCT_method_ptr inverse_DCT;
+
+    /* Force some input to be done if we are getting ahead of the input. */
+    while (cinfo.input_scan_number < cinfo.output_scan_number ||
+     (cinfo.input_scan_number is cinfo.output_scan_number &&
+        cinfo.input_iMCU_row <= cinfo.output_iMCU_row))
+    {
+        if (consume_input(cinfo) is JPEG_SUSPENDED)
+            return JPEG_SUSPENDED;
+    }
+
+    /* OK, output from the virtual arrays. */
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* Don't bother to IDCT an uninteresting component. */
+        if (! compptr.component_needed)
+            continue;
+        /* Align the virtual buffer for this component. */
+        buffer = coef.whole_image[ci];
+        int buffer_offset = cinfo.output_iMCU_row * compptr.v_samp_factor;
+        /* Count non-dummy DCT block rows in this iMCU row. */
+        if (cinfo.output_iMCU_row < last_iMCU_row)
+            block_rows = compptr.v_samp_factor;
+        else {
+            /* NB: can't use last_row_height here; it is input-side-dependent! */
+            block_rows = (compptr.height_in_blocks % compptr.v_samp_factor);
+            if (block_rows is 0) block_rows = compptr.v_samp_factor;
+        }
+//      inverse_DCT = cinfo.idct.inverse_DCT[ci];
+        output_ptr = output_buf[ci];
+        int output_ptr_offset = output_buf_offset[ci];
+        /* Loop over all DCT blocks to be processed. */
+        for (block_row = 0; block_row < block_rows; block_row++) {
+            buffer_ptr = buffer[block_row+buffer_offset];
+            int buffer_ptr_offset = 0;
+            output_col = 0;
+            for (block_num = 0; block_num < compptr.width_in_blocks; block_num++) {
+                jpeg_idct_islow(cinfo, compptr, buffer_ptr[buffer_ptr_offset], output_ptr, output_ptr_offset, output_col);
+
+                buffer_ptr_offset++;
+                output_col += compptr.DCT_scaled_size;
+            }
+            output_ptr_offset += compptr.DCT_scaled_size;
+        }
+    }
+
+    if (++(cinfo.output_iMCU_row) < cinfo.total_iMCU_rows)
+        return JPEG_ROW_COMPLETED;
+    return JPEG_SCAN_COMPLETED;
+}
+
+static void post_process_data (jpeg_decompress_struct cinfo,
+                byte[][][] input_buf, int[] input_buf_offset, int[] in_row_group_ctr,
+                int in_row_groups_avail,
+                byte[][] output_buf, int[] out_row_ctr,
+                int out_rows_avail)
+{
+    upsample(cinfo, input_buf, input_buf_offset, in_row_group_ctr, in_row_groups_avail, output_buf, out_row_ctr, out_rows_avail);
+}
+
+static void set_bottom_pointers (jpeg_decompress_struct cinfo)
+/* Change the pointer lists to duplicate the last sample row at the bottom
+ * of the image.    whichptr indicates which xbuffer holds the final iMCU row.
+ * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
+ */
+{
+    jpeg_d_main_controller main = cinfo.main;
+    int ci, i, rgroup, iMCUheight, rows_left;
+    jpeg_component_info compptr;
+    byte[][] xbuf;
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        /* Count sample rows in one iMCU row and in one row group */
+        iMCUheight = compptr.v_samp_factor * compptr.DCT_scaled_size;
+        rgroup = iMCUheight / cinfo.min_DCT_scaled_size;
+        /* Count nondummy sample rows remaining for this component */
+        rows_left = (compptr.downsampled_height % iMCUheight);
+        if (rows_left is 0) rows_left = iMCUheight;
+        /* Count nondummy row groups.   Should get same answer for each component,
+         * so we need only do it once.
+         */
+        if (ci is 0) {
+            main.rowgroups_avail = ((rows_left-1) / rgroup + 1);
+        }
+        /* Duplicate the last real sample row rgroup*2 times; this pads out the
+         * last partial rowgroup and ensures at least one full rowgroup of context.
+         */
+        xbuf = main.xbuffer[main.whichptr][ci];
+        int xbuf_offset = main.xbuffer_offset[main.whichptr][ci];
+        for (i = 0; i < rgroup * 2; i++) {
+            xbuf[rows_left + i + xbuf_offset] = xbuf[rows_left-1 + xbuf_offset];
+        }
+    }
+}
+
+static void set_wraparound_pointers (jpeg_decompress_struct cinfo)
+/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
+ * This changes the pointer list state from top-of-image to the normal state.
+ */
+{
+    jpeg_d_main_controller main = cinfo.main;
+    int ci, i, rgroup;
+    int M = cinfo.min_DCT_scaled_size;
+    jpeg_component_info compptr;
+    byte[][] xbuf0, xbuf1;
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        rgroup = (compptr.v_samp_factor * compptr.DCT_scaled_size) / cinfo.min_DCT_scaled_size; /* height of a row group of component */
+        xbuf0 = main.xbuffer[0][ci];
+        int xbuf0_offset = main.xbuffer_offset[0][ci];
+        xbuf1 = main.xbuffer[1][ci];
+        int xbuf1_offset = main.xbuffer_offset[1][ci];
+        for (i = 0; i < rgroup; i++) {
+            xbuf0[i - rgroup + xbuf0_offset] = xbuf0[rgroup*(M+1) + i + xbuf0_offset];
+            xbuf1[i - rgroup + xbuf1_offset] = xbuf1[rgroup*(M+1) + i + xbuf1_offset];
+            xbuf0[rgroup*(M+2) + i + xbuf0_offset] = xbuf0[i + xbuf0_offset];
+            xbuf1[rgroup*(M+2) + i + xbuf1_offset] = xbuf1[i + xbuf1_offset];
+        }
+    }
+}
+
+static void process_data_crank_post (jpeg_decompress_struct cinfo,
+    byte[][] output_buf, int[] out_row_ctr,
+    int out_rows_avail)
+{
+    error();
+}
+
+static void process_data_context_main (jpeg_decompress_struct cinfo,
+    byte[][] output_buf, int[] out_row_ctr,
+    int out_rows_avail)
+{
+    jpeg_d_main_controller main = cinfo.main;
+
+    /* Read input data if we haven't filled the main buffer yet */
+    if (! main.buffer_full) {
+        int result;
+        switch (cinfo.coef.decompress_data) {
+            case DECOMPRESS_DATA:
+                result = decompress_data(cinfo, main.xbuffer[main.whichptr], main.xbuffer_offset[main.whichptr]);
+                break;
+            case DECOMPRESS_SMOOTH_DATA:
+                result = decompress_smooth_data(cinfo, main.xbuffer[main.whichptr], main.xbuffer_offset[main.whichptr]);
+                break;
+            case DECOMPRESS_ONEPASS:
+                result = decompress_onepass(cinfo, main.xbuffer[main.whichptr], main.xbuffer_offset[main.whichptr]);
+                break;
+            default: result = 0;
+        }
+        if (result is 0)
+            return;         /* suspension forced, can do nothing more */
+        main.buffer_full = true;    /* OK, we have an iMCU row to work with */
+        main.iMCU_row_ctr++;    /* count rows received */
+    }
+
+    /* Postprocessor typically will not swallow all the input data it is handed
+     * in one call (due to filling the output buffer first).    Must be prepared
+     * to exit and restart. This switch lets us keep track of how far we got.
+     * Note that each case falls through to the next on successful completion.
+     */
+    switch (main.context_state) {
+        case CTX_POSTPONED_ROW:
+            /* Call postprocessor using previously set pointers for postponed row */
+            post_process_data (cinfo, main.xbuffer[main.whichptr], main.xbuffer_offset[main.whichptr], main.rowgroup_ctr, main.rowgroups_avail, output_buf, out_row_ctr, out_rows_avail);
+            if (main.rowgroup_ctr[0] < main.rowgroups_avail)
+                return;         /* Need to suspend */
+            main.context_state = CTX_PREPARE_FOR_IMCU;
+            if (out_row_ctr[0] >= out_rows_avail)
+                return;         /* Postprocessor exactly filled output buf */
+            /*FALLTHROUGH*/
+        case CTX_PREPARE_FOR_IMCU:
+            /* Prepare to process first M-1 row groups of this iMCU row */
+            main.rowgroup_ctr[0] = 0;
+            main.rowgroups_avail = (cinfo.min_DCT_scaled_size - 1);
+            /* Check for bottom of image: if so, tweak pointers to "duplicate"
+             * the last sample row, and adjust rowgroups_avail to ignore padding rows.
+             */
+            if (main.iMCU_row_ctr is cinfo.total_iMCU_rows)
+                set_bottom_pointers(cinfo);
+            main.context_state = CTX_PROCESS_IMCU;
+            /*FALLTHROUGH*/
+        case CTX_PROCESS_IMCU:
+            /* Call postprocessor using previously set pointers */
+            post_process_data (cinfo, main.xbuffer[main.whichptr], main.xbuffer_offset[main.whichptr], main.rowgroup_ctr, main.rowgroups_avail, output_buf, out_row_ctr, out_rows_avail);
+            if (main.rowgroup_ctr[0] < main.rowgroups_avail)
+                return;         /* Need to suspend */
+            /* After the first iMCU, change wraparound pointers to normal state */
+            if (main.iMCU_row_ctr is 1)
+                set_wraparound_pointers(cinfo);
+            /* Prepare to load new iMCU row using other xbuffer list */
+            main.whichptr ^= 1; /* 0=>1 or 1=>0 */
+            main.buffer_full = false;
+            /* Still need to process last row group of this iMCU row, */
+            /* which is saved at index M+1 of the other xbuffer */
+            main.rowgroup_ctr[0] = (cinfo.min_DCT_scaled_size + 1);
+            main.rowgroups_avail =  (cinfo.min_DCT_scaled_size + 2);
+            main.context_state = CTX_POSTPONED_ROW;
+        default:
+    }
+}
+
+static void process_data_simple_main (jpeg_decompress_struct cinfo, byte[][] output_buf, int[] out_row_ctr, int out_rows_avail) {
+    jpeg_d_main_controller main = cinfo.main;
+    int rowgroups_avail;
+
+    /* Read input data if we haven't filled the main buffer yet */
+    if (! main.buffer_full) {
+        int result;
+        switch (cinfo.coef.decompress_data) {
+            case DECOMPRESS_DATA:
+                result = decompress_data(cinfo, main.buffer, main.buffer_offset);
+                break;
+            case DECOMPRESS_SMOOTH_DATA:
+                result = decompress_smooth_data(cinfo, main.buffer, main.buffer_offset);
+                break;
+            case DECOMPRESS_ONEPASS:
+                result = decompress_onepass(cinfo, main.buffer, main.buffer_offset);
+                break;
+            default: result = 0;
+        }
+        if (result is 0)
+            return;         /* suspension forced, can do nothing more */
+        main.buffer_full = true;    /* OK, we have an iMCU row to work with */
+    }
+
+    /* There are always min_DCT_scaled_size row groups in an iMCU row. */
+    rowgroups_avail = cinfo.min_DCT_scaled_size;
+    /* Note: at the bottom of the image, we may pass extra garbage row groups
+     * to the postprocessor.    The postprocessor has to check for bottom
+     * of image anyway (at row resolution), so no point in us doing it too.
+     */
+
+    /* Feed the postprocessor */
+    post_process_data (cinfo, main.buffer, main.buffer_offset, main.rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr, out_rows_avail);
+
+    /* Has postprocessor consumed all the data yet? If so, mark buffer empty */
+    if (main.rowgroup_ctr[0] >= rowgroups_avail) {
+        main.buffer_full = false;
+        main.rowgroup_ctr[0] = 0;
+    }
+}
+
+static int jpeg_read_scanlines (jpeg_decompress_struct cinfo, byte[][] scanlines, int max_lines) {
+
+    if (cinfo.global_state !is DSTATE_SCANNING)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    if (cinfo.output_scanline >= cinfo.output_height) {
+//      WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+        return 0;
+    }
+
+    /* Call progress monitor hook if present */
+//  if (cinfo.progress !is NULL) {
+//      cinfo.progress.pass_counter = cast(long) cinfo.output_scanline;
+//      cinfo.progress.pass_limit = cast(long) cinfo.output_height;
+//      (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
+//  }
+
+    /* Process some data */
+    cinfo.row_ctr[0] = 0;
+    switch (cinfo.main.process_data) {
+        case PROCESS_DATA_SIMPLE_MAIN:
+            process_data_simple_main (cinfo, scanlines, cinfo.row_ctr, max_lines);
+            break;
+        case PROCESS_DATA_CONTEXT_MAIN:
+            process_data_context_main (cinfo, scanlines, cinfo.row_ctr, max_lines);
+            break;
+        case PROCESS_DATA_CRANK_POST:
+            process_data_crank_post (cinfo, scanlines, cinfo.row_ctr, max_lines);
+            break;
+        default: error();
+    }
+    cinfo.output_scanline += cinfo.row_ctr[0];
+    return cinfo.row_ctr[0];
+}
+
+
+static bool output_pass_setup (jpeg_decompress_struct cinfo) {
+    if (cinfo.global_state !is DSTATE_PRESCAN) {
+        /* First call: do pass setup */
+        prepare_for_output_pass (cinfo);
+        cinfo.output_scanline = 0;
+        cinfo.global_state = DSTATE_PRESCAN;
+    }
+    /* Loop over any required dummy passes */
+    while (cinfo.master.is_dummy_pass) {
+        error();
+//#ifdef QUANT_2PASS_SUPPORTED
+//      /* Crank through the dummy pass */
+//      while (cinfo.output_scanline < cinfo.output_height) {
+//          JDIMENSION last_scanline;
+//          /* Call progress monitor hook if present */
+//          if (cinfo.progress !is NULL) {
+//  cinfo.progress.pass_counter = cast(long) cinfo.output_scanline;
+//  cinfo.progress.pass_limit = cast(long) cinfo.output_height;
+//  (*cinfo.progress.progress_monitor) ((j_common_ptr) cinfo);
+//          }
+//          /* Process some data */
+//          last_scanline = cinfo.output_scanline;
+//          (*cinfo.main.process_data) (cinfo, (JSAMPARRAY) NULL,
+//                      &cinfo.output_scanline, (JDIMENSION) 0);
+//          if (cinfo.output_scanline is last_scanline)
+//  return FALSE;       /* No progress made, must suspend */
+//      }
+//      /* Finish up dummy pass, and set up for another one */
+//      (*cinfo.master.finish_output_pass) (cinfo);
+//      (*cinfo.master.prepare_for_output_pass) (cinfo);
+//      cinfo.output_scanline = 0;
+//#else
+//      ERREXIT(cinfo, JERR_NOT_COMPILED);
+//#endif /* QUANT_2PASS_SUPPORTED */
+    }
+    /* Ready for application to drive output pass through
+     * jpeg_read_scanlines or jpeg_read_raw_data.
+     */
+    cinfo.global_state = cinfo.raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
+    return true;
+}
+
+static bool get_dht (jpeg_decompress_struct cinfo)
+/* Process a DHT marker */
+{
+    int length;
+    byte[] bits = new byte[17];
+    byte[] huffval = new byte[256];
+    int i, index, count;
+    JHUFF_TBL htblptr;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    length -= 2;
+
+    while (length > 16) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        index = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+//      TRACEMS1(cinfo, 1, JTRC_DHT, index);
+
+        bits[0] = 0;
+        count = 0;
+        for (i = 1; i <= 16; i++) {
+            if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        bits[i] = cinfo.buffer[cinfo.bytes_offset++];
+            count += bits[i] & 0xFF;
+        }
+
+        length -= 1 + 16;
+
+//      TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+//           bits[1], bits[2], bits[3], bits[4],
+//           bits[5], bits[6], bits[7], bits[8]);
+//      TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+//           bits[9], bits[10], bits[11], bits[12],
+//           bits[13], bits[14], bits[15], bits[16]);
+
+        /* Here we just do minimal validation of the counts to avoid walking
+         * off the end of our table space.  jdhuff.c will check more carefully.
+         */
+        if (count > 256 || (count) > length)
+            error();
+//          ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+        for (i = 0; i < count; i++) {
+            if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+            huffval[i] = cinfo.buffer[cinfo.bytes_offset++];
+        }
+
+        length -= count;
+
+        if ((index & 0x10) !is 0) {      /* AC table definition */
+            index -= 0x10;
+            htblptr = cinfo.ac_huff_tbl_ptrs[index] = new JHUFF_TBL();
+        } else {            /* DC table definition */
+            htblptr = cinfo.dc_huff_tbl_ptrs[index] = new JHUFF_TBL();
+        }
+
+        if (index < 0 || index >= NUM_HUFF_TBLS)
+            error();
+//          ERREXIT1(cinfo, JERR_DHT_INDEX, index);
+
+        System.arraycopy(bits, 0, htblptr.bits, 0, bits.length);
+        System.arraycopy(huffval, 0, htblptr.huffval, 0, huffval.length);
+    }
+
+    if (length !is 0)
+        error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    return true;
+}
+
+
+static bool get_dqt (jpeg_decompress_struct cinfo)
+/* Process a DQT marker */
+{
+    int length;
+    int n, i, prec;
+    int tmp;
+    JQUANT_TBL quant_ptr;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    length -= 2;
+
+    while (length > 0) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    n = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        prec = n >> 4;
+        n &= 0x0F;
+
+//      TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
+
+        if (n >= NUM_QUANT_TBLS)
+            error();
+//          ERREXIT1(cinfo, JERR_DQT_INDEX, n);
+
+        if (cinfo.quant_tbl_ptrs[n] is null)
+            cinfo.quant_tbl_ptrs[n] = new JQUANT_TBL();
+        quant_ptr = cinfo.quant_tbl_ptrs[n];
+
+        for (i = 0; i < DCTSIZE2; i++) {
+            if (prec !is 0) {
+                if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+                if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                tmp |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+            } else {
+                    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                tmp = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+            }
+            /* We convert the zigzag-order table to natural array order. */
+            quant_ptr.quantval[jpeg_natural_order[i]] = cast(short) tmp;
+        }
+
+//      if (cinfo.err.trace_level >= 2) {
+//          for (i = 0; i < DCTSIZE2; i += 8) {
+//              TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
+//                  quant_ptr.quantval[i],   quant_ptr.quantval[i+1],
+//                   quant_ptr.quantval[i+2], quant_ptr.quantval[i+3],
+//                   quant_ptr.quantval[i+4], quant_ptr.quantval[i+5],
+//                   quant_ptr.quantval[i+6], quant_ptr.quantval[i+7]);
+//          }
+//      }
+
+        length -= (DCTSIZE2+1);
+        if (prec !is 0) length -= DCTSIZE2;
+    }
+
+    if (length !is 0)
+        error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    return true;
+}
+
+static bool get_dri (jpeg_decompress_struct cinfo)
+/* Process a DRI marker */
+{
+    int length;
+    int tmp;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (length !is 4)
+    error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    tmp = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    tmp |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+//  TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
+
+    cinfo.restart_interval = tmp;
+
+    return true;
+}
+
+static bool get_dac (jpeg_decompress_struct cinfo)
+/* Process a DAC marker */
+{
+    int length;
+    int index, val;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    length -= 2;
+
+    while (length > 0) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        index = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        val = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+        length -= 2;
+
+//      TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+
+        if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+            error();
+//          ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+
+        if (index >= NUM_ARITH_TBLS) { /* define AC table */
+            cinfo.arith_ac_K[index-NUM_ARITH_TBLS] = cast(byte) val;
+        } else {            /* define DC table */
+            cinfo.arith_dc_L[index] = cast(byte) (val & 0x0F);
+            cinfo.arith_dc_U[index] = cast(byte) (val >> 4);
+            if (cinfo.arith_dc_L[index] > cinfo.arith_dc_U[index])
+                error();
+//  ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+        }
+    }
+
+    if (length !is 0)
+        error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    return true;
+}
+
+
+static bool get_sos (jpeg_decompress_struct cinfo)
+/* Process a SOS marker */
+{
+    int length;
+    int i, ci, n, c, cc;
+    jpeg_component_info compptr = null;
+
+    if (! cinfo.marker.saw_SOF)
+        error();
+//      ERREXIT(cinfo, JERR_SOS_NO_SOF);
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    n = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+//  TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+    if (length !is (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
+        error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    cinfo.comps_in_scan = n;
+
+    /* Collect the component-spec parameters */
+
+    for (i = 0; i < n; i++) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        cc = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+        for (ci = 0; ci < cinfo.num_components; ci++) {
+            compptr = cinfo.comp_info[ci];
+            if (cc is compptr.component_id)
+                break;
+        }
+
+        if (ci is cinfo.num_components)
+            error();
+//          ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+
+        cinfo.cur_comp_info[i] = compptr;
+        compptr.dc_tbl_no = (c >> 4) & 15;
+        compptr.ac_tbl_no = (c       ) & 15;
+
+//      TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, compptr.dc_tbl_no, compptr.ac_tbl_no);
+    }
+
+    /* Collect the additional scan parameters Ss, Se, Ah/Al. */
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    cinfo.Ss = c;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    cinfo.Se = c;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    cinfo.Ah = (c >> 4) & 15;
+    cinfo.Al = (c        ) & 15;
+
+//  TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo.Ss, cinfo.Se, cinfo.Ah, cinfo.Al);
+
+    /* Prepare to scan data & restart markers */
+    cinfo.marker.next_restart_num = 0;
+
+    /* Count another SOS marker */
+    cinfo.input_scan_number++;
+
+    return true;
+}
+
+static bool get_sof (jpeg_decompress_struct cinfo, bool is_prog, bool is_arith) {
+    int length;
+    int c, ci;
+
+    cinfo.progressive_mode = is_prog;
+    cinfo.arith_code = is_arith;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.data_precision = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.image_height = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.image_height |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.image_width = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.image_width |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    cinfo.num_components = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    length -= 8;
+
+//  TRACEMS4(cinfo, 1, JTRC_SOF, cinfo.unread_marker,
+//       cast(int) cinfo.image_width, cast(int) cinfo.image_height,
+//       cinfo.num_components);
+
+    if (cinfo.marker.saw_SOF)
+        error();
+//      ERREXIT(cinfo, JERR_SOF_DUPLICATE);
+
+    /* We don't support files in which the image height is initially specified */
+    /* as 0 and is later redefined by DNL.  As long as we have to check that,   */
+    /* might as well have a general sanity check. */
+    if (cinfo.image_height <= 0 || cinfo.image_width <= 0 || cinfo.num_components <= 0)
+        error();
+//      ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+    if (length !is (cinfo.num_components * 3))
+        error();
+//      ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+    if (cinfo.comp_info is null)    /* do only once, even if suspend */
+        cinfo.comp_info = new jpeg_component_info[cinfo.num_components];
+
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        jpeg_component_info compptr = cinfo.comp_info[ci] = new jpeg_component_info();
+        compptr.component_index = ci;
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        compptr.component_id = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        compptr.h_samp_factor = (c >> 4) & 15;
+        compptr.v_samp_factor = (c       ) & 15;
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        compptr.quant_tbl_no = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+//      TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
+//           compptr.component_id, compptr.h_samp_factor,
+//           compptr.v_samp_factor, compptr.quant_tbl_no);
+    }
+
+    cinfo.marker.saw_SOF = true;
+
+    return true;
+}
+
+static void sep_upsample (jpeg_decompress_struct cinfo, byte[][][] input_buf, int[] input_buf_offset,
+        int[] in_row_group_ctr, int in_row_groups_avail,
+        byte[][] output_buf, int[] out_row_ctr, int out_rows_avail)
+{
+    jpeg_upsampler upsample = cinfo.upsample;
+    int ci;
+    jpeg_component_info compptr;
+    int num_rows;
+
+    /* Fill the conversion buffer, if it's empty */
+    if (upsample.next_row_out >= cinfo.max_v_samp_factor) {
+        for (ci = 0; ci < cinfo.num_components; ci++) {
+            compptr = cinfo.comp_info[ci];
+            /* Invoke per-component upsample method.    Notice we pass a POINTER
+             * to color_buf[ci], so that fullsize_upsample can change it.
+             */
+            int offset = input_buf_offset[ci] + (in_row_group_ctr[0] * upsample.rowgroup_height[ci]);
+            switch (upsample.methods[ci]) {
+                case NOOP_UPSAMPLE: noop_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case FULLSIZE_UPSAMPLE: fullsize_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case H2V1_FANCY_UPSAMPLE: h2v1_fancy_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case H2V1_UPSAMPLE: h2v1_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case H2V2_FANCY_UPSAMPLE: h2v2_fancy_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case H2V2_UPSAMPLE: h2v2_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+                case INT_UPSAMPLE: int_upsample(cinfo, compptr, input_buf[ci], offset, upsample.color_buf, upsample.color_buf_offset, ci); break;
+            default:
+            }
+        }
+        upsample.next_row_out = 0;
+    }
+
+    /* Color-convert and emit rows */
+
+    /* How many we have in the buffer: */
+    num_rows =  (cinfo.max_v_samp_factor - upsample.next_row_out);
+    /* Not more than the distance to the end of the image.  Need this test
+     * in case the image height is not a multiple of max_v_samp_factor:
+     */
+    if (num_rows > upsample.rows_to_go)
+        num_rows = upsample.rows_to_go;
+    /* And not more than what the client can accept: */
+    out_rows_avail -= out_row_ctr[0];
+    if (num_rows > out_rows_avail)
+        num_rows = out_rows_avail;
+
+    switch (cinfo.cconvert.color_convert) {
+        case NULL_CONVERT: null_convert (cinfo, upsample.color_buf, upsample.color_buf_offset, upsample.next_row_out, output_buf, out_row_ctr[0], num_rows); break;
+        case GRAYSCALE_CONVERT: grayscale_convert (cinfo, upsample.color_buf, upsample.color_buf_offset, upsample.next_row_out, output_buf, out_row_ctr[0], num_rows); break;
+        case YCC_RGB_CONVERT: ycc_rgb_convert (cinfo, upsample.color_buf, upsample.color_buf_offset, upsample.next_row_out, output_buf, out_row_ctr[0], num_rows); break;
+        case GRAY_RGB_CONVERT: gray_rgb_convert (cinfo, upsample.color_buf, upsample.color_buf_offset, upsample.next_row_out, output_buf, out_row_ctr[0], num_rows); break;
+        case YCCK_CMYK_CONVERT: error(); break;
+            default:
+    }
+
+    /* Adjust counts */
+    out_row_ctr[0] += num_rows;
+    upsample.rows_to_go -= num_rows;
+    upsample.next_row_out += num_rows;
+    /* When the buffer is emptied, declare this input row group consumed */
+    if (upsample.next_row_out >= cinfo.max_v_samp_factor) {
+        in_row_group_ctr[0]++;
+    }
+}
+
+static void noop_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+     byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    output_data_ptr[output_data_index] = null;  /* safety check */
+}
+
+static void fullsize_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+     byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    output_data_ptr[output_data_index] = input_data;
+    output_data_offset[output_data_index] = input_data_offset;
+}
+
+static void h2v1_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+     byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    byte[][] output_data = output_data_ptr[output_data_index];
+    byte[] inptr, outptr;
+    byte invalue;
+    int outend;
+    int inrow;
+    output_data_offset[output_data_index] = 0;
+
+    for (inrow = 0; inrow < cinfo.max_v_samp_factor; inrow++) {
+        inptr = input_data[inrow+input_data_offset];
+        outptr = output_data[inrow];
+        int inptr_offset = 0, outptr_offset = 0;
+        outend = outptr_offset + cinfo.output_width;
+        while (outptr_offset < outend) {
+            invalue = inptr[inptr_offset++];    /* don't need GETJSAMPLE() here */
+            outptr[outptr_offset++] = invalue;
+            outptr[outptr_offset++] = invalue;
+        }
+    }
+}
+
+static void h2v2_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+    byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    byte[][] output_data = output_data_ptr[output_data_index];
+    byte[] inptr, outptr;
+    byte invalue;
+    int outend;
+    int inrow, outrow;
+    output_data_offset[output_data_index] = 0;
+
+    inrow = outrow = 0;
+    while (outrow < cinfo.max_v_samp_factor) {
+        inptr = input_data[inrow+input_data_offset];
+        outptr = output_data[outrow];
+        int inptr_offset = 0, outptr_offset = 0;
+        outend = outptr_offset + cinfo.output_width;
+        while (outptr_offset < outend) {
+            invalue = inptr[inptr_offset++];    /* don't need GETJSAMPLE() here */
+            outptr[outptr_offset++] = invalue;
+            outptr[outptr_offset++] = invalue;
+        }
+        jcopy_sample_rows(output_data, outrow, output_data, outrow+1, 1, cinfo.output_width);
+        inrow++;
+        outrow += 2;
+    }
+}
+
+static void h2v1_fancy_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+     byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    byte[][] output_data = output_data_ptr[output_data_index];
+    byte[] inptr, outptr;
+    int invalue;
+    int colctr;
+    int inrow;
+    output_data_offset[output_data_index] = 0;
+
+    for (inrow = 0; inrow < cinfo.max_v_samp_factor; inrow++) {
+        inptr = input_data[inrow+input_data_offset];
+        outptr = output_data[inrow];
+        int inptr_offset = 0, outptr_offset = 0;
+        /* Special case for first column */
+        invalue = inptr[inptr_offset++] & 0xFF;
+        outptr[outptr_offset++] = cast(byte) invalue;
+        outptr[outptr_offset++] = cast(byte) ((invalue * 3 + (inptr[inptr_offset] & 0xFF) + 2) >> 2);
+
+        for (colctr = compptr.downsampled_width - 2; colctr > 0; colctr--) {
+            /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
+            invalue = (inptr[inptr_offset++] & 0xFF) * 3;
+            outptr[outptr_offset++] = cast(byte) ((invalue + (inptr[inptr_offset-2] & 0xFF) + 1) >> 2);
+            outptr[outptr_offset++] = cast(byte) ((invalue + (inptr[inptr_offset] & 0xFF) + 2) >> 2);
+        }
+
+        /* Special case for last column */
+        invalue = (inptr[inptr_offset] & 0xFF);
+        outptr[outptr_offset++] = cast(byte) ((invalue * 3 + (inptr[inptr_offset-1] & 0xFF) + 1) >> 2);
+        outptr[outptr_offset++] = cast(byte) invalue;
+    }
+}
+
+static void h2v2_fancy_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+    byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    byte[][] output_data = output_data_ptr[output_data_index];
+    byte[] inptr0, inptr1, outptr;
+    int thiscolsum, lastcolsum, nextcolsum;
+    int colctr;
+    int inrow, outrow, v;
+    output_data_offset[output_data_index] = 0;
+
+    inrow = outrow = 0;
+    while (outrow < cinfo.max_v_samp_factor) {
+        for (v = 0; v < 2; v++) {
+            /* inptr0 points to nearest input row, inptr1 points to next nearest */
+            inptr0 = input_data[inrow+input_data_offset];
+            if (v is 0)     /* next nearest is row above */
+                inptr1 = input_data[inrow-1+input_data_offset];
+            else            /* next nearest is row below */
+                inptr1 = input_data[inrow+1+input_data_offset];
+            outptr = output_data[outrow++];
+
+            int inptr0_offset = 0, inptr1_offset = 0, outptr_offset = 0;
+
+            /* Special case for first column */
+            thiscolsum = (inptr0[inptr0_offset++] & 0xFF) * 3 + (inptr1[inptr1_offset++] & 0xFF);
+            nextcolsum = (inptr0[inptr0_offset++] & 0xFF) * 3 + (inptr1[inptr1_offset++] & 0xFF);
+            outptr[outptr_offset++] = cast(byte) ((thiscolsum * 4 + 8) >> 4);
+            outptr[outptr_offset++] = cast(byte) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+            lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+
+            for (colctr = compptr.downsampled_width - 2; colctr > 0; colctr--) {
+                /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
+                /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
+                nextcolsum = (inptr0[inptr0_offset++] & 0xFF) * 3 + (inptr1[inptr1_offset++] & 0xFF);
+                outptr[outptr_offset++] = cast(byte) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+                outptr[outptr_offset++] = cast(byte) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+                lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+            }
+
+            /* Special case for last column */
+            outptr[outptr_offset++] = cast(byte) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+            outptr[outptr_offset++] = cast(byte) ((thiscolsum * 4 + 7) >> 4);
+        }
+        inrow++;
+    }
+}
+
+static void int_upsample (jpeg_decompress_struct cinfo, jpeg_component_info compptr,
+     byte[][] input_data, int input_data_offset, byte[][][] output_data_ptr, int[] output_data_offset, int output_data_index)
+{
+    jpeg_upsampler upsample = cinfo.upsample;
+    byte[][] output_data = output_data_ptr[output_data_index];
+    byte[] inptr, outptr;
+    byte invalue;
+    int h;
+    int outend;
+    int h_expand, v_expand;
+    int inrow, outrow;
+    output_data_offset[output_data_index] = 0;
+
+    h_expand = upsample.h_expand[compptr.component_index];
+    v_expand = upsample.v_expand[compptr.component_index];
+
+    inrow = outrow = 0;
+    while (outrow < cinfo.max_v_samp_factor) {
+        /* Generate one output row with proper horizontal expansion */
+        inptr = input_data[inrow+input_data_offset];
+        int inptr_offset = 0;
+        outptr = output_data[outrow];
+        int outptr_offset = 0;
+        outend = outptr_offset + cinfo.output_width;
+        while (outptr_offset < outend) {
+            invalue = inptr[inptr_offset++];    /* don't need GETJSAMPLE() here */
+            for (h = h_expand; h > 0; h--) {
+                outptr[outptr_offset++] = invalue;
+            }
+        }
+        /* Generate any additional output rows by duplicating the first one */
+        if (v_expand > 1) {
+            jcopy_sample_rows(output_data, outrow, output_data, outrow+1, v_expand-1, cinfo.output_width);
+        }
+        inrow++;
+        outrow += v_expand;
+    }
+}
+
+static void null_convert (jpeg_decompress_struct cinfo,
+    byte[][][] input_buf, int[] input_buf_offset, int input_row,
+    byte[][] output_buf, int output_buf_offset, int num_rows)
+{
+    byte[] inptr, outptr;
+    int count;
+    int num_components = cinfo.num_components;
+    int num_cols = cinfo.output_width;
+    int ci;
+
+    while (--num_rows >= 0) {
+        for (ci = 0; ci < num_components; ci++) {
+            inptr = input_buf[ci][input_row+input_buf_offset[0]];
+            outptr = output_buf[output_buf_offset];
+            /* BGR instead of RGB */
+            int offset = 0;
+            switch (ci) {
+                case 2: offset = RGB_BLUE; break;
+                case 1: offset = RGB_GREEN; break;
+                case 0: offset = RGB_RED; break;
+            default:
+            }
+            int outptr_offset = offset, inptr_offset = 0;
+            for (count = num_cols; count > 0; count--) {
+                outptr[outptr_offset] = inptr[inptr_offset++];  /* needn't bother with GETJSAMPLE() here */
+                outptr_offset += num_components;
+            }
+        }
+        input_row++;
+        output_buf_offset++;
+    }
+}
+
+static void grayscale_convert (jpeg_decompress_struct cinfo,
+    byte[][][] input_buf, int[] input_buf_offset, int input_row,
+    byte[][] output_buf, int output_buf_offset, int num_rows)
+{
+  jcopy_sample_rows(input_buf[0], input_row+input_buf_offset[0], output_buf, output_buf_offset,
+            num_rows, cinfo.output_width);
+}
+
+static void gray_rgb_convert (jpeg_decompress_struct cinfo,
+    byte[][][] input_buf, int[] input_buf_offset, int input_row,
+    byte[][] output_buf, int output_buf_offset, int num_rows)
+{
+    byte[] inptr, outptr;
+    int col;
+    int num_cols = cinfo.output_width;
+
+    while (--num_rows >= 0) {
+        inptr = input_buf[0][input_row+++input_buf_offset[0]];
+        outptr = output_buf[output_buf_offset++];
+        int outptr_offset = 0;
+        for (col = 0; col < num_cols; col++) {
+            /* We can dispense with GETJSAMPLE() here */
+            outptr[RGB_RED+outptr_offset] = outptr[RGB_GREEN+outptr_offset] = outptr[RGB_BLUE+outptr_offset] = inptr[col];
+            outptr_offset += RGB_PIXELSIZE;
+        }
+    }
+}
+
+static void ycc_rgb_convert (jpeg_decompress_struct cinfo,
+    byte[][][] input_buf, int[] input_buf_offset, int input_row,
+    byte[][] output_buf, int output_buf_offset, int num_rows)
+{
+    jpeg_color_deconverter cconvert = cinfo.cconvert;
+    int y, cb, cr;
+    byte[] outptr;
+    byte[] inptr0, inptr1, inptr2;
+    int col;
+    int num_cols = cinfo.output_width;
+    /* copy these pointers into registers if possible */
+    byte[] range_limit = cinfo.sample_range_limit;
+    int range_limit_offset = cinfo.sample_range_limit_offset;
+    int[] Crrtab = cconvert.Cr_r_tab;
+    int[] Cbbtab = cconvert.Cb_b_tab;
+    int[] Crgtab = cconvert.Cr_g_tab;
+    int[] Cbgtab = cconvert.Cb_g_tab;
+//      SHIFT_TEMPS
+
+    while (--num_rows >= 0) {
+        inptr0 = input_buf[0][input_row+input_buf_offset[0]];
+        inptr1 = input_buf[1][input_row+input_buf_offset[1]];
+        inptr2 = input_buf[2][input_row+input_buf_offset[2]];
+        input_row++;
+        outptr = output_buf[output_buf_offset++];
+        int outptr_offset = 0;
+        for (col = 0; col < num_cols; col++) {
+            y = (inptr0[col] & 0xFF);
+            cb = (inptr1[col] & 0xFF);
+            cr = (inptr2[col] & 0xFF);
+            /* Range-limiting is essential due to noise introduced by DCT losses. */
+            outptr[outptr_offset + RGB_RED] =   range_limit[y + Crrtab[cr] + range_limit_offset];
+            outptr[outptr_offset + RGB_GREEN] = range_limit[y + ((Cbgtab[cb] + Crgtab[cr]>>SCALEBITS)) + range_limit_offset];
+            outptr[outptr_offset + RGB_BLUE] =  range_limit[y + Cbbtab[cb] + range_limit_offset];
+            outptr_offset += RGB_PIXELSIZE;
+        }
+    }
+}
+
+static bool process_APPn(int n, jpeg_decompress_struct cinfo) {
+    if (n is 0 || n is 14) {
+        return get_interesting_appn(cinfo);
+    }
+    return skip_variable(cinfo);
+}
+
+static bool process_COM(jpeg_decompress_struct cinfo) {
+    return skip_variable(cinfo);
+}
+
+static void skip_input_data (jpeg_decompress_struct cinfo, int num_bytes) {
+    if (num_bytes > 0) {
+        while (num_bytes > cinfo.bytes_in_buffer - cinfo.bytes_offset) {
+            num_bytes -= cinfo.bytes_in_buffer - cinfo.bytes_offset;
+            if (!fill_input_buffer(cinfo)) error();
+            /* note we assume that fill_input_buffer will never return FALSE,
+             * so suspension need not be handled.
+             */
+        }
+        cinfo.bytes_offset += num_bytes;
+    }
+}
+
+static bool skip_variable (jpeg_decompress_struct cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+    int length;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+
+    length -= 2;
+
+//  TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo.unread_marker, cast(int) length);
+
+    if (length > 0) {
+        skip_input_data (cinfo, length);
+    }
+
+    return true;
+}
+
+static bool get_interesting_appn (jpeg_decompress_struct cinfo)
+/* Process an APP0 or APP14 marker without saving it */
+{
+    int length;
+    byte[] b = new byte[APPN_DATA_LEN];
+    int i, numtoread;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length = (cinfo.buffer[cinfo.bytes_offset++] & 0xFF) << 8;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    length |= cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    length -= 2;
+
+    /* get the interesting part of the marker data */
+    if (length >= APPN_DATA_LEN)
+        numtoread = APPN_DATA_LEN;
+    else if (length > 0)
+        numtoread = length;
+    else
+        numtoread = 0;
+    for (i = 0; i < numtoread; i++) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        b[i] = cinfo.buffer[cinfo.bytes_offset++];
+    }
+    length -= numtoread;
+
+    /* process it */
+    switch (cinfo.unread_marker) {
+        case M_APP0:
+            examine_app0(cinfo, b, numtoread, length);
+            break;
+        case M_APP14:
+            examine_app14(cinfo, b, numtoread, length);
+            break;
+        default:
+            /* can't get here unless jpeg_save_markers chooses wrong processor */
+            error();
+//          ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo.unread_marker);
+            break;
+    }
+
+    /* skip any remaining data -- could be lots */
+    if (length > 0)
+        skip_input_data (cinfo, length);
+
+    return true;
+}
+
+static void examine_app0 (jpeg_decompress_struct cinfo, byte[] data, int datalen, int remaining)
+/* Examine first few bytes from an APP0.
+ * Take appropriate action if it is a JFIF marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+    int totallen = datalen + remaining;
+
+    if (datalen >= APP0_DATA_LEN &&
+            (data[0] & 0xFF) is 0x4A &&
+            (data[1] & 0xFF) is 0x46 &&
+            (data[2] & 0xFF) is 0x49 &&
+            (data[3] & 0xFF) is 0x46 &&
+            (data[4] & 0xFF) is 0)
+    {
+        /* Found JFIF APP0 marker: save info */
+        cinfo.saw_JFIF_marker = true;
+        cinfo.JFIF_major_version = (data[5]);
+        cinfo.JFIF_minor_version = cast(byte)(data[6] & 0xFF);
+        cinfo.density_unit = cast(byte)(data[7] & 0xFF);
+        cinfo.X_density = cast(short)(((data[8] & 0xFF) << 8) + (data[9] & 0xFF));
+        cinfo.Y_density = cast(short)(((data[10] & 0xFF) << 8) + (data[11] & 0xFF));
+        /* Check version.
+         * Major version must be 1, anything else signals an incompatible change.
+         * (We used to treat this as an error, but now it's a nonfatal warning,
+         * because some bozo at Hijaak couldn't read the spec.)
+         * Minor version should be 0..2, but process anyway if newer.
+         */
+        if (cinfo.JFIF_major_version !is 1) {
+//          WARNMS2(cinfo, JWRN_JFIF_MAJOR,
+//              cinfo.JFIF_major_version, cinfo.JFIF_minor_version);
+        }
+        /* Generate trace messages */
+//      TRACEMS5(cinfo, 1, JTRC_JFIF,
+//           cinfo.JFIF_major_version, cinfo.JFIF_minor_version,
+//           cinfo.X_density, cinfo.Y_density, cinfo.density_unit);
+        /* Validate thumbnail dimensions and issue appropriate messages */
+        if (((data[12] & 0xFF) | (data[13]) & 0xFF) !is 0) {
+//          TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+//               GETJOCTET(data[12]), GETJOCTET(data[13]));
+        }
+        totallen -= APP0_DATA_LEN;
+        if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) {
+//          TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, cast(int) totallen);
+        }
+    } else if (datalen >= 6 &&
+            (data[0] & 0xFF) is 0x4A &&
+            (data[1] & 0xFF) is 0x46 &&
+            (data[2] & 0xFF) is 0x58 &&
+            (data[3] & 0xFF) is 0x58 &&
+            (data[4] & 0xFF) is 0)
+    {
+        /* Found JFIF "JFXX" extension APP0 marker */
+        /* The library doesn't actually do anything with these,
+         * but we try to produce a helpful trace message.
+         */
+        switch ((data[5]) & 0xFF) {
+            case 0x10:
+//              TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, cast(int) totallen);
+                break;
+            case 0x11:
+//              TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, cast(int) totallen);
+                break;
+            case 0x13:
+//              TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, cast(int) totallen);
+                break;
+            default:
+//              TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, GETJOCTET(data[5]), cast(int) totallen);
+            break;
+        }
+    } else {
+        /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+//      TRACEMS1(cinfo, 1, JTRC_APP0, cast(int) totallen);
+    }
+}
+
+static void examine_app14 (jpeg_decompress_struct cinfo, byte[] data, int datalen, int remaining)
+/* Examine first few bytes from an APP14.
+ * Take appropriate action if it is an Adobe marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+    int /*version, flags0, flags1, */transform;
+
+    if (datalen >= APP14_DATA_LEN &&
+            (data[0] & 0xFF) is 0x41 &&
+            (data[1] & 0xFF) is 0x64 &&
+            (data[2] & 0xFF) is 0x6F &&
+            (data[3] & 0xFF) is 0x62 &&
+            (data[4] & 0xFF) is 0x65)
+    {
+        /* Found Adobe APP14 marker */
+//      version = ((data[5] & 0xFF) << 8) + (data[6] & 0xFF);
+//      flags0 = ((data[7] & 0xFF) << 8) + (data[8] & 0xFF);
+//      flags1 = ((data[9] & 0xFF) << 8) + (data[10] & 0xFF);
+        transform = (data[11] & 0xFF);
+//      TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
+        cinfo.saw_Adobe_marker = true;
+        cinfo.Adobe_transform = cast(byte) transform;
+    } else {
+        /* Start of APP14 does not match "Adobe", or too short */
+//      TRACEMS1(cinfo, 1, JTRC_APP14, cast(int) (datalen + remaining));
+    }
+}
+
+static bool get_soi (jpeg_decompress_struct cinfo) /* Process an SOI marker */ {
+    int i;
+
+//  TRACEMS(cinfo, 1, JTRC_SOI);
+
+    if (cinfo.marker.saw_SOI)
+        error();
+//      ERREXIT(cinfo, JERR_SOI_DUPLICATE);
+
+    /* Reset all parameters that are defined to be reset by SOI */
+
+    for (i = 0; i < NUM_ARITH_TBLS; i++) {
+        cinfo.arith_dc_L[i] = 0;
+        cinfo.arith_dc_U[i] = 1;
+        cinfo.arith_ac_K[i] = 5;
+    }
+    cinfo.restart_interval = 0;
+
+    /* Set initial assumptions for colorspace etc */
+
+    cinfo.jpeg_color_space = JCS_UNKNOWN;
+    cinfo.CCIR601_sampling = false; /* Assume non-CCIR sampling??? */
+
+    cinfo.saw_JFIF_marker = false;
+    cinfo.JFIF_major_version = 1; /* set default JFIF APP0 values */
+    cinfo.JFIF_minor_version = 1;
+    cinfo.density_unit = 0;
+    cinfo.X_density = 1;
+    cinfo.Y_density = 1;
+    cinfo.saw_Adobe_marker = false;
+    cinfo.Adobe_transform = 0;
+
+    cinfo.marker.saw_SOI = true;
+
+    return true;
+}
+
+static void jinit_input_controller (jpeg_decompress_struct cinfo)
+{
+    /* Initialize state: can't use reset_input_controller since we don't
+     * want to try to reset other modules yet.
+     */
+    jpeg_input_controller inputctl = cinfo.inputctl = new jpeg_input_controller();
+    inputctl.has_multiple_scans = false; /* "unknown" would be better */
+    inputctl.eoi_reached = false;
+    inputctl.inheaders = true;
+}
+
+static void reset_marker_reader (jpeg_decompress_struct cinfo) {
+    jpeg_marker_reader marker = cinfo.marker;
+
+    cinfo.comp_info = null;     /* until allocated by get_sof */
+    cinfo.input_scan_number = 0;        /* no SOS seen yet */
+    cinfo.unread_marker = 0;        /* no pending marker */
+    marker.saw_SOI = false;     /* set internal state too */
+    marker.saw_SOF = false;
+    marker.discarded_bytes = 0;
+//  marker.cur_marker = null;
+}
+
+static void reset_input_controller (jpeg_decompress_struct cinfo) {
+    jpeg_input_controller inputctl = cinfo.inputctl;
+
+    inputctl.has_multiple_scans = false; /* "unknown" would be better */
+    inputctl.eoi_reached = false;
+    inputctl.inheaders = true;
+    /* Reset other modules */
+    reset_marker_reader (cinfo);
+    /* Reset progression state -- would be cleaner if entropy decoder did this */
+    cinfo.coef_bits = null;
+}
+
+static void finish_output_pass (jpeg_decompress_struct cinfo) {
+    jpeg_decomp_master master = cinfo.master;
+
+    if (cinfo.quantize_colors) {
+        error(SWT.ERROR_NOT_IMPLEMENTED);
+//      (*cinfo.cquantize.finish_pass) (cinfo);
+    }
+    master.pass_number++;
+}
+
+static void jpeg_destroy (jpeg_decompress_struct cinfo) {
+    /* We need only tell the memory manager to release everything. */
+    /* NB: mem pointer is NULL if memory mgr failed to initialize. */
+//  if (cinfo.mem !is NULL)
+//      (*cinfo.mem.self_destruct) (cinfo);
+//  cinfo.mem = NULL;       /* be safe if jpeg_destroy is called twice */
+    cinfo.global_state = 0; /* mark it destroyed */
+}
+
+static void jpeg_destroy_decompress (jpeg_decompress_struct cinfo) {
+    jpeg_destroy(cinfo); /* use common routine */
+}
+
+static bool jpeg_input_complete (jpeg_decompress_struct cinfo) {
+    /* Check for valid jpeg object */
+    if (cinfo.global_state < DSTATE_START || cinfo.global_state > DSTATE_STOPPING)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    return cinfo.inputctl.eoi_reached;
+}
+
+static bool jpeg_start_output (jpeg_decompress_struct cinfo, int scan_number) {
+    if (cinfo.global_state !is DSTATE_BUFIMAGE && cinfo.global_state !is DSTATE_PRESCAN)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    /* Limit scan number to valid range */
+    if (scan_number <= 0)
+        scan_number = 1;
+    if (cinfo.inputctl.eoi_reached && scan_number > cinfo.input_scan_number)
+        scan_number = cinfo.input_scan_number;
+    cinfo.output_scan_number = scan_number;
+    /* Perform any dummy output passes, and set up for the real pass */
+    return output_pass_setup(cinfo);
+}
+
+static bool jpeg_finish_output (jpeg_decompress_struct cinfo) {
+    if ((cinfo.global_state is DSTATE_SCANNING || cinfo.global_state is DSTATE_RAW_OK) && cinfo.buffered_image) {
+        /* Terminate this pass. */
+        /* We do not require the whole pass to have been completed. */
+        finish_output_pass (cinfo);
+        cinfo.global_state = DSTATE_BUFPOST;
+    } else if (cinfo.global_state !is DSTATE_BUFPOST) {
+        /* BUFPOST = repeat call after a suspension, anything else is error */
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    }
+    /* Read markers looking for SOS or EOI */
+    while (cinfo.input_scan_number <= cinfo.output_scan_number && !cinfo.inputctl.eoi_reached) {
+        if (consume_input (cinfo) is JPEG_SUSPENDED)
+            return false;       /* Suspend, come back later */
+    }
+    cinfo.global_state = DSTATE_BUFIMAGE;
+    return true;
+}
+
+static bool jpeg_finish_decompress (jpeg_decompress_struct cinfo) {
+    if ((cinfo.global_state is DSTATE_SCANNING || cinfo.global_state is DSTATE_RAW_OK) && ! cinfo.buffered_image) {
+        /* Terminate final pass of non-buffered mode */
+        if (cinfo.output_scanline < cinfo.output_height)
+            error();
+//          ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+        finish_output_pass (cinfo);
+        cinfo.global_state = DSTATE_STOPPING;
+    } else if (cinfo.global_state is DSTATE_BUFIMAGE) {
+        /* Finishing after a buffered-image operation */
+        cinfo.global_state = DSTATE_STOPPING;
+    } else if (cinfo.global_state !is DSTATE_STOPPING) {
+        /* STOPPING = repeat call after a suspension, anything else is error */
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    }
+    /* Read until EOI */
+    while (! cinfo.inputctl.eoi_reached) {
+        if (consume_input (cinfo) is JPEG_SUSPENDED)
+            return false;       /* Suspend, come back later */
+    }
+    /* Do final cleanup */
+//  (*cinfo.src.term_source) (cinfo);
+    /* We can use jpeg_abort to release memory and reset global_state */
+    jpeg_abort(cinfo);
+    return true;
+}
+
+
+static int jpeg_read_header (jpeg_decompress_struct cinfo, bool require_image) {
+    int retcode;
+
+    if (cinfo.global_state !is DSTATE_START && cinfo.global_state !is DSTATE_INHEADER)
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+
+    retcode = jpeg_consume_input(cinfo);
+
+    switch (retcode) {
+        case JPEG_REACHED_SOS:
+            retcode = JPEG_HEADER_OK;
+            break;
+        case JPEG_REACHED_EOI:
+            if (require_image)      /* Complain if application wanted an image */
+                error();
+//              ERREXIT(cinfo, JERR_NO_IMAGE);
+            /* Reset to start state; it would be safer to require the application to
+             * call jpeg_abort, but we can't change it now for compatibility reasons.
+             * A side effect is to free any temporary memory (there shouldn't be any).
+             */
+            jpeg_abort(cinfo); /* sets state = DSTATE_START */
+            retcode = JPEG_HEADER_TABLES_ONLY;
+            break;
+        case JPEG_SUSPENDED:
+            /* no work */
+            break;
+        default:
+    }
+
+    return retcode;
+}
+
+static int dummy_consume_data (jpeg_decompress_struct cinfo) {
+    return JPEG_SUSPENDED;  /* Always indicate nothing was done */
+}
+
+static int consume_data (jpeg_decompress_struct cinfo) {
+    jpeg_d_coef_controller coef = cinfo.coef;
+    int MCU_col_num;    /* index of current MCU within row */
+    int blkn, ci, xindex, yindex, yoffset;
+    int start_col;
+//  short[][][][] buffer = new short[MAX_COMPS_IN_SCAN][][][];
+    short[][] buffer_ptr;
+    jpeg_component_info compptr;
+
+//  /* Align the virtual buffers for the components used in this scan. */
+//  for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+//      compptr = cinfo.cur_comp_info[ci];
+//      buffer[ci] = coef.whole_image[compptr.component_index];
+//      /* Note: entropy decoder expects buffer to be zeroed,
+//       * but this is handled automatically by the memory manager
+//       * because we requested a pre-zeroed array.
+//       */
+//  }
+
+    /* Loop to process one whole iMCU row */
+    for (yoffset = coef.MCU_vert_offset; yoffset < coef.MCU_rows_per_iMCU_row; yoffset++) {
+        for (MCU_col_num = coef.MCU_ctr; MCU_col_num < cinfo.MCUs_per_row; MCU_col_num++) {
+            /* Construct list of pointers to DCT blocks belonging to this MCU */
+            blkn = 0; /* index of current DCT block within MCU */
+            for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+                compptr = cinfo.cur_comp_info[ci];
+                start_col = MCU_col_num * compptr.MCU_width;
+                for (yindex = 0; yindex < compptr.MCU_height; yindex++) {
+//                  buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+                    buffer_ptr = coef.whole_image[compptr.component_index][yindex+yoffset+cinfo.input_iMCU_row*compptr.v_samp_factor];
+                    int buffer_ptr_offset = start_col;
+                    for (xindex = 0; xindex < compptr.MCU_width; xindex++) {
+                        coef.MCU_buffer[blkn++] = buffer_ptr[buffer_ptr_offset++];
+                    }
+                }
+            }
+            /* Try to fetch the MCU. */
+            if (! cinfo.entropy.decode_mcu (cinfo, coef.MCU_buffer)) {
+                /* Suspension forced; update state counters and exit */
+                coef.MCU_vert_offset = yoffset;
+                coef.MCU_ctr = MCU_col_num;
+                return JPEG_SUSPENDED;
+            }
+        }
+        /* Completed an MCU row, but perhaps not an iMCU row */
+        coef.MCU_ctr = 0;
+    }
+    /* Completed the iMCU row, advance counters for next one */
+    if (++(cinfo.input_iMCU_row) < cinfo.total_iMCU_rows) {
+        coef.start_iMCU_row(cinfo);
+        return JPEG_ROW_COMPLETED;
+    }
+    /* Completed the scan */
+    finish_input_pass (cinfo);
+    return JPEG_SCAN_COMPLETED;
+}
+
+static int consume_input (jpeg_decompress_struct cinfo) {
+    switch (cinfo.inputctl.consume_input) {
+        case COEF_CONSUME_INPUT:
+             switch (cinfo.coef.consume_data) {
+                case CONSUME_DATA: return consume_data(cinfo);
+                case DUMMY_CONSUME_DATA: return dummy_consume_data(cinfo);
+                default: error();
+             }
+             break;
+        case INPUT_CONSUME_INPUT:
+            return consume_markers(cinfo);
+        default:
+            error();
+    }
+    return 0;
+}
+
+static bool fill_input_buffer(jpeg_decompress_struct cinfo) {
+    try {
+        InputStream inputStream = cinfo.inputStream;
+        int nbytes = inputStream.read(cinfo.buffer);
+        if (nbytes <= 0) {
+            if (cinfo.start_of_file)    /* Treat empty input file as fatal error */
+                error();
+//              ERREXIT(cinfo, JERR_INPUT_EMPTY);
+//          WARNMS(cinfo, JWRN_JPEG_EOF);
+            /* Insert a fake EOI marker */
+            cinfo.buffer[0] = cast(byte)0xFF;
+            cinfo.buffer[1] = cast(byte)M_EOI;
+            nbytes = 2;
+        }
+        cinfo.bytes_in_buffer = nbytes;
+        cinfo.bytes_offset = 0;
+        cinfo.start_of_file = false;
+    } catch (IOException e) {
+        error(SWT.ERROR_IO);
+        return false;
+    }
+    return true;
+}
+
+static bool first_marker (jpeg_decompress_struct cinfo) {
+    /* Like next_marker, but used to obtain the initial SOI marker. */
+    /* For this marker, we do not allow preceding garbage or fill; otherwise,
+     * we might well scan an entire input file before realizing it ain't JPEG.
+     * If an application wants to process non-JFIF files, it must seek to the
+     * SOI before calling the JPEG library.
+     */
+    int c, c2;
+
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+    c2 = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+    if (c !is 0xFF || c2 !is M_SOI)
+        error();
+//      ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+    cinfo.unread_marker = c2;
+
+    return true;
+}
+
+static bool next_marker (jpeg_decompress_struct cinfo) {
+    int c;
+
+    for (;;) {
+        if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+        c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        /* Skip any non-FF bytes.
+         * This may look a bit inefficient, but it will not occur in a valid file.
+         * We sync after each discarded byte so that a suspending data source
+         * can discard the byte from its buffer.
+         */
+        while (c !is 0xFF) {
+            cinfo.marker.discarded_bytes++;
+            if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+            c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        }
+        /* This loop swallows any duplicate FF bytes.   Extra FFs are legal as
+         * pad bytes, so don't count them in discarded_bytes.   We assume there
+         * will not be so many consecutive FF bytes as to overflow a suspending
+         * data source's input buffer.
+         */
+        do {
+             if (cinfo.bytes_offset is cinfo.bytes_in_buffer) fill_input_buffer(cinfo);
+                c = cinfo.buffer[cinfo.bytes_offset++] & 0xFF;
+        } while (c is 0xFF);
+        if (c !is 0)
+            break;          /* found a valid marker, exit loop */
+        /* Reach here if we found a stuffed-zero data sequence (FF/00).
+         * Discard it and loop back to try again.
+         */
+        cinfo.marker.discarded_bytes += 2;
+    }
+
+    if (cinfo.marker.discarded_bytes !is 0) {
+//      WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo.marker.discarded_bytes, c);
+        cinfo.marker.discarded_bytes = 0;
+    }
+
+    cinfo.unread_marker = c;
+
+    return true;
+}
+
+static int read_markers (jpeg_decompress_struct cinfo) {
+    /* Outer loop repeats once for each marker. */
+    for (;;) {
+        /* Collect the marker proper, unless we already did. */
+        /* NB: first_marker() enforces the requirement that SOI appear first. */
+        if (cinfo.unread_marker is 0) {
+            if (! cinfo.marker.saw_SOI) {
+                if (! first_marker(cinfo))
+                    return JPEG_SUSPENDED;
+                } else {
+                    if (! next_marker(cinfo))
+                        return JPEG_SUSPENDED;
+                }
+        }
+        /* At this point cinfo.unread_marker contains the marker code and the
+         * input point is just past the marker proper, but before any parameters.
+         * A suspension will cause us to return with this state still true.
+         */
+        switch (cinfo.unread_marker) {
+            case M_SOI:
+                if (! get_soi(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_SOF0:        /* Baseline */
+            case M_SOF1:        /* Extended sequential, Huffman */
+                if (! get_sof(cinfo, false, false))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_SOF2:        /* Progressive, Huffman */
+                if (! get_sof(cinfo, true, false))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_SOF9:        /* Extended sequential, arithmetic */
+                if (! get_sof(cinfo, false, true))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_SOF10:       /* Progressive, arithmetic */
+                if (! get_sof(cinfo, true, true))
+                    return JPEG_SUSPENDED;
+                break;
+
+            /* Currently unsupported SOFn types */
+            case M_SOF3:        /* Lossless, Huffman */
+            case M_SOF5:        /* Differential sequential, Huffman */
+            case M_SOF6:        /* Differential progressive, Huffman */
+            case M_SOF7:        /* Differential lossless, Huffman */
+            case M_JPG:         /* Reserved for JPEG extensions */
+            case M_SOF11:       /* Lossless, arithmetic */
+            case M_SOF13:       /* Differential sequential, arithmetic */
+            case M_SOF14:       /* Differential progressive, arithmetic */
+            case M_SOF15:       /* Differential lossless, arithmetic */
+                error();
+//              ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo.unread_marker);
+                break;
+
+            case M_SOS:
+                if (! get_sos(cinfo))
+                    return JPEG_SUSPENDED;
+                cinfo.unread_marker = 0;    /* processed the marker */
+                return JPEG_REACHED_SOS;
+
+            case M_EOI:
+//              TRACEMS(cinfo, 1, JTRC_EOI);
+                cinfo.unread_marker = 0;    /* processed the marker */
+                return JPEG_REACHED_EOI;
+
+            case M_DAC:
+                if (! get_dac(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_DHT:
+                if (! get_dht(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_DQT:
+                if (! get_dqt(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_DRI:
+                if (! get_dri(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_APP0:
+            case M_APP1:
+            case M_APP2:
+            case M_APP3:
+            case M_APP4:
+            case M_APP5:
+            case M_APP6:
+            case M_APP7:
+            case M_APP8:
+            case M_APP9:
+            case M_APP10:
+            case M_APP11:
+            case M_APP12:
+            case M_APP13:
+            case M_APP14:
+            case M_APP15:
+                if (! process_APPn(cinfo.unread_marker - M_APP0, cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_COM:
+                if (! process_COM(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            case M_RST0:        /* these are all parameterless */
+            case M_RST1:
+            case M_RST2:
+            case M_RST3:
+            case M_RST4:
+            case M_RST5:
+            case M_RST6:
+            case M_RST7:
+            case M_TEM:
+//              TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo.unread_marker);
+                break;
+
+            case M_DNL:         /* Ignore DNL ... perhaps the wrong thing */
+                if (! skip_variable(cinfo))
+                    return JPEG_SUSPENDED;
+                break;
+
+            default:            /* must be DHP, EXP, JPGn, or RESn */
+                /* For now, we treat the reserved markers as fatal errors since they are
+                 * likely to be used to signal incompatible JPEG Part 3 extensions.
+                 * Once the JPEG 3 version-number marker is well defined, this code
+                 * ought to change!
+                 */
+                error();
+ //             ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo.unread_marker);
+                break;
+        }
+        /* Successfully processed marker, so reset state variable */
+        cinfo.unread_marker = 0;
+    } /* end loop */
+}
+
+static long jdiv_round_up (long a, long b)
+/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
+/* Assumes a >= 0, b > 0 */
+{
+    return (a + b - 1) / b;
+}
+
+static void initial_setup (jpeg_decompress_struct cinfo)
+/* Called once, when first SOS marker is reached */
+{
+    int ci;
+    jpeg_component_info compptr;
+
+    /* Make sure image isn't bigger than I can handle */
+    if (cinfo.image_height >    JPEG_MAX_DIMENSION || cinfo.image_width > JPEG_MAX_DIMENSION)
+        error();
+//      ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+    /* For now, precision must match compiled-in value... */
+    if (cinfo.data_precision !is BITS_IN_JSAMPLE)
+        error(" [data precision=" ~ to!(String)(cinfo.data_precision) ~ "]");
+//      ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo.data_precision);
+
+    /* Check that number of components won't exceed internal array sizes */
+    if (cinfo.num_components > MAX_COMPONENTS)
+        error();
+//      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo.num_components, MAX_COMPONENTS);
+
+    /* Compute maximum sampling factors; check factor validity */
+    cinfo.max_h_samp_factor = 1;
+    cinfo.max_v_samp_factor = 1;
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        if (compptr.h_samp_factor<=0 || compptr.h_samp_factor>MAX_SAMP_FACTOR || compptr.v_samp_factor<=0 || compptr.v_samp_factor>MAX_SAMP_FACTOR)
+            error();
+//          ERREXIT(cinfo, JERR_BAD_SAMPLING);
+        cinfo.max_h_samp_factor = Math.max(cinfo.max_h_samp_factor, compptr.h_samp_factor);
+        cinfo.max_v_samp_factor = Math.max(cinfo.max_v_samp_factor, compptr.v_samp_factor);
+    }
+
+    /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
+     * In the full decompressor, this will be overridden by jdmaster.c;
+     * but in the transcoder, jdmaster.c is not used, so we must do it here.
+     */
+    cinfo.min_DCT_scaled_size = DCTSIZE;
+
+    /* Compute dimensions of components */
+    for (ci = 0; ci < cinfo.num_components; ci++) {
+        compptr = cinfo.comp_info[ci];
+        compptr.DCT_scaled_size = DCTSIZE;
+        /* Size in DCT blocks */
+        compptr.width_in_blocks = cast(int)jdiv_round_up(cast(long) cinfo.image_width * cast(long) compptr.h_samp_factor, (cinfo.max_h_samp_factor * DCTSIZE));
+        compptr.height_in_blocks = cast(int)jdiv_round_up(cast(long) cinfo.image_height * cast(long) compptr.v_samp_factor, (cinfo.max_v_samp_factor * DCTSIZE));
+        /* downsampled_width and downsampled_height will also be overridden by
+         * jdmaster.c if we are doing full decompression.   The transcoder library
+         * doesn't use these values, but the calling application might.
+         */
+        /* Size in samples */
+        compptr.downsampled_width = cast(int)jdiv_round_up(cast(long) cinfo.image_width * cast(long) compptr.h_samp_factor, cinfo.max_h_samp_factor);
+        compptr.downsampled_height = cast(int)jdiv_round_up(cast(long) cinfo.image_height * cast(long) compptr.v_samp_factor, cinfo.max_v_samp_factor);
+        /* Mark component needed, until color conversion says otherwise */
+        compptr.component_needed = true;
+        /* Mark no quantization table yet saved for component */
+        compptr.quant_table = null;
+    }
+
+    /* Compute number of fully interleaved MCU rows. */
+    cinfo.total_iMCU_rows = cast(int)jdiv_round_up( cinfo.image_height, (cinfo.max_v_samp_factor*DCTSIZE));
+
+    /* Decide whether file contains multiple scans */
+    if (cinfo.comps_in_scan < cinfo.num_components || cinfo.progressive_mode)
+        cinfo.inputctl.has_multiple_scans = true;
+    else
+        cinfo.inputctl.has_multiple_scans = false;
+}
+
+
+static void per_scan_setup (jpeg_decompress_struct cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo.comps_in_scan and cinfo.cur_comp_info[] were set from SOS marker */
+{
+    int ci, mcublks, tmp = 0;
+    jpeg_component_info compptr;
+
+    if (cinfo.comps_in_scan is 1) {
+
+        /* Noninterleaved (single-component) scan */
+        compptr = cinfo.cur_comp_info[0];
+
+        /* Overall image size in MCUs */
+        cinfo.MCUs_per_row = compptr.width_in_blocks;
+        cinfo.MCU_rows_in_scan = compptr.height_in_blocks;
+
+        /* For noninterleaved scan, always one block per MCU */
+        compptr.MCU_width = 1;
+        compptr.MCU_height = 1;
+        compptr.MCU_blocks = 1;
+        compptr.MCU_sample_width = compptr.DCT_scaled_size;
+        compptr.last_col_width = 1;
+        /* For noninterleaved scans, it is convenient to define last_row_height
+         * as the number of block rows present in the last iMCU row.
+         */
+        tmp = (compptr.height_in_blocks % compptr.v_samp_factor);
+        if (tmp is 0) tmp = compptr.v_samp_factor;
+        compptr.last_row_height = tmp;
+
+        /* Prepare array describing MCU composition */
+        cinfo.blocks_in_MCU = 1;
+        cinfo.MCU_membership[0] = 0;
+
+    } else {
+
+        /* Interleaved (multi-component) scan */
+        if (cinfo.comps_in_scan <= 0 || cinfo.comps_in_scan > MAX_COMPS_IN_SCAN)
+            error();
+//          ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo.comps_in_scan, MAX_COMPS_IN_SCAN);
+
+        /* Overall image size in MCUs */
+        cinfo.MCUs_per_row = cast(int)jdiv_round_up( cinfo.image_width, (cinfo.max_h_samp_factor*DCTSIZE));
+        cinfo.MCU_rows_in_scan = cast(int)jdiv_round_up( cinfo.image_height, (cinfo.max_v_samp_factor*DCTSIZE));
+
+        cinfo.blocks_in_MCU = 0;
+
+        for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+            compptr = cinfo.cur_comp_info[ci];
+            /* Sampling factors give # of blocks of component in each MCU */
+            compptr.MCU_width = compptr.h_samp_factor;
+            compptr.MCU_height = compptr.v_samp_factor;
+            compptr.MCU_blocks = compptr.MCU_width * compptr.MCU_height;
+            compptr.MCU_sample_width = compptr.MCU_width * compptr.DCT_scaled_size;
+            /* Figure number of non-dummy blocks in last MCU column & row */
+            tmp = (compptr.width_in_blocks % compptr.MCU_width);
+            if (tmp is 0) tmp = compptr.MCU_width;
+            compptr.last_col_width = tmp;
+            tmp = (compptr.height_in_blocks % compptr.MCU_height);
+            if (tmp is 0) tmp = compptr.MCU_height;
+            compptr.last_row_height = tmp;
+            /* Prepare array describing MCU composition */
+            mcublks = compptr.MCU_blocks;
+            if (cinfo.blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
+                error();
+//  ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+            while (mcublks-- > 0) {
+                cinfo.MCU_membership[cinfo.blocks_in_MCU++] = ci;
+            }
+        }
+
+    }
+}
+
+static void latch_quant_tables (jpeg_decompress_struct cinfo) {
+    int ci, qtblno;
+    jpeg_component_info compptr;
+    JQUANT_TBL qtbl;
+
+    for (ci = 0; ci < cinfo.comps_in_scan; ci++) {
+        compptr = cinfo.cur_comp_info[ci];
+        /* No work if we already saved Q-table for this component */
+        if (compptr.quant_table !is null)
+            continue;
+        /* Make sure specified quantization table is present */
+        qtblno = compptr.quant_tbl_no;
+        if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo.quant_tbl_ptrs[qtblno] is null)
+            error();
+//          ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+        /* OK, save away the quantization table */
+        qtbl = new JQUANT_TBL();
+        System.arraycopy(cinfo.quant_tbl_ptrs[qtblno].quantval, 0, qtbl.quantval, 0, qtbl.quantval.length);
+        qtbl.sent_table = cinfo.quant_tbl_ptrs[qtblno].sent_table;
+        compptr.quant_table = qtbl;
+    }
+}
+
+static void jpeg_make_d_derived_tbl (jpeg_decompress_struct cinfo, bool isDC, int tblno, d_derived_tbl dtbl) {
+    JHUFF_TBL htbl;
+    int p, i = 0, l, si, numsymbols;
+    int lookbits, ctr;
+    byte[] huffsize = new byte[257];
+    int[] huffcode = new int[257];
+    int code;
+
+    /* Note that huffsize[] and huffcode[] are filled in code-length order,
+     * paralleling the order of the symbols themselves in htbl.huffval[].
+     */
+
+    /* Find the input Huffman table */
+    if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+        error();
+//      ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+    htbl = isDC ? cinfo.dc_huff_tbl_ptrs[tblno] : cinfo.ac_huff_tbl_ptrs[tblno];
+    if (htbl is null)
+        error();
+//      ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+    /* Allocate a workspace if we haven't already done so. */
+    dtbl.pub = htbl;        /* fill in back link */
+
+    /* Figure C.1: make table of Huffman code length for each symbol */
+
+    p = 0;
+    for (l = 1; l <= 16; l++) {
+        i = htbl.bits[l] & 0xFF;
+        if (i < 0 || p + i > 256)   /* protect against table overrun */
+            error();
+//          ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+        while (i-- !is 0)
+            huffsize[p++] = cast(byte) l;
+    }
+    huffsize[p] = 0;
+    numsymbols = p;
+
+    /* Figure C.2: generate the codes themselves */
+    /* We also validate that the counts represent a legal Huffman code tree. */
+
+    code = 0;
+    si = huffsize[0];
+    p = 0;
+    while ( huffsize[p] !is 0) {
+        while (( huffsize[p]) is si) {
+            huffcode[p++] = code;
+            code++;
+        }
+        /* code is now 1 more than the last code used for codelength si; but
+         * it must still fit in si bits, since no code is allowed to be all ones.
+         */
+        if (( code) >= (( 1) << si))
+            error();
+//          ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+        code <<= 1;
+        si++;
+    }
+
+    /* Figure F.15: generate decoding tables for bit-sequential decoding */
+
+    p = 0;
+    for (l = 1; l <= 16; l++) {
+        if ((htbl.bits[l] & 0xFF) !is 0) {
+            /* valoffset[l] = huffval[] index of 1st symbol of code length l,
+             * minus the minimum code of length l
+             */
+            dtbl.valoffset[l] = p - huffcode[p];
+            p += (htbl.bits[l] & 0xFF);
+            dtbl.maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+        } else {
+            dtbl.maxcode[l] = -1;   /* -1 if no codes of this length */
+        }
+    }
+    dtbl.maxcode[17] = 0xFFFFF; /* ensures jpeg_huff_decode terminates */
+
+    /* Compute lookahead tables to speed up decoding.
+     * First we set all the table entries to 0, indicating "too long";
+     * then we iterate through the Huffman codes that are short enough and
+     * fill in all the entries that correspond to bit sequences starting
+     * with that code.
+     */
+
+    for (int j = 0; j < dtbl.look_nbits.length; j++) {
+        dtbl.look_nbits[j] = 0;
+    }
+
+    p = 0;
+    for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
+        for (i = 1; i <= (htbl.bits[l] & 0xFF); i++, p++) {
+            /* l = current code's length, p = its index in huffcode[] & huffval[]. */
+            /* Generate left-justified code followed by all possible bit sequences */
+            lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
+            for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+                dtbl.look_nbits[lookbits] = l;
+                dtbl.look_sym[lookbits] = htbl.huffval[p];
+                lookbits++;
+            }
+        }
+    }
+
+    /* Validate symbols as being reasonable.
+     * For AC tables, we make no check, but accept all byte values 0..255.
+     * For DC tables, we require the symbols to be in range 0..15.
+     * (Tighter bounds could be applied depending on the data depth and mode,
+     * but this is sufficient to ensure safe decoding.)
+     */
+    if (isDC) {
+        for (i = 0; i < numsymbols; i++) {
+            int sym = htbl.huffval[i] & 0xFF;
+            if (sym < 0 || sym > 15)
+                error();
+//              ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+        }
+    }
+}
+
+static void start_input_pass (jpeg_decompress_struct cinfo) {
+    per_scan_setup(cinfo);
+    latch_quant_tables(cinfo);
+    cinfo.entropy.start_pass(cinfo);
+    cinfo.coef.start_input_pass (cinfo);
+    cinfo.inputctl.consume_input = COEF_CONSUME_INPUT;
+}
+
+static void finish_input_pass (jpeg_decompress_struct cinfo) {
+    cinfo.inputctl.consume_input = INPUT_CONSUME_INPUT;
+}
+
+static int consume_markers (jpeg_decompress_struct cinfo) {
+    jpeg_input_controller inputctl = cinfo.inputctl;
+    int val;
+
+    if (inputctl.eoi_reached) /* After hitting EOI, read no further */
+        return JPEG_REACHED_EOI;
+
+    val = read_markers (cinfo);
+
+    switch (val) {
+    case JPEG_REACHED_SOS:  /* Found SOS */
+        if (inputctl.inheaders) {   /* 1st SOS */
+            initial_setup(cinfo);
+            inputctl.inheaders = false;
+            /* Note: start_input_pass must be called by jdmaster.c
+             * before any more input can be consumed.   jdapimin.c is
+             * responsible for enforcing this sequencing.
+             */
+        } else {            /* 2nd or later SOS marker */
+            if (! inputctl.has_multiple_scans)
+                error();
+//              ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+            start_input_pass(cinfo);
+        }
+        break;
+    case JPEG_REACHED_EOI:  /* Found EOI */
+        inputctl.eoi_reached = true;
+        if (inputctl.inheaders) {   /* Tables-only datastream, apparently */
+            if (cinfo.marker.saw_SOF)
+                error();
+//              ERREXIT(cinfo, JERR_SOF_NO_SOS);
+        } else {
+            /* Prevent infinite loop in coef ctlr's decompress_data routine
+             * if user set output_scan_number larger than number of scans.
+             */
+            if (cinfo.output_scan_number > cinfo.input_scan_number)
+                cinfo.output_scan_number = cinfo.input_scan_number;
+        }
+        break;
+    case JPEG_SUSPENDED:
+        break;
+    default:
+    }
+
+    return val;
+}
+
+static void default_decompress_parms (jpeg_decompress_struct cinfo) {
+    /* Guess the input colorspace, and set output colorspace accordingly. */
+    /* (Wish JPEG committee had provided a real way to specify this...) */
+    /* Note application may override our guesses. */
+    switch (cinfo.num_components) {
+        case 1:
+            cinfo.jpeg_color_space = JCS_GRAYSCALE;
+            cinfo.out_color_space = JCS_GRAYSCALE;
+            break;
+
+        case 3:
+            if (cinfo.saw_JFIF_marker) {
+                cinfo.jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
+            } else if (cinfo.saw_Adobe_marker) {
+                switch (cinfo.Adobe_transform) {
+                    case 0:
+                        cinfo.jpeg_color_space = JCS_RGB;
+                        break;
+                    case 1:
+                        cinfo.jpeg_color_space = JCS_YCbCr;
+                        break;
+                    default:
+//                      WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo.Adobe_transform);
+                        cinfo.jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+                    break;
+                }
+            } else {
+                /* Saw no special markers, try to guess from the component IDs */
+                int cid0 = cinfo.comp_info[0].component_id;
+                int cid1 = cinfo.comp_info[1].component_id;
+                int cid2 = cinfo.comp_info[2].component_id;
+
+                if (cid0 is 1 && cid1 is 2 && cid2 is 3)
+                    cinfo.jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+                else if (cid0 is 82 && cid1 is 71 && cid2 is 66)
+                    cinfo.jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+                else {
+//                  TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
+                    cinfo.jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+                }
+            }
+            /* Always guess RGB is proper output colorspace. */
+            cinfo.out_color_space = JCS_RGB;
+            break;
+
+        case 4:
+            if (cinfo.saw_Adobe_marker) {
+                switch (cinfo.Adobe_transform) {
+                    case 0:
+                        cinfo.jpeg_color_space = JCS_CMYK;
+                        break;
+                    case 2:
+                        cinfo.jpeg_color_space = JCS_YCCK;
+                        break;
+                    default:
+//                      WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo.Adobe_transform);
+                        cinfo.jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+                        break;
+                }
+            } else {
+                /* No special markers, assume straight CMYK. */
+                cinfo.jpeg_color_space = JCS_CMYK;
+            }
+            cinfo.out_color_space = JCS_CMYK;
+            break;
+
+        default:
+            cinfo.jpeg_color_space = JCS_UNKNOWN;
+            cinfo.out_color_space = JCS_UNKNOWN;
+            break;
+    }
+
+    /* Set defaults for other decompression parameters. */
+    cinfo.scale_num = 1;        /* 1:1 scaling */
+    cinfo.scale_denom = 1;
+    cinfo.output_gamma = 1.0;
+    cinfo.buffered_image = false;
+    cinfo.raw_data_out = false;
+    cinfo.dct_method = JDCT_DEFAULT;
+    cinfo.do_fancy_upsampling = true;
+    cinfo.do_block_smoothing = true;
+    cinfo.quantize_colors = false;
+    /* We set these in case application only sets quantize_colors. */
+    cinfo.dither_mode = JDITHER_FS;
+    cinfo.two_pass_quantize = true;
+    cinfo.desired_number_of_colors = 256;
+    cinfo.colormap = null;
+    /* Initialize for no mode change in buffered-image mode. */
+    cinfo.enable_1pass_quant = false;
+    cinfo.enable_external_quant = false;
+    cinfo.enable_2pass_quant = false;
+}
+
+static void init_source(jpeg_decompress_struct cinfo) {
+    cinfo.buffer = new byte[INPUT_BUFFER_SIZE];
+    cinfo.bytes_in_buffer = 0;
+    cinfo.bytes_offset = 0;
+    cinfo.start_of_file = true;
+}
+
+static int jpeg_consume_input (jpeg_decompress_struct cinfo) {
+    int retcode = JPEG_SUSPENDED;
+
+    /* NB: every possible DSTATE value should be listed in this switch */
+    switch (cinfo.global_state) {
+    case DSTATE_START:
+        /* Start-of-datastream actions: reset appropriate modules */
+        reset_input_controller(cinfo);
+        /* Initialize application's data source module */
+        init_source (cinfo);
+        cinfo.global_state = DSTATE_INHEADER;
+        /*FALLTHROUGH*/
+    case DSTATE_INHEADER:
+        retcode = consume_input(cinfo);
+        if (retcode is JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
+            /* Set up default parameters based on header data */
+            default_decompress_parms(cinfo);
+            /* Set global state: ready for start_decompress */
+            cinfo.global_state = DSTATE_READY;
+        }
+        break;
+    case DSTATE_READY:
+        /* Can't advance past first SOS until start_decompress is called */
+        retcode = JPEG_REACHED_SOS;
+        break;
+    case DSTATE_PRELOAD:
+    case DSTATE_PRESCAN:
+    case DSTATE_SCANNING:
+    case DSTATE_RAW_OK:
+    case DSTATE_BUFIMAGE:
+    case DSTATE_BUFPOST:
+    case DSTATE_STOPPING:
+        retcode = consume_input (cinfo);
+        break;
+    default:
+        error();
+//      ERREXIT1(cinfo, JERR_BAD_STATE, cinfo.global_state);
+    }
+    return retcode;
+}
+
+
+static void jpeg_abort (jpeg_decompress_struct cinfo) {
+//  int pool;
+//
+//  /* Releasing pools in reverse order might help avoid fragmentation
+//   * with some (brain-damaged) malloc libraries.
+//   */
+//  for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+//      (*cinfo.mem.free_pool) (cinfo, pool);
+//  }
+
+    /* Reset overall state for possible reuse of object */
+    if (cinfo.is_decompressor) {
+        cinfo.global_state = DSTATE_START;
+        /* Try to keep application from accessing now-deleted marker list.
+         * A bit kludgy to do it here, but this is the most central place.
+         */
+//      ((j_decompress_ptr) cinfo).marker_list = null;
+    } else {
+        cinfo.global_state = CSTATE_START;
+    }
+}
+
+
+static bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] buffer = new byte[2];
+        stream.read(buffer);
+        stream.unread(buffer);
+        return (buffer[0] & 0xFF) is 0xFF && (buffer[1] & 0xFF) is M_SOI;
+    } catch (Exception e) {
+        return false;
+    }
+}
+
+static ImageData[] loadFromByteStream(InputStream inputStream, ImageLoader loader) {
+    jpeg_decompress_struct cinfo = new jpeg_decompress_struct();
+    cinfo.inputStream = inputStream;
+    jpeg_create_decompress(cinfo);
+    jpeg_read_header(cinfo, true);
+    cinfo.buffered_image = cinfo.progressive_mode && loader.hasListeners();
+    jpeg_start_decompress(cinfo);
+    PaletteData palette = null;
+    switch (cinfo.out_color_space) {
+        case JCS_RGB:
+            palette = new PaletteData(0xFF, 0xFF00, 0xFF0000);
+            break;
+        case JCS_GRAYSCALE:
+            RGB[] colors = new RGB[256];
+            for (int i = 0; i < colors.length; i++) {
+                colors[i] = new RGB(i, i, i);
+            }
+            palette = new PaletteData(colors);
+            break;
+        default:
+            error();
+    }
+    int scanlinePad = 4;
+    int row_stride = (((cinfo.output_width * cinfo.out_color_components * 8 + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad;
+    byte[][] buffer = new byte[][]( 1, row_stride );
+    byte[] data = new byte[row_stride * cinfo.output_height];
+    ImageData imageData = ImageData.internal_new(
+            cinfo.output_width, cinfo.output_height, palette.isDirect ? 24 : 8, palette, scanlinePad, data,
+            0, null, null, -1, -1, SWT.IMAGE_JPEG, 0, 0, 0, 0);
+    if (cinfo.buffered_image) {
+        bool done;
+        do {
+            int incrementCount = cinfo.input_scan_number - 1;
+            jpeg_start_output(cinfo, cinfo.input_scan_number);
+            while (cinfo.output_scanline < cinfo.output_height) {
+                int offset = row_stride * cinfo.output_scanline;
+                jpeg_read_scanlines(cinfo, buffer, 1);
+                System.arraycopy(buffer[0], 0, data, offset, row_stride);
+            }
+            jpeg_finish_output(cinfo);
+            loader.notifyListeners(new ImageLoaderEvent(loader, cast(ImageData)imageData.clone(), incrementCount, done = jpeg_input_complete(cinfo)));
+        } while (!done);
+    } else {
+        while (cinfo.output_scanline < cinfo.output_height) {
+            int offset = row_stride * cinfo.output_scanline;
+            jpeg_read_scanlines(cinfo, buffer, 1);
+            System.arraycopy(buffer[0], 0, data, offset, row_stride);
+        }
+    }
+    jpeg_finish_decompress(cinfo);
+    jpeg_destroy_decompress(cinfo);
+    return [imageData];
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGEndOfImage.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGEndOfImage;
+
+import org.eclipse.swt.internal.image.JPEGFixedSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+final class JPEGEndOfImage : JPEGFixedSizeSegment {
+
+    public this() {
+        super();
+    }
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public override int signature() {
+        return JPEGFileFormat.EOI;
+    }
+
+    public override int fixedSize() {
+        return 2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1904 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved.  This source file is made available under the terms contained in the README file
+ * accompanying this program.  The README file should be located in the about_files directory of the
+ * plug-in that contains this source file.
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGFileFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.JPEGFrameHeader;
+import org.eclipse.swt.internal.image.JPEGScanHeader;
+import org.eclipse.swt.internal.image.JPEGHuffmanTable;
+import org.eclipse.swt.internal.image.JPEGAppn;
+import org.eclipse.swt.internal.image.JPEGSegment;
+import org.eclipse.swt.internal.image.FileFormat;
+import org.eclipse.swt.internal.image.JPEGComment;
+import org.eclipse.swt.internal.image.JPEGArithmeticConditioningTable;
+import org.eclipse.swt.internal.image.JPEGRestartInterval;
+import org.eclipse.swt.internal.image.JPEGQuantizationTable;
+import org.eclipse.swt.internal.image.JPEGStartOfImage;
+import org.eclipse.swt.internal.image.JPEGDecoder;
+import org.eclipse.swt.internal.image.JPEGEndOfImage;
+import java.lang.all;
+
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.PaletteData;
+
+import tango.core.Exception;
+
+final class JPEGFileFormat : FileFormat {
+    int restartInterval;
+    JPEGFrameHeader frameHeader;
+    int imageWidth, imageHeight;
+    int interleavedMcuCols, interleavedMcuRows;
+    int maxV, maxH;
+    bool progressive;
+    int samplePrecision;
+    int nComponents;
+    int[][] frameComponents;
+    int[] componentIds;
+    byte[][] imageComponents;
+    int[] dataUnit;
+    int[][][] dataUnits;
+    int[] precedingDCs;
+    JPEGScanHeader scanHeader;
+    byte[] dataBuffer;
+    int currentBitCount;
+    int bufferCurrentPosition;
+    int restartsToGo;
+    int nextRestartNumber;
+    JPEGHuffmanTable[] acHuffmanTables;
+    JPEGHuffmanTable[] dcHuffmanTables;
+    int[][] quantizationTables;
+    int currentByte;
+    int encoderQFactor = 75;
+    int eobrun = 0;
+    /* JPEGConstants */
+    public static const int DCTSIZE = 8;
+    public static const int DCTSIZESQR = 64;
+    /* JPEGFixedPointConstants */
+    public static const int FIX_0_899976223 = 7373;
+    public static const int FIX_1_961570560 = 16069;
+    public static const int FIX_2_053119869 = 16819;
+    public static const int FIX_0_298631336 = 2446;
+    public static const int FIX_1_847759065 = 15137;
+    public static const int FIX_1_175875602 = 9633;
+    public static const int FIX_3_072711026 = 25172;
+    public static const int FIX_0_765366865 = 6270;
+    public static const int FIX_2_562915447 = 20995;
+    public static const int FIX_0_541196100 = 4433;
+    public static const int FIX_0_390180644 = 3196;
+    public static const int FIX_1_501321110 = 12299;
+    /* JPEGMarkerCodes */
+    public static const int APP0  = 0xFFE0;
+    public static const int APP15 = 0xFFEF;
+    public static const int COM   = 0xFFFE;
+    public static const int DAC   = 0xFFCC;
+    public static const int DHP   = 0xFFDE;
+    public static const int DHT   = 0xFFC4;
+    public static const int DNL   = 0xFFDC;
+    public static const int DRI   = 0xFFDD;
+    public static const int DQT   = 0xFFDB;
+    public static const int EOI   = 0xFFD9;
+    public static const int EXP   = 0xFFDF;
+    public static const int JPG   = 0xFFC8;
+    public static const int JPG0  = 0xFFF0;
+    public static const int JPG13 = 0xFFFD;
+    public static const int RST0  = 0xFFD0;
+    public static const int RST1  = 0xFFD1;
+    public static const int RST2  = 0xFFD2;
+    public static const int RST3  = 0xFFD3;
+    public static const int RST4  = 0xFFD4;
+    public static const int RST5  = 0xFFD5;
+    public static const int RST6  = 0xFFD6;
+    public static const int RST7  = 0xFFD7;
+    public static const int SOF0  = 0xFFC0;
+    public static const int SOF1  = 0xFFC1;
+    public static const int SOF2  = 0xFFC2;
+    public static const int SOF3  = 0xFFC3;
+    public static const int SOF5  = 0xFFC5;
+    public static const int SOF6  = 0xFFC6;
+    public static const int SOF7  = 0xFFC7;
+    public static const int SOF9  = 0xFFC9;
+    public static const int SOF10 = 0xFFCA;
+    public static const int SOF11 = 0xFFCB;
+    public static const int SOF13 = 0xFFCD;
+    public static const int SOF14 = 0xFFCE;
+    public static const int SOF15 = 0xFFCF;
+    public static const int SOI   = 0xFFD8;
+    public static const int SOS   = 0xFFDA;
+    public static const int TEM   = 0xFF01;
+    /* JPEGFrameComponentParameterConstants */
+    public static const int TQI = 0;
+    public static const int HI  = 1;
+    public static const int VI  = 2;
+    public static const int CW  = 3;
+    public static const int CH  = 4;
+    /* JPEGScanComponentParameterConstants */
+    public static const int DC  = 0;
+    public static const int AC  = 1;
+    /* JFIF Component Constants */
+    public static const int ID_Y        = 1 - 1;
+    public static const int ID_CB   = 2 - 1;
+    public static const int ID_CR   = 3 - 1;
+    public static /*const*/ RGB[] RGB16;
+    public static const int[] ExtendTest = [
+        0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
+        4096, 8192, 16384, 32768, 65536, 131072, 262144
+    ];
+    public static const int[] ExtendOffset = [
+        0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047,
+        -4095, -8191, -16383, -32767, -65535, -131071, -262143
+    ];
+    public static const int[] ZigZag8x8 = [
+        0, 1, 8, 16, 9, 2, 3, 10,
+        17, 24, 32, 25, 18, 11, 4, 5,
+        12, 19, 26, 33, 40, 48, 41, 34,
+        27, 20, 13, 6, 7, 14, 21, 28,
+        35, 42, 49, 56, 57, 50, 43, 36,
+        29, 22, 15, 23, 30, 37, 44, 51,
+        58, 59, 52, 45, 38, 31, 39, 46,
+        53, 60, 61, 54, 47, 55, 62, 63
+    ];
+
+    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() {
+
+        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;
+        }
+        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;
+            }
+            nBitsTable[i] = nBits;
+        }
+        NBitsTable = nBitsTable;
+    }
+void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) {
+    int srcWidth = image.width;
+    int srcHeight = image.height;
+    int vhFactor = maxV * maxH;
+    int[] frameComponent;
+    imageComponents = new byte[][](nComponents);
+    for (int i = 0; i < nComponents; i++) {
+        frameComponent = frameComponents[componentIds[i]];
+        imageComponents[i] = new byte[frameComponent[CW] * frameComponent[CH]];
+    }
+    frameComponent = frameComponents[componentIds[ID_Y]];
+    for (int yPos = 0; yPos < srcHeight; yPos++) {
+        int srcOfs = yPos * srcWidth;
+        int dstOfs = yPos * frameComponent[CW];
+        System.arraycopy(dataYComp, srcOfs, imageComponents[ID_Y], dstOfs, srcWidth);
+    }
+    frameComponent = frameComponents[componentIds[ID_CB]];
+    for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
+        int destRowIndex = yPos * frameComponent[CW];
+        for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
+            int sum = 0;
+            for (int iv = 0; iv < maxV; iv++) {
+                int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
+                for (int ih = 0; ih < maxH; ih++) {
+                    sum += dataCbComp[srcIndex + ih] & 0xFF;
+                }
+            }
+            imageComponents[ID_CB][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
+        }
+    }
+    frameComponent = frameComponents[componentIds[ID_CR]];
+    for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
+        int destRowIndex = yPos * frameComponent[CW];
+        for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
+            int sum = 0;
+            for (int iv = 0; iv < maxV; iv++) {
+                int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
+                for (int ih = 0; ih < maxH; ih++) {
+                    sum += dataCrComp[srcIndex + ih] & 0xFF;
+                }
+            }
+            imageComponents[ID_CR][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
+        }
+    }
+    for (int iComp = 0; iComp < nComponents; iComp++) {
+        byte[] imageComponent = imageComponents[iComp];
+        frameComponent = frameComponents[componentIds[iComp]];
+        int hFactor = frameComponent[HI];
+        int vFactor = frameComponent[VI];
+        int componentWidth = frameComponent[CW];
+        int componentHeight = frameComponent[CH];
+        int compressedWidth = srcWidth / (maxH / hFactor);
+        int compressedHeight = srcHeight / (maxV / vFactor);
+        if (compressedWidth < componentWidth) {
+            int delta = componentWidth - compressedWidth;
+            for (int yPos = 0; yPos < compressedHeight; yPos++) {
+                int dstOfs = ((yPos + 1) * componentWidth - delta);
+                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 > 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);
+            }
+        }
+    }
+}
+void convert4BitRGBToYCbCr(ImageData image) {
+    RGB[] rgbs = image.getRGBs();
+    int paletteSize = rgbs.length;
+    byte[] yComp = new byte[paletteSize];
+    byte[] cbComp = new byte[paletteSize];
+    byte[] crComp = new byte[paletteSize];
+    int srcWidth = image.width;
+    int srcHeight = image.height;
+    for (int i = 0; i < paletteSize; i++) {
+        RGB color = rgbs[i];
+        int r = color.red;
+        int g = color.green;
+        int b = color.blue;
+        int n = RYTable[r] + GYTable[g] + BYTable[b];
+        yComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) yComp[i]--;
+        n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+        cbComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) cbComp[i]--;
+        n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+        crComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) crComp[i]--;
+    }
+    int bSize = srcWidth * srcHeight;
+    byte[] dataYComp = new byte[bSize];
+    byte[] dataCbComp = new byte[bSize];
+    byte[] dataCrComp = new byte[bSize];
+    byte[] origData = image.data;
+    int bytesPerLine = image.bytesPerLine;
+    int maxScanlineByte = srcWidth >> 1;
+    for (int yPos = 0; yPos < srcHeight; yPos++) {
+        for (int xPos = 0; xPos < maxScanlineByte; xPos++) {
+            int srcIndex = yPos * bytesPerLine + xPos;
+            int dstIndex = yPos * srcWidth + (xPos * 2);
+            int value2 = origData[srcIndex] & 0xFF;
+            int value1 = value2 >> 4;
+            value2 &= 0x0F;
+            dataYComp[dstIndex] = yComp[value1];
+            dataCbComp[dstIndex] = cbComp[value1];
+            dataCrComp[dstIndex] = crComp[value1];
+            dataYComp[dstIndex + 1] = yComp[value2];
+            dataCbComp[dstIndex + 1] = cbComp[value2];
+            dataCrComp[dstIndex + 1] = crComp[value2];
+        }
+    }
+    compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+void convert8BitRGBToYCbCr(ImageData image) {
+    RGB[] rgbs = image.getRGBs();
+    int paletteSize = rgbs.length;
+    byte[] yComp = new byte[paletteSize];
+    byte[] cbComp = new byte[paletteSize];
+    byte[] crComp = new byte[paletteSize];
+    int srcWidth = image.width;
+    int srcHeight = image.height;
+    for (int i = 0; i < paletteSize; i++) {
+        RGB color = rgbs[i];
+        int r = color.red;
+        int g = color.green;
+        int b = color.blue;
+        int n = RYTable[r] + GYTable[g] + BYTable[b];
+        yComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) yComp[i]--;
+        n = RCbTable[r] + GCbTable[g] + BCbTable[b];
+        cbComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) cbComp[i]--;
+        n = RCrTable[r] + GCrTable[g] + BCrTable[b];
+        crComp[i] = cast(byte)(n >> 16);
+        if ((n < 0) && ((n & 0xFFFF) !is 0)) crComp[i]--;
+    }
+    int dstWidth = image.width;
+    int dstHeight = srcHeight;
+    int stride = ((srcWidth + 3) >> 2) << 2;
+    int bSize = dstWidth * dstHeight;
+    byte[] dataYComp = new byte[bSize];
+    byte[] dataCbComp = new byte[bSize];
+    byte[] dataCrComp = new byte[bSize];
+    byte[] origData = image.data;
+    for (int yPos = 0; yPos < srcHeight; yPos++) {
+        int srcRowIndex = yPos * stride;
+        int dstRowIndex = yPos * dstWidth;
+        for (int xPos = 0; xPos < srcWidth; xPos++) {
+            int value = origData[srcRowIndex + xPos] & 0xFF;
+            int dstIndex = dstRowIndex + xPos;
+            dataYComp[dstIndex] = yComp[value];
+            dataCbComp[dstIndex] = cbComp[value];
+            dataCrComp[dstIndex] = crComp[value];
+        }
+    }
+    compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+byte[] convertCMYKToRGB() {
+    /* Unsupported CMYK format. Answer an empty byte array. */
+    return new byte[0];
+}
+void convertImageToYCbCr(ImageData image) {
+    switch (image.depth) {
+        case 4:
+            convert4BitRGBToYCbCr(image);
+            return;
+        case 8:
+            convert8BitRGBToYCbCr(image);
+            return;
+        case 16:
+        case 24:
+        case 32:
+            convertMultiRGBToYCbCr(image);
+            return;
+        default:
+            SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+    }
+    return;
+}
+void convertMultiRGBToYCbCr(ImageData image) {
+    int srcWidth = image.width;
+    int srcHeight = image.height;
+    int bSize = srcWidth * srcHeight;
+    byte[] dataYComp = new byte[bSize];
+    byte[] dataCbComp = new byte[bSize];
+    byte[] dataCrComp = new byte[bSize];
+    PaletteData palette = image.palette;
+    int[] buffer = new int[srcWidth];
+    if (palette.isDirect) {
+        int redMask = palette.redMask;
+        int greenMask = palette.greenMask;
+        int blueMask = palette.blueMask;
+        int redShift = palette.redShift;
+        int greenShift = palette.greenShift;
+        int blueShift = palette.blueShift;
+        for (int yPos = 0; yPos < srcHeight; yPos++) {
+            image.getPixels(0, yPos, srcWidth, buffer, 0);
+            int dstRowIndex = yPos * srcWidth;
+            for (int xPos = 0; xPos < srcWidth; xPos++) {
+                int pixel = buffer[xPos];
+                int dstDataIndex = dstRowIndex + xPos;
+                int r = pixel & redMask;
+                r = (redShift < 0) ? r >>> -redShift : r << redShift;
+                int g = pixel & greenMask;
+                g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
+                int b = pixel & blueMask;
+                b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
+                dataYComp[dstDataIndex] = cast(byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
+                dataCbComp[dstDataIndex] = cast(byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
+                dataCrComp[dstDataIndex] = cast(byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) >> 16);
+            }
+        }
+    } else {
+        for (int yPos = 0; yPos < srcHeight; yPos++) {
+            image.getPixels(0, yPos, srcWidth, buffer, 0);
+            int dstRowIndex = yPos * srcWidth;
+            for (int xPos = 0; xPos < srcWidth; xPos++) {
+                int pixel = buffer[xPos];
+                int dstDataIndex = dstRowIndex + xPos;
+                RGB rgb = palette.getRGB(pixel);
+                int r = rgb.red;
+                int g = rgb.green;
+                int b = rgb.blue;
+                dataYComp[dstDataIndex] = cast(byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
+                dataCbComp[dstDataIndex] = cast(byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
+                dataCrComp[dstDataIndex] = cast(byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) >> 16);
+            }
+        }
+    }
+    compress(image, dataYComp, dataCbComp, dataCrComp);
+}
+byte[] convertYToRGB() {
+    int compWidth = frameComponents[componentIds[ID_Y]][CW];
+    int bytesPerLine = (((imageWidth * 8 + 7) / 8) + 3) / 4 * 4;
+    byte[] data = new byte[bytesPerLine * imageHeight];
+    byte[] yComp = imageComponents[ID_Y];
+    int destIndex = 0;
+    for (int i = 0; i < imageHeight; i++) {
+        int srcIndex = i * compWidth;
+        for (int j = 0; j < bytesPerLine; j++) {
+            int y = yComp[srcIndex] & 0xFF;
+            if (y < 0) {
+                y = 0;
+            } else {
+                if (y > 255) y = 255;
+            }
+            if (j >= imageWidth) {
+                y = 0;
+            }
+            data[destIndex] = cast(byte)y;
+            srcIndex++;
+            destIndex++;
+        }
+    }
+    return data;
+}
+byte[] convertYCbCrToRGB() {
+    /**
+     * Convert existing image components into an RGB format.
+     * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+     * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+     * The conversion equations to be implemented are therefore
+     *  R = Y                + 1.40200 * Cr
+     *  G = Y - 0.34414 * Cb - 0.71414 * Cr
+     *  B = Y + 1.77200 * Cb
+     * where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
+     * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+     *
+     * To avoid floating-point arithmetic, we represent the fractional constants
+     * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+     * the products by 2^16, with appropriate rounding, to get the correct answer.
+     * Notice that Y, being an integral input, does not contribute any fraction
+     * so it need not participate in the rounding.
+     *
+     * For even more speed, we avoid doing any multiplications in the inner loop
+     * by precalculating the constants times Cb and Cr for all possible values.
+     * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+     * for 12-bit samples it is still acceptable.  It's not very reasonable for
+     * 16-bit samples, but if you want lossless storage you shouldn't be changing
+     * colorspace anyway.
+     * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+     * values for the G calculation are left scaled up, since we must add them
+     * together before rounding.
+     */
+    int bSize = imageWidth * imageHeight * nComponents;
+    byte[] rgbData = new byte[bSize];
+    int destIndex = 0;
+    expandImageComponents();
+    byte[] yComp = imageComponents[ID_Y];
+    byte[] cbComp = imageComponents[ID_CB];
+    byte[] crComp = imageComponents[ID_CR];
+    int compWidth = frameComponents[componentIds[ID_Y]][CW];
+    for (int v = 0; v < imageHeight; v++) {
+        int srcIndex = v * compWidth;
+        for (int i = 0; i < imageWidth; i++) {
+            int y = yComp[srcIndex] & 0xFF;
+            int cb = cbComp[srcIndex] & 0xFF;
+            int cr = crComp[srcIndex] & 0xFF;
+            int r = y + CrRTable[cr];
+            int g = y + ((CbGTable[cb] + CrGTable[cr]) >> 16);
+            int b = y + CbBTable[cb];
+            if (r < 0) {
+                r = 0;
+            } else {
+                if (r > 255) r = 255;
+            }
+            if (g < 0) {
+                g = 0;
+            } else {
+                if (g > 255) g = 255;
+            }
+            if (b < 0) {
+                b = 0;
+            } else {
+                if (b > 255) b = 255;
+            }
+            rgbData[destIndex] = cast(byte)b;
+            rgbData[destIndex + 1] = cast(byte)g;
+            rgbData[destIndex + 2] = cast(byte)r;
+            destIndex += 3;
+            srcIndex++;
+        }
+    }
+    return rgbData;
+}
+void decodeACCoefficients(int[] dataUnit, int iComp) {
+    int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
+    JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+    int k = 1;
+    while (k < 64) {
+        int rs = decodeUsingTable(acTable);
+        int r = rs >> 4;
+        int s = rs & 0xF;
+        if (s is 0) {
+            if (r is 15) {
+                k += 16;
+            } else {
+                break;
+            }
+        } else {
+            k += r;
+            int bits = receive(s);
+            dataUnit[ZigZag8x8[k]] = extendBy(bits, s);
+            k++;
+        }
+    }
+}
+void decodeACFirstCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
+    if (eobrun > 0) {
+        eobrun--;
+        return;
+    }
+    int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
+    JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+    int k = start;
+    while (k <= end) {
+        int rs = decodeUsingTable(acTable);
+        int r = rs >> 4;
+        int s = rs & 0xF;
+        if (s is 0) {
+            if (r is 15) {
+                k += 16;
+            } else {
+                eobrun = (1 << r) + receive(r) - 1;
+                break;
+            }
+        } else {
+            k += r;
+            int bits = receive(s);
+            dataUnit[ZigZag8x8[k]] = extendBy(bits, s) << approxBit;
+            k++;
+        }
+    }
+}
+void decodeACRefineCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
+    int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
+    JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+    int k = start;
+    while (k <= end) {
+        if (eobrun > 0) {
+            while (k <= end) {
+                int zzIndex = ZigZag8x8[k];
+                if (dataUnit[zzIndex] !is 0) {
+                    dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+                }
+                k++;
+            }
+            eobrun--;
+        } else {
+            int rs = decodeUsingTable(acTable);
+            int r = rs >> 4;
+            int s = rs & 0xF;
+            if (s is 0) {
+                if (r is 15) {
+                    int zeros = 0;
+                    while (zeros < 16 && k <= end) {
+                        int zzIndex = ZigZag8x8[k];
+                        if (dataUnit[zzIndex] !is 0) {
+                            dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+                        } else {
+                            zeros++;
+                        }
+                        k++;
+                    }
+                } else {
+                    eobrun = (1 << r) + receive(r);
+                }
+            } else {
+                int bit = receive(s);
+                int zeros = 0;
+                int zzIndex = ZigZag8x8[k];
+                while ((zeros < r || dataUnit[zzIndex] !is 0) && k <= end) {
+                    if (dataUnit[zzIndex] !is 0) {
+                        dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
+                    } else {
+                        zeros++;
+                    }
+                    k++;
+                    zzIndex = ZigZag8x8[k];
+                }
+                if (bit !is 0) {
+                    dataUnit[zzIndex] = 1 << approxBit;
+                } else {
+                    dataUnit[zzIndex] = -1 << approxBit;
+                }
+                k++;
+            }
+        }
+    }
+}
+int refineAC(int ac, int approxBit) {
+    if (ac > 0) {
+        int bit = nextBit();
+        if (bit !is 0) {
+            ac += 1 << approxBit;
+        }
+    } else if (ac < 0) {
+        int bit = nextBit();
+        if (bit !is 0) {
+            ac += -1 << approxBit;
+        }
+    }
+    return ac;
+}
+void decodeDCCoefficient(int[] dataUnit, int iComp, bool first, int approxBit) {
+    int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
+    JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
+    int lastDC = 0;
+    if (progressive && !first) {
+        int bit = nextBit();
+        lastDC = dataUnit[0] + (bit << approxBit);
+    } else {
+        lastDC = precedingDCs[iComp];
+        int nBits = decodeUsingTable(dcTable);
+        if (nBits !is 0) {
+            int bits = receive(nBits);
+            int diff = extendBy(bits, nBits);
+            lastDC += diff;
+            precedingDCs[iComp] = lastDC;
+        }
+        if (progressive) {
+            lastDC = lastDC << approxBit;
+        }
+    }
+    dataUnit[0] = lastDC;
+}
+void dequantize(int[] dataUnit, int iComp) {
+    int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
+    for (int i = 0; i < dataUnit.length; i++) {
+        int zzIndex = ZigZag8x8[i];
+        dataUnit[zzIndex] = dataUnit[zzIndex] * qTable[i];
+    }
+}
+byte[] decodeImageComponents() {
+    if (nComponents is 3) { // compIds 1, 2, 3
+        return convertYCbCrToRGB();
+    }
+//  if (nComponents is 3) { // compIds 1, 4, 5
+//      Unsupported CMYK format.
+//      return convertYIQToRGB();
+//  }
+    if (nComponents is 4) {
+        return convertCMYKToRGB();
+    }
+    return convertYToRGB();
+}
+void decodeMCUAtXAndY(int xmcu, int ymcu, int nComponentsInScan, bool first, int start, int end, int approxBit) {
+    for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
+        int scanComponent = iComp;
+        while (scanHeader.componentParameters[componentIds[scanComponent]] is null) {
+            scanComponent++;
+        }
+        int[] frameComponent = frameComponents[componentIds[scanComponent]];
+        int hi = frameComponent[HI];
+        int vi = frameComponent[VI];
+        if (nComponentsInScan is 1) {
+            hi = 1;
+            vi = 1;
+        }
+        int compWidth = frameComponent[CW];
+        for (int ivi = 0; ivi < vi; ivi++) {
+            for (int ihi = 0; ihi < hi; ihi++) {
+                if (progressive) {
+                    // Progressive: First scan - create a new data unit.
+                    // Subsequent scans - refine the existing data unit.
+                    int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
+                    dataUnit = dataUnits[scanComponent][index];
+                    if (dataUnit is null) {
+                        dataUnit = new int[64];
+                        dataUnits[scanComponent][index] = dataUnit;
+                    }
+                } else {
+                    // Sequential: Clear and reuse the data unit buffer.
+                    for (int i = 0; i < dataUnit.length; i++) {
+                        dataUnit[i] = 0;
+                    }
+                }
+                if (!progressive || scanHeader.isDCProgressiveScan()) {
+                    decodeDCCoefficient(dataUnit, scanComponent, first, approxBit);
+                }
+                if (!progressive) {
+                    decodeACCoefficients(dataUnit, scanComponent);
+                } else {
+                    if (scanHeader.isACProgressiveScan()) {
+                        if (first) {
+                            decodeACFirstCoefficients(dataUnit, scanComponent, start, end, approxBit);
+                        } else {
+                            decodeACRefineCoefficients(dataUnit, scanComponent, start, end, approxBit);
+                        }
+                    }
+                    if (loader.hasListeners()) {
+                        // Dequantization, IDCT, up-sampling and color conversion
+                        // are done on a copy of the coefficient data in order to
+                        // display the image incrementally.
+                        int[] temp = dataUnit;
+                        dataUnit = new int[64];
+                        System.arraycopy(temp, 0, dataUnit, 0, 64);
+                    }
+                }
+                if (!progressive || (progressive && loader.hasListeners())) {
+                    dequantize(dataUnit, scanComponent);
+                    inverseDCT(dataUnit);
+                    storeData(dataUnit, scanComponent, xmcu, ymcu, hi, ihi, vi, ivi);
+                }
+            }
+        }
+    }
+}
+void decodeScan() {
+    if (progressive && !scanHeader.verifyProgressiveScan()) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    int nComponentsInScan = scanHeader.getNumberOfImageComponents();
+    int mcuRowsInScan = interleavedMcuRows;
+    int mcusPerRow = interleavedMcuCols;
+    if (nComponentsInScan is 1) {
+        // Non-interleaved.
+        int scanComponent = 0;
+        while (scanHeader.componentParameters[componentIds[scanComponent]] is null) {
+            scanComponent++;
+        }
+        int[] frameComponent = frameComponents[componentIds[scanComponent]];
+        int hi = frameComponent[HI];
+        int vi = frameComponent[VI];
+        int mcuWidth = DCTSIZE * maxH / hi;
+        int mcuHeight = DCTSIZE * maxV / vi;
+        mcusPerRow = (imageWidth + mcuWidth - 1) / mcuWidth;
+        mcuRowsInScan = (imageHeight + mcuHeight - 1) / mcuHeight;
+    }
+    bool first = scanHeader.isFirstScan();
+    int start = scanHeader.getStartOfSpectralSelection();
+    int end = scanHeader.getEndOfSpectralSelection();
+    int approxBit = scanHeader.getApproxBitPositionLow();
+    restartsToGo = restartInterval;
+    nextRestartNumber = 0;
+    for (int ymcu = 0; ymcu < mcuRowsInScan; ymcu++) {
+        for (int xmcu = 0; xmcu < mcusPerRow; xmcu++) {
+            if (restartInterval !is 0) {
+                if (restartsToGo is 0) processRestartInterval();
+                restartsToGo--;
+            }
+            decodeMCUAtXAndY(xmcu, ymcu, nComponentsInScan, first, start, end, approxBit);
+        }
+    }
+}
+int decodeUsingTable(JPEGHuffmanTable huffmanTable) {
+    int i = 0;
+    int[] maxCodes = huffmanTable.getDhMaxCodes();
+    int[] minCodes = huffmanTable.getDhMinCodes();
+    int[] valPtrs = huffmanTable.getDhValPtrs();
+    int[] huffVals = huffmanTable.getDhValues();
+    int code = nextBit();
+    while (code > maxCodes[i]) {
+        code = code * 2 + nextBit();
+        i++;
+    }
+    int j = valPtrs[i] + code - minCodes[i];
+    return huffVals[j];
+}
+void emit(int huffCode, int nBits) {
+    if (nBits is 0) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    int[] power2m1 = [
+        1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
+        16383, 32767, 65535, 131125
+    ];
+    int code = (huffCode & power2m1[nBits - 1]) << (24 - nBits - currentBitCount);
+    byte[] codeBuffer = new byte[4];
+    codeBuffer[0] = cast(byte)(code & 0xFF);
+    codeBuffer[1] = cast(byte)((code >> 8) & 0xFF);
+    codeBuffer[2] = cast(byte)((code >> 16) & 0xFF);
+    codeBuffer[3] = cast(byte)((code >> 24) & 0xFF);
+    int abs = nBits - (8 - currentBitCount);
+    if (abs < 0) abs = -abs;
+    if ((abs >> 3) > 0) {
+        currentByte += codeBuffer[2];
+        emitByte(cast(byte)currentByte);
+        emitByte(codeBuffer[1]);
+        currentByte = codeBuffer[0];
+        currentBitCount += nBits - 16;
+    } else {
+        currentBitCount += nBits;
+        if (currentBitCount >= 8) {
+            currentByte += codeBuffer[2];
+            emitByte(cast(byte)currentByte);
+            currentByte = codeBuffer[1];
+            currentBitCount -= 8;
+        } else {
+            currentByte += codeBuffer[2];
+        }
+    }
+}
+void emitByte(byte byteValue) {
+    if (bufferCurrentPosition >= 512) {
+        resetOutputBuffer();
+    }
+    dataBuffer[bufferCurrentPosition] = byteValue;
+    bufferCurrentPosition++;
+    if (byteValue is -1) {
+        emitByte(cast(byte)0);
+    }
+}
+void encodeACCoefficients(int[] dataUnit, int iComp) {
+    int[] sParams = scanHeader.componentParameters[iComp];
+    JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
+    int[] ehCodes = acTable.ehCodes;
+    byte[] ehSizes = acTable.ehCodeLengths;
+    int r = 0;
+    int k = 1;
+    while (k < 64) {
+        k++;
+        int acValue = dataUnit[ZigZag8x8[k - 1]];
+        if (acValue is 0) {
+            if (k is 64) {
+                emit(ehCodes[0], ehSizes[0] & 0xFF);
+            } else {
+                r++;
+            }
+        } else {
+            while (r > 15) {
+                emit(ehCodes[0xF0], ehSizes[0xF0] & 0xFF);
+                r -= 16;
+            }
+            if (acValue < 0) {
+                int absACValue = acValue;
+                if (absACValue < 0) absACValue = -absACValue;
+                int nBits = NBitsTable[absACValue];
+                int rs = r * 16 + nBits;
+                emit(ehCodes[rs], ehSizes[rs] & 0xFF);
+                emit(0xFFFFFF - absACValue, nBits);
+            } else {
+                int nBits = NBitsTable[acValue];
+                int rs = r * 16 + nBits;
+                emit(ehCodes[rs], ehSizes[rs] & 0xFF);
+                emit(acValue, nBits);
+            }
+            r = 0;
+        }
+    }
+}
+void encodeDCCoefficients(int[] dataUnit, int iComp) {
+    int[] sParams = scanHeader.componentParameters[iComp];
+    JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
+    int lastDC = precedingDCs[iComp];
+    int dcValue = dataUnit[0];
+    int diff = dcValue - lastDC;
+    precedingDCs[iComp] = dcValue;
+    if (diff < 0) {
+        int absDiff = 0 - diff;
+        int nBits = NBitsTable[absDiff];
+        emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
+        emit(0xFFFFFF - absDiff, nBits);
+    } else {
+        int nBits = NBitsTable[diff];
+        emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
+        if (nBits !is 0) {
+            emit(diff, nBits);
+        }
+    }
+}
+void encodeMCUAtXAndY(int xmcu, int ymcu) {
+    int nComponentsInScan = scanHeader.getNumberOfImageComponents();
+    dataUnit = new int[64];
+    for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
+        int[] frameComponent = frameComponents[componentIds[iComp]];
+        int hi = frameComponent[HI];
+        int vi = frameComponent[VI];
+        for (int ivi = 0; ivi < vi; ivi++) {
+            for (int ihi = 0; ihi < hi; ihi++) {
+                extractData(dataUnit, iComp, xmcu, ymcu, ihi, ivi);
+                forwardDCT(dataUnit);
+                quantizeData(dataUnit, iComp);
+                encodeDCCoefficients(dataUnit, iComp);
+                encodeACCoefficients(dataUnit, iComp);
+            }
+        }
+    }
+}
+void encodeScan() {
+    for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
+        for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
+            encodeMCUAtXAndY(xmcu, ymcu);
+        }
+    }
+    if (currentBitCount !is 0) {
+        emitByte(cast(byte)currentByte);
+    }
+    resetOutputBuffer();
+}
+void expandImageComponents() {
+    for (int iComp = 0; iComp < nComponents; iComp++) {
+        int[] frameComponent = frameComponents[componentIds[iComp]];
+        int hi = frameComponent[HI];
+        int vi = frameComponent[VI];
+        int upH = maxH / hi;
+        int upV = maxV / vi;
+        if ((upH * upV) > 1) {
+            byte[] component = imageComponents[iComp];
+            int compWidth = frameComponent[CW];
+            int compHeight = frameComponent[CH];
+            int upCompWidth = compWidth * upH;
+            int upCompHeight = compHeight * upV;
+            ImageData src = new ImageData(compWidth, compHeight, 8, new PaletteData(RGB16), 4, component);
+            ImageData dest = src.scaledTo(upCompWidth, upCompHeight);
+            imageComponents[iComp] = dest.data;
+        }
+    }
+}
+int extendBy(int diff, int t) {
+    if (diff < ExtendTest[t]) {
+        return diff + ExtendOffset[t];
+    } else {
+        return diff;
+    }
+}
+void extractData(int[] dataUnit, int iComp, int xmcu, int ymcu, int ihi, int ivi) {
+    byte[] compImage = imageComponents[iComp];
+    int[] frameComponent = frameComponents[componentIds[iComp]];
+    int hi = frameComponent[HI];
+    int vi = frameComponent[VI];
+    int compWidth = frameComponent[CW];
+    int srcIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
+    int destIndex = 0;
+    for (int i = 0; i < DCTSIZE; i++) {
+        for (int col = 0; col < DCTSIZE; col++) {
+            dataUnit[destIndex] = (compImage[srcIndex + col] & 0xFF) - 128;
+            destIndex++;
+        }
+        srcIndex += compWidth;
+    }
+}
+void forwardDCT(int[] dataUnit) {
+    for (int row = 0; row < 8; row++) {
+        int rIndex = row * DCTSIZE;
+        int tmp0 = dataUnit[rIndex] + dataUnit[rIndex + 7];
+        int tmp7 = dataUnit[rIndex] - dataUnit[rIndex + 7];
+        int tmp1 = dataUnit[rIndex + 1] + dataUnit[rIndex + 6];
+        int tmp6 = dataUnit[rIndex + 1] - dataUnit[rIndex + 6];
+        int tmp2 = dataUnit[rIndex + 2] + dataUnit[rIndex + 5];
+        int tmp5 = dataUnit[rIndex + 2] - dataUnit[rIndex + 5];
+        int tmp3 = dataUnit[rIndex + 3] + dataUnit[rIndex + 4];
+        int tmp4 = dataUnit[rIndex + 3] - dataUnit[rIndex + 4];
+
+        /**
+         * Even part per LL&M figure 1 --- note that published figure
+         * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
+         */
+        int tmp10 = tmp0 + tmp3;
+        int tmp13 = tmp0 - tmp3;
+        int tmp11 = tmp1 + tmp2;
+        int tmp12 = tmp1 - tmp2;
+
+        dataUnit[rIndex] = (tmp10 + tmp11) * 4;
+        dataUnit[rIndex + 4]  = (tmp10 - tmp11) * 4;
+
+        int z1 = (tmp12 + tmp13) * FIX_0_541196100;
+        int n = z1 + (tmp13 * FIX_0_765366865) + 1024;
+        dataUnit[rIndex + 2] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 2]--;
+        n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 1024;
+        dataUnit[rIndex + 6] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 6]--;
+
+        /**
+         * Odd part per figure 8 --- note paper omits factor of sqrt(2).
+         * cK represents cos(K*pi/16).
+         * i0..i3 in the paper are tmp4..tmp7 here.
+         */
+        z1 = tmp4 + tmp7;
+        int z2 = tmp5 + tmp6;
+        int z3 = tmp4 + tmp6;
+        int z4 = tmp5 + tmp7;
+        int z5 = (z3 + z4) * FIX_1_175875602;   // sqrt(2) * c3
+
+        tmp4 *= FIX_0_298631336;    // sqrt(2) * (-c1+c3+c5-c7)
+        tmp5 *= FIX_2_053119869;    // sqrt(2) * ( c1+c3-c5+c7)
+        tmp6 *= FIX_3_072711026;    // sqrt(2) * ( c1+c3+c5-c7)
+        tmp7 *= FIX_1_501321110;    // sqrt(2) * ( c1+c3-c5-c7)
+        z1 *= 0 - FIX_0_899976223;  // sqrt(2) * (c7-c3)
+        z2 *= 0 - FIX_2_562915447;  // sqrt(2) * (-c1-c3)
+        z3 *= 0 - FIX_1_961570560;  // sqrt(2) * (-c3-c5)
+        z4 *= 0 - FIX_0_390180644;  // sqrt(2) * (c5-c3)
+
+        z3 += z5;
+        z4 += z5;
+
+        n = tmp4 + z1 + z3 + 1024;
+        dataUnit[rIndex + 7] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 7]--;
+        n = tmp5 + z2 + z4 + 1024;
+        dataUnit[rIndex + 5] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 5]--;
+        n = tmp6 + z2 + z3 + 1024;
+        dataUnit[rIndex + 3] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 3]--;
+        n = tmp7 + z1 + z4 + 1024;
+        dataUnit[rIndex + 1] = n >> 11;
+        if ((n < 0) && ((n & 0x07FF) !is 0)) dataUnit[rIndex + 1]--;
+    }
+
+    /**
+     * Pass 2: process columns.
+     * Note that we must descale the results by a factor of 8 is 2**3,
+     * and also undo the PASS1_BITS scaling.
+     */
+    for (int col = 0; col < 8; col++) {
+        int c0 = col;
+        int c1 = col + 8;
+        int c2 = col + 16;
+        int c3 = col + 24;
+        int c4 = col + 32;
+        int c5 = col + 40;
+        int c6 = col + 48;
+        int c7 = col + 56;
+        int tmp0 = dataUnit[c0] + dataUnit[c7];
+        int tmp7 = dataUnit[c0] - dataUnit[c7];
+        int tmp1 = dataUnit[c1] + dataUnit[c6];
+        int tmp6 = dataUnit[c1] - dataUnit[c6];
+        int tmp2 = dataUnit[c2] + dataUnit[c5];
+        int tmp5 = dataUnit[c2] - dataUnit[c5];
+        int tmp3 = dataUnit[c3] + dataUnit[c4];
+        int tmp4 = dataUnit[c3] - dataUnit[c4];
+
+        /**
+         * Even part per LL&M figure 1 --- note that published figure
+         * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
+         */
+        int tmp10 = tmp0 + tmp3;
+        int tmp13 = tmp0 - tmp3;
+        int tmp11 = tmp1 + tmp2;
+        int tmp12 = tmp1 - tmp2;
+
+        int n = tmp10 + tmp11 + 16;
+        dataUnit[c0] = n >> 5;
+        if ((n < 0) && ((n & 0x1F) !is 0)) dataUnit[c0]--;
+        n = tmp10 - tmp11 + 16;
+        dataUnit[c4] = n >> 5;
+        if ((n < 0) && ((n & 0x1F) !is 0)) dataUnit[c4]--;
+
+        int z1 = (tmp12 + tmp13) * FIX_0_541196100;
+        n = z1 + (tmp13 * FIX_0_765366865) + 131072;
+        dataUnit[c2] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c2]--;
+        n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 131072;
+        dataUnit[c6] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c6]--;
+
+        /**
+         * Odd part per figure 8 --- note paper omits factor of sqrt(2).
+         * cK represents cos(K*pi/16).
+         * i0..i3 in the paper are tmp4..tmp7 here.
+         */
+        z1 = tmp4 + tmp7;
+        int z2 = tmp5 + tmp6;
+        int z3 = tmp4 + tmp6;
+        int z4 = tmp5 + tmp7;
+        int z5 = (z3 + z4) * FIX_1_175875602;   // sqrt(2) * c3
+
+        tmp4 *= FIX_0_298631336;    // sqrt(2) * (-c1+c3+c5-c7)
+        tmp5 *= FIX_2_053119869;    // sqrt(2) * ( c1+c3-c5+c7)
+        tmp6 *= FIX_3_072711026;    // sqrt(2) * ( c1+c3+c5-c7)
+        tmp7 *= FIX_1_501321110;    // sqrt(2) * ( c1+c3-c5-c7)
+        z1 *= 0 - FIX_0_899976223;  // sqrt(2) * (c7-c3)
+        z2 *= 0 - FIX_2_562915447;  // sqrt(2) * (-c1-c3)
+        z3 *= 0 - FIX_1_961570560;  // sqrt(2) * (-c3-c5)
+        z4 *= 0 - FIX_0_390180644;  // sqrt(2) * (c5-c3)
+
+        z3 += z5;
+        z4 += z5;
+
+        n = tmp4 + z1 + z3 + 131072;
+        dataUnit[c7] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c7]--;
+        n = tmp5 + z2 + z4 + 131072;
+        dataUnit[c5] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c5]--;
+        n = tmp6 + z2 + z3 + 131072;
+        dataUnit[c3] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c3]--;
+        n = tmp7 + z1 + z4 + 131072;
+        dataUnit[c1] = n >> 18;
+        if ((n < 0) && ((n & 0x3FFFF) !is 0)) dataUnit[c1]--;
+    }
+}
+void getAPP0() {
+    JPEGAppn appn = new JPEGAppn(inputStream);
+    if (!appn.verify()) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+}
+void getCOM() {
+    new JPEGComment(inputStream);
+}
+void getDAC() {
+    new JPEGArithmeticConditioningTable(inputStream);
+}
+void getDHT() {
+    JPEGHuffmanTable dht = new JPEGHuffmanTable(inputStream);
+    if (!dht.verify()) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    if (acHuffmanTables is null) {
+        acHuffmanTables = new JPEGHuffmanTable[4];
+    }
+    if (dcHuffmanTables is null) {
+        dcHuffmanTables = new JPEGHuffmanTable[4];
+    }
+    JPEGHuffmanTable[] dhtTables = dht.getAllTables();
+    for (int i = 0; i < dhtTables.length; i++) {
+        JPEGHuffmanTable dhtTable = dhtTables[i];
+        if (dhtTable.getTableClass() is 0) {
+            dcHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
+        } else {
+            acHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
+        }
+    }
+}
+void getDNL() {
+    new JPEGRestartInterval(inputStream);
+}
+void getDQT() {
+    JPEGQuantizationTable dqt = new JPEGQuantizationTable(inputStream);
+    int[][] currentTables = quantizationTables;
+    if (currentTables is null) {
+        currentTables = new int[][](4);
+    }
+    int[] dqtTablesKeys = dqt.getQuantizationTablesKeys();
+    int[][] dqtTablesValues = dqt.getQuantizationTablesValues();
+    for (int i = 0; i < dqtTablesKeys.length; i++) {
+        int index = dqtTablesKeys[i];
+        currentTables[index] = dqtTablesValues[i];
+    }
+    quantizationTables = currentTables;
+}
+void getDRI() {
+    JPEGRestartInterval dri = new JPEGRestartInterval(inputStream);
+    if (!dri.verify()) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    restartInterval = dri.getRestartInterval();
+}
+void inverseDCT(int[] dataUnit) {
+    for (int row = 0; row < 8; row++) {
+        int rIndex = row * DCTSIZE;
+        /**
+         * Due to quantization, we will usually find that many of the input
+         * coefficients are zero, especially the AC terms.  We can exploit this
+         * by short-circuiting the IDCT calculation for any row in which all
+         * the AC terms are zero.  In that case each output is equal to the
+         * DC coefficient (with scale factor as needed).
+         * With typical images and quantization tables, half or more of the
+         * row DCT calculations can be simplified this way.
+         */
+        if (isZeroInRow(dataUnit, rIndex)) {
+            int dcVal = dataUnit[rIndex] << 2;
+            for (int i = rIndex + 7; i >= rIndex; i--) {
+                dataUnit[i] = dcVal;
+            }
+        } else {
+            /**
+             * Even part: reverse the even part of the forward DCT.
+             * The rotator is sqrt(2)*c(-6).
+             */
+            int z2 = dataUnit[rIndex + 2];
+            int z3 = dataUnit[rIndex + 6];
+            int z1 = (z2 + z3) * FIX_0_541196100;
+            int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
+            int tmp3 = z1 + (z2 * FIX_0_765366865);
+            int tmp0 = (dataUnit[rIndex] + dataUnit[rIndex + 4]) << 13;
+            int tmp1 = (dataUnit[rIndex] - dataUnit[rIndex + 4]) << 13;
+            int tmp10 = tmp0 + tmp3;
+            int tmp13 = tmp0 - tmp3;
+            int tmp11 = tmp1 + tmp2;
+            int tmp12 = tmp1 - tmp2;
+            /**
+             * Odd part per figure 8; the matrix is unitary and hence its
+             * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+             */
+            tmp0 = dataUnit[rIndex + 7];
+            tmp1 = dataUnit[rIndex + 5];
+            tmp2 = dataUnit[rIndex + 3];
+            tmp3 = dataUnit[rIndex + 1];
+            z1 = tmp0 + tmp3;
+            z2 = tmp1 + tmp2;
+            z3 = tmp0 + tmp2;
+            int z4 = tmp1 + tmp3;
+            int z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
+
+            tmp0 *= FIX_0_298631336;        /* sqrt(2) * (-c1+c3+c5-c7) */
+            tmp1 *= FIX_2_053119869;        /* sqrt(2) * ( c1+c3-c5+c7) */
+            tmp2 *= FIX_3_072711026;        /* sqrt(2) * ( c1+c3+c5-c7) */
+            tmp3 *= FIX_1_501321110;        /* sqrt(2) * ( c1+c3-c5-c7) */
+            z1 *= 0 - FIX_0_899976223;  /* sqrt(2) * (c7-c3) */
+            z2 *= 0 - FIX_2_562915447;  /* sqrt(2) * (-c1-c3) */
+            z3 *= 0 - FIX_1_961570560;  /* sqrt(2) * (-c3-c5) */
+            z4 *= 0 - FIX_0_390180644;  /* sqrt(2) * (c5-c3) */
+
+            z3 += z5;
+            z4 += z5;
+            tmp0 += z1 + z3;
+            tmp1 += z2 + z4;
+            tmp2 += z2 + z3;
+            tmp3 += z1 + z4;
+
+            dataUnit[rIndex] = (tmp10 + tmp3 + 1024) >> 11;
+            dataUnit[rIndex + 7] = (tmp10 - tmp3 + 1024) >> 11;
+            dataUnit[rIndex + 1] = (tmp11 + tmp2 + 1024) >> 11;
+            dataUnit[rIndex + 6] = (tmp11 - tmp2 + 1024) >> 11;
+            dataUnit[rIndex + 2] = (tmp12 + tmp1 + 1024) >> 11;
+            dataUnit[rIndex + 5] = (tmp12 - tmp1 + 1024) >> 11;
+            dataUnit[rIndex + 3] = (tmp13 + tmp0 + 1024) >> 11;
+            dataUnit[rIndex + 4] = (tmp13 - tmp0 + 1024) >> 11;
+         }
+    }
+    /**
+     * Pass 2: process columns.
+     * Note that we must descale the results by a factor of 8 is 2**3,
+     * and also undo the PASS1_BITS scaling.
+     */
+    for (int col = 0; col < 8; col++) {
+        int c0 = col;
+        int c1 = col + 8;
+        int c2 = col + 16;
+        int c3 = col + 24;
+        int c4 = col + 32;
+        int c5 = col + 40;
+        int c6 = col + 48;
+        int c7 = col + 56;
+        if (isZeroInColumn(dataUnit, col)) {
+            int dcVal = (dataUnit[c0] + 16) >> 5;
+            dataUnit[c0] = dcVal;
+            dataUnit[c1] = dcVal;
+            dataUnit[c2] = dcVal;
+            dataUnit[c3] = dcVal;
+            dataUnit[c4] = dcVal;
+            dataUnit[c5] = dcVal;
+            dataUnit[c6] = dcVal;
+            dataUnit[c7] = dcVal;
+        } else {
+            /**
+             * Even part: reverse the even part of the forward DCT.
+             * The rotator is sqrt(2)*c(-6).
+             */
+            int z0 = dataUnit[c0];
+            int z2 = dataUnit[c2];
+            int z3 = dataUnit[c6];
+            int z4 = dataUnit[c4];
+            int z1 = (z2 + z3) * FIX_0_541196100;
+            int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
+            int tmp3 = z1 + (z2 * FIX_0_765366865);
+            int tmp0 = (z0 + z4) << 13;
+            int tmp1 = (z0 - z4) << 13;
+            int tmp10 = tmp0 + tmp3;
+            int tmp13 = tmp0 - tmp3;
+            int tmp11 = tmp1 + tmp2;
+            int tmp12 = tmp1 - tmp2;
+            /**
+             * Odd part per figure 8; the matrix is unitary and hence its
+             * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+             */
+            tmp0 = dataUnit[c7];
+            tmp1 = dataUnit[c5];
+            tmp2 = dataUnit[c3];
+            tmp3 = dataUnit[c1];
+            z1 = tmp0 + tmp3;
+            z2 = tmp1 + tmp2;
+            z3 = tmp0 + tmp2;
+            z4 = tmp1 + tmp3;
+            z0 = (z3 + z4) * FIX_1_175875602;   /* sqrt(2) * c3 */
+
+            tmp0 *= FIX_0_298631336;        /* sqrt(2) * (-c1+c3+c5-c7) */
+            tmp1 *= FIX_2_053119869;        /* sqrt(2) * ( c1+c3-c5+c7) */
+            tmp2 *= FIX_3_072711026;        /* sqrt(2) * ( c1+c3+c5-c7) */
+            tmp3 *= FIX_1_501321110;        /* sqrt(2) * ( c1+c3-c5-c7) */
+            z1 *= 0 - FIX_0_899976223;  /* sqrt(2) * (c7-c3) */
+            z2 *= 0 - FIX_2_562915447;  /* sqrt(2) * (-c1-c3) */
+            z3 *= 0 - FIX_1_961570560;  /* sqrt(2) * (-c3-c5) */
+            z4 *= 0 - FIX_0_390180644;  /* sqrt(2) * (c5-c3) */
+
+            z3 += z0;
+            z4 += z0;
+
+            tmp0 += z1 + z3;
+            tmp1 += z2 + z4;
+            tmp2 += z2 + z3;
+            tmp3 += z1 + z4;
+
+            /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+            dataUnit[c0] = (tmp10 + tmp3 + 131072) >> 18;
+            dataUnit[c7] = (tmp10 - tmp3 + 131072) >> 18;
+            dataUnit[c1] = (tmp11 + tmp2 + 131072) >> 18;
+            dataUnit[c6] = (tmp11 - tmp2 + 131072) >> 18;
+            dataUnit[c2] = (tmp12 + tmp1 + 131072) >> 18;
+            dataUnit[c5] = (tmp12 - tmp1 + 131072) >> 18;
+            dataUnit[c3] = (tmp13 + tmp0 + 131072) >> 18;
+            dataUnit[c4] = (tmp13 - tmp0 + 131072) >> 18;
+        }
+    }
+}
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        JPEGStartOfImage soi = new JPEGStartOfImage(stream);
+        stream.unread(soi.reference);
+        return soi.verify();  // we no longer check for appN
+    } catch (Exception e) {
+        return false;
+    }
+}
+bool isZeroInColumn(int[] dataUnit, int col) {
+    return dataUnit[col + 8] is 0 && dataUnit[col + 16] is 0
+            && dataUnit[col + 24] is 0 && dataUnit[col + 32] is 0
+            && dataUnit[col + 40] is 0 && dataUnit[col + 48] is 0
+            && dataUnit[col + 56] is 0;
+}
+bool isZeroInRow(int[] dataUnit, int rIndex) {
+    return dataUnit[rIndex + 1] is 0 && dataUnit[rIndex + 2] is 0
+            && dataUnit[rIndex + 3] is 0 && dataUnit[rIndex + 4] is 0
+            && dataUnit[rIndex + 5] is 0 && dataUnit[rIndex + 6] is 0
+            && dataUnit[rIndex + 7] is 0;
+}
+override ImageData[] loadFromByteStream() {
+    //TEMPORARY CODE
+    //PORTING_FIXME
+    if (/+System.getProperty("org.eclipse.swt.internal.image.JPEGFileFormat_3.2") is null+/ true ) {
+        return JPEGDecoder.loadFromByteStream(inputStream, loader);
+    }
+    JPEGStartOfImage soi = new JPEGStartOfImage(inputStream);
+    if (!soi.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    restartInterval = 0;
+
+    /* Process the tables preceding the frame header. */
+    processTables();
+
+    /* Start of Frame. */
+    frameHeader = new JPEGFrameHeader(inputStream);
+    if (!frameHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    imageWidth = frameHeader.getSamplesPerLine();
+    imageHeight = frameHeader.getNumberOfLines();
+    maxH = frameHeader.getMaxHFactor();
+    maxV = frameHeader.getMaxVFactor();
+    int mcuWidth = maxH * DCTSIZE;
+    int mcuHeight = maxV * DCTSIZE;
+    interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
+    interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
+    progressive = frameHeader.isProgressive();
+    samplePrecision = frameHeader.getSamplePrecision();
+    nComponents = frameHeader.getNumberOfImageComponents();
+    frameComponents = frameHeader.componentParameters;
+    componentIds = frameHeader.componentIdentifiers;
+    imageComponents = new byte[][](nComponents);
+    if (progressive) {
+        // Progressive jpeg: need to keep all of the data units.
+        dataUnits = new int[][][](nComponents);
+    } else {
+        // Sequential jpeg: only need one data unit.
+        dataUnit = new int[8 * 8];
+    }
+    for (int i = 0; i < nComponents; i++) {
+        int[] frameComponent = frameComponents[componentIds[i]];
+        int bufferSize = frameComponent[CW] * frameComponent[CH];
+        imageComponents[i] = new byte[bufferSize];
+        if (progressive) {
+            dataUnits[i] = new int[][](bufferSize);
+        }
+    }
+
+    /* Process the tables preceding the scan header. */
+    processTables();
+
+    /* Start of Scan. */
+    scanHeader = new JPEGScanHeader(inputStream);
+    if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    /* Process scan(s) and further tables until EOI. */
+    int progressiveScanCount = 0;
+    bool done = false;
+    while(!done) {
+        resetInputBuffer();
+        precedingDCs = new int[4];
+        decodeScan();
+        if (progressive && loader.hasListeners()) {
+            ImageData imageData = createImageData();
+            loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, false));
+            progressiveScanCount++;
+        }
+
+        /* Unread any buffered data before looking for tables again. */
+        int delta = 512 - bufferCurrentPosition - 1;
+        if (delta > 0) {
+            byte[] unreadBuffer = new byte[delta];
+            System.arraycopy(dataBuffer, bufferCurrentPosition + 1, unreadBuffer, 0, delta);
+            try {
+                inputStream.unread(unreadBuffer);
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+        }
+
+        /* Process the tables preceding the next scan header. */
+        JPEGSegment jpegSegment = processTables();
+        if (jpegSegment is null || jpegSegment.getSegmentMarker() is EOI) {
+            done = true;
+        } else {
+            scanHeader = new JPEGScanHeader(inputStream);
+            if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+    }
+
+    if (progressive) {
+        for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
+            for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
+                for (int iComp = 0; iComp < nComponents; iComp++) {
+                    int[] frameComponent = frameComponents[componentIds[iComp]];
+                    int hi = frameComponent[HI];
+                    int vi = frameComponent[VI];
+                    int compWidth = frameComponent[CW];
+                    for (int ivi = 0; ivi < vi; ivi++) {
+                        for (int ihi = 0; ihi < hi; ihi++) {
+                            int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
+                            dataUnit = dataUnits[iComp][index];
+                            dequantize(dataUnit, iComp);
+                            inverseDCT(dataUnit);
+                            storeData(dataUnit, iComp, xmcu, ymcu, hi, ihi, vi, ivi);
+                        }
+                    }
+                }
+            }
+        }
+        dataUnits = null; // release memory
+    }
+    ImageData imageData = createImageData();
+    if (progressive && loader.hasListeners()) {
+        loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, true));
+    }
+    return [imageData];
+}
+ImageData createImageData() {
+    return ImageData.internal_new(
+        imageWidth,
+        imageHeight,
+        nComponents * samplePrecision,
+        setUpPalette(),
+        nComponents is 1 ? 4 : 1,
+        decodeImageComponents(),
+        0,
+        null,
+        null,
+        -1,
+        -1,
+        SWT.IMAGE_JPEG,
+        0,
+        0,
+        0,
+        0);
+}
+int nextBit() {
+    if (currentBitCount !is 0) {
+        currentBitCount--;
+        currentByte *= 2;
+        if (currentByte > 255) {
+            currentByte -= 256;
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+    bufferCurrentPosition++;
+    if (bufferCurrentPosition >= 512) {
+        resetInputBuffer();
+        bufferCurrentPosition = 0;
+    }
+    currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+    currentBitCount = 8;
+    byte nextByte;
+    if (bufferCurrentPosition is 511) {
+        resetInputBuffer();
+        currentBitCount = 8;
+        nextByte = dataBuffer[0];
+    } else {
+        nextByte = dataBuffer[bufferCurrentPosition + 1];
+    }
+    if (currentByte is 0xFF) {
+        if (nextByte is 0) {
+            bufferCurrentPosition ++;
+            currentBitCount--;
+            currentByte *= 2;
+            if (currentByte > 255) {
+                currentByte -= 256;
+                return 1;
+            } else {
+                return 0;
+            }
+        } else {
+            if ((nextByte & 0xFF) + 0xFF00 is DNL) {
+                getDNL();
+                return 0;
+            } else {
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+                return 0;
+            }
+        }
+    } else {
+        currentBitCount--;
+        currentByte *= 2;
+        if (currentByte > 255) {
+            currentByte -= 256;
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+}
+void processRestartInterval() {
+    do {
+        bufferCurrentPosition++;
+        if (bufferCurrentPosition > 511) {
+            resetInputBuffer();
+            bufferCurrentPosition = 0;
+        }
+        currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+    } while (currentByte !is 0xFF);
+    while (currentByte is 0xFF) {
+        bufferCurrentPosition++;
+        if (bufferCurrentPosition > 511) {
+            resetInputBuffer();
+            bufferCurrentPosition = 0;
+        }
+        currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+    }
+    if (currentByte !is ((RST0 + nextRestartNumber) & 0xFF)) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    bufferCurrentPosition++;
+    if (bufferCurrentPosition > 511) {
+        resetInputBuffer();
+        bufferCurrentPosition = 0;
+    }
+    currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
+    currentBitCount = 8;
+    restartsToGo = restartInterval;
+    nextRestartNumber = (nextRestartNumber + 1) & 0x7;
+    precedingDCs = new int[4];
+    eobrun = 0;
+}
+/* Process all markers until a frame header, scan header, or EOI is found. */
+JPEGSegment processTables() {
+    while (true) {
+        JPEGSegment jpegSegment = seekUnspecifiedMarker(inputStream);
+        if (jpegSegment is null) return null;
+        JPEGFrameHeader sof = new JPEGFrameHeader(jpegSegment.reference);
+        if (sof.verify()) {
+            return jpegSegment;
+        }
+        int marker = jpegSegment.getSegmentMarker();
+        switch (marker) {
+            case SOI: // there should only be one SOI per file
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            case EOI:
+            case SOS:
+                return jpegSegment;
+            case DQT:
+                getDQT();
+                break;
+            case DHT:
+                getDHT();
+                break;
+            case DAC:
+                getDAC();
+                break;
+            case DRI:
+                getDRI();
+                break;
+            case APP0:
+                getAPP0();
+                break;
+            case COM:
+                getCOM();
+                break;
+            default:
+                skipSegmentFrom(inputStream);
+
+        }
+    }
+}
+void quantizeData(int[] dataUnit, int iComp) {
+    int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
+    for (int i = 0; i < dataUnit.length; i++) {
+        int zzIndex = ZigZag8x8[i];
+        int data = dataUnit[zzIndex];
+        int absData = data < 0 ? 0 - data : data;
+        int qValue = qTable[i];
+        int q2 = qValue >> 1;
+        absData += q2;
+        if (absData < qValue) {
+            dataUnit[zzIndex] = 0;
+        } else {
+            absData /= qValue;
+            if (data >= 0) {
+                dataUnit[zzIndex] = absData;
+            } else {
+                dataUnit[zzIndex] = 0 - absData;
+            }
+        }
+    }
+}
+int receive(int nBits) {
+    int v = 0;
+    for (int i = 0; i < nBits; i++) {
+        v = v * 2 + nextBit();
+    }
+    return v;
+}
+void resetInputBuffer() {
+    if (dataBuffer is null) {
+        dataBuffer = new byte[512];
+    }
+    try {
+        inputStream.read(dataBuffer);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    currentBitCount = 0;
+    bufferCurrentPosition = -1;
+}
+void resetOutputBuffer() {
+    if (dataBuffer is null) {
+        dataBuffer = new byte[512];
+    } else {
+        try {
+            outputStream.write(dataBuffer, 0, bufferCurrentPosition);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+    bufferCurrentPosition = 0;
+}
+static JPEGSegment seekUnspecifiedMarker(LEDataInputStream byteStream) {
+    byte[] byteArray = new byte[2];
+    try {
+        while (true) {
+            if (byteStream.read(byteArray, 0, 1) !is 1) return null;
+            if (byteArray[0] is cast(byte) 0xFF) {
+                if (byteStream.read(byteArray, 1, 1) !is 1) return null;
+                if (byteArray[1] !is cast(byte) 0xFF && byteArray[1] !is 0) {
+                    byteStream.unread(byteArray);
+                    return new JPEGSegment(byteArray);
+                }
+            }
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return null;
+}
+PaletteData setUpPalette() {
+    if (nComponents is 1) {
+        RGB[] entries = new RGB[256];
+        for (int i = 0; i < 256; i++) {
+            entries[i] = new RGB(i, i, i);
+        }
+        return new PaletteData(entries);
+    }
+    return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+}
+static void skipSegmentFrom(LEDataInputStream byteStream) {
+    try {
+        byte[] byteArray = new byte[4];
+        JPEGSegment jpegSegment = new JPEGSegment(byteArray);
+
+        if (byteStream.read(byteArray) !is byteArray.length) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        if (!(byteArray[0] is -1 && byteArray[1] !is 0 && byteArray[1] !is -1)) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        int delta = jpegSegment.getSegmentLength() - 2;
+        byteStream.skip(delta);
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+void storeData(int[] dataUnit, int iComp, int xmcu, int ymcu, int hi, int ihi, int vi, int ivi) {
+    byte[] compImage = imageComponents[iComp];
+    int[] frameComponent = frameComponents[componentIds[iComp]];
+    int compWidth = frameComponent[CW];
+    int destIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
+    int srcIndex = 0;
+    for (int i = 0; i < DCTSIZE; i++) {
+        for (int col = 0; col < DCTSIZE; col++) {
+            int x = dataUnit[srcIndex] + 128;
+            if (x < 0) {
+                x = 0;
+            } else {
+                if (x > 255) x = 255;
+            }
+            compImage[destIndex + col] = cast(byte)x;
+            srcIndex++;
+        }
+        destIndex += compWidth;
+    }
+}
+override void unloadIntoByteStream(ImageLoader loader) {
+    ImageData image = loader.data[0];
+    if (!(new JPEGStartOfImage()).writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    JPEGAppn appn = new JPEGAppn([cast(byte)0xFF, cast(byte)0xE0, 0, 0x10, 0x4A, 0x46, 0x49, 0x46, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]);
+    if (!appn.writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    quantizationTables = new int[][](4);
+    JPEGQuantizationTable chromDQT = JPEGQuantizationTable.defaultChrominanceTable();
+    chromDQT.scaleBy(encoderQFactor);
+    int[] jpegDQTKeys = chromDQT.getQuantizationTablesKeys();
+    int[][] jpegDQTValues = chromDQT.getQuantizationTablesValues();
+    for (int i = 0; i < jpegDQTKeys.length; i++) {
+        quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
+    }
+    JPEGQuantizationTable lumDQT = JPEGQuantizationTable.defaultLuminanceTable();
+    lumDQT.scaleBy(encoderQFactor);
+    jpegDQTKeys = lumDQT.getQuantizationTablesKeys();
+    jpegDQTValues = lumDQT.getQuantizationTablesValues();
+    for (int i = 0; i < jpegDQTKeys.length; i++) {
+        quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
+    }
+    if (!lumDQT.writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    if (!chromDQT.writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    int frameLength, scanLength, precision;
+    int[][] frameParams, scanParams;
+    if (image.depth is 1) {
+        frameLength = 11;
+        frameParams = new int[][](1);
+        frameParams[0] = [1, 1, 1, 0, 0];
+        scanParams = new int[][](1);
+        scanParams[0] = [0, 0];
+        scanLength = 8;
+        nComponents = 1;
+        precision = 1;
+    } else {
+        frameLength = 17;
+        frameParams = new int[][](3);
+        frameParams[0] = [0, 2, 2, 0, 0];
+        frameParams[1] = [1, 1, 1, 0, 0];
+        frameParams[2] = [1, 1, 1, 0, 0];
+        scanParams = new int[][](3);
+        scanParams[0] = [0, 0];
+        scanParams[1] = [1, 1];
+        scanParams[2] = [1, 1];
+        scanLength = 12;
+        nComponents = 3;
+        precision = 8;
+    }
+    imageWidth = image.width;
+    imageHeight = image.height;
+    frameHeader = new JPEGFrameHeader(new byte[19]);
+    frameHeader.setSegmentMarker(SOF0);
+    frameHeader.setSegmentLength(frameLength);
+    frameHeader.setSamplePrecision(precision);
+    frameHeader.setSamplesPerLine(imageWidth);
+    frameHeader.setNumberOfLines(imageHeight);
+    frameHeader.setNumberOfImageComponents(nComponents);
+    frameHeader.componentParameters = frameParams;
+    frameHeader.componentIdentifiers = [0, 1, 2];
+    frameHeader.initializeContents();
+    if (!frameHeader.writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    frameComponents = frameParams;
+    componentIds = frameHeader.componentIdentifiers;
+    maxH = frameHeader.getMaxHFactor();
+    maxV = frameHeader.getMaxVFactor();
+    int mcuWidth = maxH * DCTSIZE;
+    int mcuHeight = maxV * DCTSIZE;
+    interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
+    interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
+    acHuffmanTables = new JPEGHuffmanTable[4];
+    dcHuffmanTables = new JPEGHuffmanTable[4];
+    JPEGHuffmanTable[] dhtTables = [
+        JPEGHuffmanTable.getDefaultDCLuminanceTable(),
+        JPEGHuffmanTable.getDefaultDCChrominanceTable(),
+        JPEGHuffmanTable.getDefaultACLuminanceTable(),
+        JPEGHuffmanTable.getDefaultACChrominanceTable()
+    ];
+    for (int i = 0; i < dhtTables.length; i++) {
+        JPEGHuffmanTable dhtTable = dhtTables[i];
+        if (!dhtTable.writeToStream(outputStream)) {
+            SWT.error(SWT.ERROR_IO);
+        }
+        JPEGHuffmanTable[] allTables = dhtTable.getAllTables();
+        for (int j = 0; j < allTables.length; j++) {
+            JPEGHuffmanTable huffmanTable = allTables[j];
+            if (huffmanTable.getTableClass() is 0) {
+                dcHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
+            } else {
+                acHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
+            }
+        }
+    }
+    precedingDCs = new int[4];
+    scanHeader = new JPEGScanHeader(new byte[14]);
+    scanHeader.setSegmentMarker(SOS);
+    scanHeader.setSegmentLength(scanLength);
+    scanHeader.setNumberOfImageComponents(nComponents);
+    scanHeader.setStartOfSpectralSelection(0);
+    scanHeader.setEndOfSpectralSelection(63);
+    scanHeader.componentParameters = scanParams;
+    scanHeader.initializeContents();
+    if (!scanHeader.writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+    convertImageToYCbCr(image);
+    resetOutputBuffer();
+    currentByte = 0;
+    currentBitCount = 0;
+    encodeScan();
+    if (!(new JPEGEndOfImage()).writeToStream(outputStream)) {
+        SWT.error(SWT.ERROR_IO);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFixedSizeSegment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGFixedSizeSegment;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.JPEGSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+import tango.core.Exception;
+
+
+abstract class JPEGFixedSizeSegment : JPEGSegment {
+
+    public this() {
+        reference = new byte[fixedSize()];
+        setSegmentMarker(signature());
+    }
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        reference = new byte[fixedSize()];
+        try {
+            byteStream.read(reference);
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+
+    abstract public int fixedSize();
+
+    public override int getSegmentLength() {
+        return fixedSize() - 2;
+    }
+
+    public override void setSegmentLength(int length) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGFrameHeader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGFrameHeader;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import java.lang.all;
+
+final class JPEGFrameHeader : JPEGVariableSizeSegment {
+    int maxVFactor;
+    int maxHFactor;
+    public int[] componentIdentifiers;
+    public int[][] componentParameters;
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+        initializeComponentParameters();
+    }
+
+    public int getSamplePrecision() {
+        return reference[4] & 0xFF;
+    }
+
+    public int getNumberOfLines() {
+        return (reference[5] & 0xFF) << 8 | (reference[6] & 0xFF);
+    }
+
+    public int getSamplesPerLine() {
+        return (reference[7] & 0xFF) << 8 | (reference[8] & 0xFF);
+    }
+
+    public int getNumberOfImageComponents() {
+        return reference[9] & 0xFF;
+    }
+
+    public void setSamplePrecision(int precision) {
+        reference[4] = cast(byte)(precision & 0xFF);
+    }
+
+    public void setNumberOfLines(int anInteger) {
+        reference[5] = cast(byte)((anInteger & 0xFF00) >> 8);
+        reference[6] = cast(byte)(anInteger & 0xFF);
+    }
+
+    public void setSamplesPerLine(int samples) {
+        reference[7] = cast(byte)((samples & 0xFF00) >> 8);
+        reference[8] = cast(byte)(samples & 0xFF);
+    }
+
+    public void setNumberOfImageComponents(int anInteger) {
+        reference[9] = cast(byte)(anInteger & 0xFF);
+    }
+
+    public int getMaxHFactor() {
+        return maxHFactor;
+    }
+
+    public int getMaxVFactor() {
+        return maxVFactor;
+    }
+
+    public void setMaxHFactor(int anInteger) {
+        maxHFactor = anInteger;
+    }
+
+    public void setMaxVFactor(int anInteger) {
+        maxVFactor = anInteger;
+    }
+
+    /* Used when decoding. */
+    void initializeComponentParameters() {
+        int nf = getNumberOfImageComponents();
+        componentIdentifiers = new int[nf];
+        int[][] compSpecParams;
+        int hmax = 1;
+        int vmax = 1;
+        for (int i = 0; i < nf; i++) {
+            int ofs = i * 3 + 10;
+            int ci = reference[ofs] & 0xFF;
+            componentIdentifiers[i] = ci;
+            int hi = (reference[ofs + 1] & 0xFF) >> 4;
+            int vi = reference[ofs + 1] & 0xF;
+            int tqi = reference[ofs + 2] & 0xFF;
+            if (hi > hmax) {
+                hmax = hi;
+            }
+            if (vi > vmax) {
+                vmax = vi;
+            }
+            int[] compParam = new int[5];
+            compParam[0] = tqi;
+            compParam[1] = hi;
+            compParam[2] = vi;
+            if (compSpecParams.length <= ci) {
+                int[][] newParams = new int[][](ci + 1);
+                System.arraycopy(compSpecParams, 0, newParams, 0, compSpecParams.length);
+                compSpecParams = newParams;
+            }
+            compSpecParams[ci] = compParam;
+        }
+        int x = getSamplesPerLine();
+        int y = getNumberOfLines();
+        int[] multiples = [ 8, 16, 24, 32 ];
+        for (int i = 0; i < nf; i++) {
+            int[] compParam = compSpecParams[componentIdentifiers[i]];
+            int hi = compParam[1];
+            int vi = compParam[2];
+            int compWidth = (x * hi + hmax - 1) / hmax;
+            int compHeight = (y * vi + vmax - 1) / vmax;
+            int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
+            int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
+            compParam[3] = dsWidth;
+            compParam[4] = dsHeight;
+        }
+        setMaxHFactor(hmax);
+        setMaxVFactor(vmax);
+        componentParameters = compSpecParams;
+    }
+
+    /* Used when encoding. */
+    public void initializeContents() {
+        int nf = getNumberOfImageComponents();
+        if (nf is 0 || nf !is componentParameters.length) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        int hmax = 0;
+        int vmax = 0;
+        int[][] compSpecParams = componentParameters;
+        for (int i = 0; i < nf; i++) {
+            int ofs = i * 3 + 10;
+            int[] compParam = compSpecParams[componentIdentifiers[i]];
+            int hi = compParam[1];
+            int vi = compParam[2];
+            if (hi * vi > 4) {
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            }
+            reference[ofs] = cast(byte)(i + 1);
+            reference[ofs + 1] = cast(byte)(hi * 16 + vi);
+            reference[ofs + 2] = cast(byte)(compParam[0]);
+            if (hi > hmax) hmax = hi;
+            if (vi > vmax) vmax = vi;
+        }
+        int x = getSamplesPerLine();
+        int y = getNumberOfLines();
+        int[] multiples = [8, 16, 24, 32];
+        for (int i = 0; i < nf; i++) {
+            int[] compParam = compSpecParams[componentIdentifiers[i]];
+            int hi = compParam[1];
+            int vi = compParam[2];
+            int compWidth = (x * hi + hmax - 1) / hmax;
+            int compHeight = (y * vi + vmax - 1) / vmax;
+            int dsWidth = roundUpToMultiple(compWidth, multiples[hi - 1]);
+            int dsHeight = roundUpToMultiple(compHeight, multiples[vi - 1]);
+            compParam[3] = dsWidth;
+            compParam[4] = dsHeight;
+        }
+        setMaxHFactor(hmax);
+        setMaxVFactor(vmax);
+    }
+
+    int roundUpToMultiple(int anInteger, int mInteger) {
+        int a = anInteger + mInteger - 1;
+        return a - (a % mInteger);
+    }
+
+    /*
+     * Verify the information contained in the receiver is correct.
+     * Answer true if the header contains a valid marker. Otherwise,
+     * answer false. Valid Start Of Frame markers are:
+     *  SOF_0  - Baseline DCT, Huffman coding
+     *  SOF_1  - Extended sequential DCT, Huffman coding
+     *  SOF_2  - Progressive DCT, Huffman coding
+     *  SOF_3  - Lossless (sequential), Huffman coding
+     *  SOF_5  - Differential sequential, Huffman coding
+     *  SOF_6  - Differential progressive, Huffman coding
+     *  SOF_7  - Differential lossless, Huffman coding
+     *  SOF_9  - Extended sequential DCT, arithmetic coding
+     *  SOF_10 - Progressive DCT, arithmetic coding
+     *  SOF_11 - Lossless (sequential), arithmetic coding
+     *  SOF_13 - Differential sequential, arithmetic coding
+     *  SOF_14 - Differential progressive, arithmetic coding
+     *  SOF_15 - Differential lossless, arithmetic coding
+     */
+    public override bool verify() {
+        int marker = getSegmentMarker();
+        return (marker >= JPEGFileFormat.SOF0 && marker <= JPEGFileFormat.SOF3) ||
+            (marker >= JPEGFileFormat.SOF5 && marker <= JPEGFileFormat.SOF7) ||
+            (marker >= JPEGFileFormat.SOF9 && marker <= JPEGFileFormat.SOF11) ||
+            (marker >= JPEGFileFormat.SOF13 && marker <= JPEGFileFormat.SOF15);
+    }
+
+    public bool isProgressive() {
+        int marker = getSegmentMarker();
+        return marker is JPEGFileFormat.SOF2
+            || marker is JPEGFileFormat.SOF6
+            || marker is JPEGFileFormat.SOF10
+            || marker is JPEGFileFormat.SOF14;
+    }
+
+    public bool isArithmeticCoding() {
+        return getSegmentMarker() >= JPEGFileFormat.SOF9;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGHuffmanTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGHuffmanTable;
+
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+
+import java.lang.System;
+/**
+ * JPEGHuffmanTable class actually represents two types of object:
+ * 1) A DHT (Define Huffman Tables) segment, which may represent
+ *  as many as 4 Huffman tables. In this case, the tables are
+ *  stored in the allTables array.
+ * 2) A single Huffman table. In this case, the allTables array
+ *  will be null.
+ * The 'reference' field is stored in both types of object, but
+ * 'initialize' is only called if the object represents a DHT.
+ */
+final class JPEGHuffmanTable : JPEGVariableSizeSegment {
+    JPEGHuffmanTable[] allTables;
+    int tableClass;
+    int tableIdentifier;
+    int[] dhMaxCodes;
+    int[] dhMinCodes;
+    int[] dhValPtrs;
+    int[] dhValues;
+    int[] ehCodes;
+    byte[] ehCodeLengths;
+    static byte[] DCLuminanceTable = [
+        cast(byte)255, cast(byte)196, 0, 31, 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+    ];
+    static byte[] DCChrominanceTable = [
+        cast(byte)255, cast(byte)196, 0, 31, 1, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+    ];
+    static byte[] ACLuminanceTable = [
+        cast(byte)255, cast(byte)196, 0, cast(byte)181, 16, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125,
+        1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81, 97, 7, 34, 113, 20,
+        50, cast(byte)129, cast(byte)145, cast(byte)161, 8, 35, 66, cast(byte)177, cast(byte)193, 21, 82, cast(byte)209, cast(byte)240, 36, 51, 98,
+        114, cast(byte)130, 9, 10, 22, 23, 24, 25, 26, 37, 38, 39, 40, 41, 42, 52, 53,
+        54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87,
+        88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117, 118,
+        119, 120, 121, 122, cast(byte)131, cast(byte)132, cast(byte)133, cast(byte)134, cast(byte)135, cast(byte)136, cast(byte)137, cast(byte)138, cast(byte)146, cast(byte)147, cast(byte)148,
+        cast(byte)149, cast(byte)150, cast(byte)151, cast(byte)152, cast(byte)153, cast(byte)154, cast(byte)162, cast(byte)163, cast(byte)164, cast(byte)165, cast(byte)166, cast(byte)167, cast(byte)168, cast(byte)169, cast(byte)170,
+        cast(byte)178, cast(byte)179, cast(byte)180, cast(byte)181, cast(byte)182, cast(byte)183, cast(byte)184, cast(byte)185, cast(byte)186, cast(byte)194, cast(byte)195, cast(byte)196, cast(byte)197, cast(byte)198, cast(byte)199,
+        cast(byte)200, cast(byte)201, cast(byte)202, cast(byte)210, cast(byte)211, cast(byte)212, cast(byte)213, cast(byte)214, cast(byte)215, cast(byte)216, cast(byte)217, cast(byte)218, cast(byte)225, cast(byte)226, cast(byte)227,
+        cast(byte)228, cast(byte)229, cast(byte)230, cast(byte)231, cast(byte)232, cast(byte)233, cast(byte)234, cast(byte)241, cast(byte)242, cast(byte)243, cast(byte)244, cast(byte)245, cast(byte)246, cast(byte)247, cast(byte)248,
+        cast(byte)249, cast(byte)250
+    ];
+    static byte[] ACChrominanceTable = [
+        cast(byte)255, cast(byte)196, 0, cast(byte)181, 17, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0,
+        1, 2, 119, 0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97, 113, 19, 34,
+        50, cast(byte)129, 8, 20, 66, cast(byte)145, cast(byte)161, cast(byte)177, cast(byte)193, 9, 35,
+        51, 82, cast(byte)240, 21, 98, 114, cast(byte)209, 10, 22, 36, 52, cast(byte)225, 37,
+        cast(byte)241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 67,
+        68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102,
+        103, 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122, cast(byte)130,
+        cast(byte)131, cast(byte)132, cast(byte)133, cast(byte)134, cast(byte)135, cast(byte)136, cast(byte)137,
+        cast(byte)138, cast(byte)146, cast(byte)147, cast(byte)148, cast(byte)149, cast(byte)150, cast(byte)151,
+        cast(byte)152, cast(byte)153, cast(byte)154, cast(byte)162, cast(byte)163, cast(byte)164, cast(byte)165,
+        cast(byte)166, cast(byte)167, cast(byte)168, cast(byte)169, cast(byte)170, cast(byte)178, cast(byte)179,
+        cast(byte)180, cast(byte)181, cast(byte)182, cast(byte)183, cast(byte)184, cast(byte)185, cast(byte)186,
+        cast(byte)194, cast(byte)195, cast(byte)196, cast(byte)197, cast(byte)198, cast(byte)199, cast(byte)200,
+        cast(byte)201, cast(byte)202, cast(byte)210, cast(byte)211, cast(byte)212, cast(byte)213, cast(byte)214,
+        cast(byte)215, cast(byte)216, cast(byte)217, cast(byte)218, cast(byte)226, cast(byte)227, cast(byte)228,
+        cast(byte)229, cast(byte)230, cast(byte)231, cast(byte)232, cast(byte)233, cast(byte)234, cast(byte)242,
+        cast(byte)243, cast(byte)244, cast(byte)245, cast(byte)246, cast(byte)247, cast(byte)248, cast(byte)249,
+        cast(byte)250
+    ];
+
+public this(byte[] reference) {
+    super(reference);
+}
+
+public this(LEDataInputStream byteStream) {
+    super(byteStream);
+    initialize();
+}
+
+public JPEGHuffmanTable[] getAllTables() {
+    return allTables;
+}
+
+public static JPEGHuffmanTable getDefaultACChrominanceTable() {
+    JPEGHuffmanTable result = new JPEGHuffmanTable(ACChrominanceTable);
+    result.initialize();
+    return result;
+}
+
+public static JPEGHuffmanTable getDefaultACLuminanceTable() {
+    JPEGHuffmanTable result = new JPEGHuffmanTable(ACLuminanceTable);
+    result.initialize();
+    return result;
+}
+
+public static JPEGHuffmanTable getDefaultDCChrominanceTable() {
+    JPEGHuffmanTable result = new JPEGHuffmanTable(DCChrominanceTable);
+    result.initialize();
+    return result;
+}
+
+public static JPEGHuffmanTable getDefaultDCLuminanceTable() {
+    JPEGHuffmanTable result = new JPEGHuffmanTable(DCLuminanceTable);
+    result.initialize();
+    return result;
+}
+
+public int[] getDhMaxCodes() {
+    return dhMaxCodes;
+}
+
+public int[] getDhMinCodes() {
+    return dhMinCodes;
+}
+
+public int[] getDhValPtrs() {
+    return dhValPtrs;
+}
+
+public int[] getDhValues() {
+    return dhValues;
+}
+
+public int getTableClass() {
+    return tableClass;
+}
+
+public int getTableIdentifier() {
+    return tableIdentifier;
+}
+
+void initialize() {
+    int totalLength = getSegmentLength() - 2;
+    int ofs = 4;
+    int[] bits = new int[16];
+    JPEGHuffmanTable[] huffTables = new JPEGHuffmanTable[8]; // maximum is 4 AC + 4 DC
+    int huffTableCount = 0;
+    while (totalLength > 0) {
+        int tc = (reference[ofs] & 0xFF) >> 4; // table class: AC (1) or DC (0)
+        int tid = reference[ofs] & 0xF; // table id: 0-1 baseline, 0-3 prog/ext
+        ofs++;
+
+        /* Read the 16 count bytes and add them together to get the table size. */
+        int count = 0;
+        for (int i = 0; i < bits.length; i++) {
+            int bCount = reference[ofs + i] & 0xFF;
+            bits[i] = bCount;
+            count += bCount;
+        }
+        ofs += 16;
+        totalLength -= 17;
+
+        /* Read the table. */
+        int[] huffVals = new int[count];
+        for (int i = 0; i < count; i++) {
+            huffVals[i] = reference[ofs + i] & 0xFF;
+        }
+        ofs += count;
+        totalLength -= count;
+
+        /* Calculate the lengths. */
+        int[] huffCodeLengths = new int[50]; // start with 50 and increment as needed
+        int huffCodeLengthsIndex = 0;
+        for (int i = 0; i < 16; i++) {
+            for (int j = 0; j < bits[i]; j++) {
+                if (huffCodeLengthsIndex >= huffCodeLengths.length) {
+                    int[] newHuffCodeLengths = new int[huffCodeLengths.length + 50];
+                    System.arraycopy(huffCodeLengths, 0, newHuffCodeLengths, 0, huffCodeLengths.length);
+                    huffCodeLengths = newHuffCodeLengths;
+                }
+                huffCodeLengths[huffCodeLengthsIndex] = i + 1;
+                huffCodeLengthsIndex++;
+            }
+        }
+
+        /* Truncate huffCodeLengths to the correct size. */
+        if (huffCodeLengthsIndex < huffCodeLengths.length) {
+            int[] newHuffCodeLengths = new int[huffCodeLengthsIndex];
+            System.arraycopy(huffCodeLengths, 0, newHuffCodeLengths, 0, huffCodeLengthsIndex);
+            huffCodeLengths = newHuffCodeLengths;
+        }
+
+        /* Calculate the Huffman codes. */
+        int[] huffCodes = new int[50]; // start with 50 and increment as needed
+        int huffCodesIndex = 0;
+        int k = 1;
+        int code = 0;
+        int si = huffCodeLengths[0];
+        int p = 0;
+        while (p < huffCodeLengthsIndex) {
+            while ((p < huffCodeLengthsIndex) && (huffCodeLengths[p] is si)) {
+                if (huffCodesIndex >= huffCodes.length) {
+                    int[] newHuffCodes = new int[huffCodes.length + 50];
+                    System.arraycopy(huffCodes, 0, newHuffCodes, 0, huffCodes.length);
+                    huffCodes = newHuffCodes;
+                }
+                huffCodes[huffCodesIndex] = code;
+                huffCodesIndex++;
+                code++;
+                p++;
+            }
+            code *= 2;
+            si++;
+        }
+
+        /* Truncate huffCodes to the correct size. */
+        if (huffCodesIndex < huffCodes.length) {
+            int[] newHuffCodes = new int[huffCodesIndex];
+            System.arraycopy(huffCodes, 0, newHuffCodes, 0, huffCodesIndex);
+            huffCodes = newHuffCodes;
+        }
+
+        /* Calculate the maximum and minimum codes */
+        k = 0;
+        int[] maxCodes = new int[16];
+        int[] minCodes = new int[16];
+        int[] valPtrs = new int[16];
+        for (int i = 0; i < 16; i++) {
+            int bSize = bits[i];
+            if (bSize is 0) {
+                maxCodes[i] = -1;
+            } else {
+                valPtrs[i] = k;
+                minCodes[i] = huffCodes[k];
+                k += bSize;
+                maxCodes[i] = huffCodes[k - 1];
+            }
+        }
+
+        /* Calculate the eHuffman codes and lengths. */
+        int[] eHuffCodes = new int[256];
+        byte[] eHuffSize = new byte[256];
+        for (int i = 0; i < huffCodesIndex; i++) {
+            eHuffCodes[huffVals[i]] = huffCodes[i];
+            eHuffSize[huffVals[i]] = cast(byte)huffCodeLengths[i];
+        }
+
+        /* Create the new JPEGHuffmanTable and add it to the allTables array. */
+        JPEGHuffmanTable dhtTable = new JPEGHuffmanTable(reference);
+        dhtTable.tableClass = tc;
+        dhtTable.tableIdentifier = tid;
+        dhtTable.dhValues = huffVals;
+        dhtTable.dhMinCodes = minCodes;
+        dhtTable.dhMaxCodes = maxCodes;
+        dhtTable.dhValPtrs = valPtrs;
+        dhtTable.ehCodes = eHuffCodes;
+        dhtTable.ehCodeLengths = eHuffSize;
+        huffTables[huffTableCount] = dhtTable;
+        huffTableCount++;
+    }
+    allTables = new JPEGHuffmanTable[huffTableCount];
+    System.arraycopy(huffTables, 0, allTables, 0, huffTableCount);
+}
+
+public override int signature() {
+    return JPEGFileFormat.DHT;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGQuantizationTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGQuantizationTable;
+
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+
+import java.lang.System;
+
+final class JPEGQuantizationTable : JPEGVariableSizeSegment {
+    public static byte[] DefaultLuminanceQTable = [
+        cast(byte)255, cast(byte)219, 0, 67, 0,
+        16, 11, 10, 16, 24, 40, 51, 61,
+        12, 12, 14, 19, 26, 58, 60, 55,
+        14, 13, 16, 24, 40, 57, 69, 56,
+        14, 17, 22, 29, 51, 87, 80, 62,
+        18, 22, 37, 56, 68, 109, 103, 77,
+        24, 35, 55, 64, 81, 104, 113, 92,
+        49, 64, 78, 87, 103, 121, 120, 101,
+        72, 92, 95, 98, 112, 100, 103, 99
+    ];
+    public static byte[] DefaultChrominanceQTable = [
+        cast(byte)255, cast(byte)219, 0, 67, 1,
+        17, 18, 24, 47, 99, 99, 99, 99,
+        18, 21, 26, 66, 99, 99, 99, 99,
+        24, 26, 56, 99, 99, 99, 99, 99,
+        47, 66, 99, 99, 99, 99, 99, 99,
+        99, 99, 99, 99, 99, 99, 99, 99,
+        99, 99, 99, 99, 99, 99, 99, 99,
+        99, 99, 99, 99, 99, 99, 99, 99,
+        99, 99, 99, 99, 99, 99, 99, 99
+    ];
+
+public this(byte[] reference) {
+    super(reference);
+}
+
+public this(LEDataInputStream byteStream) {
+    super(byteStream);
+}
+
+public static JPEGQuantizationTable defaultChrominanceTable() {
+    byte[] data = new byte[DefaultChrominanceQTable.length];
+    System.arraycopy(DefaultChrominanceQTable, 0, data, 0, data.length);
+    return new JPEGQuantizationTable(data);
+}
+
+public static JPEGQuantizationTable defaultLuminanceTable() {
+    byte[] data = new byte[DefaultLuminanceQTable.length];
+    System.arraycopy(DefaultLuminanceQTable, 0, data, 0, data.length);
+    return new JPEGQuantizationTable(data);
+}
+
+public int[] getQuantizationTablesKeys() {
+    int[] keys = new int[4];
+    int keysIndex = 0;
+    int totalLength = getSegmentLength() - 2;
+    int ofs = 4;
+    while (totalLength > 64) {
+        int tq = reference[ofs] & 0xF;
+        int pq = (reference[ofs] & 0xFF) >> 4;
+        if (pq is 0) {
+            ofs += 65;
+            totalLength -= 65;
+        } else {
+            ofs += 129;
+            totalLength -= 129;
+        }
+        if (keysIndex >= keys.length) {
+            int[] newKeys = new int[keys.length + 4];
+            System.arraycopy(keys, 0, newKeys, 0, keys.length);
+            keys = newKeys;
+        }
+        keys[keysIndex] = tq;
+        keysIndex++;
+    }
+    int[] newKeys = new int[keysIndex];
+    System.arraycopy(keys, 0, newKeys, 0, keysIndex);
+    return newKeys;
+}
+
+public int[][] getQuantizationTablesValues() {
+    int[][] values = new int[][](4);
+    int valuesIndex = 0;
+    int totalLength = getSegmentLength() - 2;
+    int ofs = 4;
+    while (totalLength > 64) {
+        int[] qk = new int[64];
+        int pq = (reference[ofs] & 0xFF) >> 4;
+        if (pq is 0) {
+            for (int i = 0; i < qk.length; i++) {
+                qk[i] = reference[ofs + i + 1] & 0xFF;
+            }
+            ofs += 65;
+            totalLength -= 65;
+        } else {
+            for (int i = 0; i < qk.length; i++) {
+                int idx = (i - 1) * 2 ;
+                qk[i] = (reference[ofs + idx + 1] & 0xFF) * 256 + (reference[ofs + idx + 2] & 0xFF);
+            }
+            ofs += 129;
+            totalLength -= 129;
+        }
+        if (valuesIndex >= values.length) {
+            int[][] newValues = new int[][](values.length + 4);
+            System.arraycopy(values, 0, newValues, 0, values.length);
+            values = newValues;
+        }
+        values[valuesIndex] = qk;
+        valuesIndex++;
+    }
+    int[][] newValues = new int[][](valuesIndex);
+    System.arraycopy(values, 0, newValues, 0, valuesIndex);
+    return newValues;
+}
+
+public void scaleBy(int qualityFactor) {
+    int qFactor = qualityFactor;
+    if (qFactor <= 0) {
+        qFactor = 1;
+    }
+    if (qFactor > 100) {
+        qFactor = 100;
+    }
+    if (qFactor < 50) {
+        qFactor = 5000 / qFactor;
+    } else {
+        qFactor = 200 - (qFactor * 2);
+    }
+    int totalLength = getSegmentLength() - 2;
+    int ofs = 4;
+    while (totalLength > 64) {
+//      int tq = reference[ofs] & 0xFF;
+        int pq = (reference[ofs] & 0xFF) >> 4;
+        if (pq is 0) {
+            for (int i = ofs + 1; i <= ofs + 64; i++) {
+                int temp = ((reference[i] & 0xFF) * qFactor + 50) / 100;
+                if (temp <= 0) temp = 1;
+                if (temp > 255) temp = 255;
+                reference[i] = cast(byte)temp;
+            }
+            ofs += 65;
+            totalLength -= 65;
+        } else {
+            for (int i = ofs + 1; i <= ofs + 128; i += 2) {
+                int temp = (((reference[i] & 0xFF) * 256 + (reference[i + 1] & 0xFF)) * qFactor + 50) / 100;
+                if (temp <= 0) temp = 1;
+                if (temp > 32767) temp = 32767;
+                reference[i] = cast(byte)(temp >> 8);
+                reference[i + 1] = cast(byte)(temp & 0xFF);
+            }
+            ofs += 129;
+            totalLength -= 129;
+        }
+    }
+}
+
+public override int signature() {
+    return JPEGFileFormat.DQT;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGRestartInterval.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGRestartInterval;
+
+import org.eclipse.swt.internal.image.JPEGFixedSizeSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+
+final class JPEGRestartInterval : JPEGFixedSizeSegment {
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+    }
+
+    public override int signature() {
+        return JPEGFileFormat.DRI;
+    }
+
+    public int getRestartInterval() {
+        return ((reference[4] & 0xFF) << 8 | (reference[5] & 0xFF));
+    }
+
+    public override int fixedSize() {
+        return 6;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGScanHeader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGScanHeader;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+import java.lang.all;
+
+final class JPEGScanHeader : JPEGVariableSizeSegment {
+    public int[][] componentParameters;
+
+public this(byte[] reference) {
+    super(reference);
+}
+
+public this(LEDataInputStream byteStream) {
+    super(byteStream);
+    initializeComponentParameters();
+}
+
+public int getApproxBitPositionHigh() {
+    return reference[(2 * getNumberOfImageComponents()) + 7] >> 4;
+}
+
+public int getApproxBitPositionLow() {
+    return reference[(2 * getNumberOfImageComponents()) + 7] & 0xF;
+}
+
+public int getEndOfSpectralSelection() {
+    return reference[(2 * getNumberOfImageComponents()) + 6];
+}
+
+public int getNumberOfImageComponents() {
+    return reference[4];
+}
+
+public int getStartOfSpectralSelection() {
+    return reference[(2 * getNumberOfImageComponents()) + 5];
+}
+
+/* Used when decoding. */
+void initializeComponentParameters() {
+    int compCount = getNumberOfImageComponents();
+    componentParameters = null;
+    for (int i = 0; i < compCount; i++) {
+        int ofs = 5 + i * 2;
+        int cid = reference[ofs] & 0xFF;
+        int dc = (reference[ofs + 1] & 0xFF) >> 4;
+        int ac = reference[ofs + 1] & 0xF;
+        if (componentParameters.length <= cid) {
+            int[][] newParams = new int[][](cid + 1);
+            System.arraycopy(componentParameters, 0, newParams, 0, componentParameters.length);
+            componentParameters = newParams;
+        }
+        componentParameters[cid] = [ dc, ac ];
+    }
+}
+
+/* Used when encoding. */
+public void initializeContents() {
+    int compCount = getNumberOfImageComponents();
+    int[][] compSpecParams = componentParameters;
+    if (compCount is 0 || compCount !is compSpecParams.length) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    for (int i = 0; i < compCount; i++) {
+        int ofs = i * 2 + 5;
+        int[] compParams = compSpecParams[i];
+        reference[ofs] = cast(byte)(i + 1);
+        reference[ofs + 1] = cast(byte)(compParams[0] * 16 + compParams[1]);
+    }
+}
+
+public void setEndOfSpectralSelection(int anInteger) {
+    reference[(2 * getNumberOfImageComponents()) + 6] = cast(byte)anInteger;
+}
+
+public void setNumberOfImageComponents(int anInteger) {
+    reference[4] = cast(byte)(anInteger & 0xFF);
+}
+
+public void setStartOfSpectralSelection(int anInteger) {
+    reference[(2 * getNumberOfImageComponents()) + 5] = cast(byte)anInteger;
+}
+
+public override int signature() {
+    return JPEGFileFormat.SOS;
+}
+
+public bool verifyProgressiveScan() {
+    int start = getStartOfSpectralSelection();
+    int end = getEndOfSpectralSelection();
+    int low = getApproxBitPositionLow();
+    int high = getApproxBitPositionHigh();
+    int count = getNumberOfImageComponents();
+    if ((start is 0 && end is 00) || (start <= end && end <= 63)) {
+        if (low <= 13 && high <= 13 && (high is 0 || high is low + 1)) {
+            return start is 0 || (start > 0 && count is 1);
+        }
+    }
+    return false;
+}
+
+public bool isACProgressiveScan() {
+    return getStartOfSpectralSelection() !is 0 && getEndOfSpectralSelection() !is 0;
+}
+
+public bool isDCProgressiveScan() {
+    return getStartOfSpectralSelection() is 0 && getEndOfSpectralSelection() is 0;
+}
+
+public bool isFirstScan() {
+    return getApproxBitPositionHigh() is 0;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGSegment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGSegment;
+
+import org.eclipse.swt.internal.image.LEDataOutputStream;
+
+import tango.core.Exception;
+
+class JPEGSegment {
+    public byte[] reference;
+
+    this() {
+    }
+
+    public this(byte[] reference) {
+        this.reference = reference;
+    }
+
+    public int signature() {
+        return 0;
+    }
+
+    public bool verify() {
+        return getSegmentMarker() is signature();
+    }
+
+    public int getSegmentMarker() {
+        return ((reference[0] & 0xFF) << 8 | (reference[1] & 0xFF));
+    }
+
+    public void setSegmentMarker(int marker) {
+        reference[0] = cast(byte)((marker & 0xFF00) >> 8);
+        reference[1] = cast(byte)(marker & 0xFF);
+    }
+
+    public int getSegmentLength() {
+        return ((reference[2] & 0xFF) << 8 | (reference[3] & 0xFF));
+    }
+
+    public void setSegmentLength(int length) {
+        reference[2] = cast(byte)((length & 0xFF00) >> 8);
+        reference[3] = cast(byte)(length & 0xFF);
+    }
+
+    public bool writeToStream(LEDataOutputStream byteStream) {
+        try {
+            byteStream.write(reference);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGStartOfImage.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGStartOfImage;
+
+import org.eclipse.swt.internal.image.JPEGFixedSizeSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.JPEGFileFormat;
+
+final class JPEGStartOfImage : JPEGFixedSizeSegment {
+
+    public this() {
+        super();
+    }
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        super(byteStream);
+    }
+
+    public override int signature() {
+        return JPEGFileFormat.SOI;
+    }
+
+    public override int fixedSize() {
+        return 2;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/JPEGVariableSizeSegment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.JPEGVariableSizeSegment;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.JPEGSegment;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+
+import tango.core.Exception;
+
+abstract class JPEGVariableSizeSegment : JPEGSegment {
+
+    public this(byte[] reference) {
+        super(reference);
+    }
+
+    public this(LEDataInputStream byteStream) {
+        try {
+            byte[] header = new byte[4];
+            byteStream.read(header);
+            reference = header; // to use getSegmentLength()
+            byte[] contents = new byte[getSegmentLength() + 2];
+            contents[0] = header[0];
+            contents[1] = header[1];
+            contents[2] = header[2];
+            contents[3] = header[3];
+            byteStream.read(contents, 4, contents.length - 4);
+            reference = contents;
+        } catch (Exception e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LEDataInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.LEDataInputStream;
+
+
+import java.io.InputStream;
+import java.lang.System;
+import tango.core.Exception;
+
+final class LEDataInputStream : InputStream{
+
+    alias InputStream.read read;
+
+    InputStream host;
+
+    int position;
+
+    /**
+     * The byte array containing the bytes to read.
+     */
+    protected byte[] buf;
+
+    /**
+     * The current position within the byte array <code>buf</code>. A value
+     * equal to buf.length indicates no bytes available.  A value of
+     * 0 indicates the buffer is full.
+     */
+    protected int pos;
+
+
+    public this(InputStream input) {
+        this(input, 512);
+    }
+
+    public this(InputStream input, int bufferSize) {
+        host = input;
+        if (bufferSize > 0) {
+            buf = new byte[bufferSize];
+            pos = bufferSize;
+        }
+        else throw new IllegalArgumentException("bufferSize must be greater zero" );
+    }
+
+    public void close() {
+        buf = null;
+        if (host !is null) {
+            host.close();
+            host = null;
+        }
+    }
+
+    /**
+     * Answer how many bytes were read.
+     */
+    public int getPosition() {
+        return position;
+    }
+
+    /**
+     * Answers how many bytes are available for reading without blocking
+     */
+    public override int available() {
+        if (buf is null) throw new IOException("buf is null");
+        return (buf.length - pos) + host.available();
+    }
+
+    /**
+     * Answer the next byte of the input stream.
+     */
+    public override int read() {
+        if (buf is null) throw new IOException("buf is null");
+        if (pos < buf.length) {
+            position++;
+            return (buf[pos++] & 0xFF);
+        }
+        int c = host.read();
+        if (c !is -1 ) position++;
+        return c;
+    }
+
+    /**
+     * Don't imitate the JDK behaviour of reading a random number
+     * of bytes when you can actually read them all.
+     */
+    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;
+        }
+        position += read;
+        if (read is 0 && read !is len) return -1;
+        return read;
+    }
+
+    /**
+     * Reads at most <code>length</code> bytes from this LEDataInputStream and
+     * stores them in byte array <code>buffer</code> starting at <code>offset</code>.
+     * <p>
+     * Answer the number of bytes actually read or -1 if no bytes were read and
+     * end of stream was encountered.  This implementation reads bytes from
+     * the pushback buffer first, then the target stream if more bytes are required
+     * to satisfy <code>count</code>.
+     * </p>
+     * @param buffer the byte array in which to store the read bytes.
+     * @param offset the offset in <code>buffer</code> to store the read bytes.
+     * @param length the maximum number of bytes to store in <code>buffer</code>.
+     *
+     * @return int the number of bytes actually read or -1 if end of stream.
+     *
+     * @exception java.io.IOException if an IOException occurs.
+     */
+    private int readData(byte[] buffer, int offset, int len) {
+        if (buf is null) throw new IOException("buf is null");
+        if (offset < 0 || offset > buffer.length ||
+            len < 0 || (len > buffer.length - offset)) {
+            throw new ArrayBoundsException(__FILE__,__LINE__);
+            }
+
+        int cacheCopied = 0;
+        int newOffset = offset;
+
+        // Are there pushback bytes available?
+        int available = buf.length - pos;
+        if (available > 0) {
+            cacheCopied = (available >= len) ? len : available;
+            System.arraycopy(buf, pos, buffer, newOffset, cacheCopied);
+            newOffset += cacheCopied;
+            pos += cacheCopied;
+        }
+
+        // Have we copied enough?
+        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;
+    }
+
+    /**
+     * Answer an integer comprised of the next
+     * four bytes of the input stream.
+     */
+    public int readInt() {
+        byte[4] buf = void;
+        read(buf);
+        return ((buf[3] & 0xFF) << 24) | 
+            ((buf[2] & 0xFF) << 16) | 
+            ((buf[1] & 0xFF) << 8) | 
+            (buf[0] & 0xFF);
+    }
+
+    /**
+     * Answer a short comprised of the next
+     * two bytes of the input stream.
+     */
+    public short readShort() {
+        byte[2] buf = void;
+        read(buf);
+        return cast(short)(((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF));
+    }
+
+    /**
+     * Push back the entire content of the given buffer <code>b</code>.
+     * <p>
+     * The bytes are pushed so that they would be read back b[0], b[1], etc.
+     * If the push back buffer cannot handle the bytes copied from <code>b</code>,
+     * an IOException will be thrown and no byte will be pushed back.
+     * </p>
+     *
+     * @param b the byte array containing bytes to push back into the stream
+     *
+     * @exception   java.io.IOException if the pushback buffer is too small
+     */
+    public void unread(byte[] b) {
+        int l = b.length;
+        if (l > pos) throw new IOException("cannot unread");
+        position -= l;
+        pos -= l;
+        System.arraycopy(b, 0, buf, pos, l);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LEDataOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.LEDataOutputStream;
+
+
+import java.io.OutputStream;
+
+final class LEDataOutputStream : OutputStream {
+
+    alias OutputStream.write write;
+
+    OutputStream ostr;
+
+public this(OutputStream output) {
+    this.ostr = output;
+}
+/**
+ * Write the specified number of bytes of the given byte array,
+ * starting at the specified offset, to the output stream.
+ */
+public override void write(byte b[], int off, int len) {
+    ostr.write(b, off, len);
+}
+/**
+ * Write the given byte to the output stream.
+ */
+public override void write(int b)  {
+    ostr.write(b);
+}
+/**
+ * Write the given byte to the output stream.
+ */
+public void writeByte(byte b) {
+    ostr.write(b);
+}
+/**
+ * Write the four bytes of the given integer
+ * to the output stream.
+ */
+public void writeInt(int theInt) {
+    ostr.write(theInt & 0xFF);
+    ostr.write((theInt >> 8) & 0xFF);
+    ostr.write((theInt >> 16) & 0xFF);
+    ostr.write((theInt >> 24) & 0xFF);
+}
+/**
+ * Write the two bytes of the given short
+ * to the output stream.
+ */
+public void writeShort(int theShort) {
+    ostr.write(theShort & 0xFF);
+    ostr.write((theShort >> 8) & 0xFF);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LZWCodec.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,487 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.LZWCodec;
+
+
+import org.eclipse.swt.internal.image.LZWNode;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.LEDataOutputStream;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.ImageLoaderEvent;
+import java.lang.all;
+
+import tango.core.Exception;
+
+final class LZWCodec {
+    int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft,
+        codeSize, clearCode, endCode, newCodes, topSlot, currentSlot,
+        imageWidth, imageHeight, imageX, imageY, pass, line, codeMask;
+    byte[] block, lineArray;
+    int[] stack, suffix, prefix;
+    LZWNode[] nodeStack;
+    LEDataInputStream inputStream;
+    LEDataOutputStream outputStream;
+    ImageData image;
+    ImageLoader loader;
+    bool interlaced;
+    static final int[] MASK_TABLE = [
+        0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F,
+        0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
+    ];
+
+/**
+ * Decode the input.
+ */
+void decode() {
+    int code;
+    int oc = 0;
+    int fc = 0;
+    byte[] buf = new byte[imageWidth];
+    int stackIndex = 0;
+    int bufIndex = 0;
+    int c;
+    while ((c = nextCode()) !is endCode) {
+        if (c is clearCode) {
+            codeSize = bitsPerPixel + 1;
+            codeMask = MASK_TABLE[bitsPerPixel];
+            currentSlot = newCodes;
+            topSlot = 1 << codeSize;
+            while ((c = nextCode()) is clearCode) {}
+            if (c !is endCode) {
+                oc = fc = c;
+                buf[bufIndex] = cast(byte)c;
+                bufIndex++;
+                if (bufIndex is imageWidth) {
+                    nextPutPixels(buf);
+                    bufIndex = 0;
+                }
+            }
+        } else {
+            code = c;
+            if (code >= currentSlot) {
+                code = oc;
+                stack[stackIndex] = fc;
+                stackIndex++;
+            }
+            while (code >= newCodes) {
+                stack[stackIndex] = suffix[code];
+                stackIndex++;
+                code = prefix[code];
+            }
+            stack[stackIndex] = code;
+            stackIndex++;
+            if (currentSlot < topSlot) {
+                fc = code;
+                suffix[currentSlot] = fc;
+                prefix[currentSlot] = oc;
+                currentSlot++;
+                oc = c;
+            }
+            if (currentSlot >= topSlot) {
+                if (codeSize < 12) {
+                    codeMask = MASK_TABLE[codeSize];
+                    codeSize++;
+                    topSlot = topSlot + topSlot;
+                }
+            }
+            while (stackIndex > 0) {
+                stackIndex--;
+                buf[bufIndex] = cast(byte)stack[stackIndex];
+                bufIndex++;
+                if (bufIndex is imageWidth) {
+                    nextPutPixels(buf);
+                    bufIndex = 0;
+                }
+            }
+        }
+    }
+    if (bufIndex !is 0 && line < imageHeight) {
+        nextPutPixels(buf);
+    }
+}
+/**
+ * Decode the LZW-encoded bytes in the given byte stream
+ * into the given DeviceIndependentImage.
+ */
+public void decode(LEDataInputStream inputStream, ImageLoader loader, ImageData image, bool interlaced, int depth) {
+    this.inputStream = inputStream;
+    this.loader = loader;
+    this.image = image;
+    this.interlaced = interlaced;
+    this.bitsPerPixel = depth;
+    initializeForDecoding();
+    decode();
+}
+/**
+ * Encode the image.
+ */
+void encode() {
+    nextPutCode(clearCode);
+    int lastPrefix = encodeLoop();
+    nextPutCode(lastPrefix);
+    nextPutCode(endCode);
+
+    // Write out last partial block
+    if (bitsLeft is 8) {
+        block[0] = cast(byte)(blockIndex - 1); // Nothing in last byte
+    } else {
+        block[0] = cast(byte)(blockIndex); // Last byte has data
+    }
+    writeBlock();
+
+    // Write out empty block to indicate the end (if needed)
+    if (block[0] !is 0) {
+        block[0] = 0;
+        writeBlock();
+    }
+}
+/**
+ * Encode the bytes into the given byte stream
+ * from the given DeviceIndependentImage.
+ */
+public void encode(LEDataOutputStream byteStream, ImageData image) {
+    this.outputStream = byteStream;
+    this.image = image;
+    initializeForEncoding();
+    encode();
+}
+/**
+ * Encoding loop broken out to allow early return.
+ */
+int encodeLoop() {
+    int pixel = nextPixel();
+    bool found;
+    LZWNode node;
+    while (true) {
+        int currentPrefix = pixel;
+        node = nodeStack[currentPrefix];
+        found = true;
+        pixel = nextPixel();
+        if (pixel < 0)
+            return currentPrefix;
+        while (found && (node.children !is null)) {
+            node = node.children;
+            while (found && (node.suffix !is pixel)) {
+                if (pixel < node.suffix) {
+                    if (node.left is null) {
+                        node.left = new LZWNode();
+                        found = false;
+                    }
+                    node = node.left;
+                } else {
+                    if (node.right is null) {
+                        node.right = new LZWNode();
+                        found = false;
+                    }
+                    node = node.right;
+                }
+            }
+            if (found) {
+                currentPrefix = node.code;
+                pixel = nextPixel();
+                if (pixel < 0)
+                    return currentPrefix;
+            }
+        }
+        if (found) {
+            node.children = new LZWNode();
+            node = node.children;
+        }
+        node.children = null;
+        node.left = null;
+        node.right = null;
+        node.code = currentSlot;
+        node.prefix = currentPrefix;
+        node.suffix = pixel;
+        nextPutCode(currentPrefix);
+        currentSlot++;
+        // Off by one?
+        if (currentSlot < 4096) {
+            if (currentSlot > topSlot) {
+                codeSize++;
+                codeMask = MASK_TABLE[codeSize - 1];
+                topSlot *= 2;
+            }
+        } else {
+            nextPutCode(clearCode);
+            for (int i = 0; i < nodeStack.length; i++)
+                nodeStack[i].children = null;
+            codeSize = bitsPerPixel + 1;
+            codeMask = MASK_TABLE[codeSize - 1];
+            currentSlot = newCodes;
+            topSlot = 1 << codeSize;
+        }
+    }
+}
+/**
+ * Initialize the receiver for decoding the given
+ * byte array.
+ */
+void initializeForDecoding() {
+    pass = 1;
+    line = 0;
+    codeSize = bitsPerPixel + 1;
+    topSlot = 1 << codeSize;
+    clearCode = 1 << bitsPerPixel;
+    endCode = clearCode + 1;
+    newCodes = currentSlot = endCode + 1;
+    currentByte = -1;
+    blockSize = bitsLeft = 0;
+    blockIndex = 0;
+    codeMask = MASK_TABLE[codeSize - 1];
+    stack = new int[4096];
+    suffix = new int[4096];
+    prefix = new int[4096];
+    block = new byte[256];
+    imageWidth = image.width;
+    imageHeight = image.height;
+}
+/**
+ * Initialize the receiver for encoding the given
+ * byte array.
+ */
+void initializeForEncoding() {
+    interlaced = false;
+    bitsPerPixel = image.depth;
+    codeSize = bitsPerPixel + 1;
+    topSlot = 1 << codeSize;
+    clearCode = 1 << bitsPerPixel;
+    endCode = clearCode + 1;
+    newCodes = currentSlot = endCode + 1;
+    bitsLeft = 8;
+    currentByte = 0;
+    blockIndex = 1;
+    blockSize = 255;
+    block = new byte[blockSize];
+    block[0] = cast(byte)(blockSize - 1);
+    nodeStack = new LZWNode[1 << bitsPerPixel];
+    for (int i = 0; i < nodeStack.length; i++) {
+        LZWNode node = new LZWNode();
+        node.code = i + 1;
+        node.prefix = -1;
+        node.suffix = i + 1;
+        nodeStack[i] = node;
+    }
+    imageWidth = image.width;
+    imageHeight = image.height;
+    imageY = -1;
+    lineArray = new byte[imageWidth];
+    imageX = imageWidth + 1; // Force a read
+}
+/**
+ * Answer the next code from the input byte array.
+ */
+int nextCode() {
+    int code;
+    if (bitsLeft is 0) {
+        if (blockIndex >= blockSize) {
+            blockSize = readBlock();
+            blockIndex = 0;
+            if (blockSize is 0) return endCode;
+        }
+        blockIndex++;
+        currentByte = block[blockIndex] & 0xFF;
+        bitsLeft = 8;
+        code = currentByte;
+    } else {
+        int shift = bitsLeft - 8;
+        if (shift < 0)
+            code = currentByte >> (0 - shift);
+        else
+            code = currentByte << shift;
+    }
+    while (codeSize > bitsLeft) {
+        if (blockIndex >= blockSize) {
+            blockSize = readBlock();
+            blockIndex = 0;
+            if (blockSize is 0) return endCode;
+        }
+        blockIndex++;
+        currentByte = block[blockIndex] & 0xFF;
+        code += currentByte << bitsLeft;
+        bitsLeft += 8;
+    }
+    bitsLeft -= codeSize;
+    return code & codeMask;
+}
+/**
+ * Answer the next pixel to encode in the image
+ */
+int nextPixel() {
+    imageX++;
+    if (imageX > imageWidth) {
+        imageY++;
+        if (imageY >= imageHeight) {
+            return -1;
+        } else {
+            nextPixels(lineArray, imageWidth);
+        }
+        imageX = 1;
+    }
+    return this.lineArray[imageX - 1] & 0xFF;
+}
+/**
+ * Copy a row of pixel values from the image.
+ */
+void nextPixels(byte[] buf, int lineWidth) {
+    if (image.depth is 8) {
+        System.arraycopy(image.data, imageY * image.bytesPerLine, buf, 0, lineWidth);
+    } else {
+        image.getPixels(0, imageY, lineWidth, buf, 0);
+    }
+}
+/**
+ * Output aCode to the output stream.
+ */
+void nextPutCode(int aCode) {
+    int codeToDo = aCode;
+    int codeBitsToDo = codeSize;
+    // Fill in the remainder of the current byte with the
+    // *high-order* bits of the code.
+    int c = codeToDo & MASK_TABLE[bitsLeft - 1];
+    currentByte = currentByte | (c << (8 - bitsLeft));
+    block[blockIndex] = cast(byte)currentByte;
+    codeBitsToDo -= bitsLeft;
+    if (codeBitsToDo < 1) {
+        // The whole code fit in the first byte, so we are done.
+        bitsLeft -= codeSize;
+        if (bitsLeft is 0) {
+            // We used the whole last byte, so get ready
+            // for the next one.
+            bitsLeft = 8;
+            blockIndex++;
+            if (blockIndex >= blockSize) {
+                writeBlock();
+                blockIndex = 1;
+            }
+            currentByte = 0;
+        }
+        return;
+    }
+    codeToDo = codeToDo >> bitsLeft;
+
+    // Fill in any remaining whole bytes (i.e. not the last one!)
+    blockIndex++;
+    if (blockIndex >= blockSize) {
+        writeBlock();
+        blockIndex = 1;
+    }
+    while (codeBitsToDo >= 8) {
+        currentByte = codeToDo & 0xFF;
+        block[blockIndex] = cast(byte)currentByte;
+        codeToDo = codeToDo >> 8;
+        codeBitsToDo -= 8;
+        blockIndex++;
+        if (blockIndex >= blockSize) {
+            writeBlock();
+            blockIndex = 1;
+        }
+    }
+    // Fill the *low-order* bits of the last byte with the remainder
+    bitsLeft = 8 - codeBitsToDo;
+    currentByte = codeToDo;
+    block[blockIndex] = cast(byte)currentByte;
+}
+/**
+ * Copy a row of pixel values to the image.
+ */
+void nextPutPixels(byte[] buf) {
+    if (image.depth is 8) {
+        // Slight optimization for depth = 8.
+        int start = line * image.bytesPerLine;
+        for (int i = 0; i < imageWidth; i++)
+            image.data[start + i] = buf[i];
+    } else {
+        image.setPixels(0, line, imageWidth, buf, 0);
+    }
+    if (interlaced) {
+        if (pass is 1) {
+            copyRow(buf, 7);
+            line += 8;
+        } else if (pass is 2) {
+            copyRow(buf, 3);
+            line += 8;
+        } else if (pass is 3) {
+            copyRow(buf, 1);
+            line += 4;
+        } else if (pass is 4) {
+            line += 2;
+        } else if (pass is 5) {
+            line += 0;
+        }
+        if (line >= imageHeight) {
+            pass++;
+            if (pass is 2) line = 4;
+            else if (pass is 3) line = 2;
+            else if (pass is 4) line = 1;
+            else if (pass is 5) line = 0;
+            if (pass < 5) {
+                if (loader.hasListeners()) {
+                    ImageData imageCopy = cast(ImageData) image.clone();
+                    loader.notifyListeners(
+                        new ImageLoaderEvent(loader, imageCopy, pass - 2, false));
+                }
+            }
+        }
+        if (line >= imageHeight) line = 0;
+    } else {
+        line++;
+    }
+}
+/**
+ * Copy duplicate rows of pixel values to the image.
+ * This is to fill in rows if the image is interlaced.
+ */
+void copyRow(byte[] buf, int copies) {
+    for (int i = 1; i <= copies; i++) {
+        if (line + i < imageHeight) {
+            image.setPixels(0, line + i, imageWidth, buf, 0);
+        }
+    }
+}
+/**
+ * Read a block from the byte stream.
+ * Return the number of bytes read.
+ * Throw an exception if the block could not be read.
+ */
+int readBlock() {
+    int size = -1;
+    try {
+        size = inputStream.read();
+        if (size is -1) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        block[0] = cast(byte)size;
+        size = inputStream.read(block, 1, size);
+        if (size is -1) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return size;
+}
+/**
+ * Write a block to the byte stream.
+ * Throw an exception if the block could not be written.
+ */
+void writeBlock() {
+    try {
+        outputStream.write(block, 0, (block[0] & 0xFF) + 1);
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/LZWNode.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.LZWNode;
+
+
+final class LZWNode {
+    public LZWNode left, right, children;
+    public int code, prefix, suffix;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/OS2BMPFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.OS2BMPFileFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.FileFormat;
+import java.io.ByteArrayOutputStream;
+import java.lang.all;
+
+import tango.core.Exception;
+
+final class OS2BMPFileFormat : FileFormat {
+    static final int BMPFileHeaderSize = 14;
+    static final int BMPHeaderFixedSize = 12;
+    int width, height, bitCount;
+
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] header = new byte[18];
+        stream.read(header);
+        stream.unread(header);
+        int infoHeaderSize = (header[14] & 0xFF) | ((header[15] & 0xFF) << 8) | ((header[16] & 0xFF) << 16) | ((header[17] & 0xFF) << 24);
+        return header[0] is 0x42 && header[1] is 0x4D && infoHeaderSize is BMPHeaderFixedSize;
+    } catch (Exception e) {
+        return false;
+    }
+}
+byte[] loadData(byte[] infoHeader) {
+    int stride = (width * bitCount + 7) / 8;
+    stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
+    byte[] data = loadData(infoHeader, stride);
+    flipScanLines(data, stride, height);
+    return data;
+}
+byte[] loadData(byte[] infoHeader, int stride) {
+    int dataSize = height * stride;
+    byte[] data = new byte[dataSize];
+    try {
+        if (inputStream.read(data) !is dataSize)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return data;
+}
+int[] loadFileHeader() {
+    int[] header = new int[5];
+    try {
+        header[0] = inputStream.readShort();
+        header[1] = inputStream.readInt();
+        header[2] = inputStream.readShort();
+        header[3] = inputStream.readShort();
+        header[4] = inputStream.readInt();
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    if (header[0] !is 0x4D42)
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return header;
+}
+override ImageData[] loadFromByteStream() {
+    int[] fileHeader = loadFileHeader();
+    byte[] infoHeader = new byte[BMPHeaderFixedSize];
+    try {
+        inputStream.read(infoHeader);
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8);
+    height = (infoHeader[6] & 0xFF) | ((infoHeader[7] & 0xFF) << 8);
+    bitCount = (infoHeader[10] & 0xFF) | ((infoHeader[11] & 0xFF) << 8);
+    PaletteData palette = loadPalette(infoHeader);
+    if (inputStream.getPosition() < fileHeader[4]) {
+        // Seek to the specified offset
+        try {
+            inputStream.skip(fileHeader[4] - inputStream.getPosition());
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+    byte[] data = loadData(infoHeader);
+    int type = SWT.IMAGE_OS2_BMP;
+    return [
+        ImageData.internal_new(
+            width,
+            height,
+            bitCount,
+            palette,
+            4,
+            data,
+            0,
+            null,
+            null,
+            -1,
+            -1,
+            type,
+            0,
+            0,
+            0,
+            0)
+    ];
+}
+PaletteData loadPalette(byte[] infoHeader) {
+    if (bitCount <= 8) {
+        int numColors = 1 << bitCount;
+        byte[] buf = new byte[numColors * 3];
+        try {
+            if (inputStream.read(buf) !is buf.length)
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        return paletteFromBytes(buf, numColors);
+    }
+    if (bitCount is 16) return new PaletteData(0x7C00, 0x3E0, 0x1F);
+    if (bitCount is 24) return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+    return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+}
+PaletteData paletteFromBytes(byte[] bytes, int numColors) {
+    int bytesOffset = 0;
+    RGB[] colors = new RGB[numColors];
+    for (int i = 0; i < numColors; i++) {
+        colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
+            bytes[bytesOffset + 1] & 0xFF,
+            bytes[bytesOffset] & 0xFF);
+        bytesOffset += 3;
+    }
+    return new PaletteData(colors);
+}
+/**
+ * Answer a byte array containing the BMP representation of
+ * the given device independent palette.
+ */
+static byte[] paletteToBytes(PaletteData pal) {
+    int n = pal.colors is null ? 0 : (pal.colors.length < 256 ? pal.colors.length : 256);
+    byte[] bytes = new byte[n * 3];
+    int offset = 0;
+    for (int i = 0; i < n; i++) {
+        RGB col = pal.colors[i];
+        bytes[offset] = cast(byte)col.blue;
+        bytes[offset + 1] = cast(byte)col.green;
+        bytes[offset + 2] = cast(byte)col.red;
+        offset += 3;
+    }
+    return bytes;
+}
+/**
+ * Unload the given image's data into the given byte stream.
+ * Answer the number of bytes written.
+ */
+int unloadData(ImageData image, OutputStream ostr) {
+    int bmpBpl = 0;
+    try {
+        int bpl = (image.width * image.depth + 7) / 8;
+        bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
+        int linesPerBuf = 32678 / bmpBpl;
+        byte[] buf = new byte[linesPerBuf * bmpBpl];
+        byte[] data = image.data;
+        int imageBpl = image.bytesPerLine;
+        int dataIndex = imageBpl * (image.height - 1); // Start at last line
+        if (image.depth is 16) {
+            for (int y = 0; y < image.height; y += linesPerBuf) {
+                int count = image.height - y;
+                if (linesPerBuf < count) count = linesPerBuf;
+                int bufOffset = 0;
+                for (int i = 0; i < count; i++) {
+                    for (int wIndex = 0; wIndex < bpl; wIndex += 2) {
+                        buf[bufOffset + wIndex + 1] = data[dataIndex + wIndex + 1];
+                        buf[bufOffset + wIndex] = data[dataIndex + wIndex];
+                    }
+                    bufOffset += bmpBpl;
+                    dataIndex -= imageBpl;
+                }
+                ostr.write(buf, 0, bufOffset);
+            }
+        } else {
+            for (int y = 0; y < image.height; y += linesPerBuf) {
+                int tmp = image.height - y;
+                int count = tmp < linesPerBuf ? tmp : linesPerBuf;
+                int bufOffset = 0;
+                for (int i = 0; i < count; i++) {
+                    System.arraycopy(data, dataIndex, buf, bufOffset, bpl);
+                    bufOffset += bmpBpl;
+                    dataIndex -= imageBpl;
+                }
+                ostr.write(buf, 0, bufOffset);
+            }
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return bmpBpl * image.height;
+}
+/**
+ * Unload a DeviceIndependentImage using Windows .BMP format into the given
+ * byte stream.
+ */
+override void unloadIntoByteStream(ImageLoader loader) {
+    ImageData image = loader.data[0];
+    byte[] rgbs;
+    int numCols;
+    if (!((image.depth is 1) || (image.depth is 4) || (image.depth is 8) ||
+          (image.depth is 16) || (image.depth is 24) || (image.depth is 32)))
+            SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+    PaletteData pal = image.palette;
+    if ((image.depth is 16) || (image.depth is 24) || (image.depth is 32)) {
+        if (!pal.isDirect)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        numCols = 0;
+        rgbs = null;
+    } else {
+        if (pal.isDirect)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        numCols = pal.colors.length;
+        rgbs = paletteToBytes(pal);
+    }
+    // Fill in file header, except for bfsize, which is done later.
+    int headersSize = BMPFileHeaderSize + BMPHeaderFixedSize;
+    int[] fileHeader = new int[5];
+    fileHeader[0] = 0x4D42; // Signature
+    fileHeader[1] = 0; // File size - filled in later
+    fileHeader[2] = 0; // Reserved 1
+    fileHeader[3] = 0; // Reserved 2
+    fileHeader[4] = headersSize; // Offset to data
+    if (rgbs !is null) {
+        fileHeader[4] += rgbs.length;
+    }
+
+    // Prepare data. This is done first so we don't have to try to rewind
+    // the stream and fill in the details later.
+    ByteArrayOutputStream ostr = new ByteArrayOutputStream();
+    unloadData(image, ostr);
+    byte[] data = ostr.toByteArray();
+
+    // Calculate file size
+    fileHeader[1] = fileHeader[4] + data.length;
+
+    // Write the headers
+    try {
+        outputStream.writeShort(fileHeader[0]);
+        outputStream.writeInt(fileHeader[1]);
+        outputStream.writeShort(fileHeader[2]);
+        outputStream.writeShort(fileHeader[3]);
+        outputStream.writeInt(fileHeader[4]);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    try {
+        outputStream.writeInt(BMPHeaderFixedSize);
+        outputStream.writeShort(image.width);
+        outputStream.writeShort(image.height);
+        outputStream.writeShort(1);
+        outputStream.writeShort(cast(short)image.depth);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+
+    // Unload palette
+    if (numCols > 0) {
+        try {
+            outputStream.write(rgbs);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+
+    // Unload the data
+    try {
+        outputStream.write(data);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+void flipScanLines(byte[] data, int stride, int height) {
+    int i1 = 0;
+    int i2 = (height - 1) * stride;
+    for (int i = 0; i < height / 2; i++) {
+        for (int index = 0; index < stride; index++) {
+            byte b = data[index + i1];
+            data[index + i1] = data[index + i2];
+            data[index + i2] = b;
+        }
+        i1 += stride;
+        i2 -= stride;
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PNGFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PNGFileFormat;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoaderEvent;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.image.FileFormat;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngPlteChunk;
+import org.eclipse.swt.internal.image.PngChunkReader;
+import org.eclipse.swt.internal.image.PngChunk;
+import org.eclipse.swt.internal.image.PngTrnsChunk;
+import org.eclipse.swt.internal.image.PngIdatChunk;
+import org.eclipse.swt.internal.image.PngEncoder;
+import org.eclipse.swt.internal.image.PngInputStream;
+import org.eclipse.swt.internal.image.PngDecodingDataStream;
+import java.lang.all;
+
+import java.io.BufferedInputStream;
+
+import tango.core.Exception;
+
+final class PNGFileFormat : FileFormat {
+    static final int SIGNATURE_LENGTH = 8;
+    static final int PRIME = 65521;
+    PngIhdrChunk headerChunk;
+    PngPlteChunk paletteChunk;
+    ImageData imageData;
+    byte[] data;
+    byte[] alphaPalette;
+    byte headerByte1;
+    byte headerByte2;
+    int adler;
+
+/**
+ * Skip over signature data. This has already been
+ * verified in isFileFormat().
+ */
+void readSignature()  {
+    byte[] signature = new byte[SIGNATURE_LENGTH];
+    inputStream.read(signature);
+}
+/**
+ * Load the PNG image from the byte stream.
+ */
+override ImageData[] loadFromByteStream() {
+    try {
+        readSignature();
+        PngChunkReader chunkReader = new PngChunkReader(inputStream);
+        headerChunk = chunkReader.getIhdrChunk();
+        int width = headerChunk.getWidth(), height = headerChunk.getHeight();
+        if (width <= 0 || height <= 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+        int imageSize = getAlignedBytesPerRow() * height;
+        data = new byte[imageSize];
+        imageData = ImageData.internal_new(
+            width,
+            height,
+            headerChunk.getSwtBitsPerPixel(),
+            new PaletteData(0, 0, 0),
+            4,
+            data,
+            0,
+            null,
+            null,
+            -1,
+            -1,
+            SWT.IMAGE_PNG,
+            0,
+            0,
+            0,
+            0);
+
+        if (headerChunk.usesDirectColor()) {
+            imageData.palette = headerChunk.getPaletteData();
+        }
+
+        // Read and process chunks until the IEND chunk is encountered.
+        while (chunkReader.hasMoreChunks()) {
+            readNextChunk(chunkReader);
+        }
+
+        return [imageData];
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+        return null;
+    }
+}
+/**
+ * Read and handle the next chunk of data from the
+ * PNG file.
+ */
+void readNextChunk(PngChunkReader chunkReader)  {
+    PngChunk chunk = chunkReader.readNextChunk();
+    switch (chunk.getChunkType()) {
+        case PngChunk.CHUNK_IEND:
+            break;
+        case PngChunk.CHUNK_PLTE:
+            if (!headerChunk.usesDirectColor()) {
+                paletteChunk = cast(PngPlteChunk) chunk;
+                imageData.palette = paletteChunk.getPaletteData();
+            }
+            break;
+        case PngChunk.CHUNK_tRNS:
+            PngTrnsChunk trnsChunk = cast(PngTrnsChunk) chunk;
+            if (trnsChunk.getTransparencyType(headerChunk) is
+                PngTrnsChunk.TRANSPARENCY_TYPE_PIXEL)
+            {
+                imageData.transparentPixel =
+                    trnsChunk.getSwtTransparentPixel(headerChunk);
+            } else {
+                alphaPalette = trnsChunk.getAlphaValues(headerChunk, paletteChunk);
+                int transparentCount = 0, transparentPixel = -1;
+                for (int i = 0; i < alphaPalette.length; i++) {
+                    if ((alphaPalette[i] & 0xFF) !is 255) {
+                        transparentCount++;
+                        transparentPixel = i;
+                    }
+                }
+                if (transparentCount is 0) {
+                    alphaPalette = null;
+                } else if (transparentCount is 1 && alphaPalette[transparentPixel] is 0) {
+                    alphaPalette = null;
+                    imageData.transparentPixel = transparentPixel;
+                }
+            }
+            break;
+        case PngChunk.CHUNK_IDAT:
+            if (chunkReader.readPixelData()) {
+                // All IDAT chunks in an image file must be
+                // sequential. If the pixel data has already
+                // been read and another IDAT block is encountered,
+                // then this is an invalid image.
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+            } else {
+                // Read in the pixel data for the image. This should
+                // go through all the image's IDAT chunks.
+                PngIdatChunk dataChunk = cast(PngIdatChunk) chunk;
+                readPixelData(dataChunk, chunkReader);
+            }
+            break;
+        default:
+            if (chunk.isCritical()) {
+                // All critical chunks must be supported.
+                SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
+            }
+    }
+}
+override void unloadIntoByteStream(ImageLoader loader) {
+    PngEncoder encoder = new PngEncoder(loader);
+    encoder.encode(outputStream);
+}
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] signature = new byte[SIGNATURE_LENGTH];
+        stream.read(signature);
+        stream.unread(signature);
+        if ((signature[0] & 0xFF) !is 137) return false; //137
+        if ((signature[1] & 0xFF) !is 80) return false; //P
+        if ((signature[2] & 0xFF) !is 78) return false; //N
+        if ((signature[3] & 0xFF) !is 71) return false; //G
+        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>     
+        return true;
+    } catch (Exception e) {
+        return false;
+    }
+}
+/**
+ * SWT does not support 16-bit depths. If this image uses
+ * 16-bit depths, convert the data to an 8-bit depth.
+ */
+byte[] validateBitDepth(byte[] data) {
+    if (headerChunk.getBitDepth() > 8) {
+        byte[] result = new byte[data.length / 2];
+        compress16BitDepthTo8BitDepth(data, 0, result, 0, result.length);
+        return result;
+    } else {
+        return data;
+    }
+}
+/**
+ * SWT does not support greyscale as a color type. For
+ * plain grayscale, we create a palette. For Grayscale
+ * with Alpha, however, we need to convert the pixels
+ * to use RGB values.
+ * Note: This method assumes that the bit depth of the
+ * data has already been restricted to 8 or less.
+ */
+void setPixelData(byte[] data, ImageData imageData) {
+    switch (headerChunk.getColorType()) {
+        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+        {
+            int width = imageData.width;
+            int height = imageData.height;
+            int destBytesPerLine = imageData.bytesPerLine;
+            /*
+            * If the image uses 16-bit depth, it is converted
+            * to an 8-bit depth image.
+            */
+            int srcBytesPerLine = getAlignedBytesPerRow();
+            if (headerChunk.getBitDepth() > 8) srcBytesPerLine /= 2;
+
+            byte[] rgbData = new byte[destBytesPerLine * height];
+            byte[] alphaData = new byte[width * height];
+            for (int y = 0; y < height; y++) {
+                int srcIndex = srcBytesPerLine * y;
+                int destIndex = destBytesPerLine * y;
+                int destAlphaIndex = width * y;
+                for (int x = 0; x < width; x++) {
+                    byte grey = data[srcIndex];
+                    byte alpha = data[srcIndex + 1];
+                    rgbData[destIndex + 0] = grey;
+                    rgbData[destIndex + 1] = grey;
+                    rgbData[destIndex + 2] = grey;
+                    alphaData[destAlphaIndex] = alpha;
+                    srcIndex += 2;
+                    destIndex += 3;
+                    destAlphaIndex++;
+                }
+            }
+            imageData.data = rgbData;
+            imageData.alphaData = alphaData;
+            break;
+        }
+        case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
+        {
+            int width = imageData.width;
+            int height = imageData.height;
+            int destBytesPerLine = imageData.bytesPerLine;
+            int srcBytesPerLine = getAlignedBytesPerRow();
+            /*
+            * If the image uses 16-bit depth, it is converted
+            * to an 8-bit depth image.
+            */
+            if (headerChunk.getBitDepth() > 8) srcBytesPerLine /= 2;
+
+            byte[] rgbData = new byte[destBytesPerLine * height];
+            byte[] alphaData = new byte[width * height];
+            for (int y = 0; y < height; y++) {
+                int srcIndex = srcBytesPerLine * y;
+                int destIndex = destBytesPerLine * y;
+                int destAlphaIndex = width * y;
+                for (int x = 0; x < width; x++) {
+                    rgbData[destIndex + 0] = data[srcIndex + 0];
+                    rgbData[destIndex + 1] = data[srcIndex + 1];
+                    rgbData[destIndex + 2] = data[srcIndex + 2];
+                    alphaData[destAlphaIndex] = data[srcIndex + 3];
+                    srcIndex += 4;
+                    destIndex += 3;
+                    destAlphaIndex++;
+                }
+            }
+            imageData.data = rgbData;
+            imageData.alphaData = alphaData;
+            break;
+        }
+        case PngIhdrChunk.COLOR_TYPE_RGB:
+            imageData.data = data;
+            break;
+        case PngIhdrChunk.COLOR_TYPE_PALETTE:
+            imageData.data = data;
+            if (alphaPalette !is null) {
+                int size = imageData.width * imageData.height;
+                byte[] alphaData = new byte[size];
+                byte[] pixelData = new byte[size];
+                imageData.getPixels(0, 0, size, pixelData, 0);
+                for (int i = 0; i < pixelData.length; i++) {
+                    alphaData[i] = alphaPalette[pixelData[i] & 0xFF];
+                }
+                imageData.alphaData = alphaData;
+            }
+            break;
+        default:
+            imageData.data = data;
+            break;
+    }
+}
+/**
+ * PNG supports some color types and bit depths that are
+ * unsupported by SWT. If the image uses an unsupported
+ * color type (either of the gray scale types) or bit
+ * depth (16), convert the data to an SWT-supported
+ * format. Then assign the data into the ImageData given.
+ */
+void setImageDataValues(byte[] data, ImageData imageData) {
+    byte[] result = validateBitDepth(data);
+    setPixelData(result, imageData);
+}
+/**
+ * Read the image data from the data stream. This must handle
+ * decoding the data, filtering, and interlacing.
+ */
+void readPixelData(PngIdatChunk chunk, PngChunkReader chunkReader)  {
+    InputStream stream = new PngInputStream(chunk, chunkReader);
+    //TEMPORARY CODE
+    //PORTING_FIXME
+    bool use3_2 = true;//System.getProperty("org.eclipse.swt.internal.image.PNGFileFormat_3.2") !is null;
+    InputStream inflaterStream = use3_2 ? null : Compatibility.newInflaterInputStream(stream);
+    if (inflaterStream !is null) {
+        stream = inflaterStream;
+    } else {
+        stream = new PngDecodingDataStream(stream);
+    }
+    int interlaceMethod = headerChunk.getInterlaceMethod();
+    if (interlaceMethod is PngIhdrChunk.INTERLACE_METHOD_NONE) {
+        readNonInterlacedImage(stream);
+    } else {
+        readInterlacedImage(stream);
+    }
+    /*
+    * InflaterInputStream does not consume all bytes in the stream
+    * when it is closed. This may leave unread IDAT chunks. The fix
+    * is to read all available bytes before closing it.
+    */
+    while (stream.available() > 0) stream.read();
+    stream.close();
+}
+/**
+ * Answer the number of bytes in a word-aligned row of pixel data.
+ */
+int getAlignedBytesPerRow() {
+    return ((getBytesPerRow(headerChunk.getWidth()) + 3) / 4) * 4;
+}
+/**
+ * Answer the number of bytes in each row of the image
+ * data. Each PNG row is byte-aligned, so images with bit
+ * depths less than a byte may have unused bits at the
+ * end of each row. The value of these bits is undefined.
+ */
+int getBytesPerRow() {
+    return getBytesPerRow(headerChunk.getWidth());
+}
+/**
+ * Answer the number of bytes needed to represent a pixel.
+ * This value depends on the image's color type and bit
+ * depth.
+ * Note that this method rounds up if an image's pixel size
+ * isn't byte-aligned.
+ */
+int getBytesPerPixel() {
+    int bitsPerPixel = headerChunk.getBitsPerPixel();
+    return (bitsPerPixel + 7) / 8;
+}
+/**
+ * Answer the number of bytes in a row of the given pixel
+ * width. Each row is byte-aligned, so images with bit
+ * depths less than a byte may have unused bits at the
+ * end of each row. The value of these bits is undefined.
+ */
+int getBytesPerRow(int rowWidthInPixels) {
+    int bitsPerPixel = headerChunk.getBitsPerPixel();
+    int bitsPerRow = bitsPerPixel * rowWidthInPixels;
+    int bitsPerByte = 8;
+    return (bitsPerRow + (bitsPerByte - 1)) / bitsPerByte;
+}
+/**
+ * 1. Read one of the seven frames of interlaced data.
+ * 2. Update the imageData.
+ * 3. Notify the image loader's listeners of the frame load.
+ */
+void readInterlaceFrame(
+    InputStream inputStream,
+    int rowInterval,
+    int columnInterval,
+    int startRow,
+    int startColumn,
+    int frameCount)
+{
+    int width = headerChunk.getWidth();
+    int alignedBytesPerRow = getAlignedBytesPerRow();
+    int height = headerChunk.getHeight();
+    if (startRow >= height || startColumn >= width) return;
+
+    int pixelsPerRow = (width - startColumn + columnInterval - 1) / columnInterval;
+    int bytesPerRow = getBytesPerRow(pixelsPerRow);
+    byte[] row1 = new byte[bytesPerRow];
+    byte[] row2 = new byte[bytesPerRow];
+    byte[] currentRow = row1;
+    byte[] lastRow = row2;
+    for (int row = startRow; row < height; row += rowInterval) {
+        byte filterType = cast(byte)inputStream.read();
+        int read = 0;
+        while (read !is bytesPerRow) {
+            read += inputStream.read(currentRow, read, bytesPerRow - read);
+        }
+        filterRow(currentRow, lastRow, filterType);
+        if (headerChunk.getBitDepth() >= 8) {
+            int bytesPerPixel = getBytesPerPixel();
+            int dataOffset = (row * alignedBytesPerRow) + (startColumn * bytesPerPixel);
+            for (int rowOffset = 0; rowOffset < currentRow.length; rowOffset += bytesPerPixel) {
+                for (int byteOffset = 0; byteOffset < bytesPerPixel; byteOffset++) {
+                    data[dataOffset + byteOffset] = currentRow[rowOffset + byteOffset];
+                }
+                dataOffset += (columnInterval * bytesPerPixel);
+            }
+        } else {
+            int bitsPerPixel = headerChunk.getBitDepth();
+            int pixelsPerByte = 8 / bitsPerPixel;
+            int column = startColumn;
+            int rowBase = row * alignedBytesPerRow;
+            int valueMask = 0;
+            for (int i = 0; i < bitsPerPixel; i++) {
+                valueMask <<= 1;
+                valueMask |= 1;
+            }
+            int maxShift = 8 - bitsPerPixel;
+            for (int byteOffset = 0; byteOffset < currentRow.length; byteOffset++) {
+                for (int bitOffset = maxShift; bitOffset >= 0; bitOffset -= bitsPerPixel) {
+                    if (column < width) {
+                        int dataOffset = rowBase + (column * bitsPerPixel / 8);
+                        int value = (currentRow[byteOffset] >> bitOffset) & valueMask;
+                        int dataShift = maxShift - (bitsPerPixel * (column % pixelsPerByte));
+                        data[dataOffset] |= value << dataShift;
+                    }
+                    column += columnInterval;
+                }
+            }
+        }
+        currentRow = (currentRow is row1) ? row2 : row1;
+        lastRow = (lastRow is row1) ? row2 : row1;
+    }
+    setImageDataValues(data, imageData);
+    fireInterlacedFrameEvent(frameCount);
+}
+/**
+ * Read the pixel data for an interlaced image from the
+ * data stream.
+ */
+void readInterlacedImage(InputStream inputStream)  {
+    readInterlaceFrame(inputStream, 8, 8, 0, 0, 0);
+    readInterlaceFrame(inputStream, 8, 8, 0, 4, 1);
+    readInterlaceFrame(inputStream, 8, 4, 4, 0, 2);
+    readInterlaceFrame(inputStream, 4, 4, 0, 2, 3);
+    readInterlaceFrame(inputStream, 4, 2, 2, 0, 4);
+    readInterlaceFrame(inputStream, 2, 2, 0, 1, 5);
+    readInterlaceFrame(inputStream, 2, 1, 1, 0, 6);
+}
+/**
+ * Fire an event to let listeners know that an interlaced
+ * frame has been loaded.
+ * finalFrame should be true if the image has finished
+ * loading, false if there are more frames to come.
+ */
+void fireInterlacedFrameEvent(int frameCount) {
+    if (loader.hasListeners()) {
+        ImageData image = cast(ImageData) imageData.clone();
+        bool finalFrame = frameCount is 6;
+        loader.notifyListeners(new ImageLoaderEvent(loader, image, frameCount, finalFrame));
+    }
+}
+/**
+ * Read the pixel data for a non-interlaced image from the
+ * data stream.
+ * Update the imageData to reflect the new data.
+ */
+void readNonInterlacedImage(InputStream inputStream)  {
+    int dataOffset = 0;
+    int alignedBytesPerRow = getAlignedBytesPerRow();
+    int bytesPerRow = getBytesPerRow();
+    byte[] row1 = new byte[bytesPerRow];
+    byte[] row2 = new byte[bytesPerRow];
+    byte[] currentRow = row1;
+    byte[] lastRow = row2;
+    int height = headerChunk.getHeight();
+    for (int row = 0; row < height; row++) {
+        byte filterType = cast(byte)inputStream.read();
+        int read = 0;
+        while (read !is bytesPerRow) {
+            read += inputStream.read(currentRow, read, bytesPerRow - read);
+        }
+        filterRow(currentRow, lastRow, filterType);
+        System.arraycopy(currentRow, 0, data, dataOffset, bytesPerRow);
+        dataOffset += alignedBytesPerRow;
+        currentRow = (currentRow is row1) ? row2 : row1;
+        lastRow = (lastRow is row1) ? row2 : row1;
+    }
+    setImageDataValues(data, imageData);
+}
+/**
+ * SWT does not support 16-bit depth color formats.
+ * Convert the 16-bit data to 8-bit data.
+ * The correct way to do this is to multiply each
+ * 16 bit value by the value:
+ * (2^8 - 1) / (2^16 - 1).
+ * The fast way to do this is just to drop the low
+ * byte of the 16-bit value.
+ */
+static void compress16BitDepthTo8BitDepth(
+    byte[] source,
+    int sourceOffset,
+    byte[] destination,
+    int destinationOffset,
+    int numberOfValues)
+{
+    //double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);
+    for (int i = 0; i < numberOfValues; i++) {
+        int sourceIndex = sourceOffset + (2 * i);
+        int destinationIndex = destinationOffset + i;
+        //int value = (source[sourceIndex] << 8) | source[sourceIndex + 1];
+        //byte compressedValue = (byte)(value * multiplier);
+        byte compressedValue = source[sourceIndex];
+        destination[destinationIndex] = compressedValue;
+    }
+}
+/**
+ * SWT does not support 16-bit depth color formats.
+ * Convert the 16-bit data to 8-bit data.
+ * The correct way to do this is to multiply each
+ * 16 bit value by the value:
+ * (2^8 - 1) / (2^16 - 1).
+ * The fast way to do this is just to drop the low
+ * byte of the 16-bit value.
+ */
+static int compress16BitDepthTo8BitDepth(int value) {
+    //double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);
+    //byte compressedValue = (byte)(value * multiplier);
+    return value >> 8;
+}
+/**
+ * PNG supports four filtering types. These types are applied
+ * per row of image data. This method unfilters the given row
+ * based on the filterType.
+ */
+void filterRow(byte[] row, byte[] previousRow, int filterType) {
+    int byteOffset = headerChunk.getFilterByteOffset();
+    switch (filterType) {
+        case PngIhdrChunk.FILTER_NONE:
+            break;
+        case PngIhdrChunk.FILTER_SUB:
+            for (int i = byteOffset; i < row.length; i++) {
+                int current = row[i] & 0xFF;
+                int left = row[i - byteOffset] & 0xFF;
+                row[i] = cast(byte)((current + left) & 0xFF);
+            }
+            break;
+        case PngIhdrChunk.FILTER_UP:
+            for (int i = 0; i < row.length; i++) {
+                int current = row[i] & 0xFF;
+                int above = previousRow[i] & 0xFF;
+                row[i] = cast(byte)((current + above) & 0xFF);
+            }
+            break;
+        case PngIhdrChunk.FILTER_AVERAGE:
+            for (int i = 0; i < row.length; i++) {
+                int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;
+                int above = previousRow[i] & 0xFF;
+                int current = row[i] & 0xFF;
+                row[i] = cast(byte)((current + ((left + above) / 2)) & 0xFF);
+            }
+            break;
+        case PngIhdrChunk.FILTER_PAETH:
+            for (int i = 0; i < row.length; i++) {
+                int left = (i < byteOffset) ? 0 : row[i - byteOffset] & 0xFF;
+                int aboveLeft = (i < byteOffset) ? 0 : previousRow[i - byteOffset] & 0xFF;
+                int above = previousRow[i] & 0xFF;
+
+                int a = Math.abs(above - aboveLeft);
+                int b = Math.abs(left - aboveLeft);
+                int c = Math.abs(left - aboveLeft + above - aboveLeft);
+
+                int preductor = 0;
+                if (a <= b && a <= c) {
+                    preductor = left;
+                } else if (b <= c) {
+                    preductor = above;
+                } else {
+                    preductor = aboveLeft;
+                }
+
+                int currentValue = row[i] & 0xFF;
+                row[i] = cast(byte) ((currentValue + preductor) & 0xFF);
+            }
+            break;
+        default:
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,386 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngChunk;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngPlteChunk;
+import org.eclipse.swt.internal.image.PngIdatChunk;
+import org.eclipse.swt.internal.image.PngIendChunk;
+import org.eclipse.swt.internal.image.PngTrnsChunk;
+import java.lang.all;
+
+import tango.core.Exception;
+import tango.text.convert.Format;
+
+class PngChunk {
+    byte[] reference;
+
+    static const int LENGTH_OFFSET = 0;
+    static const int TYPE_OFFSET = 4;
+    static const int DATA_OFFSET = 8;
+
+    static const int TYPE_FIELD_LENGTH = 4;
+    static const int LENGTH_FIELD_LENGTH = 4;
+    static const int MIN_LENGTH = 12;
+
+    static const int CHUNK_UNKNOWN = -1;
+    // Critical chunks.
+    static const int CHUNK_IHDR = 0;
+    static const int CHUNK_PLTE = 1;
+    static const int CHUNK_IDAT = 2;
+    static const int CHUNK_IEND = 3;
+    // Non-critical chunks.
+    static const int CHUNK_tRNS = 5;
+
+    static const byte[] TYPE_IHDR = cast(byte[])"IHDR";//{(byte) 'I', (byte) 'H', (byte) 'D', (byte) 'R'};
+    static const byte[] TYPE_PLTE = cast(byte[])"PLTE";//{(byte) 'P', (byte) 'L', (byte) 'T', (byte) 'E'};
+    static const byte[] TYPE_IDAT = cast(byte[])"IDAT";//{(byte) 'I', (byte) 'D', (byte) 'A', (byte) 'T'};
+    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'};
+
+    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);
+                }
+            }
+        }
+    }
+
+    int length;
+
+/**
+ * Construct a PngChunk using the reference bytes
+ * given.
+ */
+this(byte[] reference) {
+    setReference(reference);
+    if (reference.length < LENGTH_OFFSET + LENGTH_FIELD_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    length = getInt32(LENGTH_OFFSET);
+}
+
+/**
+ * Construct a PngChunk with the specified number of
+ * data bytes.
+ */
+this(int dataLength) {
+    this(new byte[MIN_LENGTH + dataLength]);
+    setLength(dataLength);
+}
+
+/**
+ * Get the PngChunk's reference byteArray;
+ */
+byte[] getReference() {
+    return reference;
+}
+
+/**
+ * Set the PngChunk's reference byteArray;
+ */
+void setReference(byte[] reference) {
+    this.reference = reference;
+}
+
+/**
+ * Get the 16-bit integer from the reference byte
+ * array at the given offset.
+ */
+int getInt16(int offset) {
+    int answer = 0;
+    answer |= (reference[offset] & 0xFF) << 8;
+    answer |= (reference[offset + 1] & 0xFF);
+    return answer;
+}
+
+/**
+ * Set the 16-bit integer in the reference byte
+ * array at the given offset.
+ */
+void setInt16(int offset, int value) {
+    reference[offset] = cast(byte) ((value >> 8) & 0xFF);
+    reference[offset + 1] = cast(byte) (value & 0xFF);
+}
+
+/**
+ * Get the 32-bit integer from the reference byte
+ * array at the given offset.
+ */
+int getInt32(int offset) {
+    int answer = 0;
+    answer |= (reference[offset] & 0xFF) << 24;
+    answer |= (reference[offset + 1] & 0xFF) << 16;
+    answer |= (reference[offset + 2] & 0xFF) << 8;
+    answer |= (reference[offset + 3] & 0xFF);
+    return answer;
+}
+
+/**
+ * Set the 32-bit integer in the reference byte
+ * array at the given offset.
+ */
+void setInt32(int offset, int value) {
+    reference[offset] = cast(byte) ((value >> 24) & 0xFF);
+    reference[offset + 1] = cast(byte) ((value >> 16) & 0xFF);
+    reference[offset + 2] = cast(byte) ((value >> 8) & 0xFF);
+    reference[offset + 3] = cast(byte) (value & 0xFF);
+}
+
+/**
+ * Get the length of the data component of this chunk.
+ * This is not the length of the entire chunk.
+ */
+int getLength() {
+    return length;
+}
+
+/**
+ * Set the length of the data component of this chunk.
+ * This is not the length of the entire chunk.
+ */
+void setLength(int value) {
+    setInt32(LENGTH_OFFSET, value);
+    length = value;
+}
+
+/**
+ * Get the chunk type. This is a four byte value.
+ * Each byte should be an ASCII character.
+ * The first byte is upper case if the chunk is critical.
+ * The second byte is upper case if the chunk is publicly defined.
+ * The third byte must be upper case.
+ * The fourth byte is upper case if the chunk is unsafe to copy.
+ * Public chunk types are defined by the PNG Development Group.
+ */
+byte[] getTypeBytes() {
+    byte[] type = new byte[4];
+    System.arraycopy(reference, TYPE_OFFSET, type, 0, TYPE_FIELD_LENGTH);
+    return type;
+}
+
+/**
+ * Set the chunk type. This is a four byte value.
+ * Each byte should be an ASCII character.
+ * The first byte is upper case if the chunk is critical.
+ * The second byte is upper case if the chunk is publicly defined.
+ * The third byte must be upper case.
+ * The fourth byte is upper case if the chunk is unsafe to copy.
+ * Public chunk types are defined by the PNG Development Group.
+ */
+void setType(byte[] value) {
+    if (value.length !is TYPE_FIELD_LENGTH) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    System.arraycopy(value, 0, reference, TYPE_OFFSET, TYPE_FIELD_LENGTH);
+}
+
+/**
+ * Get the chunk's data.
+ */
+byte[] getData() {
+    int dataLength = getLength();
+    if (reference.length < MIN_LENGTH + dataLength) {
+        SWT.error (SWT.ERROR_INVALID_RANGE);
+    }
+    byte[] data = new byte[dataLength];
+    System.arraycopy(reference, DATA_OFFSET, data, 0, dataLength);
+    return data;
+}
+
+/**
+ * Set the chunk's data.
+ * This method has two side-effects.
+ * 1. It will set the length field to be the length
+ *    of the data array given.
+ * 2. It will set the CRC field to the computed CRC
+ *    value of the data array given.
+ */
+void setData(byte[] data) {
+    setLength(data.length);
+    System.arraycopy(data, 0, reference, DATA_OFFSET, data.length);
+    setCRC(computeCRC());
+}
+
+/**
+ * Get the CRC value for the chunk's data.
+ * Ensure that the length field has a good
+ * value before making this call.
+ */
+int getCRC() {
+    int crcOffset = DATA_OFFSET + getLength();
+    return getInt32(crcOffset);
+}
+
+/**
+ * Set the CRC value for the chunk's data.
+ * Ensure that the length field has a good
+ * value before making this call.
+ */
+void setCRC(int value) {
+    int crcOffset = DATA_OFFSET + getLength();
+    setInt32(crcOffset, value);
+}
+
+/**
+ * Get the chunk's total size including the length, type, and crc fields.
+ */
+int getSize() {
+    return MIN_LENGTH + getLength();
+}
+
+/**
+ * Compute the CRC value for the chunk's data. Answer
+ * whether this value matches the value stored in the
+ * chunk.
+ */
+bool checkCRC() {
+    int crc = computeCRC();
+    int storedCRC = getCRC();
+    return crc is storedCRC;
+}
+
+/**
+ * Answer the CRC value of chunk's data.
+ */
+int computeCRC() {
+    int crc = 0xFFFFFFFF;
+    int start = TYPE_OFFSET;
+    int stop = DATA_OFFSET + getLength();
+    for (int i = start; i < stop; i++) {
+        int index = (crc ^ reference[i]) & 0xFF;
+        crc =  CRC_TABLE[index] ^ ((crc >> 8) & 0x00FFFFFF);
+    }
+    return ~crc;
+}
+
+bool typeMatchesArray(byte[] array) {
+    for (int i = 0; i < TYPE_FIELD_LENGTH; i++) {
+        if (reference[TYPE_OFFSET + i] !is array[i]){
+            return false;
+        }
+    }
+    return true;
+}
+
+bool isCritical() {
+    char c = cast(char) getTypeBytes()[0];
+    return 'A' <= c && c <= 'Z';
+}
+
+int getChunkType() {
+    if (typeMatchesArray(TYPE_IHDR)) return CHUNK_IHDR;
+    if (typeMatchesArray(TYPE_PLTE)) return CHUNK_PLTE;
+    if (typeMatchesArray(TYPE_IDAT)) return CHUNK_IDAT;
+    if (typeMatchesArray(TYPE_IEND)) return CHUNK_IEND;
+    if (typeMatchesArray(TYPE_tRNS)) return CHUNK_tRNS;
+    return CHUNK_UNKNOWN;
+}
+
+/**
+ * Read the next PNG chunk from the input stream given.
+ * If unable to read a chunk, return null.
+ */
+static PngChunk readNextFromStream(LEDataInputStream stream) {
+    try {
+        int headerLength = LENGTH_FIELD_LENGTH + TYPE_FIELD_LENGTH;
+        byte[] headerBytes = new byte[headerLength];
+        int result = stream.read(headerBytes, 0, headerLength);
+        stream.unread(headerBytes);
+        if (result !is headerLength) return null;
+
+        PngChunk tempChunk = new PngChunk(headerBytes);
+
+        int chunkLength = tempChunk.getSize();
+        byte[] chunk = new byte[chunkLength];
+
+        result = stream.read(chunk, 0, chunkLength);
+        if (result !is chunkLength) return null;
+
+        switch (tempChunk.getChunkType()) {
+            case CHUNK_IHDR:
+                return new PngIhdrChunk(chunk);
+            case CHUNK_PLTE:
+                return new PngPlteChunk(chunk);
+            case CHUNK_IDAT:
+                return new PngIdatChunk(chunk);
+            case CHUNK_IEND:
+                return new PngIendChunk(chunk);
+            case CHUNK_tRNS:
+                return new PngTrnsChunk(chunk);
+            default:
+                return new PngChunk(chunk);
+        }
+    } catch (IOException e) {
+        return null;
+    }
+}
+
+/**
+ * Answer whether the chunk is a valid PNG chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+    if (reference.length < MIN_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    byte[] type = getTypeBytes();
+
+    // The third character MUST be upper case.
+    char c = cast(char) type[2];
+    if (!('A' <= c && c <= 'Z')) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    // All characters must be letters.
+    for (int i = 0; i < TYPE_FIELD_LENGTH; i++) {
+        c = cast(char) type[i];
+        if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+    }
+
+    // The stored CRC must match the data's computed CRC.
+    if (!checkCRC()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+/**
+ * Provided so that subclasses can override and add
+ * data to the toString() call.
+ */
+String contributeToString() {
+    return "";
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public override String toString() {
+    String buffer = Format( "{\n\tLength: {}\n\tType: {}{}\n\tCRC: {:X}\n}",
+        getLength(),
+        cast(String) getTypeBytes(),
+        contributeToString(),
+        getCRC());
+    return buffer;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngChunkReader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngChunkReader;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngPlteChunk;
+import org.eclipse.swt.internal.image.PngTrnsChunk;
+import org.eclipse.swt.internal.image.PngChunk;
+
+public class PngChunkReader {
+    LEDataInputStream inputStream;
+    PngFileReadState readState;
+    PngIhdrChunk headerChunk;
+    PngPlteChunk paletteChunk;
+
+this(LEDataInputStream inputStream) {
+    this.inputStream = inputStream;
+    readState = new PngFileReadState();
+    headerChunk = null;
+}
+
+PngIhdrChunk getIhdrChunk() {
+    if (headerChunk is null) {
+        PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+        if (chunk is null) SWT.error(SWT.ERROR_INVALID_IMAGE);
+        if(( headerChunk = cast(PngIhdrChunk) chunk ) !is null ){
+            headerChunk.validate(readState, null);
+        }
+        else{
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+    }
+    return headerChunk;
+}
+
+PngChunk readNextChunk() {
+    if (headerChunk is null) return getIhdrChunk();
+
+    PngChunk chunk = PngChunk.readNextFromStream(inputStream);
+    if (chunk is null) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    switch (chunk.getChunkType()) {
+        case PngChunk.CHUNK_tRNS:
+            (cast(PngTrnsChunk) chunk).validate(readState, headerChunk, paletteChunk);
+            break;
+        case PngChunk.CHUNK_PLTE:
+            chunk.validate(readState, headerChunk);
+            paletteChunk = cast(PngPlteChunk) chunk;
+            break;
+        default:
+            chunk.validate(readState, headerChunk);
+    }
+    if (readState.readIDAT && !(chunk.getChunkType() is PngChunk.CHUNK_IDAT)) {
+        readState.readPixelData = true;
+    }
+    return chunk;
+}
+
+bool readPixelData() {
+    return readState.readPixelData;
+}
+
+bool hasMoreChunks() {
+    return !readState.readIEND;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngDecodingDataStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngDecodingDataStream;
+
+
+import java.io.InputStream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.PngLzBlockReader;
+
+public class PngDecodingDataStream : InputStream {
+
+    alias InputStream.read read;
+
+    InputStream stream;
+    byte currentByte;
+    int nextBitIndex;
+
+    PngLzBlockReader lzBlockReader;
+    int adlerValue;
+
+    static final int PRIME = 65521;
+    static final int MAX_BIT = 7;
+
+this(InputStream stream) {
+    super();
+    this.stream = stream;
+    nextBitIndex = MAX_BIT + 1;
+    adlerValue = 1;
+    lzBlockReader = new PngLzBlockReader(this);
+    readCompressedDataHeader();
+    lzBlockReader.readNextBlockHeader();
+}
+
+/**
+ * This method should be called when the image decoder thinks
+ * that all of the compressed image data has been read. This
+ * method will ensure that the next data value is an end of
+ * block marker. If there are more blocks after this one,
+ * the method will read them and ensure that they are empty.
+ */
+void assertImageDataAtEnd() {
+    lzBlockReader.assertCompressedDataAtEnd();
+}
+
+public override void close() {
+    assertImageDataAtEnd();
+    checkAdler();
+}
+
+int getNextIdatBits(int length) {
+    int value = 0;
+    for (int i = 0; i < length; i++) {
+        value |= (getNextIdatBit() << i);
+    }
+    return value;
+}
+
+int getNextIdatBit() {
+    if (nextBitIndex > MAX_BIT) {
+        currentByte = getNextIdatByte();
+        nextBitIndex = 0;
+    }
+    return (currentByte & (1 << nextBitIndex)) >> nextBitIndex++;
+}
+
+byte getNextIdatByte() {
+    byte nextByte = cast(byte)stream.read();
+    nextBitIndex = MAX_BIT + 1;
+    return nextByte;
+}
+
+void updateAdler(byte value) {
+    int low = adlerValue & 0xFFFF;
+    int high = (adlerValue >> 16) & 0xFFFF;
+    int valueInt = value & 0xFF;
+    low = (low + valueInt) % PRIME;
+    high = (low + high) % PRIME;
+    adlerValue = (high << 16) | low;
+}
+
+public override int read() {
+    byte nextDecodedByte = lzBlockReader.getNextByte();
+    updateAdler(nextDecodedByte);
+    return nextDecodedByte & 0xFF;
+}
+
+public override int read(byte[] buffer, int off, int len) {
+    for (int i = 0; i < len; i++) {
+        int b = read();
+        if (b is -1) return i;
+        buffer[off + i] = cast(byte)b;
+    }
+    return len;
+}
+
+void error() {
+    SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+private void readCompressedDataHeader() {
+    byte headerByte1 = getNextIdatByte();
+    byte headerByte2 = getNextIdatByte();
+
+    int number = ((headerByte1 & 0xFF) << 8) | (headerByte2 & 0xFF);
+    if (number % 31 !is 0) error();
+
+    int compressionMethod = headerByte1 & 0x0F;
+    if (compressionMethod !is 8) error();
+
+    int windowSizeHint = (headerByte1 & 0xF0) >> 4;
+    if (windowSizeHint > 7) error();
+    int windowSize = (1 << (windowSizeHint + 8));
+    lzBlockReader.setWindowSize(windowSize);
+
+    int dictionary = (headerByte2 & (1 << 5));
+    if (dictionary !is 0) error();
+
+//  int compressionLevel = (headerByte2 & 0xC0) >> 6;
+}
+
+void checkAdler() {
+    int storedAdler = 0;
+    storedAdler |= ((getNextIdatByte() & 0xFF) << 24);
+    storedAdler |= ((getNextIdatByte() & 0xFF) << 16);
+    storedAdler |= ((getNextIdatByte() & 0xFF) << 8);
+    storedAdler |=  (getNextIdatByte() & 0xFF);
+    if (storedAdler !is adlerValue) error();
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngDeflater.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,623 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngDeflater;
+
+import java.io.ByteArrayOutputStream;
+
+public class PngDeflater {
+
+    static const int BASE = 65521;
+    static const int WINDOW = 32768;
+    static const int MIN_LENGTH = 3;
+    static const int MAX_MATCHES = 32;
+    static const int HASH = 8209;
+
+    byte[] istr;
+    int inLength;
+
+    ByteArrayOutputStream bytes;
+
+    int adler32 = 1;
+
+    int buffer, bitCount;
+
+    Link[HASH] hashtable;// = new Link[HASH];
+    Link[WINDOW] window;// = new Link[WINDOW];
+    int nextWindow;
+
+public this(){
+    bytes = new ByteArrayOutputStream(1024);
+}
+
+class Link {
+
+    int hash, value;
+    Link previous, next;
+
+    this() {
+
+        this.hash = 0;
+        this.value = 0;
+        this.previous = null;
+        this.next = null;
+
+    }
+
+}
+
+static class Match {
+
+    int length, distance;
+
+    this(int length, int distance) {
+
+        this.length = length;
+        this.distance = distance;
+
+    }
+
+}
+
+static const short mirrorBytes[] = [ cast(short)
+
+    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+
+];
+
+static class Code {
+
+    int code, extraBits, min, max;
+
+    this(int code, int extraBits, int min, int max) {
+
+        this.code = code;
+        this.extraBits = extraBits;
+        this.min = min;
+        this.max = max;
+
+    }
+
+}
+
+static const Code lengthCodes[];
+static const Code distanceCodes[];
+
+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)];
+}
+
+void writeShortLSB(ByteArrayOutputStream baos, int theShort) {
+
+    byte byte1 = cast(byte) (theShort & 0xff);
+    byte byte2 = cast(byte) ((theShort >> 8) & 0xff);
+    byte[] temp = [byte1, byte2];
+    baos.write(temp, 0, 2);
+
+}
+
+void writeInt(ByteArrayOutputStream baos, int theInt) {
+
+    byte byte1 = cast(byte) ((theInt >> 24) & 0xff);
+    byte byte2 = cast(byte) ((theInt >> 16) & 0xff);
+    byte byte3 = cast(byte) ((theInt >> 8) & 0xff);
+    byte byte4 = cast(byte) (theInt & 0xff);
+    byte[] temp = [byte1, byte2, byte3, byte4];
+    baos.write(temp, 0, 4);
+
+}
+
+void updateAdler(byte value) {
+
+    int low = adler32 & 0xffff;
+    int high = (adler32 >> 16) & 0xffff;
+    int valueInt = value & 0xff;
+    low = (low + valueInt) % BASE;
+    high = (low + high) % BASE;
+    adler32 = (high << 16) | low;
+
+}
+
+int hash(byte[] bytes) {
+
+    int hash = ((bytes[0] & 0xff) << 24 | (bytes[1] & 0xff) << 16 | (bytes[2] & 0xff) << 8) % HASH;
+    if (hash < 0) {
+        hash = hash + HASH;
+    }
+    return hash;
+
+}
+
+void writeBits(int value, int count) {
+
+    buffer |= value << bitCount;
+    bitCount += count;
+    if (bitCount >= 16) {
+        bytes.write(cast(byte) buffer);
+        bytes.write(cast(byte) (buffer >>> 8));
+        buffer >>>= 16;
+        bitCount -= 16;
+    }
+
+}
+
+void alignToByte() {
+
+    if (bitCount > 0) {
+        bytes.write(cast(byte) buffer);
+        if (bitCount > 8) bytes.write(cast(byte) (buffer >>> 8));
+    }
+    buffer = 0;
+    bitCount = 0;
+
+}
+
+void outputLiteral(byte literal) {
+
+    int i = literal & 0xff;
+
+    if (i <= 143) {
+        // 0 through 143 are 8 bits long starting at 00110000
+        writeBits(mirrorBytes[0x30 + i], 8);
+    }
+    else {
+        // 144 through 255 are 9 bits long starting at 110010000
+        writeBits(1 + 2 * mirrorBytes[0x90 - 144 + i], 9);
+    }
+
+}
+
+Code findCode(int value, Code[] codes) {
+
+    int i, j, k;
+
+    i = -1;
+    j = codes.length;
+    while (true) {
+        k = (j + i) / 2;
+        if (value < codes[k].min) {
+            j = k;
+        }
+        else if (value > codes[k].max) {
+            i = k;
+        }
+        else {
+            return codes[k];
+        }
+    }
+
+}
+
+void outputMatch(int length, int distance) {
+
+    Code d, l;
+    int thisLength;
+
+    while (length > 0) {
+
+        // we can transmit matches of lengths 3 through 258 inclusive
+        // so if length exceeds 258, we must transmit in several steps,
+        // with 258 or less in each step
+
+        if (length > 260) {
+            thisLength = 258;
+        }
+        else if (length <= 258) {
+            thisLength = length;
+        }
+        else {
+            thisLength = length - 3;
+        }
+
+        length = length - thisLength;
+
+        // find length code
+        l = findCode(thisLength, lengthCodes);
+
+        // transmit the length code
+        // 256 through 279 are 7 bits long starting at 0000000
+        // 280 through 287 are 8 bits long starting at 11000000
+        if (l.code <= 279) {
+            writeBits(mirrorBytes[(l.code - 256) * 2], 7);
+        }
+        else {
+            writeBits(mirrorBytes[0xc0 - 280 + l.code], 8);
+        }
+
+        // transmit the extra bits
+        if (l.extraBits !is 0) {
+            writeBits(thisLength - l.min, l.extraBits);
+        }
+
+        // find distance code
+        d = findCode(distance, distanceCodes);
+
+        // transmit the distance code
+        // 5 bits long starting at 00000
+        writeBits(mirrorBytes[d.code * 8], 5);
+
+        // transmit the extra bits
+        if (d.extraBits !is 0) {
+            writeBits(distance - d.min, d.extraBits);
+        }
+
+    }
+
+}
+
+Match findLongestMatch(int position, Link firstPosition) {
+
+    Link link = firstPosition;
+    int numberOfMatches = 0;
+    Match bestMatch = new Match(-1, -1);
+
+    while (true) {
+
+        int matchPosition = link.value;
+
+        if (position - matchPosition < WINDOW && matchPosition !is 0) {
+
+            int i;
+
+            for (i = 1; position + i < inLength; i++) {
+                if (istr[position + i] !is istr[matchPosition + i]) {
+                    break;
+                }
+            }
+
+            if (i >= MIN_LENGTH) {
+
+                if (i > bestMatch.length) {
+                    bestMatch.length = i;
+                    bestMatch.distance = position - matchPosition;
+                }
+
+                numberOfMatches = numberOfMatches + 1;
+
+                if (numberOfMatches is MAX_MATCHES) {
+                    break;
+                }
+
+            }
+
+        }
+
+        link = link.next;
+        if (link is null) {
+            break;
+        }
+
+    }
+
+    if (bestMatch.length < MIN_LENGTH || bestMatch.distance < 1 || bestMatch.distance > WINDOW) {
+        return null;
+    }
+
+    return bestMatch;
+
+}
+
+void updateHashtable(int to, int from) {
+
+    byte[] data = new byte[3];
+    int hashval;
+    Link temp;
+
+    for (int i = to; i < from; i++) {
+
+        if (i + MIN_LENGTH > inLength) {
+            break;
+        }
+
+        data[0] = istr[i];
+        data[1] = istr[i + 1];
+        data[2] = istr[i + 2];
+
+        hashval = hash(data);
+
+        if (window[nextWindow].previous !is null) {
+            window[nextWindow].previous.next = null;
+        }
+        else if (window[nextWindow].hash !is 0) {
+            hashtable[window[nextWindow].hash].next = null;
+        }
+
+        window[nextWindow].hash = hashval;
+        window[nextWindow].value = i;
+        window[nextWindow].previous = null;
+        temp = window[nextWindow].next = hashtable[hashval].next;
+        hashtable[hashval].next = window[nextWindow];
+        if (temp !is null) {
+            temp.previous = window[nextWindow];
+        }
+
+        nextWindow = nextWindow + 1;
+        if (nextWindow is WINDOW) {
+            nextWindow = 0;
+        }
+
+    }
+
+}
+
+void compress() {
+
+    int position, newPosition;
+    byte[] data = new byte[3];
+    int hashval;
+    for (int i = 0; i < HASH; i++) {
+        hashtable[i] = new Link();
+    }
+    for (int i = 0; i < WINDOW; i++) {
+        window[i] = new Link();
+    }
+    nextWindow = 0;
+    Link firstPosition;
+    Match match;
+    int deferredPosition = -1;
+    Match deferredMatch = null;
+
+    writeBits(0x01, 1); // BFINAL = 0x01 (final block)
+    writeBits(0x01, 2); // BTYPE = 0x01 (compression with fixed Huffman codes)
+
+    // just output first byte so we never match at zero
+    outputLiteral(istr[0]);
+    position = 1;
+
+    while (position < inLength) {
+
+        if (inLength - position < MIN_LENGTH) {
+            outputLiteral(istr[position]);
+            position = position + 1;
+            continue;
+        }
+
+        data[0] = istr[position];
+        data[1] = istr[position + 1];
+        data[2] = istr[position + 2];
+
+        hashval = hash(data);
+        firstPosition = hashtable[hashval];
+
+        match = findLongestMatch(position, firstPosition);
+
+        updateHashtable(position, position + 1);
+
+        if (match !is null) {
+
+            if (deferredMatch !is null) {
+                if (match.length > deferredMatch.length + 1) {
+                    // output literal at deferredPosition
+                    outputLiteral(istr[deferredPosition]);
+                    // defer this match
+                    deferredPosition = position;
+                    deferredMatch = match;
+                    position = position + 1;
+                }
+                else {
+                    // output deferredMatch
+                    outputMatch(deferredMatch.length, deferredMatch.distance);
+                    newPosition = deferredPosition + deferredMatch.length;
+                    deferredPosition = -1;
+                    deferredMatch = null;
+                    updateHashtable(position + 1, newPosition);
+                    position = newPosition;
+                }
+            }
+            else {
+                // defer this match
+                deferredPosition = position;
+                deferredMatch = match;
+                position = position + 1;
+            }
+
+        }
+
+        else {
+
+            // no match found
+            if (deferredMatch !is null) {
+                outputMatch(deferredMatch.length, deferredMatch.distance);
+                newPosition = deferredPosition + deferredMatch.length;
+                deferredPosition = -1;
+                deferredMatch = null;
+                updateHashtable(position + 1, newPosition);
+                position = newPosition;
+            }
+            else {
+                outputLiteral(istr[position]);
+                position = position + 1;
+            }
+
+        }
+
+    }
+
+    writeBits(0, 7); // end of block code
+    alignToByte();
+
+}
+
+void compressHuffmanOnly() {
+
+    int position;
+
+    writeBits(0x01, 1); // BFINAL = 0x01 (final block)
+    writeBits(0x01, 2); // BTYPE = 0x01 (compression with fixed Huffman codes)
+
+    for (position = 0; position < inLength;) {
+
+        outputLiteral(istr[position]);
+        position = position + 1;
+
+    }
+
+    writeBits(0, 7); // end of block code
+    alignToByte();
+
+}
+
+void store() {
+
+    // stored blocks are limited to 0xffff bytes
+
+    int start = 0;
+    int length = inLength;
+    int blockLength;
+    int BFINAL = 0x00; // BFINAL = 0x00 or 0x01 (if final block), BTYPE = 0x00 (no compression)
+
+    while (length > 0) {
+
+        if (length < 65535) {
+            blockLength = length;
+            BFINAL = 0x01;
+        }
+        else {
+            blockLength = 65535;
+            BFINAL = 0x00;
+        }
+
+        // write data header
+        bytes.write(cast(byte) BFINAL);
+        writeShortLSB(bytes, blockLength); // LEN
+        writeShortLSB(bytes, blockLength ^ 0xffff); // NLEN (one's complement of LEN)
+
+        // write actual data
+        bytes.write(istr, start, blockLength);
+
+        length = length - blockLength;
+        start = start + blockLength;
+
+    }
+
+}
+
+public byte[] deflate(byte[] input) {
+
+    istr = input;
+    inLength = input.length;
+
+    // write zlib header
+    bytes.write(cast(byte) 0x78); // window size = 0x70 (32768), compression method = 0x08
+    bytes.write(cast(byte) 0x9C); // compression level = 0x80 (default), check bits = 0x1C
+
+    // compute checksum
+    for (int i = 0; i < inLength; i++) {
+        updateAdler(istr[i]);
+    }
+
+    //store();
+
+    //compressHuffmanOnly();
+
+    compress();
+
+    // write checksum
+    writeInt(bytes, adler32);
+
+    return bytes.toByteArray();
+
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngEncoder.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,370 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngEncoder;
+
+import org.eclipse.swt.internal.image.LEDataOutputStream;
+import org.eclipse.swt.internal.image.PngDeflater;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.Compatibility;
+import org.eclipse.swt.internal.image.PngChunk;
+
+import tango.core.Exception;
+
+final class PngEncoder {
+
+    static const byte SIGNATURE[] = [cast(byte) '\211', cast(byte) 'P', cast(byte) 'N', cast(byte) 'G', cast(byte) '\r', cast(byte) '\n', cast(byte) '\032', cast(byte) '\n'];
+    static const byte TAG_IHDR[] = [cast(byte) 'I', cast(byte) 'H', cast(byte) 'D', cast(byte) 'R'];
+    static const byte TAG_PLTE[] = [cast(byte) 'P', cast(byte) 'L', cast(byte) 'T', cast(byte) 'E'];
+    static const byte TAG_TRNS[] = [cast(byte) 't', cast(byte) 'R', cast(byte) 'N', cast(byte) 'S'];
+    static const byte TAG_IDAT[] = [cast(byte) 'I', cast(byte) 'D', cast(byte) 'A', cast(byte) 'T'];
+    static const byte TAG_IEND[] = [cast(byte) 'I', cast(byte) 'E', cast(byte) 'N', cast(byte) 'D'];
+
+    ByteArrayOutputStream bytes;
+    PngChunk chunk;
+
+    ImageLoader loader;
+    ImageData data;
+    int transparencyType;
+
+    int width, height, bitDepth, colorType;
+
+    int compressionMethod = 0;
+    int filterMethod = 0;
+    int interlaceMethod = 0;
+
+public this(ImageLoader loader) {
+    this.bytes = new ByteArrayOutputStream(1024);
+    this.loader = loader;
+    this.data = loader.data[0];
+    this.transparencyType = data.getTransparencyType();
+
+    this.width = data.width;
+    this.height = data.height;
+
+    this.bitDepth = 8;
+
+    this.colorType = 2;
+
+    if (data.palette.isDirect) {
+        if (transparencyType is SWT.TRANSPARENCY_ALPHA) {
+            this.colorType = 6;
+        }
+    }
+    else {
+        this.colorType = 3;
+    }
+
+    if (!(colorType is 2 || colorType is 3 || colorType is 6)) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+}
+
+void writeShort(ByteArrayOutputStream baos, int theShort) {
+
+    byte byte1 = cast(byte) ((theShort >> 8) & 0xff);
+    byte byte2 = cast(byte) (theShort & 0xff);
+    byte[] temp = [byte1, byte2];
+    baos.write(temp, 0, 2);
+
+}
+
+void writeInt(ByteArrayOutputStream baos, int theInt) {
+
+    byte byte1 = cast(byte) ((theInt >> 24) & 0xff);
+    byte byte2 = cast(byte) ((theInt >> 16) & 0xff);
+    byte byte3 = cast(byte) ((theInt >> 8) & 0xff);
+    byte byte4 = cast(byte) (theInt & 0xff);
+    byte[] temp = [byte1, byte2, byte3, byte4];
+    baos.write(temp, 0, 4);
+
+}
+
+void writeChunk(byte[] tag, byte[] buffer) {
+
+    int bufferLength = (buffer !is null) ? buffer.length : 0;
+
+    chunk = new PngChunk(bufferLength);
+
+    writeInt(bytes, bufferLength);
+    bytes.write(tag, 0, 4);
+    chunk.setType(tag);
+    if (bufferLength !is 0) {
+        bytes.write(buffer, 0, bufferLength);
+        chunk.setData(buffer);
+    }
+    else {
+        chunk.setCRC(chunk.computeCRC());
+    }
+    writeInt(bytes, chunk.getCRC());
+
+}
+
+void writeSignature() {
+
+    bytes.write(SIGNATURE, 0, 8);
+
+}
+
+void writeHeader() {
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream(13);
+
+    writeInt(baos, width);
+    writeInt(baos, height);
+    baos.write(bitDepth);
+    baos.write(colorType);
+    baos.write(compressionMethod);
+    baos.write(filterMethod);
+    baos.write(interlaceMethod);
+
+    writeChunk(TAG_IHDR, baos.toByteArray());
+
+}
+
+void writePalette() {
+
+    RGB[] RGBs = data.palette.getRGBs();
+
+    if (RGBs.length > 256) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream(RGBs.length);
+
+    for (int i = 0; i < RGBs.length; i++) {
+
+        baos.write(cast(byte) RGBs[i].red);
+        baos.write(cast(byte) RGBs[i].green);
+        baos.write(cast(byte) RGBs[i].blue);
+
+    }
+
+    writeChunk(TAG_PLTE, baos.toByteArray());
+
+}
+
+void writeTransparency() {
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+    switch (transparencyType) {
+
+        case SWT.TRANSPARENCY_ALPHA:
+
+            int pixelValue, alphaValue;
+
+            byte[] alphas = new byte[data.palette.getRGBs().length];
+
+            for (int y = 0; y < height; y++) {
+
+                for (int x = 0; x < width; x++) {
+
+                    pixelValue = data.getPixel(x, y);
+                    alphaValue = data.getAlpha(x, y);
+
+                    alphas[pixelValue] = cast(byte) alphaValue;
+
+                }
+
+            }
+
+            baos.write(alphas, 0, alphas.length);
+
+            break;
+
+        case SWT.TRANSPARENCY_PIXEL:
+
+            int pixel = data.transparentPixel;
+
+            if (colorType is 2) {
+
+                int redMask = data.palette.redMask;
+                int redShift = data.palette.redShift;
+                int greenMask = data.palette.greenMask;
+                int greenShift = data.palette.greenShift;
+                int blueShift = data.palette.blueShift;
+                int blueMask = data.palette.blueMask;
+
+                int r = pixel & redMask;
+                r = (redShift < 0) ? r >>> -redShift : r << redShift;
+                int g = pixel & greenMask;
+                g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
+                int b = pixel & blueMask;
+                b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
+
+                writeShort(baos, r);
+                writeShort(baos, g);
+                writeShort(baos, b);
+
+            }
+
+            if (colorType is 3) {
+
+                byte[] padding = new byte[pixel + 1];
+
+                for (int i = 0; i < pixel; i++) {
+
+                    padding[i] = cast(byte) 255;
+
+                }
+
+                padding[pixel] = cast(byte) 0;
+
+                baos.write(padding, 0, padding.length);
+
+            }
+
+            break;
+        default:
+
+    }
+
+    writeChunk(TAG_TRNS, baos.toByteArray());
+
+}
+
+void writeImageData() {
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+    OutputStream os = Compatibility.newDeflaterOutputStream(baos);
+    if (os is null) os = baos;
+
+    if (colorType is 3) {
+
+        byte[] lineData = new byte[width];
+
+        for (int y = 0; y < height; y++) {
+
+            int filter = 0;
+            os.write(filter);
+
+            data.getPixels(0, y, width, lineData, 0);
+
+            for (int x = 0; x < lineData.length; x++) {
+
+                os.write(lineData[x]);
+
+            }
+
+        }
+
+    }
+
+    else {
+
+        int[] lineData = new int[width];
+        byte[] alphaData = null;
+        if (colorType is 6) {
+            alphaData = new byte[width];
+        }
+
+        int redMask = data.palette.redMask;
+        int redShift = data.palette.redShift;
+        int greenMask = data.palette.greenMask;
+        int greenShift = data.palette.greenShift;
+        int blueShift = data.palette.blueShift;
+        int blueMask = data.palette.blueMask;
+
+        for (int y = 0; y < height; y++) {
+
+            int filter = 0;
+            os.write(filter);
+
+            data.getPixels(0, y, width, lineData, 0);
+
+            if (colorType is 6) {
+                data.getAlphas(0, y, width, alphaData, 0);
+            }
+
+            for (int x = 0; x < lineData.length; x++) {
+
+                int pixel = lineData[x];
+
+                int r = pixel & redMask;
+                r = (redShift < 0) ? r >>> -redShift : r << redShift;
+                int g = pixel & greenMask;
+                g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
+                int b = pixel & blueMask;
+                b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
+
+                os.write(r);
+                os.write(g);
+                os.write(b);
+
+                if (colorType is 6) {
+                    os.write(alphaData[x]);
+                }
+
+            }
+
+        }
+
+    }
+
+    os.flush();
+    os.close();
+
+    byte[] compressed = baos.toByteArray();
+    if (os is baos) {
+        PngDeflater deflater = new PngDeflater();
+        compressed = deflater.deflate(compressed);
+    }
+
+    writeChunk(TAG_IDAT, compressed);
+
+}
+
+void writeEnd() {
+
+    writeChunk(TAG_IEND, null);
+
+}
+
+public void encode(LEDataOutputStream outputStream) {
+
+    try {
+
+        writeSignature();
+        writeHeader();
+
+        if (colorType is 3) {
+            writePalette();
+        }
+
+        bool transparencyAlpha = (transparencyType is SWT.TRANSPARENCY_ALPHA);
+        bool transparencyPixel = (transparencyType is SWT.TRANSPARENCY_PIXEL);
+        bool type2Transparency = (colorType is 2 && transparencyPixel);
+        bool type3Transparency = (colorType is 3 && (transparencyAlpha || transparencyPixel));
+
+        if (type2Transparency || type3Transparency) {
+            writeTransparency();
+        }
+
+        writeImageData();
+        writeEnd();
+
+        outputStream.write(bytes.toByteArray());
+
+    }
+
+    catch (IOException e) {
+
+        SWT.error(SWT.ERROR_IO, e);
+
+    }
+
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngFileReadState.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngFileReadState;
+
+
+class PngFileReadState {
+    bool readIHDR;
+    bool readPLTE;
+    bool readIDAT;
+    bool readIEND;
+
+    // Non - critical chunks
+    bool readTRNS;
+
+    // Set to true after IDATs have been read.
+    bool readPixelData;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngHuffmanTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngHuffmanTable;
+
+import org.eclipse.swt.internal.image.PngDecodingDataStream;
+
+public class PngHuffmanTable {
+    CodeLengthInfo[] codeLengthInfo;
+    int[] codeValues;
+
+    static const int MAX_CODE_LENGTH = 15;
+    static const int BAD_CODE = 0xFFFFFFF;
+    static const int incs[] = [1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1];
+
+this (int[] lengths) {
+    initialize(lengths);
+    generateTable(lengths);
+}
+
+private void initialize(int[] lengths) {
+    codeValues = new int[lengths.length];
+    for (int i = 0; i < codeValues.length; i++) {
+        codeValues[i] = i;
+    }
+
+    // minCodesByLength[n] : The smallest Huffman code of length n + 1.
+    // maxCodesByLength[n] : The largest Huffman code of length n + 1.
+    // indexesByLength[n] : Index into the values array. First value with a code of length n + 1.
+    codeLengthInfo = new CodeLengthInfo[MAX_CODE_LENGTH];
+    for (int i = 0; i < MAX_CODE_LENGTH; i++) {
+        codeLengthInfo[i] = new CodeLengthInfo();
+        codeLengthInfo[i].length = i;
+        codeLengthInfo[i].baseIndex = 0;
+        codeLengthInfo[i].min = BAD_CODE;
+        codeLengthInfo[i].max = -1;
+    }
+}
+
+private void generateTable(int[] lengths) {
+    // Sort the values using shellsort. Primary key is code size. Secondary key is value.
+    int codeValuesTemp;
+    for (int k = 0; k < 16; k++) {
+        for (int h = incs[k], i = h; i < lengths.length; i++) {
+            int v = lengths[i];
+            codeValuesTemp = codeValues[i];
+            int j = i;
+            while (j >= h && (lengths[j - h] > v || (lengths[j - h] is v && codeValues[j - h] > codeValuesTemp))) {
+                lengths[j] = lengths[j - h];
+                codeValues[j] = codeValues[j - h];
+                j -= h;
+            }
+            lengths[j] = v;
+            codeValues[j] = codeValuesTemp;
+        }
+    }
+
+    // These values in these arrays correspond to the elements of the
+    // "values" array. The Huffman code for codeValues[N] is codes[N]
+    // and the length of the code is lengths[N].
+    int[] codes = new int[lengths.length];
+    int lastLength = 0;
+    int code = 0;
+    for (int i = 0; i < lengths.length; i++) {
+        while (lastLength !is lengths[i]) {
+            lastLength++;
+            code <<= 1;
+        }
+        if (lastLength !is 0) {
+            codes[i] = code;
+            code++;
+        }
+    }
+
+    int last = 0;
+    for (int i = 0; i < lengths.length; i++) {
+        if (last !is lengths[i]) {
+            last = lengths[i];
+            codeLengthInfo[last - 1].baseIndex = i;
+            codeLengthInfo[last - 1].min = codes[i];
+        }
+        if (last !is 0) codeLengthInfo[last - 1].max = codes[i];
+    }
+}
+
+int getNextValue(PngDecodingDataStream stream) {
+    int code = stream.getNextIdatBit();
+    int codelength = 0;
+
+    // Here we are taking advantage of the fact that 1 bits are used as
+    // a prefix to the longer codeValues.
+    while (codelength < MAX_CODE_LENGTH && code > codeLengthInfo[codelength].max) {
+        code = ((code << 1) | stream.getNextIdatBit());
+        codelength++;
+    }
+    if (codelength >= MAX_CODE_LENGTH) stream.error();
+
+    // Now we have a Huffman code of length (codelength + 1) that
+    // is somewhere in the range
+    // minCodesByLength[codelength]..maxCodesByLength[codelength].
+    // This code is the (offset + 1)'th code of (codelength + 1);
+    int offset = code - codeLengthInfo[codelength].min;
+
+    // indexesByLength[codelength] is the first code of length (codelength + 1)
+    // so now we can look up the value for the Huffman code in the table.
+    int index = codeLengthInfo[codelength].baseIndex + offset;
+    return codeValues[index];
+}
+
+static class CodeLengthInfo {
+    int length;
+    int max;
+    int min;
+    int baseIndex;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngHuffmanTables.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngHuffmanTables;
+
+import org.eclipse.swt.internal.image.PngHuffmanTable;
+import org.eclipse.swt.internal.image.PngDecodingDataStream;
+import org.eclipse.swt.internal.image.PngLzBlockReader;
+
+public class PngHuffmanTables {
+    PngHuffmanTable literalTable;
+    PngHuffmanTable distanceTable;
+
+    static PngHuffmanTable FixedLiteralTable;
+    static PngHuffmanTable FixedDistanceTable;
+
+    static final int LiteralTableSize = 288;
+    static final int[] FixedLiteralLengths = [
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
+        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+    ];
+
+    static final int DistanceTableSize = 32;
+    static final int[] FixedDistanceLengths = [
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+    ];
+
+    static final int LengthCodeTableSize = 19;
+    static final int[] LengthCodeOrder = [
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
+        11, 4, 12, 3, 13, 2, 14, 1, 15
+    ];
+
+static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream)  {
+    return new PngHuffmanTables(stream);
+}
+static PngHuffmanTables getFixedTables() {
+    return new PngHuffmanTables();
+}
+
+private PngHuffmanTable getFixedLiteralTable() {
+    if (FixedLiteralTable is null) {
+        FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
+    }
+    return FixedLiteralTable;
+}
+
+private PngHuffmanTable getFixedDistanceTable() {
+    if (FixedDistanceTable is null) {
+        FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
+    }
+    return FixedDistanceTable;
+}
+
+private this () {
+    literalTable = getFixedLiteralTable();
+    distanceTable = getFixedDistanceTable();
+}
+
+private this (PngDecodingDataStream stream)  {
+    int literals = PngLzBlockReader.FIRST_LENGTH_CODE
+        + stream.getNextIdatBits(5);
+    int distances = PngLzBlockReader.FIRST_DISTANCE_CODE
+        + stream.getNextIdatBits(5);
+    int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE
+        + stream.getNextIdatBits(4);
+
+    if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
+        stream.error();
+    }
+
+    /* Tricky, tricky, tricky. The length codes are stored in
+     * a very odd order. (For the order, see the definition of
+     * the static field lengthCodeOrder.) Also, the data may
+     * not contain values for all the codes. It may just contain
+     * values for the first X number of codes. The table should
+     * be of size <LengthCodeTableSize> regardless of the number
+     * of values actually given in the table.
+     */
+    int[] lengthCodes = new int[LengthCodeTableSize];
+    for (int i = 0; i < codeLengthCodes; i++) {
+        lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
+    }
+    PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
+
+    int[] literalLengths = readLengths(
+        stream, literals, codeLengthsTable, LiteralTableSize);
+    int[] distanceLengths = readLengths(
+        stream, distances, codeLengthsTable, DistanceTableSize);
+
+    literalTable = new PngHuffmanTable(literalLengths);
+    distanceTable = new PngHuffmanTable(distanceLengths);
+}
+
+private int [] readLengths (PngDecodingDataStream stream,
+    int numLengths,
+    PngHuffmanTable lengthsTable,
+    int tableSize)
+{
+    int[] lengths = new int[tableSize];
+
+    for (int index = 0; index < numLengths;) {
+        int value = lengthsTable.getNextValue(stream);
+        if (value < 16) {
+            // Literal value
+            lengths[index] = value;
+            index++;
+        } else if (value is 16) {
+            // Repeat the previous code 3-6 times.
+            int count = stream.getNextIdatBits(2) + 3;
+            for (int i = 0; i < count; i++) {
+                lengths[index] = lengths [index - 1];
+                index++;
+            }
+        } else if (value is 17) {
+            // Repeat 0 3-10 times.
+            int count = stream.getNextIdatBits(3) + 3;
+            for (int i = 0; i < count; i++) {
+                lengths[index] = 0;
+                index++;
+            }
+        } else if (value is 18) {
+            // Repeat 0 11-138 times.
+            int count = stream.getNextIdatBits(7) + 11;
+            for (int i = 0; i < count; i++) {
+                lengths[index] = 0;
+                index++;
+            }
+        } else {
+            stream.error();
+        }
+    }
+    return lengths;
+}
+
+int getNextLiteralValue(PngDecodingDataStream stream)  {
+    return literalTable.getNextValue(stream);
+}
+
+int getNextDistanceValue(PngDecodingDataStream stream)  {
+    return distanceTable.getNextValue(stream);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIdatChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngIdatChunk;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngChunk;
+import java.lang.all;
+
+class PngIdatChunk : PngChunk {
+
+    static const int HEADER_BYTES_LENGTH = 2;
+    static const int ADLER_FIELD_LENGTH = 4;
+    static const int HEADER_BYTE1_DATA_OFFSET = DATA_OFFSET + 0;
+    static const int HEADER_BYTE2_DATA_OFFSET = DATA_OFFSET + 1;
+    static const int ADLER_DATA_OFFSET = DATA_OFFSET + 2; // plus variable compressed data length
+
+this(byte headerByte1, byte headerByte2, byte[] data, int adler) {
+    super(data.length + HEADER_BYTES_LENGTH + ADLER_FIELD_LENGTH);
+    setType(TYPE_IDAT);
+    reference[HEADER_BYTE1_DATA_OFFSET] = headerByte1;
+    reference[HEADER_BYTE2_DATA_OFFSET] = headerByte2;
+    System.arraycopy(data, 0, reference, DATA_OFFSET, data.length);
+    setInt32(ADLER_DATA_OFFSET, adler);
+    setCRC(computeCRC());
+}
+
+this(byte[] reference) {
+    super(reference);
+}
+
+override int getChunkType() {
+    return CHUNK_IDAT;
+}
+
+/**
+ * Answer whether the chunk is a valid IDAT chunk.
+ */
+override void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+    if (!readState.readIHDR
+        || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+        || readState.readIEND)
+    {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } else {
+        readState.readIDAT = true;
+    }
+
+    super.validate(readState, headerChunk);
+}
+
+byte getDataByteAtOffset(int offset) {
+    return reference[DATA_OFFSET + offset];
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIendChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngIendChunk;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngChunk;
+
+class PngIendChunk : PngChunk {
+
+this() {
+    super(0);
+    setType(TYPE_IEND);
+    setCRC(computeCRC());
+}
+
+this(byte[] reference){
+    super(reference);
+}
+
+override int getChunkType() {
+    return CHUNK_IEND;
+}
+
+/**
+ * Answer whether the chunk is a valid IEND chunk.
+ */
+override void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+    // An IEND chunk is invalid if no IHDR has been read.
+    // Or if a palette is required and has not been read.
+    // Or if no IDAT chunk has been read.
+    if (!readState.readIHDR
+        || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+        || !readState.readIDAT
+        || readState.readIEND)
+    {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } else {
+        readState.readIEND = true;
+    }
+
+    super.validate(readState, headerChunk);
+
+    // IEND chunks are not allowed to have any data.
+    if (getLength() > 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngIhdrChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngIhdrChunk;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngChunk;
+import tango.text.convert.Format;
+
+class PngIhdrChunk : PngChunk {
+    static const int IHDR_DATA_LENGTH = 13;
+
+    static const int WIDTH_DATA_OFFSET = DATA_OFFSET + 0;
+    static const int HEIGHT_DATA_OFFSET = DATA_OFFSET + 4;
+    static const int BIT_DEPTH_OFFSET = DATA_OFFSET + 8;
+    static const int COLOR_TYPE_OFFSET = DATA_OFFSET + 9;
+    static const int COMPRESSION_METHOD_OFFSET = DATA_OFFSET + 10;
+    static const int FILTER_METHOD_OFFSET = DATA_OFFSET + 11;
+    static const int INTERLACE_METHOD_OFFSET = DATA_OFFSET + 12;
+
+    static const byte COLOR_TYPE_GRAYSCALE = 0;
+    static const byte COLOR_TYPE_RGB = 2;
+    static const byte COLOR_TYPE_PALETTE = 3;
+    static const byte COLOR_TYPE_GRAYSCALE_WITH_ALPHA = 4;
+    static const byte COLOR_TYPE_RGB_WITH_ALPHA = 6;
+
+    static const int INTERLACE_METHOD_NONE = 0;
+    static const int INTERLACE_METHOD_ADAM7 = 1;
+
+    static const int FILTER_NONE = 0;
+    static const int FILTER_SUB = 1;
+    static const int FILTER_UP = 2;
+    static const int FILTER_AVERAGE = 3;
+    static const int FILTER_PAETH = 4;
+
+    static const byte[] ValidBitDepths = [ cast(byte)1, 2, 4, 8, 16];
+    static const byte[] ValidColorTypes = [ cast(byte)0, 2, 3, 4, 6];
+
+    int width, height;
+    byte bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod;
+
+this(int width, int height, byte bitDepth, byte colorType, byte compressionMethod, byte filterMethod, byte interlaceMethod) {
+    super(IHDR_DATA_LENGTH);
+    setType(TYPE_IHDR);
+    setWidth(width);
+    setHeight(height);
+    setBitDepth(bitDepth);
+    setColorType(colorType);
+    setCompressionMethod(compressionMethod);
+    setFilterMethod(filterMethod);
+    setInterlaceMethod(interlaceMethod);
+    setCRC(computeCRC());
+}
+
+/**
+ * Construct a PNGChunk using the reference bytes
+ * given.
+ */
+this(byte[] reference) {
+    super(reference);
+    if (reference.length <= IHDR_DATA_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    width = getInt32(WIDTH_DATA_OFFSET);
+    height = getInt32(HEIGHT_DATA_OFFSET);
+    bitDepth = reference[BIT_DEPTH_OFFSET];
+    colorType = reference[COLOR_TYPE_OFFSET];
+    compressionMethod = reference[COMPRESSION_METHOD_OFFSET];
+    filterMethod = reference[FILTER_METHOD_OFFSET];
+    interlaceMethod = reference[INTERLACE_METHOD_OFFSET];
+}
+
+override int getChunkType() {
+    return CHUNK_IHDR;
+}
+
+/**
+ * Get the image's width in pixels.
+ */
+int getWidth() {
+    return width;
+}
+
+/**
+ * Set the image's width in pixels.
+ */
+void setWidth(int value) {
+    setInt32(WIDTH_DATA_OFFSET, value);
+    width = value;
+}
+
+/**
+ * Get the image's height in pixels.
+ */
+int getHeight() {
+    return height;
+}
+
+/**
+ * Set the image's height in pixels.
+ */
+void setHeight(int value) {
+    setInt32(HEIGHT_DATA_OFFSET, value);
+    height = value;
+}
+
+/**
+ * Get the image's bit depth.
+ * This is limited to the values 1, 2, 4, 8, or 16.
+ */
+byte getBitDepth() {
+    return bitDepth;
+}
+
+/**
+ * Set the image's bit depth.
+ * This is limited to the values 1, 2, 4, 8, or 16.
+ */
+void setBitDepth(byte value) {
+    reference[BIT_DEPTH_OFFSET] = value;
+    bitDepth = value;
+}
+
+/**
+ * Get the image's color type.
+ * This is limited to the values:
+ * 0 - Grayscale image.
+ * 2 - RGB triple.
+ * 3 - Palette.
+ * 4 - Grayscale with Alpha channel.
+ * 6 - RGB with Alpha channel.
+ */
+byte getColorType() {
+    return colorType;
+}
+
+/**
+ * Set the image's color type.
+ * This is limited to the values:
+ * 0 - Grayscale image.
+ * 2 - RGB triple.
+ * 3 - Palette.
+ * 4 - Grayscale with Alpha channel.
+ * 6 - RGB with Alpha channel.
+ */
+void setColorType(byte value) {
+    reference[COLOR_TYPE_OFFSET] = value;
+    colorType = value;
+}
+
+/**
+ * Get the image's compression method.
+ * This value must be 0.
+ */
+byte getCompressionMethod() {
+    return compressionMethod;
+}
+
+/**
+ * Set the image's compression method.
+ * This value must be 0.
+ */
+void setCompressionMethod(byte value) {
+    reference[COMPRESSION_METHOD_OFFSET] = value;
+    compressionMethod = value;
+}
+
+/**
+ * Get the image's filter method.
+ * This value must be 0.
+ */
+byte getFilterMethod() {
+    return filterMethod;
+}
+
+/**
+ * Set the image's filter method.
+ * This value must be 0.
+ */
+void setFilterMethod(byte value) {
+    reference[FILTER_METHOD_OFFSET] = value;
+    filterMethod = value;
+}
+
+/**
+ * Get the image's interlace method.
+ * This value is limited to:
+ * 0 - No interlacing used.
+ * 1 - Adam7 interlacing used.
+ */
+byte getInterlaceMethod() {
+    return interlaceMethod;
+}
+
+/**
+ * Set the image's interlace method.
+ * This value is limited to:
+ * 0 - No interlacing used.
+ * 1 - Adam7 interlacing used.
+ */
+void setInterlaceMethod(byte value) {
+    reference[INTERLACE_METHOD_OFFSET] = value;
+    interlaceMethod = value;
+}
+
+/**
+ * Answer whether the chunk is a valid IHDR chunk.
+ */
+override void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+    // An IHDR chunk is invalid if any other chunk has
+    // been read.
+    if (readState.readIHDR
+        || readState.readPLTE
+        || readState.readIDAT
+        || readState.readIEND)
+    {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } else {
+        readState.readIHDR = true;
+    }
+
+    super.validate(readState, headerChunk);
+
+    if (length !is IHDR_DATA_LENGTH) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    if (compressionMethod !is 0) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    if (interlaceMethod !is INTERLACE_METHOD_NONE &&
+        interlaceMethod !is INTERLACE_METHOD_ADAM7) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+
+    bool colorTypeIsValid = false;
+    for (int i = 0; i < ValidColorTypes.length; i++) {
+        if (ValidColorTypes[i] is colorType) {
+            colorTypeIsValid = true;
+            break;
+        }
+    }
+    if (!colorTypeIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    bool bitDepthIsValid = false;
+    for (int i = 0; i < ValidBitDepths.length; i++) {
+        if (ValidBitDepths[i] is bitDepth) {
+            bitDepthIsValid = true;
+            break;
+        }
+    }
+    if (!bitDepthIsValid) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    if ((colorType is COLOR_TYPE_RGB
+        || colorType is COLOR_TYPE_RGB_WITH_ALPHA
+        || colorType is COLOR_TYPE_GRAYSCALE_WITH_ALPHA)
+        && bitDepth < 8)
+    {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+
+    if (colorType is COLOR_TYPE_PALETTE && bitDepth > 8) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+}
+
+String getColorTypeString() {
+    switch (colorType) {
+        case COLOR_TYPE_GRAYSCALE:              return "Grayscale";
+        case COLOR_TYPE_RGB:                    return "RGB";
+        case COLOR_TYPE_PALETTE:                return "Palette";
+        case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:   return "Grayscale with Alpha";
+        case COLOR_TYPE_RGB_WITH_ALPHA:         return "RGB with Alpha";
+        default:                                return "Unknown - " ~ cast(char)colorType;
+    }
+}
+
+String getFilterMethodString() {
+    switch (filterMethod) {
+        case FILTER_NONE:       return "None";
+        case FILTER_SUB:        return "Sub";
+        case FILTER_UP:         return "Up";
+        case FILTER_AVERAGE:    return "Average";
+        case FILTER_PAETH:      return "Paeth";
+        default:                return "Unknown";
+    }
+}
+
+String getInterlaceMethodString() {
+    switch (interlaceMethod) {
+        case INTERLACE_METHOD_NONE:     return "Not Interlaced";
+        case INTERLACE_METHOD_ADAM7:    return "Interlaced - ADAM7";
+        default:                return "Unknown";
+    }
+}
+
+override String contributeToString() {
+    return Format( "\n\tWidth: {}\n\tHeight: {}\n\tBit Depth: {}\n\tColor Type: {}\n\tCompression Method: {}\n\tFilter Method: {}\n\tInterlace Method: {}",
+        width, height, bitDepth, getColorTypeString(), compressionMethod, getFilterMethodString(), getInterlaceMethodString() );
+}
+
+bool getMustHavePalette() {
+    return colorType is COLOR_TYPE_PALETTE;
+}
+
+bool getCanHavePalette() {
+    return colorType !is COLOR_TYPE_GRAYSCALE &&
+        colorType !is COLOR_TYPE_GRAYSCALE_WITH_ALPHA;
+}
+
+/**
+ * Answer the pixel size in bits based on the color type
+ * and bit depth.
+ */
+int getBitsPerPixel() {
+    switch (colorType) {
+        case COLOR_TYPE_RGB_WITH_ALPHA:
+            return 4 * bitDepth;
+        case COLOR_TYPE_RGB:
+            return 3 * bitDepth;
+        case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+            return 2 * bitDepth;
+        case COLOR_TYPE_GRAYSCALE:
+        case COLOR_TYPE_PALETTE:
+            return bitDepth;
+        default:
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+            return 0;
+    }
+}
+
+/**
+ * Answer the pixel size in bits based on the color type
+ * and bit depth.
+ */
+int getSwtBitsPerPixel() {
+    switch (colorType) {
+        case COLOR_TYPE_RGB_WITH_ALPHA:
+        case COLOR_TYPE_RGB:
+        case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+            return 24;
+        case COLOR_TYPE_GRAYSCALE:
+        case COLOR_TYPE_PALETTE:
+            return Math.min(bitDepth, 8);
+        default:
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+            return 0;
+    }
+}
+
+int getFilterByteOffset() {
+    if (bitDepth < 8) return 1;
+    return getBitsPerPixel() / 8;
+}
+
+bool usesDirectColor() {
+    switch (colorType) {
+        case COLOR_TYPE_GRAYSCALE:
+        case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+        case COLOR_TYPE_RGB:
+        case COLOR_TYPE_RGB_WITH_ALPHA:
+            return true;
+        default:
+            return false;
+    }
+}
+
+PaletteData createGrayscalePalette() {
+    int depth = Math.min(bitDepth, 8);
+    int max = (1 << depth) - 1;
+    int delta = 255 / max;
+    int gray = 0;
+    RGB[] rgbs = new RGB[max + 1];
+    for (int i = 0; i <= max; i++) {
+        rgbs[i] = new RGB(gray, gray, gray);
+        gray += delta;
+    }
+    return new PaletteData(rgbs);
+}
+
+PaletteData getPaletteData() {
+    switch (colorType) {
+        case COLOR_TYPE_GRAYSCALE:
+            return createGrayscalePalette();
+        case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+        case COLOR_TYPE_RGB:
+        case COLOR_TYPE_RGB_WITH_ALPHA:
+            return new PaletteData(0xFF0000, 0xFF00, 0xFF);
+        default:
+            return null;
+    }
+}
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngInputStream;
+
+import java.io.InputStream;
+import java.lang.System;
+import org.eclipse.swt.internal.image.PngIdatChunk;
+import org.eclipse.swt.internal.image.PngChunkReader;
+import org.eclipse.swt.internal.image.PngChunk;
+
+import tango.core.Exception;
+import Math = tango.math.Math;
+
+public class PngInputStream : InputStream {
+
+    alias InputStream.read read;
+
+    PngChunkReader reader;
+    PngChunk chunk;
+    int offset, length;
+
+    final static int DATA_OFFSET = 8;
+
+public this(PngIdatChunk chunk, PngChunkReader reader) {
+    this.chunk = chunk;
+    this.reader = reader;
+    length = chunk.getLength();
+    offset = 0;
+}
+
+private bool checkChunk()  {
+    while (offset is length) {
+        chunk = reader.readNextChunk();
+        if (chunk is null) throw new IOException("no data");
+        if (chunk.getChunkType() is PngChunk.CHUNK_IEND) return false;
+        if (chunk.getChunkType() !is PngChunk.CHUNK_IDAT) throw new IOException("");
+        length = chunk.getLength();
+        offset = 0;
+    }
+    return true;
+}
+
+public override void close()  {
+    chunk = null;
+}
+
+public override int read()  {
+    if (chunk is null) throw new IOException("");
+    if (offset is length && !checkChunk()) return -1;
+    int b = chunk.reference[DATA_OFFSET + offset] & 0xFF;
+    offset++;
+    return b;
+}
+
+public override int read(byte[] b, int off, int len)  {
+    if (chunk is null) throw new IOException("");
+    if (offset is length && !checkChunk()) return -1;
+    len = Math.min(len, length - offset);
+    System.arraycopy(chunk.reference, DATA_OFFSET + offset, b, off, len);
+    offset += len;
+    return len;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngLzBlockReader.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngLzBlockReader;
+
+import org.eclipse.swt.internal.image.PngDecodingDataStream;
+import org.eclipse.swt.internal.image.PngHuffmanTables;
+
+public class PngLzBlockReader {
+    bool isLastBlock;
+    byte compressionType;
+    int uncompressedBytesRemaining;
+    PngDecodingDataStream stream;
+    PngHuffmanTables huffmanTables;
+
+    byte[] window;
+    int windowIndex;
+    int copyIndex;
+    int copyBytesRemaining;
+
+    static const int UNCOMPRESSED = 0;
+    static const int COMPRESSED_FIXED = 1;
+    static const int COMPRESSED_DYNAMIC = 2;
+
+    static const int END_OF_COMPRESSED_BLOCK = 256;
+    static const int FIRST_LENGTH_CODE = 257;
+    static const int LAST_LENGTH_CODE = 285;
+    static const int FIRST_DISTANCE_CODE = 1;
+    static const int LAST_DISTANCE_CODE = 29;
+    static const int FIRST_CODE_LENGTH_CODE = 4;
+    static const int LAST_CODE_LENGTH_CODE = 19;
+
+    static const int[] lengthBases = [
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
+        31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
+    ];
+    static const int[] extraLengthBits = [
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
+    ];
+    static const int[] distanceBases = [
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129,
+        193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097,
+        6145, 8193, 12289, 16385, 24577,
+    ];
+    static const int[] extraDistanceBits = [
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,  7,
+        8,  8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13,
+    ];
+
+
+this(PngDecodingDataStream stream) {
+    this.stream = stream;
+    isLastBlock = false;
+}
+
+void setWindowSize(int windowSize) {
+    window = new byte[windowSize];
+}
+
+void readNextBlockHeader()  {
+    isLastBlock = stream.getNextIdatBit() !is 0;
+    compressionType = cast(byte)(stream.getNextIdatBits(2) & 0xFF);
+    if (compressionType > 2) stream.error();
+
+    if (compressionType is UNCOMPRESSED) {
+        byte b1 = stream.getNextIdatByte();
+        byte b2 = stream.getNextIdatByte();
+        byte b3 = stream.getNextIdatByte();
+        byte b4 = stream.getNextIdatByte();
+        if (b1 !is ~b3 || b2 !is ~b4) stream.error();
+        uncompressedBytesRemaining = (b1 & 0xFF) | ((b2 & 0xFF) << 8);
+    } else if (compressionType is COMPRESSED_DYNAMIC) {
+        huffmanTables = PngHuffmanTables.getDynamicTables(stream);
+    } else {
+        huffmanTables = PngHuffmanTables.getFixedTables();
+    }
+}
+
+byte getNextByte()  {
+    if (compressionType is UNCOMPRESSED) {
+        if (uncompressedBytesRemaining is 0) {
+            readNextBlockHeader();
+            return getNextByte();
+        }
+        uncompressedBytesRemaining--;
+        return stream.getNextIdatByte();
+    } else {
+        byte value = getNextCompressedByte();
+        if (value is END_OF_COMPRESSED_BLOCK) {
+            if (isLastBlock) stream.error();
+            readNextBlockHeader();
+            return getNextByte();
+        } else {
+            return value;
+        }
+    }
+}
+
+private void assertBlockAtEnd()  {
+    if (compressionType is UNCOMPRESSED) {
+        if (uncompressedBytesRemaining > 0) stream.error();
+    } else if (copyBytesRemaining > 0 ||
+        (huffmanTables.getNextLiteralValue(stream) !is END_OF_COMPRESSED_BLOCK))
+    {
+        stream.error();
+    }
+}
+void assertCompressedDataAtEnd()  {
+    assertBlockAtEnd();
+    while (!isLastBlock) {
+        readNextBlockHeader();
+        assertBlockAtEnd();
+    }
+}
+
+private byte getNextCompressedByte()  {
+    if (copyBytesRemaining > 0) {
+        byte value = window[copyIndex];
+        window[windowIndex] = value;
+        copyBytesRemaining--;
+
+        copyIndex++;
+        windowIndex++;
+        if (copyIndex is window.length) copyIndex = 0;
+        if (windowIndex is window.length) windowIndex = 0;
+
+        return value;
+    }
+
+    int value = huffmanTables.getNextLiteralValue(stream);
+    if (value < END_OF_COMPRESSED_BLOCK) {
+        window[windowIndex] = cast(byte) (value & 0xFF);
+        windowIndex++;
+        if (windowIndex >= window.length) windowIndex = 0;
+        return cast(byte) (value & 0xFF);
+    } else if (value is END_OF_COMPRESSED_BLOCK) {
+        readNextBlockHeader();
+        return getNextByte();
+    } else if (value <= LAST_LENGTH_CODE) {
+        int extraBits = extraLengthBits[value - FIRST_LENGTH_CODE];
+        int length = lengthBases[value - FIRST_LENGTH_CODE];
+        if (extraBits > 0) {
+            length += stream.getNextIdatBits(extraBits);
+        }
+
+        value = huffmanTables.getNextDistanceValue(stream);
+        if (value > LAST_DISTANCE_CODE) stream.error();
+        extraBits = extraDistanceBits[value];
+        int distance = distanceBases[value];
+        if (extraBits > 0) {
+            distance += stream.getNextIdatBits(extraBits);
+        }
+
+        copyIndex = windowIndex - distance;
+        if (copyIndex < 0) copyIndex += window.length;
+
+        copyBytesRemaining = length;
+        return getNextCompressedByte();
+    } else {
+        stream.error();
+        return 0;
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngPlteChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngPlteChunk;
+
+import java.lang.all;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.image.PngChunk;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+
+import tango.text.convert.Format;
+
+class PngPlteChunk : PngChunk {
+
+    int paletteSize;
+
+this(PaletteData palette) {
+    super(palette.getRGBs().length * 3);
+    paletteSize = length / 3;
+    setType(TYPE_PLTE);
+    setPaletteData(palette);
+    setCRC(computeCRC());
+}
+
+this(byte[] reference){
+    super(reference);
+    paletteSize = length / 3;
+}
+
+override int getChunkType() {
+    return CHUNK_PLTE;
+}
+
+/**
+ * Get the number of colors in this palette.
+ */
+int getPaletteSize() {
+    return paletteSize;
+}
+
+/**
+ * Get a PaletteData object representing the colors
+ * stored in this PLTE chunk.
+ * The result should be cached as the PLTE chunk
+ * does not store the palette data created.
+ */
+PaletteData getPaletteData() {
+    RGB[] rgbs = new RGB[paletteSize];
+//  int start = DATA_OFFSET;
+//  int end = DATA_OFFSET + length;
+    for (int i = 0; i < rgbs.length; i++) {
+        int offset = DATA_OFFSET + (i * 3);
+        int red = reference[offset] & 0xFF;
+        int green = reference[offset + 1] & 0xFF;
+        int blue = reference[offset + 2] & 0xFF;
+        rgbs[i] = new RGB(red, green, blue);
+    }
+    return new PaletteData(rgbs);
+}
+
+/**
+ * Set the data of a PLTE chunk to the colors
+ * stored in the specified PaletteData object.
+ */
+void setPaletteData(PaletteData palette) {
+    RGB[] rgbs = palette.getRGBs();
+    for (int i = 0; i < rgbs.length; i++) {
+        int offset = DATA_OFFSET + (i * 3);
+        reference[offset] = cast(byte) rgbs[i].red;
+        reference[offset + 1] = cast(byte) rgbs[i].green;
+        reference[offset + 2] = cast(byte) rgbs[i].blue;
+    }
+}
+
+/**
+ * Answer whether the chunk is a valid PLTE chunk.
+ */
+override void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
+    // A PLTE chunk is invalid if no IHDR has been read or if any PLTE,
+    // IDAT, or IEND chunk has been read.
+    if (!readState.readIHDR
+        || readState.readPLTE
+        || readState.readTRNS
+        || readState.readIDAT
+        || readState.readIEND)
+    {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } else {
+        readState.readPLTE = true;
+    }
+
+    super.validate(readState, headerChunk);
+
+    // Palettes cannot be included in grayscale images.
+    //
+    // Note: just ignore the palette.
+//  if (!headerChunk.getCanHavePalette()) SWT.error(SWT.ERROR_INVALID_IMAGE);
+
+    // Palette chunks' data fields must be event multiples
+    // of 3. Each 3-byte group represents an RGB value.
+    if (getLength() % 3 !is 0) SWT.error(SWT.ERROR_INVALID_IMAGE);   
+
+    // Palettes cannot have more entries than 2^bitDepth
+    // where bitDepth is the bit depth of the image given
+    // in the IHDR chunk.
+    if (1 << headerChunk.getBitDepth() < paletteSize) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+
+    // Palettes cannot have more than 256 entries.
+    if (256 < paletteSize) SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+
+override String contributeToString() {
+    return Format("\n\tPalette size:{}", paletteSize );
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/PngTrnsChunk.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.PngTrnsChunk;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.image.PngChunk;
+import org.eclipse.swt.internal.image.PNGFileFormat;
+import org.eclipse.swt.internal.image.PngFileReadState;
+import org.eclipse.swt.internal.image.PngIhdrChunk;
+import org.eclipse.swt.internal.image.PngPlteChunk;
+
+public class PngTrnsChunk : PngChunk {
+
+    alias PngChunk.validate validate;
+
+    static const int TRANSPARENCY_TYPE_PIXEL = 0;
+    static const int TRANSPARENCY_TYPE_ALPHAS = 1;
+    static const int RGB_DATA_LENGTH = 6;
+
+this(RGB rgb) {
+    super(RGB_DATA_LENGTH);
+    setType(TYPE_tRNS);
+    setInt16(DATA_OFFSET, rgb.red);
+    setInt16(DATA_OFFSET + 2, rgb.green);
+    setInt16(DATA_OFFSET + 4, rgb.blue);
+    setCRC(computeCRC());
+}
+
+this(byte[] reference){
+    super(reference);
+}
+
+override int getChunkType() {
+    return CHUNK_tRNS;
+}
+
+void validateLength(PngIhdrChunk header, PngPlteChunk paletteChunk) {
+    bool valid;
+    switch (header.getColorType()) {
+        case PngIhdrChunk.COLOR_TYPE_RGB:
+            // Three 2-byte values (RGB)
+            valid = getLength() is 6;
+            break;
+        case PngIhdrChunk.COLOR_TYPE_PALETTE:
+            // Three 2-byte values (RGB)
+            valid = getLength() <= paletteChunk.getLength();
+            break;
+        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
+            // One 2-byte value
+            valid = getLength() is 2;
+            break;
+        // Cannot use both Alpha and tRNS
+        case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
+        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
+        default:
+            valid = false;
+    }
+    if (!valid) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+}
+
+/**
+ * Answer whether the chunk is a valid tRNS chunk.
+ */
+void validate(PngFileReadState readState, PngIhdrChunk headerChunk, PngPlteChunk paletteChunk) {
+    if (!readState.readIHDR
+        || (headerChunk.getMustHavePalette() && !readState.readPLTE)
+        || readState.readIDAT
+        || readState.readIEND)
+    {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    } else {
+        readState.readTRNS = true;
+    }
+
+    validateLength(headerChunk, paletteChunk);
+
+    super.validate(readState, headerChunk);
+}
+
+
+int getTransparencyType(PngIhdrChunk header) {
+    if (header.getColorType() is PngIhdrChunk.COLOR_TYPE_PALETTE) {
+        return TRANSPARENCY_TYPE_ALPHAS;
+    }
+    return TRANSPARENCY_TYPE_PIXEL;
+}
+
+/**
+ * Answer the transparent pixel RGB value.
+ * This is not valid for palette color types.
+ * This is not valid for alpha color types.
+ * This will convert a grayscale value into
+ * a palette index.
+ * It will compress a 6 byte RGB into a 3 byte
+ * RGB.
+ */
+int getSwtTransparentPixel(PngIhdrChunk header) {
+    switch (header.getColorType()) {
+        case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
+            int gray = ((reference[DATA_OFFSET] & 0xFF) << 8)
+                + (reference[DATA_OFFSET + 1] & 0xFF);
+            if (header.getBitDepth() > 8) {
+                return PNGFileFormat.compress16BitDepthTo8BitDepth(gray);
+            }
+            return gray & 0xFF;
+        case PngIhdrChunk.COLOR_TYPE_RGB:
+            int red = ((reference[DATA_OFFSET] & 0xFF) << 8)
+                | (reference[DATA_OFFSET + 1] & 0xFF);
+            int green = ((reference[DATA_OFFSET + 2] & 0xFF) << 8)
+                | (reference[DATA_OFFSET + 3] & 0xFF);
+            int blue = ((reference[DATA_OFFSET + 4] & 0xFF) << 8)
+                | (reference[DATA_OFFSET + 5] & 0xFF);
+            if (header.getBitDepth() > 8) {
+                red = PNGFileFormat.compress16BitDepthTo8BitDepth(red);
+                green = PNGFileFormat.compress16BitDepthTo8BitDepth(green);
+                blue = PNGFileFormat.compress16BitDepthTo8BitDepth(blue);
+            }
+            return (red << 16) | (green << 8) | blue;
+        default:
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+            return -1;
+    }
+}
+
+/**
+ * Answer an array of Alpha values that correspond to the
+ * colors in the palette.
+ * This is only valid for the COLOR_TYPE_PALETTE color type.
+ */
+byte[] getAlphaValues(PngIhdrChunk header, PngPlteChunk paletteChunk) {
+    if (header.getColorType() !is PngIhdrChunk.COLOR_TYPE_PALETTE) {
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+    byte[] alphas = new byte[paletteChunk.getPaletteSize()];
+    int dataLength = getLength();
+    int i = 0;
+    for (i = 0; i < dataLength; i++) {
+        alphas[i] = reference[DATA_OFFSET + i];
+    }
+    /**
+     * Any palette entries which do not have a corresponding
+     * alpha value in the tRNS chunk are spec'd to have an
+     * alpha of 255.
+     */
+    for (int j = i; j < alphas.length; j++) {
+        alphas[j] = cast(byte) 255;
+    }
+    return alphas;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFDirectory.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,634 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.TIFFDirectory;
+
+import org.eclipse.swt.internal.image.TIFFRandomFileAccess;
+import org.eclipse.swt.internal.image.TIFFModifiedHuffmanCodec;
+import org.eclipse.swt.internal.image.LEDataOutputStream;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoaderEvent;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.SWT;
+import java.lang.all;
+
+final class TIFFDirectory {
+
+    TIFFRandomFileAccess file;
+    bool isLittleEndian;
+    ImageLoader loader;
+    int depth;
+
+    /* Directory fields */
+    int imageWidth;
+    int imageLength;
+    int[] bitsPerSample;
+    int compression;
+    int photometricInterpretation;
+    int[] stripOffsets;
+    int samplesPerPixel;
+    int rowsPerStrip;
+    int[] stripByteCounts;
+    int t4Options;
+    int colorMapOffset;
+
+    /* Encoder fields */
+    ImageData image;
+    LEDataOutputStream ostr;
+
+    static const int NO_VALUE = -1;
+
+    static const short TAG_ImageWidth = 256;
+    static const short TAG_ImageLength = 257;
+    static const short TAG_BitsPerSample = 258;
+    static const short TAG_Compression = 259;
+    static const short TAG_PhotometricInterpretation = 262;
+    static const short TAG_StripOffsets = 273;
+    static const short TAG_SamplesPerPixel = 277;
+    static const short TAG_RowsPerStrip = 278;
+    static const short TAG_StripByteCounts = 279;
+    static const short TAG_XResolution = 282;
+    static const short TAG_YResolution = 283;
+    static const short TAG_T4Options = 292;
+    static const short TAG_ResolutionUnit = 296;
+    static const short TAG_ColorMap = 320;
+
+    static const int TYPE_BYTE = 1;
+    static const int TYPE_ASCII = 2;
+    static const int TYPE_SHORT = 3;
+    static const int TYPE_LONG = 4;
+    static const int TYPE_RATIONAL = 5;
+
+    /* Different compression schemes */
+    static const int COMPRESSION_NONE = 1;
+    static const int COMPRESSION_CCITT_3_1 = 2;
+    static const int COMPRESSION_PACKBITS = 32773;
+
+    static const int IFD_ENTRY_SIZE = 12;
+
+public this(TIFFRandomFileAccess file, bool isLittleEndian, ImageLoader loader) {
+    this.file = file;
+    this.isLittleEndian = isLittleEndian;
+    this.loader = loader;
+}
+
+public this(ImageData image) {
+    this.image = image;
+}
+
+/* PackBits decoder */
+int decodePackBits(byte[] src, byte[] dest, int offsetDest) {
+    int destIndex = offsetDest;
+    int srcIndex = 0;
+    while (srcIndex < src.length) {
+        byte n = src[srcIndex];
+        if (0 <= n && n <= 127) {
+            /* Copy next n+1 bytes literally */
+            System.arraycopy(src, ++srcIndex, dest, destIndex, n + 1);
+            srcIndex += n + 1;
+            destIndex += n + 1;
+        } else if (-127 <= n && n <= -1) {
+            /* Copy next byte -n+1 times */
+            byte value = src[++srcIndex];
+            for (int j = 0; j < -n + 1; j++) {
+                dest[destIndex++] = value;
+            }
+            srcIndex++;
+        } else {
+            /* Noop when n is -128 */
+            srcIndex++;
+        }
+    }
+    /* Number of bytes copied */
+    return destIndex - offsetDest;
+}
+
+int getEntryValue(int type, byte[] buffer, int index) {
+    return toInt(buffer, index + 8, type);
+}
+
+void getEntryValue(int type, byte[] buffer, int index, int[] values)  {
+    int start = index + 8;
+    int size;
+    int offset = toInt(buffer, start, TYPE_LONG);
+    switch (type) {
+        case TYPE_SHORT: size = 2; break;
+        case TYPE_LONG: size = 4; break;
+        case TYPE_RATIONAL: size = 8; break;
+        case TYPE_ASCII:
+        case TYPE_BYTE: size = 1; break;
+        default: SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT); return;
+    }
+    if (values.length * size > 4) {
+        buffer = new byte[values.length * size];
+        file.seek(offset);
+        file.read(buffer);
+        start = 0;
+    }
+    for (int i = 0; i < values.length; i++) {
+        values[i] = toInt(buffer, start + i * size, type);
+    }
+}
+
+void decodePixels(ImageData image)  {
+    /* Each row is byte aligned */
+    byte[] imageData = new byte[(imageWidth * depth + 7) / 8 * imageLength];
+    image.data = imageData;
+    int destIndex = 0;
+    int length = stripOffsets.length;
+    for (int i = 0; i < length; i++) {
+        /* Read a strip */
+        byte[] data = new byte[](stripByteCounts[i]);
+        file.seek(stripOffsets[i]);
+        file.read(data);
+        if (compression is COMPRESSION_NONE) {
+            System.arraycopy(data, 0, imageData, destIndex, data.length);
+            destIndex += data.length;
+        } else if (compression is COMPRESSION_PACKBITS) {
+            destIndex += decodePackBits(data, imageData, destIndex);
+        } else if (compression is COMPRESSION_CCITT_3_1 || compression is 3) {
+            TIFFModifiedHuffmanCodec codec = new TIFFModifiedHuffmanCodec();
+            int nRows = rowsPerStrip;
+            if (i is length -1) {
+                int n = imageLength % rowsPerStrip;
+                if (n !is 0) nRows = n;
+            }
+            destIndex += codec.decode(data, imageData, destIndex, imageWidth, nRows);
+        }
+        if (loader.hasListeners()) {
+            loader.notifyListeners(new ImageLoaderEvent(loader, image, i, i is length - 1));
+        }
+    }
+}
+
+PaletteData getColorMap()  {
+    int numColors = 1 << bitsPerSample[0];
+    /* R, G, B entries are 16 bit wide (2 bytes) */
+    int numBytes = 3 * 2 * numColors;
+    byte[] buffer = new byte[numBytes];
+    file.seek(colorMapOffset);
+    file.read(buffer);
+    RGB[] colors = new RGB[numColors];
+    /**
+     * SWT does not support 16-bit depth color formats.
+     * Convert the 16-bit data to 8-bit data.
+     * The correct way to do this is to multiply each
+     * 16 bit value by the value:
+     * (2^8 - 1) / (2^16 - 1).
+     * The fast way to do this is just to drop the low
+     * byte of the 16-bit value.
+     */
+    int offset = isLittleEndian ? 1 : 0;
+    int startG = 2 * numColors;
+    int startB = startG + 2 * numColors;
+    for (int i = 0; i < numColors; i++) {
+        int r = buffer[offset] & 0xFF;
+        int g = buffer[startG + offset] & 0xFF;
+        int b = buffer[startB + offset] & 0xFF;
+        colors[i] = new RGB(r, g, b);
+        offset += 2;
+    }
+    return new PaletteData(colors);
+}
+
+PaletteData getGrayPalette() {
+    int numColors = 1 << bitsPerSample[0];
+    RGB[] rgbs = new RGB[numColors];
+    for (int i = 0; i < numColors; i++) {
+        int value = i * 0xFF / (numColors - 1);
+        if (photometricInterpretation is 0) value = 0xFF - value;
+        rgbs[i] = new RGB(value, value, value);
+    }
+    return new PaletteData(rgbs);
+}
+
+PaletteData getRGBPalette(int bitsR, int bitsG, int bitsB) {
+    int blueMask = 0;
+    for (int i = 0; i < bitsB; i++) {
+        blueMask |= 1 << i;
+    }
+    int greenMask = 0;
+    for (int i = bitsB; i < bitsB + bitsG; i++) {
+        greenMask |= 1 << i;
+    }
+    int redMask = 0;
+    for (int i = bitsB + bitsG; i < bitsB + bitsG + bitsR; i++) {
+        redMask |= 1 << i;
+    }
+    return new PaletteData(redMask, greenMask, blueMask);
+}
+
+int formatStrips(int rowByteSize, int nbrRows, byte[] data, int maxStripByteSize, int offsetPostIFD, int extraBytes, int[][] strips) {
+    /*
+    * Calculate the nbr of required strips given the following requirements:
+    * - each strip should, if possible, not be greater than maxStripByteSize
+    * - each strip should contain 1 or more entire rows
+    *
+    * Format the strip fields arrays so that the image data is stored in one
+    * contiguous block. This block is stored after the IFD and after any tag
+    * info described in the IFD.
+    */
+    int n, nbrRowsPerStrip;
+    if (rowByteSize > maxStripByteSize) {
+        /* Each strip contains 1 row */
+        n = data.length / rowByteSize;
+        nbrRowsPerStrip = 1;
+    } else {
+        int nbr = (data.length + maxStripByteSize - 1) / maxStripByteSize;
+        nbrRowsPerStrip = nbrRows / nbr;
+        n = (nbrRows + nbrRowsPerStrip - 1) / nbrRowsPerStrip;
+    }
+    int stripByteSize = rowByteSize * nbrRowsPerStrip;
+
+    int[] offsets = new int[n];
+    int[] counts = new int[n];
+    /*
+    * Nbr of bytes between the end of the IFD directory and the start of
+    * the image data. Keep space for at least the offsets and counts
+    * data, each field being TYPE_LONG (4 bytes). If other tags require
+    * space between the IFD and the image block, use the extraBytes
+    * parameter.
+    * If there is only one strip, the offsets and counts data is stored
+    * directly in the IFD and we need not reserve space for it.
+    */
+    int postIFDData = n is 1 ? 0 : n * 2 * 4;
+    int startOffset = offsetPostIFD + extraBytes + postIFDData; /* offset of image data */
+
+    int offset = startOffset;
+    for (int i = 0; i < n; i++) {
+        /*
+        * Store all strips sequentially to allow us
+        * to copy all pixels in one contiguous area.
+        */
+        offsets[i] = offset;
+        counts[i] = stripByteSize;
+        offset += stripByteSize;
+    }
+    /* The last strip may contain fewer rows */
+    int mod = data.length % stripByteSize;
+    if (mod !is 0) counts[counts.length - 1] = mod;
+
+    strips[0] = offsets;
+    strips[1] = counts;
+    return nbrRowsPerStrip;
+}
+
+int[] formatColorMap(RGB[] rgbs) {
+    /*
+    * In a TIFF ColorMap, all red come first, followed by
+    * green and blue. All values must be converted from
+    * 8 bit to 16 bit.
+    */
+    int[] colorMap = new int[rgbs.length * 3];
+    int offsetGreen = rgbs.length;
+    int offsetBlue = rgbs.length * 2;
+    for (int i = 0; i < rgbs.length; i++) {
+        colorMap[i] = rgbs[i].red << 8 | rgbs[i].red;
+        colorMap[i + offsetGreen] = rgbs[i].green << 8 | rgbs[i].green;
+        colorMap[i + offsetBlue] = rgbs[i].blue << 8 | rgbs[i].blue;
+    }
+    return colorMap;
+}
+
+void parseEntries(byte[] buffer)  {
+    for (int offset = 0; offset < buffer.length; offset += IFD_ENTRY_SIZE) {
+        int tag = toInt(buffer, offset, TYPE_SHORT);
+        int type = toInt(buffer, offset + 2, TYPE_SHORT);
+        int count = toInt(buffer, offset + 4, TYPE_LONG);
+        switch (tag) {
+            case TAG_ImageWidth: {
+                imageWidth = getEntryValue(type, buffer, offset);
+                break;
+            }
+            case TAG_ImageLength: {
+                imageLength = getEntryValue(type, buffer, offset);
+                break;
+            }
+            case TAG_BitsPerSample: {
+                if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                bitsPerSample = new int[count];
+                getEntryValue(type, buffer, offset, bitsPerSample);
+                break;
+            }
+            case TAG_Compression: {
+                compression = getEntryValue(type, buffer, offset);
+                break;
+            }
+            case TAG_PhotometricInterpretation: {
+                photometricInterpretation = getEntryValue(type, buffer, offset);
+                break;
+            }
+            case TAG_StripOffsets: {
+                if (type !is TYPE_LONG && type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                stripOffsets = new int[count];
+                getEntryValue(type, buffer, offset, stripOffsets);
+                break;
+            }
+            case TAG_SamplesPerPixel: {
+                if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                samplesPerPixel = getEntryValue(type, buffer, offset);
+                /* Only the basic 1 and 3 values are supported */
+                if (samplesPerPixel !is 1 && samplesPerPixel !is 3) SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+                break;
+            }
+            case TAG_RowsPerStrip: {
+                rowsPerStrip = getEntryValue(type, buffer, offset);
+                break;
+            }
+            case TAG_StripByteCounts: {
+                stripByteCounts = new int[count];
+                getEntryValue(type, buffer, offset, stripByteCounts);
+                break;
+            }
+            case TAG_XResolution: {
+                /* Ignored */
+                break;
+            }
+            case TAG_YResolution: {
+                /* Ignored */
+                break;
+            }
+            case TAG_T4Options: {
+                if (type !is TYPE_LONG) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                t4Options = getEntryValue(type, buffer, offset);
+                if ((t4Options & 0x1) is 1) {
+                    /* 2-dimensional coding is not supported */
+                    SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+                }
+                break;
+            }
+            case TAG_ResolutionUnit: {
+                /* Ignored */
+                break;
+            }
+            case TAG_ColorMap: {
+                if (type !is TYPE_SHORT) SWT.error(SWT.ERROR_INVALID_IMAGE);
+                /* Get the offset of the colorMap (use TYPE_LONG) */
+                colorMapOffset = getEntryValue(TYPE_LONG, buffer, offset);
+                break;
+            }
+            default:
+        }
+    }
+}
+
+public ImageData read()  {
+    /* Set TIFF default values */
+    bitsPerSample = [1];
+    colorMapOffset = NO_VALUE;
+    compression = 1;
+    imageLength = NO_VALUE;
+    imageWidth = NO_VALUE;
+    photometricInterpretation = NO_VALUE;
+    rowsPerStrip = Integer.MAX_VALUE;
+    samplesPerPixel = 1;
+    stripByteCounts = null;
+    stripOffsets = null;
+
+    byte[] buffer = new byte[2];
+    file.read(buffer);
+    int numberEntries = toInt(buffer, 0, TYPE_SHORT);
+    buffer = new byte[IFD_ENTRY_SIZE * numberEntries];
+    file.read(buffer);
+    parseEntries(buffer);
+
+    PaletteData palette = null;
+    depth = 0;
+    switch (photometricInterpretation) {
+        case 0:
+        case 1: {
+            /* Bilevel or Grayscale image */
+            palette = getGrayPalette();
+            depth = bitsPerSample[0];
+            break;
+        }
+        case 2: {
+            /* RGB image */
+            if (colorMapOffset !is NO_VALUE) SWT.error(SWT.ERROR_INVALID_IMAGE);
+            /* SamplesPerPixel 3 is the only value supported */
+            palette = getRGBPalette(bitsPerSample[0], bitsPerSample[1], bitsPerSample[2]);
+            depth = bitsPerSample[0] + bitsPerSample[1] + bitsPerSample[2];
+            break;
+        }
+        case 3: {
+            /* Palette Color image */
+            if (colorMapOffset is NO_VALUE) SWT.error(SWT.ERROR_INVALID_IMAGE);
+            palette = getColorMap();
+            depth = bitsPerSample[0];
+            break;
+        }
+        default: {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+    }
+
+    ImageData image = ImageData.internal_new(
+            imageWidth,
+            imageLength,
+            depth,
+            palette,
+            1,
+            null,
+            0,
+            null,
+            null,
+            -1,
+            -1,
+            SWT.IMAGE_TIFF,
+            0,
+            0,
+            0,
+            0);
+    decodePixels(image);
+    return image;
+}
+
+int toInt(byte[] buffer, int i, int type) {
+    if (type is TYPE_LONG) {
+        return isLittleEndian ?
+        (buffer[i] & 0xFF) | ((buffer[i + 1] & 0xFF) << 8) | ((buffer[i + 2] & 0xFF) << 16) | ((buffer[i + 3] & 0xFF) << 24) :
+        (buffer[i + 3] & 0xFF) | ((buffer[i + 2] & 0xFF) << 8) | ((buffer[i + 1] & 0xFF) << 16) | ((buffer[i] & 0xFF) << 24);
+    }
+    if (type is TYPE_SHORT) {
+        return isLittleEndian ?
+        (buffer[i] & 0xFF) | ((buffer[i + 1] & 0xFF) << 8) :
+        (buffer[i + 1] & 0xFF) | ((buffer[i] & 0xFF) << 8);
+    }
+    /* Invalid type */
+    SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return -1;
+}
+
+void write(int photometricInterpretation)  {
+    bool isRGB = photometricInterpretation is 2;
+    bool isColorMap = photometricInterpretation is 3;
+    bool isBiLevel = photometricInterpretation is 0 || photometricInterpretation is 1;
+
+    int imageWidth = image.width;
+    int imageLength = image.height;
+    int rowByteSize = image.bytesPerLine;
+
+    int numberEntries = isBiLevel ? 9 : 11;
+    int lengthDirectory = 2 + 12 * numberEntries + 4;
+    /* Offset following the header and the directory */
+    int nextOffset = 8 + lengthDirectory;
+
+    /* Extra space used by XResolution and YResolution values */
+    int extraBytes = 16;
+
+    int[] colorMap = null;
+    if (isColorMap) {
+        PaletteData palette = image.palette;
+        RGB[] rgbs = palette.getRGBs();
+        colorMap = formatColorMap(rgbs);
+        /* The number of entries of the Color Map must match the bitsPerSample field */
+        if (colorMap.length !is 3 * 1 << image.depth) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+        /* Extra space used by ColorMap values */
+        extraBytes += colorMap.length * 2;
+    }
+    if (isRGB) {
+        /* Extra space used by BitsPerSample values */
+        extraBytes += 6;
+    }
+    /* TIFF recommends storing the data in strips of no more than 8 Ko */
+    byte[] data = image.data;
+    int[][] strips = new int[][](2);
+    int nbrRowsPerStrip = formatStrips(rowByteSize, imageLength, data, 8192, nextOffset, extraBytes, strips);
+    int[] stripOffsets = strips[0];
+    int[] stripByteCounts = strips[1];
+
+    int bitsPerSampleOffset = NO_VALUE;
+    if (isRGB) {
+        bitsPerSampleOffset = nextOffset;
+        nextOffset += 6;
+    }
+    int stripOffsetsOffset = NO_VALUE, stripByteCountsOffset = NO_VALUE;
+    int xResolutionOffset, yResolutionOffset, colorMapOffset = NO_VALUE;
+    int cnt = stripOffsets.length;
+    if (cnt > 1) {
+        stripOffsetsOffset = nextOffset;
+        nextOffset += 4 * cnt;
+        stripByteCountsOffset = nextOffset;
+        nextOffset += 4 * cnt;
+    }
+    xResolutionOffset = nextOffset;
+    nextOffset += 8;
+    yResolutionOffset = nextOffset;
+    nextOffset += 8;
+    if (isColorMap) {
+        colorMapOffset = nextOffset;
+        nextOffset += colorMap.length * 2;
+    }
+    /* TIFF header */
+    writeHeader();
+
+    /* Image File Directory */
+    ostr.writeShort(numberEntries);
+    writeEntry(TAG_ImageWidth, TYPE_LONG, 1, imageWidth);
+    writeEntry(TAG_ImageLength, TYPE_LONG, 1, imageLength);
+    if (isColorMap) writeEntry(TAG_BitsPerSample, TYPE_SHORT, 1, image.depth);
+    if (isRGB) writeEntry(TAG_BitsPerSample, TYPE_SHORT, 3, bitsPerSampleOffset);
+    writeEntry(TAG_Compression, TYPE_SHORT, 1, COMPRESSION_NONE);
+    writeEntry(TAG_PhotometricInterpretation, TYPE_SHORT, 1, photometricInterpretation);
+    writeEntry(TAG_StripOffsets, TYPE_LONG, cnt, cnt > 1 ? stripOffsetsOffset : stripOffsets[0]);
+    if (isRGB) writeEntry(TAG_SamplesPerPixel, TYPE_SHORT, 1, 3);
+    writeEntry(TAG_RowsPerStrip, TYPE_LONG, 1, nbrRowsPerStrip);
+    writeEntry(TAG_StripByteCounts, TYPE_LONG, cnt, cnt > 1 ? stripByteCountsOffset : stripByteCounts[0]);
+    writeEntry(TAG_XResolution, TYPE_RATIONAL, 1, xResolutionOffset);
+    writeEntry(TAG_YResolution, TYPE_RATIONAL, 1, yResolutionOffset);
+    if (isColorMap) writeEntry(TAG_ColorMap, TYPE_SHORT, colorMap.length, colorMapOffset);
+    /* Offset of next IFD (0 for last IFD) */
+    ostr.writeInt(0);
+
+    /* Values longer than 4 bytes Section */
+
+    /* BitsPerSample 8,8,8 */
+    if (isRGB) for (int i = 0; i < 3; i++) ostr.writeShort(8);
+    if (cnt > 1) {
+        for (int i = 0; i < cnt; i++) ostr.writeInt(stripOffsets[i]);
+        for (int i = 0; i < cnt; i++) ostr.writeInt(stripByteCounts[i]);
+    }
+    /* XResolution and YResolution set to 300 dpi */
+    for (int i = 0; i < 2; i++) {
+        ostr.writeInt(300);
+        ostr.writeInt(1);
+    }
+    /* ColorMap */
+    if (isColorMap) for (int i = 0; i < colorMap.length; i++) ostr.writeShort(colorMap[i]);
+
+    /* Image Data */
+    ostr.write(data);
+}
+
+void writeEntry(short tag, int type, int count, int value) {
+    ostr.writeShort(tag);
+    ostr.writeShort(type);
+    ostr.writeInt(count);
+    ostr.writeInt(value);
+}
+
+void writeHeader() {
+    /* little endian */
+    ostr.write(0x49);
+    ostr.write(0x49);
+
+    /* TIFF identifier */
+    ostr.writeShort(42);
+    /*
+    * Offset of the first IFD is chosen to be 8.
+    * It is word aligned and immediately after this header.
+    */
+    ostr.writeInt(8);
+}
+
+void writeToStream(LEDataOutputStream byteStream) {
+    ostr = byteStream;
+    int photometricInterpretation = -1;
+
+    /* Scanline pad must be 1 */
+    if (image.scanlinePad !is 1) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+    switch (image.depth) {
+        case 1: {
+            /* Palette must be black and white or white and black */
+            PaletteData palette = image.palette;
+            RGB[] rgbs = palette.colors;
+            if (palette.isDirect || rgbs is null || rgbs.length !is 2) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+            RGB rgb0 = rgbs[0];
+            RGB rgb1 = rgbs[1];
+            if (!(rgb0.red is rgb0.green && rgb0.green is rgb0.blue &&
+                rgb1.red is rgb1.green && rgb1.green is rgb1.blue &&
+                ((rgb0.red is 0x0 && rgb1.red is 0xFF) || (rgb0.red is 0xFF && rgb1.red is 0x0)))) {
+                SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+            }
+            /* 0 means a color index of 0 is imaged as white */
+            photometricInterpretation = image.palette.colors[0].red is 0xFF ? 0 : 1;
+            break;
+        }
+        case 4:
+        case 8: {
+            photometricInterpretation = 3;
+            break;
+        }
+        case 24: {
+            photometricInterpretation = 2;
+            break;
+        }
+        default: {
+            SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
+        }
+    }
+    write(photometricInterpretation);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.TIFFFileFormat;
+
+import org.eclipse.swt.internal.image.TIFFRandomFileAccess;
+import org.eclipse.swt.internal.image.TIFFDirectory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.internal.image.FileFormat;
+
+import tango.core.Exception;
+
+/**
+ * Baseline TIFF decoder revision 6.0
+ * Extension T4-encoding CCITT T.4 1D
+ */
+final class TIFFFileFormat : FileFormat {
+
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] header = new byte[4];
+        stream.read(header);
+        stream.unread(header);
+        if (header[0] !is header[1]) return false;
+        if (!(header[0] is 0x49 && header[2] is 42 && header[3] is 0) &&
+            !(header[0] is 0x4d && header[2] is 0 && header[3] is 42)) {
+            return false;
+        }
+        return true;
+    } catch (Exception e) {
+        return false;
+    }
+}
+
+override ImageData[] loadFromByteStream() {
+    byte[] header = new byte[8];
+    bool isLittleEndian;
+    ImageData[] images = new ImageData[0];
+    TIFFRandomFileAccess file = new TIFFRandomFileAccess(inputStream);
+    try {
+        file.read(header);
+        if (header[0] !is header[1]) SWT.error(SWT.ERROR_INVALID_IMAGE);
+        if (!(header[0] is 0x49 && header[2] is 42 && header[3] is 0) &&
+            !(header[0] is 0x4d && header[2] is 0 && header[3] is 42)) {
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        }
+        isLittleEndian = header[0] is 0x49;
+        int offset = isLittleEndian ?
+            (header[4] & 0xFF) | ((header[5] & 0xFF) << 8) | ((header[6] & 0xFF) << 16) | ((header[7] & 0xFF) << 24) :
+            (header[7] & 0xFF) | ((header[6] & 0xFF) << 8) | ((header[5] & 0xFF) << 16) | ((header[4] & 0xFF) << 24);
+        file.seek(offset);
+        TIFFDirectory directory = new TIFFDirectory(file, isLittleEndian, loader);
+        ImageData image = directory.read();
+        /* A baseline reader is only expected to read the first directory */
+        images = [image];
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return images;
+}
+
+override void unloadIntoByteStream(ImageLoader loader) {
+    /* We do not currently support writing multi-page tiff,
+     * so we use the first image data in the loader's array. */
+    ImageData image = loader.data[0];
+    TIFFDirectory directory = new TIFFDirectory(image);
+    try {
+        directory.writeToStream(outputStream);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFModifiedHuffmanCodec.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.TIFFModifiedHuffmanCodec;
+
+import org.eclipse.swt.SWT;
+
+/*
+* Decoder for
+* - CCITT Group 3 1-Dimensional Modified Huffman run length encoding
+*   (TIFF compression type 2)
+* - CCITT T.4 bi-level encoding 1D
+*   (TIFF compression type 3 option 1D)
+*/
+final class TIFFModifiedHuffmanCodec {
+    static final short[][][] BLACK_CODE = [
+        /* 2 bits  */
+        [[ cast(short)2, 3], [ cast(short)3, 2]],
+        /* 3 bits  */
+        [[ cast(short)2, 1], [ cast(short)3, 4]],
+        /* 4 bits  */
+        [[ cast(short)2, 6], [ cast(short)3, 5]],
+        /* 5 bits  */
+        [[ cast(short)3, 7]],
+        /* 6 bits  */
+        [[ cast(short)4, 9], [ cast(short)5, 8]],
+        /* 7 bits  */
+        [[ cast(short)4, 10], [ cast(short)5, 11], [ cast(short)7, 12]],
+        /* 8 bits  */
+        [[ cast(short)4, 13], [ cast(short)7, 14]],
+        /* 9 bits  */
+        [[ cast(short)24, 15]],
+        /* 10 bits */
+        [[ cast(short)8, 18], [ cast(short)15, 64], [ cast(short)23, 16], [ cast(short)24, 17], [ cast(short)55, 0]],
+        /* 11 bits */
+        [/* EOL */[ cast(short)0, -1], [ cast(short)8, 1792], [ cast(short)23, 24], [ cast(short)24, 25], [ cast(short)40, 23], [ cast(short)55, 22], [ cast(short)103, 19],
+        [ cast(short)104, 20], [ cast(short)108, 21], [ cast(short)12, 1856], [ cast(short)13, 1920]],
+        /* 12 bits */
+        [[ cast(short)18, 1984], [ cast(short)19, 2048], [ cast(short)20, 2112], [ cast(short)21, 2176], [ cast(short)22, 2240], [ cast(short)23, 2304],
+        [ cast(short)28, 2368], [ cast(short)29, 2432], [ cast(short)30, 2496], [ cast(short)31, 2560], [ cast(short)36, 52], [ cast(short)39, 55], [ cast(short)40, 56],
+        [ cast(short)43, 59], [ cast(short)44, 60], [ cast(short)51, 320], [ cast(short)52, 384], [ cast(short)53, 448], [ cast(short)55, 53], [ cast(short)56, 54], [ cast(short)82, 50],
+        [ cast(short)83, 51], [ cast(short)84, 44], [ cast(short)85, 45], [ cast(short)86, 46], [ cast(short)87, 47], [ cast(short)88, 57], [ cast(short)89, 58], [ cast(short)90, 61],
+        [ cast(short)91, 256], [ cast(short)100, 48], [ cast(short)101, 49], [ cast(short)102, 62], [ cast(short)103, 63], [ cast(short)104, 30], [ cast(short)105, 31],
+        [ cast(short)106, 32], [ cast(short)107, 33], [ cast(short)108, 40], [ cast(short)109, 41], [ cast(short)200, 128], [ cast(short)201, 192], [ cast(short)202, 26],
+        [ cast(short)203, 27], [ cast(short)204, 28], [ cast(short)205, 29], [ cast(short)210, 34], [ cast(short)211, 35], [ cast(short)212, 36], [ cast(short)213, 37],
+        [ cast(short)214, 38], [ cast(short)215, 39], [ cast(short)218, 42], [ cast(short)219, 43]],
+        /* 13 bits */
+        [[ cast(short)74, 640], [ cast(short)75, 704], [ cast(short)76, 768], [ cast(short)77, 832], [ cast(short)82, 1280], [ cast(short)83, 1344], [ cast(short)84, 1408],
+        [ cast(short)85, 1472], [ cast(short)90, 1536], [ cast(short)91, 1600], [ cast(short)100, 1664], [ cast(short)101, 1728], [ cast(short)108, 512],
+        [ cast(short)109, 576], [ cast(short)114, 896], [ cast(short)115, 960], [ cast(short)116, 1024], [ cast(short)117, 1088], [ cast(short)118, 1152],
+        [ cast(short)119, 1216]]
+    ];
+
+    static final short[][][] WHITE_CODE = [
+        /* 4 bits */
+        [[ cast(short)7, 2], [ cast(short)8, 3], [ cast(short)11, 4], [ cast(short)12, 5], [ cast(short)14, 6], [ cast(short)15, 7]],
+        /* 5 bits */
+        [[ cast(short)7, 10], [ cast(short)8, 11], [ cast(short)18, 128], [ cast(short)19, 8], [ cast(short)20, 9], [ cast(short)27, 64]],
+        /* 6 bits */
+        [[ cast(short)3, 13], [ cast(short)7, 1], [ cast(short)8, 12], [ cast(short)23, 192], [ cast(short)24, 1664], [ cast(short)42, 16], [ cast(short)43, 17], [ cast(short)52, 14],
+        [ cast(short)53, 15]],
+        /* 7 bits */
+        [[ cast(short)3, 22], [ cast(short)4, 23], [ cast(short)8, 20], [ cast(short)12, 19], [ cast(short)19, 26], [ cast(short)23, 21], [ cast(short)24, 28], [ cast(short)36, 27],
+        [ cast(short)39, 18], [ cast(short)40, 24], [ cast(short)43, 25], [ cast(short)55, 256]],
+        /* 8 bits */
+        [[ cast(short)2, 29], [ cast(short)3, 30], [ cast(short)4, 45], [ cast(short)5, 46], [ cast(short)10, 47], [ cast(short)11, 48], [ cast(short)18, 33], [ cast(short)19, 34],
+        [ cast(short)20, 35], [ cast(short)21, 36], [ cast(short)22, 37], [ cast(short)23, 38], [ cast(short)26, 31], [ cast(short)27, 32], [ cast(short)36, 53], [ cast(short)37, 54],
+        [ cast(short)40, 39], [ cast(short)41, 40], [ cast(short)42, 41], [ cast(short)43, 42], [ cast(short)44, 43], [ cast(short)45, 44], [ cast(short)50, 61], [ cast(short)51, 62],
+        [ cast(short)52, 63], [ cast(short)53, 0], [ cast(short)54, 320], [ cast(short)55, 384], [ cast(short)74, 59], [ cast(short)75, 60], [ cast(short)82, 49], [ cast(short)83, 50],
+        [ cast(short)84, 51], [ cast(short)85, 52], [ cast(short)88, 55], [ cast(short)89, 56], [ cast(short)90, 57], [ cast(short)91, 58], [ cast(short)100, 448],
+        [ cast(short)101, 512], [ cast(short)103, 640], [ cast(short)104, 576]],
+        /* 9 bits */
+        [[ cast(short)152, 1472], [ cast(short)153, 1536], [ cast(short)154, 1600], [ cast(short)155, 1728], [ cast(short)204, 704], [ cast(short)205, 768],
+        [ cast(short)210, 832], [ cast(short)211, 896], [ cast(short)212, 960], [ cast(short)213, 1024], [ cast(short)214, 1088], [ cast(short)215, 1152],
+        [ cast(short)216, 1216], [ cast(short)217, 1280], [ cast(short)218, 1344], [ cast(short)219, 1408]],
+        /* 10 bits */
+        [],
+        /* 11 bits */
+        [[ cast(short)8, 1792], [ cast(short)12, 1856], [ cast(short)13, 1920]],
+        /* 12 bits */
+        [/* EOL */[ cast(short)1, -1], [ cast(short)18, 1984], [ cast(short)19, 2048], [ cast(short)20, 2112], [ cast(short)21, 2176], [ cast(short)22, 2240], [ cast(short)23, 2304],
+        [ cast(short)28, 2368], [ cast(short)29, 2432], [ cast(short)30, 2496], [ cast(short)31, 2560]]
+    ];
+
+    static final int BLACK_MIN_BITS = 2;
+    static final int WHITE_MIN_BITS = 4;
+
+    bool isWhite;
+    int whiteValue = 0;
+    int blackValue = 1;
+    byte[] src;
+    byte[] dest;
+    int byteOffsetSrc = 0;
+    int bitOffsetSrc = 0;
+    int byteOffsetDest = 0;
+    int bitOffsetDest = 0;
+    int code = 0;
+    int nbrBits = 0;
+    /* nbr of bytes per row */
+    int rowSize;
+
+public int decode(byte[] src, byte[] dest, int offsetDest, int rowSize, int nRows) {
+    this.src = src;
+    this.dest = dest;
+    this.rowSize = rowSize;
+    byteOffsetSrc = 0;
+    bitOffsetSrc = 0;
+    byteOffsetDest = offsetDest;
+    bitOffsetDest = 0;
+    int cnt = 0;
+    while (cnt < nRows && decodeRow()) {
+        cnt++;
+        /* byte aligned */
+        if (bitOffsetDest > 0) {
+            byteOffsetDest++;
+            bitOffsetDest = 0;
+        }
+    }
+    return byteOffsetDest - offsetDest;
+}
+
+bool decodeRow() {
+    isWhite = true;
+    int n = 0;
+    while (n < rowSize) {
+        int runLength = decodeRunLength();
+        if (runLength < 0) return false;
+        n += runLength;
+        setNextBits(isWhite ? whiteValue : blackValue, runLength);
+        isWhite = !isWhite;
+    }
+    return true;
+}
+
+int decodeRunLength() {
+    int runLength = 0;
+    int partialRun = 0;
+    short[][][] huffmanCode = isWhite ? WHITE_CODE : BLACK_CODE;
+    while (true) {
+        bool found = false;
+        nbrBits = isWhite ? WHITE_MIN_BITS : BLACK_MIN_BITS;
+        code = getNextBits(nbrBits);
+        for (int i = 0; i < huffmanCode.length; i++) {
+            for (int j = 0; j < huffmanCode[i].length; j++) {
+                if (huffmanCode[i][j][0] is code) {
+                    found = true;
+                    partialRun = huffmanCode[i][j][1];
+                    if (partialRun is -1) {
+                        /* Stop when reaching final EOL on last byte */
+                        if (byteOffsetSrc is src.length - 1) return -1;
+                        /* Group 3 starts each row with an EOL - ignore it */
+                    } else {
+                        runLength += partialRun;
+                        if (partialRun < 64) return runLength;
+                    }
+                    break;
+                }
+            }
+            if (found) break;
+            code = code << 1 | getNextBit();
+        }
+        if (!found) SWT.error(SWT.ERROR_INVALID_IMAGE);
+    }
+}
+
+int getNextBit() {
+    int value = (src[byteOffsetSrc] >>> (7 - bitOffsetSrc)) & 0x1;
+    bitOffsetSrc++;
+    if (bitOffsetSrc > 7) {
+        byteOffsetSrc++;
+        bitOffsetSrc = 0;
+    }
+    return value;
+}
+
+int getNextBits(int cnt) {
+    int value = 0;
+    for (int i = 0; i < cnt; i++) {
+        value = value << 1 | getNextBit();
+    }
+    return value;
+}
+
+void setNextBits(int value, int cnt) {
+    int n = cnt;
+    while (bitOffsetDest > 0 && bitOffsetDest <= 7 && n > 0) {
+        dest[byteOffsetDest] = value is 1 ?
+            cast(byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) :
+            cast(byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
+        n--;
+        bitOffsetDest++;
+    }
+    if (bitOffsetDest is 8) {
+        byteOffsetDest++;
+        bitOffsetDest = 0;
+    }
+    while (n >= 8) {
+        dest[byteOffsetDest++] = cast(byte) (value is 1 ? 0xFF : 0);
+        n -= 8;
+    }
+    while (n > 0) {
+        dest[byteOffsetDest] = value is 1 ?
+            cast(byte)(dest[byteOffsetDest] | (1 << (7 - bitOffsetDest))) :
+            cast(byte)(dest[byteOffsetDest] & ~(1 << (7 - bitOffsetDest)));
+        n--;
+        bitOffsetDest++;
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/TIFFRandomFileAccess.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.TIFFRandomFileAccess;
+
+import org.eclipse.swt.internal.image.LEDataInputStream;
+import Math = tango.math.Math;
+import tango.core.Exception;
+import java.lang.System;
+
+final class TIFFRandomFileAccess {
+
+    LEDataInputStream inputStream;
+    int start, current, next;
+    byte[][] buffers;
+
+    static final int CHUNK_SIZE = 8192;
+    static final int LIST_SIZE = 128;
+
+public this(LEDataInputStream stream) {
+    inputStream = stream;
+    start = current = next = inputStream.getPosition();
+    buffers = new byte[][](LIST_SIZE);
+}
+
+void seek(int pos) {
+    if (pos is current) return;
+    if (pos < start) throw new IOException( "pos < start" );
+    current = pos;
+    if (current > next) {
+        int n = current - next;
+        /* store required bytes */
+        int index = next / CHUNK_SIZE;
+        int offset = next % CHUNK_SIZE;
+        while (n > 0) {
+            if (index >= buffers.length) {
+                byte[][] oldBuffers = buffers;
+                buffers = new byte[][]( Math.max(index + 1, oldBuffers.length + LIST_SIZE) );
+                System.arraycopy(oldBuffers, 0, buffers, 0, oldBuffers.length);
+            }
+            if (buffers[index] is null) buffers[index] = new byte[CHUNK_SIZE];
+            int cnt = inputStream.read(buffers[index], offset, Math.min(n, CHUNK_SIZE - offset));
+            n -= cnt;
+            next += cnt;
+            index++;
+            offset = 0;
+        }
+    }
+}
+
+void read(byte b[]) {
+    int size = b.length;
+    int nCached = Math.min(size, next - current);
+    int nMissing = size - next + current;
+    int destNext = 0;
+    if (nCached > 0) {
+        /* Get cached bytes */
+        int index = current / CHUNK_SIZE;
+        int offset = current % CHUNK_SIZE;
+        while (nCached > 0) {
+            int cnt = Math.min(nCached, CHUNK_SIZE - offset);
+            System.arraycopy(buffers[index], offset, b, destNext, cnt);
+            nCached -= cnt;
+            destNext += cnt;
+            index++;
+            offset = 0;
+        }
+    }
+    if (nMissing > 0) {
+        /* Read required bytes */
+        int index = next / CHUNK_SIZE;
+        int offset = next % CHUNK_SIZE;
+        while (nMissing > 0) {
+            if (index >= buffers.length) {
+                byte[][] oldBuffers = buffers;
+                buffers = new byte[][](Math.max(index, oldBuffers.length + LIST_SIZE));
+                System.arraycopy(oldBuffers, 0, buffers, 0, oldBuffers.length);
+            }
+            if (buffers[index] is null) buffers[index] = new byte[CHUNK_SIZE];
+            int cnt = inputStream.read(buffers[index], offset, Math.min(nMissing, CHUNK_SIZE - offset));
+            System.arraycopy(buffers[index], offset, b, destNext, cnt);
+            nMissing -= cnt;
+            next += cnt;
+            destNext += cnt;
+            index++;
+            offset = 0;
+        }
+    }
+    current += size;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/WinBMPFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,702 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.WinBMPFileFormat;
+
+import org.eclipse.swt.internal.image.FileFormat;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import java.io.ByteArrayOutputStream;
+import org.eclipse.swt.SWT;
+import java.lang.all;
+
+import tango.core.Exception;
+
+final class WinBMPFileFormat : FileFormat {
+
+    static final int BMPFileHeaderSize = 14;
+    static final int BMPHeaderFixedSize = 40;
+    int importantColors;
+    Point pelsPerMeter;
+
+public this(){
+    pelsPerMeter = new Point(0, 0);
+}
+
+/**
+ * Compress numBytes bytes of image data from src, storing in dest
+ * (starting at 0), using the technique specified by comp.
+ * If last is true, this indicates the last line of the image.
+ * Answer the size of the compressed data.
+ */
+int compress(int comp, byte[] src, int srcOffset, int numBytes, byte[] dest, bool last) {
+    if (comp is 1) { // BMP_RLE8_COMPRESSION
+        return compressRLE8Data(src, srcOffset, numBytes, dest, last);
+    }
+    if (comp is 2) { // BMP_RLE4_COMPRESSION
+        return compressRLE4Data(src, srcOffset, numBytes, dest, last);
+    }
+    SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return 0;
+}
+int compressRLE4Data(byte[] src, int srcOffset, int numBytes, byte[] dest, bool last) {
+    int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
+    int size = 0, left, i, n;
+    byte theByte;
+    while (sp < end) {
+        /* find two consecutive bytes that are the same in the next 128 */
+        left = end - sp - 1;
+        if (left > 127)
+            left = 127;
+        for (n = 0; n < left; n++) {
+            if (src[sp + n] is src[sp + n + 1])
+                break;
+        }
+        /* if there is only one more byte in the scan line, include it */
+        if (n < 127 && n is left)
+            n++;
+        /* store the intervening data */
+        switch (n) {
+            case 0:
+                break;
+            case 1: /* handled separately because 0,2 is a command */
+                dest[dp] = 2; dp++; /* 1 byte is 2 pixels */
+                dest[dp] = src[sp];
+                dp++; sp++;
+                size += 2;
+                break;
+            default:
+                dest[dp] = 0; dp++;
+                dest[dp] = cast(byte)(n + n); dp++; /* n bytes = n*2 pixels */
+                for (i = n; i > 0; i--) {
+                    dest[dp] = src[sp];
+                    dp++; sp++;
+                }
+                size += 2 + n;
+                if ((n & 1) !is 0) { /* pad to word */
+                    dest[dp] = 0;
+                    dp++;
+                    size++;
+                }
+                break;
+        }
+        /* find the length of the next run (up to 127) and store it */
+        left = end - sp;
+        if (left > 0) {
+            if (left > 127)
+                left = 127;
+            theByte = src[sp];
+            for (n = 1; n < left; n++) {
+                if (src[sp + n] !is theByte)
+                    break;
+            }
+            dest[dp] = cast(byte)(n + n); dp++; /* n bytes = n*2 pixels */
+            dest[dp] = theByte; dp++;
+            sp += n;
+            size += 2;
+        }
+    }
+
+    /* store the end of line or end of bitmap codes */
+    dest[dp] = 0; dp++;
+    if (last) {
+        dest[dp] = 1; dp++;
+    } else {
+        dest[dp] = 0; dp++;
+    }
+    size += 2;
+
+    return size;
+}
+int compressRLE8Data(byte[] src, int srcOffset, int numBytes, byte[] dest, bool last) {
+    int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
+    int size = 0, left, i, n;
+    byte theByte;
+    while (sp < end) {
+        /* find two consecutive bytes that are the same in the next 256 */
+        left = end - sp - 1;
+        if (left > 254)
+            left = 254;
+        for (n = 0; n < left; n++) {
+            if (src[sp + n] is src[sp + n + 1])
+                break;
+        }
+        /* if there is only one more byte in the scan line, include it */
+        if (n is left)
+            n++;
+        /* store the intervening data */
+        switch (n) {
+            case 0:
+                break;
+            case 2: /* handled separately because 0,2 is a command */
+                dest[dp] = 1; dp++;
+                dest[dp] = src[sp];
+                dp++; sp++;
+                size += 2;
+                /* don't break, fall through */
+            case 1: /* handled separately because 0,1 is a command */
+                dest[dp] = 1; dp++;
+                dest[dp] = src[sp];
+                dp++; sp++;
+                size += 2;
+                break;
+            default:
+                dest[dp] = 0; dp++;
+                dest[dp] = cast(byte)n; dp++;
+                for (i = n; i > 0; i--) {
+                    dest[dp] = src[sp];
+                    dp++; sp++;
+                }
+                size += 2 + n;
+                if ((n & 1) !is 0) { /* pad to word */
+                    dest[dp] = 0;
+                    dp++;
+                    size++;
+                }
+                break;
+        }
+        /* find the length of the next run (up to 255) and store it */
+        left = end - sp;
+        if (left > 0) {
+            if (left > 255)
+                left = 255;
+            theByte = src[sp];
+            for (n = 1; n < left; n++) {
+                if (src[sp + n] !is theByte)
+                    break;
+            }
+            dest[dp] = cast(byte)n; dp++;
+            dest[dp] = theByte; dp++;
+            sp += n;
+            size += 2;
+        }
+    }
+
+    /* store the end of line or end of bitmap codes */
+    dest[dp] = 0; dp++;
+    if (last) {
+        dest[dp] = 1; dp++;
+    } else {
+        dest[dp] = 0; dp++;
+    }
+    size += 2;
+
+    return size;
+}
+void decompressData(byte[] src, byte[] dest, int stride, int cmp) {
+    if (cmp is 1) { // BMP_RLE8_COMPRESSION
+        if (decompressRLE8Data(src, src.length, stride, dest, dest.length) <= 0)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        return;
+    }
+    if (cmp is 2) { // BMP_RLE4_COMPRESSION
+        if (decompressRLE4Data(src, src.length, stride, dest, dest.length) <= 0)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        return;
+    }
+    SWT.error(SWT.ERROR_INVALID_IMAGE);
+}
+int decompressRLE4Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
+    int sp = 0;
+    int se = numBytes;
+    int dp = 0;
+    int de = destSize;
+    int x = 0, y = 0;
+    while (sp < se) {
+        int len = src[sp] & 0xFF;
+        sp++;
+        if (len is 0) {
+            len = src[sp] & 0xFF;
+            sp++;
+            switch (len) {
+                case 0: /* end of line */
+                    y++;
+                    x = 0;
+                    dp = y * stride;
+                    if (dp > de)
+                        return -1;
+                    break;
+                case 1: /* end of bitmap */
+                    return 1;
+                case 2: /* delta */
+                    x += src[sp] & 0xFF;
+                    sp++;
+                    y += src[sp] & 0xFF;
+                    sp++;
+                    dp = y * stride + x / 2;
+                    if (dp > de)
+                        return -1;
+                    break;
+                default: /* absolute mode run */
+                    if ((len & 1) !is 0) /* odd run lengths not currently supported */
+                        return -1;
+                    x += len;
+                    len = len / 2;
+                    if (len > (se - sp))
+                        return -1;
+                    if (len > (de - dp))
+                        return -1;
+                    for (int i = 0; i < len; i++) {
+                        dest[dp] = src[sp];
+                        dp++;
+                        sp++;
+                    }
+                    if ((sp & 1) !is 0)
+                        sp++; /* word align sp? */
+                    break;
+            }
+        } else {
+            if ((len & 1) !is 0)
+                return -1;
+            x += len;
+            len = len / 2;
+            byte theByte = src[sp];
+            sp++;
+            if (len > (de - dp))
+                return -1;
+            for (int i = 0; i < len; i++) {
+                dest[dp] = theByte;
+                dp++;
+            }
+        }
+    }
+    return 1;
+}
+int decompressRLE8Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
+    int sp = 0;
+    int se = numBytes;
+    int dp = 0;
+    int de = destSize;
+    int x = 0, y = 0;
+    while (sp < se) {
+        int len = src[sp] & 0xFF;
+        sp++;
+        if (len is 0) {
+            len = src[sp] & 0xFF;
+            sp++;
+            switch (len) {
+                case 0: /* end of line */
+                    y++;
+                    x = 0;
+                    dp = y * stride;
+                    if (dp > de)
+                        return -1;
+                    break;
+                case 1: /* end of bitmap */
+                    return 1;
+                case 2: /* delta */
+                    x += src[sp] & 0xFF;
+                    sp++;
+                    y += src[sp] & 0xFF;
+                    sp++;
+                    dp = y * stride + x;
+                    if (dp > de)
+                        return -1;
+                    break;
+                default: /* absolute mode run */
+                    if (len > (se - sp))
+                        return -1;
+                    if (len > (de - dp))
+                        return -1;
+                    for (int i = 0; i < len; i++) {
+                        dest[dp] = src[sp];
+                        dp++;
+                        sp++;
+                    }
+                    if ((sp & 1) !is 0)
+                        sp++; /* word align sp? */
+                    x += len;
+                    break;
+            }
+        } else {
+            byte theByte = src[sp];
+            sp++;
+            if (len > (de - dp))
+                return -1;
+            for (int i = 0; i < len; i++) {
+                dest[dp] = theByte;
+                dp++;
+            }
+            x += len;
+        }
+    }
+    return 1;
+}
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] header = new byte[18];
+        stream.read(header);
+        stream.unread(header);
+        int infoHeaderSize = (header[14] & 0xFF) | ((header[15] & 0xFF) << 8) | ((header[16] & 0xFF) << 16) | ((header[17] & 0xFF) << 24);
+        return header[0] is 0x42 && header[1] is 0x4D && infoHeaderSize >= BMPHeaderFixedSize;
+    } catch (Exception e) {
+        return false;
+    }
+}
+byte[] loadData(byte[] infoHeader) {
+    int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+    int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+    int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+    int stride = (width * bitCount + 7) / 8;
+    stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
+    byte[] data = loadData(infoHeader, stride);
+    flipScanLines(data, stride, height);
+    return data;
+}
+byte[] loadData(byte[] infoHeader, int stride) {
+    int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+    if (height < 0) height = -height;
+    int dataSize = height * stride;
+    byte[] data = new byte[dataSize];
+    int cmp = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
+    if (cmp is 0 || cmp is 3) { // BMP_NO_COMPRESSION
+        try {
+            if (inputStream.read(data) !is dataSize)
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    } else {
+        int compressedSize = (infoHeader[20] & 0xFF) | ((infoHeader[21] & 0xFF) << 8) | ((infoHeader[22] & 0xFF) << 16) | ((infoHeader[23] & 0xFF) << 24);
+        byte[] compressed = new byte[compressedSize];
+        try {
+            if (inputStream.read(compressed) !is compressedSize)
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        decompressData(compressed, data, stride, cmp);
+    }
+    return data;
+}
+int[] loadFileHeader() {
+    int[] header = new int[5];
+    try {
+        header[0] = inputStream.readShort();
+        header[1] = inputStream.readInt();
+        header[2] = inputStream.readShort();
+        header[3] = inputStream.readShort();
+        header[4] = inputStream.readInt();
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    if (header[0] !is 0x4D42)
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return header;
+}
+override ImageData[] loadFromByteStream() {
+    int[] fileHeader = loadFileHeader();
+    byte[] infoHeader = new byte[BMPHeaderFixedSize];
+    try {
+        inputStream.read(infoHeader);
+    } catch (Exception e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+    int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+    if (height < 0) height = -height;
+    int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+    this.compression = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
+    PaletteData palette = loadPalette(infoHeader);
+    if (inputStream.getPosition() < fileHeader[4]) {
+        // Seek to the specified offset
+        try {
+            inputStream.skip(fileHeader[4] - inputStream.getPosition());
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+    byte[] data = loadData(infoHeader);
+    this.importantColors = (infoHeader[36] & 0xFF) | ((infoHeader[37] & 0xFF) << 8) | ((infoHeader[38] & 0xFF) << 16) | ((infoHeader[39] & 0xFF) << 24);
+    int xPelsPerMeter = (infoHeader[24] & 0xFF) | ((infoHeader[25] & 0xFF) << 8) | ((infoHeader[26] & 0xFF) << 16) | ((infoHeader[27] & 0xFF) << 24);
+    int yPelsPerMeter = (infoHeader[28] & 0xFF) | ((infoHeader[29] & 0xFF) << 8) | ((infoHeader[30] & 0xFF) << 16) | ((infoHeader[31] & 0xFF) << 24);
+    this.pelsPerMeter = new Point(xPelsPerMeter, yPelsPerMeter);
+    int type = (this.compression is 1 /*BMP_RLE8_COMPRESSION*/) || (this.compression is 2 /*BMP_RLE4_COMPRESSION*/) ? SWT.IMAGE_BMP_RLE : SWT.IMAGE_BMP;
+    return [
+        ImageData.internal_new(
+            width,
+            height,
+            bitCount,
+            palette,
+            4,
+            data,
+            0,
+            null,
+            null,
+            -1,
+            -1,
+            type,
+            0,
+            0,
+            0,
+            0)
+    ];
+}
+PaletteData loadPalette(byte[] infoHeader) {
+    int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+    if (depth <= 8) {
+        int numColors = (infoHeader[32] & 0xFF) | ((infoHeader[33] & 0xFF) << 8) | ((infoHeader[34] & 0xFF) << 16) | ((infoHeader[35] & 0xFF) << 24);
+        if (numColors is 0) {
+            numColors = 1 << depth;
+        } else {
+            if (numColors > 256)
+                numColors = 256;
+        }
+        byte[] buf = new byte[numColors * 4];
+        try {
+            if (inputStream.read(buf) !is buf.length)
+                SWT.error(SWT.ERROR_INVALID_IMAGE);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+        return paletteFromBytes(buf, numColors);
+    }
+    if (depth is 16) {
+        if (this.compression is 3) {
+            try {
+                return new PaletteData(inputStream.readInt(), inputStream.readInt(), inputStream.readInt());
+            } catch (IOException e) {
+                SWT.error(SWT.ERROR_IO, e);
+            }
+        }
+        return new PaletteData(0x7C00, 0x3E0, 0x1F);
+    }
+    if (depth is 24) return new PaletteData(0xFF, 0xFF00, 0xFF0000);
+    if (this.compression is 3) {
+        try {
+            return new PaletteData(inputStream.readInt(), inputStream.readInt(), inputStream.readInt());
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+    return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+}
+PaletteData paletteFromBytes(byte[] bytes, int numColors) {
+    int bytesOffset = 0;
+    RGB[] colors = new RGB[numColors];
+    for (int i = 0; i < numColors; i++) {
+        colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
+            bytes[bytesOffset + 1] & 0xFF,
+            bytes[bytesOffset] & 0xFF);
+        bytesOffset += 4;
+    }
+    return new PaletteData(colors);
+}
+/**
+ * Answer a byte array containing the BMP representation of
+ * the given device independent palette.
+ */
+static byte[] paletteToBytes(PaletteData pal) {
+    int n = pal.colors is null ? 0 : (pal.colors.length < 256 ? pal.colors.length : 256);
+    byte[] bytes = new byte[n * 4];
+    int offset = 0;
+    for (int i = 0; i < n; i++) {
+        RGB col = pal.colors[i];
+        bytes[offset] = cast(byte)col.blue;
+        bytes[offset + 1] = cast(byte)col.green;
+        bytes[offset + 2] = cast(byte)col.red;
+        offset += 4;
+    }
+    return bytes;
+}
+/**
+ * Unload the given image's data into the given byte stream
+ * using the given compression strategy.
+ * Answer the number of bytes written.
+ */
+int unloadData(ImageData image, OutputStream ostr, int comp) {
+    int totalSize = 0;
+    try {
+        if (comp is 0)
+            return unloadDataNoCompression(image, ostr);
+        int bpl = (image.width * image.depth + 7) / 8;
+        int bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
+        int imageBpl = image.bytesPerLine;
+        // Compression can actually take twice as much space, in worst case
+        byte[] buf = new byte[bmpBpl * 2];
+        int srcOffset = imageBpl * (image.height - 1); // Start at last line
+        byte[] data = image.data;
+        totalSize = 0;
+        byte[] buf2 = new byte[32768];
+        int buf2Offset = 0;
+        for (int y = image.height - 1; y >= 0; y--) {
+            int lineSize = compress(comp, data, srcOffset, bpl, buf, y is 0);
+            if (buf2Offset + lineSize > buf2.length) {
+                ostr.write(buf2, 0, buf2Offset);
+                buf2Offset = 0;
+            }
+            System.arraycopy(buf, 0, buf2, buf2Offset, lineSize);
+            buf2Offset += lineSize;
+            totalSize += lineSize;
+            srcOffset -= imageBpl;
+        }
+        if (buf2Offset > 0)
+            ostr.write(buf2, 0, buf2Offset);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return totalSize;
+}
+/**
+ * Prepare the given image's data for unloading into a byte stream
+ * using no compression strategy.
+ * Answer the number of bytes written.
+ */
+int unloadDataNoCompression(ImageData image, OutputStream ostr) {
+    int bmpBpl = 0;
+    try {
+        int bpl = (image.width * image.depth + 7) / 8;
+        bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
+        int linesPerBuf = 32678 / bmpBpl;
+        byte[] buf = new byte[linesPerBuf * bmpBpl];
+        byte[] data = image.data;
+        int imageBpl = image.bytesPerLine;
+        int dataIndex = imageBpl * (image.height - 1); // Start at last line
+        if (image.depth is 16) {
+            for (int y = 0; y < image.height; y += linesPerBuf) {
+                int count = image.height - y;
+                if (linesPerBuf < count) count = linesPerBuf;
+                int bufOffset = 0;
+                for (int i = 0; i < count; i++) {
+                    for (int wIndex = 0; wIndex < bpl; wIndex += 2) {
+                        buf[bufOffset + wIndex + 1] = data[dataIndex + wIndex + 1];
+                        buf[bufOffset + wIndex] = data[dataIndex + wIndex];
+                    }
+                    bufOffset += bmpBpl;
+                    dataIndex -= imageBpl;
+                }
+                ostr.write(buf, 0, bufOffset);
+            }
+        } else {
+            for (int y = 0; y < image.height; y += linesPerBuf) {
+                int tmp = image.height - y;
+                int count = tmp < linesPerBuf ? tmp : linesPerBuf;
+                int bufOffset = 0;
+                for (int i = 0; i < count; i++) {
+                    System.arraycopy(data, dataIndex, buf, bufOffset, bpl);
+                    bufOffset += bmpBpl;
+                    dataIndex -= imageBpl;
+                }
+                ostr.write(buf, 0, bufOffset);
+            }
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return bmpBpl * image.height;
+}
+/**
+ * Unload a DeviceIndependentImage using Windows .BMP format into the given
+ * byte stream.
+ */
+override void unloadIntoByteStream(ImageLoader loader) {
+    ImageData image = loader.data[0];
+    byte[] rgbs;
+    int numCols;
+    if (!((image.depth is 1) || (image.depth is 4) || (image.depth is 8) ||
+          (image.depth is 16) || (image.depth is 24) || (image.depth is 32)))
+            SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
+    int comp = this.compression;
+    if (!((comp is 0) || ((comp is 1) && (image.depth is 8)) ||
+          ((comp is 2) && (image.depth is 4))))
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+    PaletteData pal = image.palette;
+    if ((image.depth is 16) || (image.depth is 24) || (image.depth is 32)) {
+        if (!pal.isDirect)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        numCols = 0;
+        rgbs = null;
+    } else {
+        if (pal.isDirect)
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+        numCols = pal.colors.length;
+        rgbs = paletteToBytes(pal);
+    }
+    // Fill in file header, except for bfsize, which is done later.
+    int headersSize = BMPFileHeaderSize + BMPHeaderFixedSize;
+    int[] fileHeader = new int[5];
+    fileHeader[0] = 0x4D42; // Signature
+    fileHeader[1] = 0; // File size - filled in later
+    fileHeader[2] = 0; // Reserved 1
+    fileHeader[3] = 0; // Reserved 2
+    fileHeader[4] = headersSize; // Offset to data
+    if (rgbs !is null) {
+        fileHeader[4] += rgbs.length;
+    }
+
+    // Prepare data. This is done first so we don't have to try to rewind
+    // the stream and fill in the details later.
+    ByteArrayOutputStream ostr = new ByteArrayOutputStream();
+    unloadData(image, ostr, comp);
+    byte[] data = ostr.toByteArray();
+
+    // Calculate file size
+    fileHeader[1] = fileHeader[4] + data.length;
+
+    // Write the headers
+    try {
+        outputStream.writeShort(fileHeader[0]);
+        outputStream.writeInt(fileHeader[1]);
+        outputStream.writeShort(fileHeader[2]);
+        outputStream.writeShort(fileHeader[3]);
+        outputStream.writeInt(fileHeader[4]);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    try {
+        outputStream.writeInt(BMPHeaderFixedSize);
+        outputStream.writeInt(image.width);
+        outputStream.writeInt(image.height);
+        outputStream.writeShort(1);
+        outputStream.writeShort(cast(short)image.depth);
+        outputStream.writeInt(comp);
+        outputStream.writeInt(data.length);
+        outputStream.writeInt(pelsPerMeter.x);
+        outputStream.writeInt(pelsPerMeter.y);
+        outputStream.writeInt(numCols);
+        outputStream.writeInt(importantColors);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+
+    // Unload palette
+    if (numCols > 0) {
+        try {
+            outputStream.write(rgbs);
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+        }
+    }
+
+    // Unload the data
+    try {
+        outputStream.write(data);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+void flipScanLines(byte[] data, int stride, int height) {
+    int i1 = 0;
+    int i2 = (height - 1) * stride;
+    for (int i = 0; i < height / 2; i++) {
+        for (int index = 0; index < stride; index++) {
+            byte b = data[index + i1];
+            data[index + i1] = data[index + i2];
+            data[index + i2] = b;
+        }
+        i1 += stride;
+        i2 -= stride;
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/image/WinICOFileFormat.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.image.WinICOFileFormat;
+
+import org.eclipse.swt.internal.image.FileFormat;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.internal.image.WinBMPFileFormat;
+import org.eclipse.swt.SWT;
+import java.lang.all;
+
+import tango.core.Exception;
+
+public final class WinICOFileFormat : FileFormat {
+
+byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
+    // Destructively bit invert data in the given byte array.
+    for (int i = startIndex; i < endIndex; i++) {
+        data[i] = cast(byte)(255 - data[i - startIndex]);
+    }
+    return data;
+}
+
+static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
+    if (pad is newPad) return data;
+    int stride = (width * depth + 7) / 8;
+    int bpl = (stride + (pad - 1)) / pad * pad;
+    int newBpl = (stride + (newPad - 1)) / newPad * newPad;
+    byte[] newData = new byte[height * newBpl];
+    int srcIndex = 0, destIndex = 0;
+    for (int y = 0; y < height; y++) {
+        System.arraycopy(data, srcIndex, newData, destIndex, newBpl);
+        srcIndex += bpl;
+        destIndex += newBpl;
+    }
+    return newData;
+}
+/**
+ * Answer the size in bytes of the file representation of the given
+ * icon
+ */
+int iconSize(ImageData i) {
+    int shapeDataStride = (i.width * i.depth + 31) / 32 * 4;
+    int maskDataStride = (i.width + 31) / 32 * 4;
+    int dataSize = (shapeDataStride + maskDataStride) * i.height;
+    int paletteSize = i.palette.colors !is null ? i.palette.colors.length * 4 : 0;
+    return WinBMPFileFormat.BMPHeaderFixedSize + paletteSize + dataSize;
+}
+override bool isFileFormat(LEDataInputStream stream) {
+    try {
+        byte[] header = new byte[4];
+        stream.read(header);
+        stream.unread(header);
+        return header[0] is 0 && header[1] is 0 && header[2] is 1 && header[3] is 0;
+    } catch (Exception e) {
+        return false;
+    }
+}
+bool isValidIcon(ImageData i) {
+    switch (i.depth) {
+        case 1:
+        case 4:
+        case 8:
+            if (i.palette.isDirect) return false;
+            int size = i.palette.colors.length;
+            return size is 2 || size is 16 || size is 32 || size is 256;
+        case 24:
+        case 32:
+            return i.palette.isDirect;
+        default:
+    }
+    return false;
+}
+int loadFileHeader(LEDataInputStream byteStream) {
+    int[] fileHeader = new int[3];
+    try {
+        fileHeader[0] = byteStream.readShort();
+        fileHeader[1] = byteStream.readShort();
+        fileHeader[2] = byteStream.readShort();
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    if ((fileHeader[0] !is 0) || (fileHeader[1] !is 1))
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    int numIcons = fileHeader[2];
+    if (numIcons <= 0)
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return numIcons;
+}
+int loadFileHeader(LEDataInputStream byteStream, bool hasHeader) {
+    int[] fileHeader = new int[3];
+    try {
+        if (hasHeader) {
+            fileHeader[0] = byteStream.readShort();
+            fileHeader[1] = byteStream.readShort();
+        } else {
+            fileHeader[0] = 0;
+            fileHeader[1] = 1;
+        }
+        fileHeader[2] = byteStream.readShort();
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    if ((fileHeader[0] !is 0) || (fileHeader[1] !is 1))
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    int numIcons = fileHeader[2];
+    if (numIcons <= 0)
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    return numIcons;
+}
+override ImageData[] loadFromByteStream() {
+    int numIcons = loadFileHeader(inputStream);
+    int[][] headers = loadIconHeaders(numIcons);
+    ImageData[] icons = new ImageData[headers.length];
+    for (int i = 0; i < icons.length; i++) {
+        icons[i] = loadIcon(headers[i]);
+    }
+    return icons;
+}
+/**
+ * Load one icon from the byte stream.
+ */
+ImageData loadIcon(int[] iconHeader) {
+    byte[] infoHeader = loadInfoHeader(iconHeader);
+    WinBMPFileFormat bmpFormat = new WinBMPFileFormat();
+    bmpFormat.inputStream = inputStream;
+    PaletteData palette = bmpFormat.loadPalette(infoHeader);
+    byte[] shapeData = bmpFormat.loadData(infoHeader);
+    int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+    int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+    if (height < 0) height = -height;
+    int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+    infoHeader[14] = 1;
+    infoHeader[15] = 0;
+    byte[] maskData = bmpFormat.loadData(infoHeader);
+    maskData = convertPad(maskData, width, height, 1, 4, 2);
+    bitInvertData(maskData, 0, maskData.length);
+    return ImageData.internal_new(
+        width,
+        height,
+        depth,
+        palette,
+        4,
+        shapeData,
+        2,
+        maskData,
+        null,
+        -1,
+        -1,
+        SWT.IMAGE_ICO,
+        0,
+        0,
+        0,
+        0);
+}
+int[][] loadIconHeaders(int numIcons) {
+    int[][] headers = new int[][]( numIcons, 7 );
+    try {
+        for (int i = 0; i < numIcons; i++) {
+            headers[i][0] = inputStream.read();
+            headers[i][1] = inputStream.read();
+            headers[i][2] = inputStream.readShort();
+            headers[i][3] = inputStream.readShort();
+            headers[i][4] = inputStream.readShort();
+            headers[i][5] = inputStream.readInt();
+            headers[i][6] = inputStream.readInt();
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    return headers;
+}
+byte[] loadInfoHeader(int[] iconHeader) {
+    int width = iconHeader[0];
+    int height = iconHeader[1];
+    int numColors = iconHeader[2]; // the number of colors is in the low byte, but the high byte must be 0
+    if (numColors is 0) numColors = 256; // this is specified: '00' represents '256' (0x100) colors
+    if ((numColors !is 2) && (numColors !is 8) && (numColors !is 16) &&
+        (numColors !is 32) && (numColors !is 256))
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    if (inputStream.getPosition() < iconHeader[6]) {
+        // Seek to the specified offset
+        try {
+            inputStream.skip(iconHeader[6] - inputStream.getPosition());
+        } catch (IOException e) {
+            SWT.error(SWT.ERROR_IO, e);
+            return null;
+        }
+    }
+    byte[] infoHeader = new byte[WinBMPFileFormat.BMPHeaderFixedSize];
+    try {
+        inputStream.read(infoHeader);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    if (((infoHeader[12] & 0xFF) | ((infoHeader[13] & 0xFF) << 8)) !is 1)
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    int infoWidth = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
+    int infoHeight = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
+    int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
+    if (height is infoHeight && bitCount is 1) height /= 2;
+    if (!((width is infoWidth) && (height * 2 is infoHeight) &&
+        (bitCount is 1 || bitCount is 4 || bitCount is 8 || bitCount is 24 || bitCount is 32)))
+            SWT.error(SWT.ERROR_INVALID_IMAGE);
+    infoHeader[8] = cast(byte)(height & 0xFF);
+    infoHeader[9] = cast(byte)((height >> 8) & 0xFF);
+    infoHeader[10] = cast(byte)((height >> 16) & 0xFF);
+    infoHeader[11] = cast(byte)((height >> 24) & 0xFF);
+    return infoHeader;
+}
+/**
+ * Unload a single icon
+ */
+void unloadIcon(ImageData icon) {
+    int sizeImage = (((icon.width * icon.depth + 31) / 32 * 4) +
+        ((icon.width + 31) / 32 * 4)) * icon.height;
+    try {
+        outputStream.writeInt(WinBMPFileFormat.BMPHeaderFixedSize);
+        outputStream.writeInt(icon.width);
+        outputStream.writeInt(icon.height * 2);
+        outputStream.writeShort(1);
+        outputStream.writeShort(cast(short)icon.depth);
+        outputStream.writeInt(0);
+        outputStream.writeInt(sizeImage);
+        outputStream.writeInt(0);
+        outputStream.writeInt(0);
+        outputStream.writeInt(icon.palette.colors !is null ? icon.palette.colors.length : 0);
+        outputStream.writeInt(0);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+
+    byte[] rgbs = WinBMPFileFormat.paletteToBytes(icon.palette);
+    try {
+        outputStream.write(rgbs);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    unloadShapeData(icon);
+    unloadMaskData(icon);
+}
+/**
+ * Unload the icon header for the given icon, calculating the offset.
+ */
+void unloadIconHeader(ImageData i) {
+    int headerSize = 16;
+    int offset = headerSize + 6;
+    int iconSize = iconSize(i);
+    try {
+        outputStream.write(i.width);
+        outputStream.write(i.height);
+        outputStream.writeShort(i.palette.colors !is null ? i.palette.colors.length : 0);
+        outputStream.writeShort(0);
+        outputStream.writeShort(0);
+        outputStream.writeInt(iconSize);
+        outputStream.writeInt(offset);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+override void unloadIntoByteStream(ImageLoader loader) {
+    /* We do not currently support writing multi-image ico,
+     * so we use the first image data in the loader's array. */
+    ImageData image = loader.data[0];
+    if (!isValidIcon(image))
+        SWT.error(SWT.ERROR_INVALID_IMAGE);
+    try {
+        outputStream.writeShort(0);
+        outputStream.writeShort(1);
+        outputStream.writeShort(1);
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+    unloadIconHeader(image);
+    unloadIcon(image);
+}
+/**
+ * Unload the mask data for an icon. The data is flipped vertically
+ * and inverted.
+ */
+void unloadMaskData(ImageData icon) {
+    ImageData mask = icon.getTransparencyMask();
+    int bpl = (icon.width + 7) / 8;
+    int pad = mask.scanlinePad;
+    int srcBpl = (bpl + pad - 1) / pad * pad;
+    int destBpl = (bpl + 3) / 4 * 4;
+    byte[] buf = new byte[destBpl];
+    int offset = (icon.height - 1) * srcBpl;
+    byte[] data = mask.data;
+    try {
+        for (int i = 0; i < icon.height; i++) {
+            System.arraycopy(data, offset, buf, 0, bpl);
+            bitInvertData(buf, 0, bpl);
+            outputStream.write(buf, 0, destBpl);
+            offset -= srcBpl;
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+/**
+ * Unload the shape data for an icon. The data is flipped vertically.
+ */
+void unloadShapeData(ImageData icon) {
+    int bpl = (icon.width * icon.depth + 7) / 8;
+    int pad = icon.scanlinePad;
+    int srcBpl = (bpl + pad - 1) / pad * pad;
+    int destBpl = (bpl + 3) / 4 * 4;
+    byte[] buf = new byte[destBpl];
+    int offset = (icon.height - 1) * srcBpl;
+    byte[] data = icon.data;
+    try {
+        for (int i = 0; i < icon.height; i++) {
+            System.arraycopy(data, offset, buf, 0, bpl);
+            outputStream.write(buf, 0, destBpl);
+            offset -= srcBpl;
+        }
+    } catch (IOException e) {
+        SWT.error(SWT.ERROR_IO, e);
+    }
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/Common.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,105 @@
+module org.eclipse.swt.internal.mozilla.Common; 
+
+version(Windows) {
+    const NS_WIN32 = 1;
+}
+version(linux) {
+    const NS_UNIX = 1;
+}
+
+alias uint nsresult;
+alias uint nsrefcnt;
+
+const nsnull = 0;
+
+/******************************************************************************
+
+    prtypes
+
+******************************************************************************/
+
+extern (System):
+
+alias ubyte PRUint8;
+alias byte  PRInt8;
+
+const PR_INT8_MAX = 127;
+const PR_UINT8_MAX = 255U;
+
+alias ushort PRUint16;
+alias short PRInt16;
+
+const PR_INT16_MAX = 32767;
+const PR_UINT16_MAX = 65535U;
+
+alias uint PRUint32;
+alias int PRInt32;
+
+alias long PRInt64;
+alias ulong PRUint64;
+
+alias int PRIntn;
+alias uint PRUintn;
+
+alias double PRFloat64;
+alias size_t PRSize;
+
+alias PRInt32 PROffset32;
+alias PRInt64 PROffset64;
+
+alias ptrdiff_t PRPtrdiff;
+alias uint      PRUptrdiff;
+
+alias PRIntn PRBool;
+
+const PR_TRUE = 1;
+const PR_FALSE = 0;
+
+alias PRUint8 PRPackedBool;
+
+enum
+{
+    PR_FAILURE = -1,
+    PR_SUCCESS,
+}
+
+alias int PRStatus;
+
+alias wchar PRUnichar;
+
+alias int PRWord;
+alias uint PRUword;
+
+/******************************************************************************
+
+    nscommon
+
+******************************************************************************/
+
+alias void* nsIWidget;
+alias void* nsILayoutHistoryState;
+alias void* nsIDeviceContext;
+alias void* nsPresContext;
+alias void* nsEvent;
+alias void* nsEventStatus;
+alias void* nsIPresShell;
+alias void* JSContext;
+
+alias void* PRThread;
+alias void* PLEvent;
+alias void* PLEventQueue;
+alias void* PLHandleEventProc;
+alias void* PLDestroyEventProc;
+
+/******************************************************************************
+
+    gfxtypes
+
+******************************************************************************/
+
+alias PRUint32 gfx_color;
+alias PRUint16 gfx_depth;
+alias PRInt32  gfx_format;
+
+alias void* nsIntRect;
+alias void* nsRect;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/XPCOM.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,202 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by Netscape are Copyright (C) 1998-1999
+ * Netscape Communications Corporation.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * IBM
+ * -  Binding to permit interfacing between Mozilla and SWT
+ * -  Copyright (C) 2003, 2006 IBM Corp.  All Rights Reserved.
+ * Port to the D programming language:
+ *      John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+
+module org.eclipse.swt.internal.mozilla.XPCOM;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+import org.eclipse.swt.internal.mozilla.nsIModule;
+import org.eclipse.swt.internal.mozilla.nsIComponentManager;
+import org.eclipse.swt.internal.mozilla.nsIComponentRegistrar;
+import org.eclipse.swt.internal.mozilla.nsIServiceManager;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsIDirectoryService;
+import org.eclipse.swt.internal.mozilla.nsIMemory;
+import org.eclipse.swt.internal.mozilla.nsIDebug;
+import org.eclipse.swt.internal.mozilla.nsITraceRefcnt;
+
+private import java.lang.all;
+
+/******************************************************************************
+
+  Original SWT XPCOM constant declarations for XPCOM
+
+******************************************************************************/
+   
+const String MOZILLA_FIVE_HOME = "MOZILLA_FIVE_HOME"; //$NON-NLS-1$
+const String MOZILLA_PLUGIN_PATH = "MOZ_PLUGIN_PATH"; //$NON-NLS-1$
+const String CONTENT_MAYBETEXT = "application/x-vnd.mozilla.maybe-text"; //$NON-NLS-1$
+const String CONTENT_MULTIPART = "multipart/x-mixed-replace"; //$NON-NLS-1$
+const String DOMEVENT_FOCUS = "focus"; //$NON-NLS-1$
+const String DOMEVENT_UNLOAD = "unload"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEDRAG = "draggesture"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEWHEEL = "DOMMouseScroll"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEOVER = "mouseover"; //$NON-NLS-1$
+const String DOMEVENT_MOUSEOUT = "mouseout"; //$NON-NLS-1$
+const String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$
+const String DOMEVENT_KEYDOWN = "keydown"; //$NON-NLS-1$
+const String DOMEVENT_KEYPRESS = "keypress"; //$NON-NLS-1$
+
+/* CID constants */
+const nsID NS_APPSHELL_CID = { 0x2d96b3df, 0xc051, 0x11d1, [0xa8,0x27,0x00,0x40,0x95,0x9a,0x28, 0xc9]}; //$NON-NLS-1$
+const nsID NS_CATEGORYMANAGER_CID = { 0x16d222a6, 0x1dd2, 0x11b2, [0xb6,0x93,0xf3,0x8b,0x02,0xc0,0x21,0xb2]}; //$NON-NLS-1$
+const nsID NS_DOWNLOAD_CID = { 0xe3fa9D0a, 0x1dd1, 0x11b2, [0xbd,0xef,0x8c,0x72,0x0b,0x59,0x74,0x45]}; //$NON-NLS-1$
+const nsID NS_FILEPICKER_CID = { 0x54ae32f8, 0x1dd2, 0x11b2, [0xa2,0x09,0xdf,0x7c,0x50,0x53,0x70,0xf8]}; //$NON-NLS-1$
+const nsID NS_HELPERAPPLAUNCHERDIALOG_CID = {0xf68578eb,0x6ec2,0x4169,[0xae,0x19,0x8c,0x62,0x43,0xf0,0xab,0xe1]}; //$NON-NLS-1$
+const nsID NS_INPUTSTREAMCHANNEL_CID = {0x6ddb050c,0x0d04,0x11d4,[0x98,0x6e,0x00,0xc0,0x4f,0xa0,0xcf,0x4a]}; //$NON-NLS-1$
+const nsID NS_IOSERVICE_CID = {0x9ac9e770,0x18bc,0x11d3,[0x93,0x37,0x00,0x10,0x4b,0xa0,0xfd,0x40]}; //$NON-NLS-1$
+const nsID NS_LOADGROUP_CID = {0xe1c61582,0x2a84,0x11d3,[0x8c,0xce,0x00,0x60,0xb0,0xfc,0x14,0xa3]}; //$NON-NLS-1$
+const nsID NS_PROMPTSERVICE_CID = {0xa2112d6a,0x0e28,0x421f,[0xb4,0x6a,0x25,0xc0,0xb3,0x08,0xcb,0xd0]}; //$NON-NLS-1$
+
+const String NS_CONTEXTSTACK_CONTRACTID = "@mozilla.org/js/xpc/ContextStack;1"; //$NON-NLS-1$
+const String NS_COOKIEMANAGER_CONTRACTID = "@mozilla.org/cookiemanager;1"; //$NON-NLS-1$
+const String NS_DIRECTORYSERVICE_CONTRACTID = "@mozilla.org/file/directory_service;1"; //$NON-NLS-1$
+const String NS_DOMSERIALIZER_CONTRACTID = "@mozilla.org/xmlextras/xmlserializer;1"; //$NON-NLS-1$
+const String NS_DOWNLOAD_CONTRACTID = "@mozilla.org/download;1"; //$NON-NLS-1$
+const String NS_FILEPICKER_CONTRACTID = "@mozilla.org/filepicker;1"; //$NON-NLS-1$
+const String NS_HELPERAPPLAUNCHERDIALOG_CONTRACTID = "@mozilla.org/helperapplauncherdialog;1"; //$NON-NLS-1$
+const String NS_MEMORY_CONTRACTID = "@mozilla.org/xpcom/memory-service;1"; //$NON-NLS-1$
+const String NS_OBSERVER_CONTRACTID = "@mozilla.org/observer-service;1"; //$NON-NLS-1$
+const String NS_PREFLOCALIZEDSTRING_CONTRACTID = "@mozilla.org/pref-localizedstring;1"; //$NON-NLS-1$
+const String NS_PREFSERVICE_CONTRACTID = "@mozilla.org/preferences-service;1"; //$NON-NLS-1$
+const String NS_PROMPTSERVICE_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1"; //$NON-NLS-1$
+const String NS_TRANSFER_CONTRACTID = "@mozilla.org/transfer;1"; //$NON-NLS-1$
+const String NS_WEBNAVIGATIONINFO_CONTRACTID = "@mozilla.org/webnavigation-info;1"; //$NON-NLS-1$
+const String NS_WINDOWWATCHER_CONTRACTID = "@mozilla.org/embedcomp/window-watcher;1"; //$NON-NLS-1$
+
+/* directory service constants */
+const String NS_APP_APPLICATION_REGISTRY_DIR = "AppRegD"; //$NON-NLS-1$
+const String NS_APP_CACHE_PARENT_DIR = "cachePDir"; //$NON-NLS-1$
+const String NS_APP_HISTORY_50_FILE = "UHist"; //$NON-NLS-1$
+const String NS_APP_LOCALSTORE_50_FILE = "LclSt"; //$NON-NLS-1$
+const String NS_APP_PLUGINS_DIR_LIST = "APluginsDL"; //$NON-NLS-1$
+const String NS_APP_PREF_DEFAULTS_50_DIR = "PrfDef"; //$NON-NLS-1$
+const String NS_APP_PREFS_50_DIR = "PrefD"; //$NON-NLS-1$
+const String NS_APP_PREFS_50_FILE = "PrefF"; //$NON-NLS-1$
+const String NS_APP_USER_CHROME_DIR = "UChrm"; //$NON-NLS-1$
+const String NS_APP_USER_MIMETYPES_50_FILE = "UMimTyp"; //$NON-NLS-1$
+const String NS_APP_USER_PROFILE_50_DIR = "ProfD"; //$NON-NLS-1$
+const String NS_GRE_COMPONENT_DIR = "GreComsD"; //$NON-NLS-1$
+const String NS_GRE_DIR = "GreD"; //$NON-NLS-1$
+const String NS_OS_CURRENT_PROCESS_DIR = "CurProcD"; //$NON-NLS-1$
+const String NS_OS_HOME_DIR = "Home"; //$NON-NLS-1$
+const String NS_OS_TEMP_DIR = "TmpD"; //$NON-NLS-1$
+const String NS_XPCOM_COMPONENT_DIR = "ComsD"; //$NON-NLS-1$
+const String NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD"; //$NON-NLS-1$
+const String NS_XPCOM_INIT_CURRENT_PROCESS_DIR = "MozBinD"; //$NON-NLS-1$
+
+/* XPCOM constants */
+const int NS_OK =  0;
+const int NS_COMFALSE = 1;
+const int NS_BINDING_ABORTED = 0x804B0002;
+const int NS_ERROR_BASE = 0xc1f30000;
+const int NS_ERROR_NOT_INITIALIZED =  NS_ERROR_BASE + 1;
+const int NS_ERROR_ALREADY_INITIALIZED = NS_ERROR_BASE + 2;
+const int NS_ERROR_NOT_IMPLEMENTED =  0x80004001;
+const int NS_NOINTERFACE =  0x80004002;
+const int NS_ERROR_NO_INTERFACE =  NS_NOINTERFACE;
+const int NS_ERROR_INVALID_POINTER =  0x80004003;
+const int NS_ERROR_NULL_POINTER = NS_ERROR_INVALID_POINTER;
+const int NS_ERROR_ABORT = 0x80004004;
+const int NS_ERROR_FAILURE = 0x80004005;
+const int NS_ERROR_UNEXPECTED = 0x8000ffff;
+const int NS_ERROR_OUT_OF_MEMORY = 0x8007000e;
+const int NS_ERROR_ILLEGAL_VALUE = 0x80070057;
+const int NS_ERROR_INVALID_ARG = NS_ERROR_ILLEGAL_VALUE;
+const int NS_ERROR_NO_AGGREGATION = 0x80040110;
+const int NS_ERROR_NOT_AVAILABLE = 0x80040111;
+const int NS_ERROR_FACTORY_NOT_REGISTERED = 0x80040154;
+const int NS_ERROR_FACTORY_REGISTER_AGAIN = 0x80040155;
+const int NS_ERROR_FACTORY_NOT_LOADED = 0x800401f8;
+const int NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT = NS_ERROR_BASE + 0x101;
+const int NS_ERROR_FACTORY_EXISTS = NS_ERROR_BASE + 0x100;
+const int NS_ERROR_HTMLPARSER_UNRESOLVEDDTD = 0x804e03f3;
+const int NS_ERROR_FILE_NOT_FOUND = 0x80520012;
+const int NS_ERROR_FILE_UNRECOGNIZED_PATH = 0x80520001;
+
+public nsresult NS_FAILED( nsresult result ) {
+    return result & 0x80000000;
+}
+
+public nsresult NS_SUCCEEDED( nsresult result ) {
+    return !(result & 0x80000000);
+}
+
+public PRUint32 strlen_PRUnichar ( PRUnichar* str )
+{
+    PRUint32 len = 0;
+    if (str !is null) 
+        while (*(str++) != 0) len++;
+    return len;
+}
+
+/******************************************************************************
+
+    XPCOM Startup functions
+
+******************************************************************************/
+
+extern (System):
+
+struct nsStaticModuleInfo
+{
+    char *name;
+    nsGetModuleProc getModule;
+}
+
+alias nsresult function (nsIComponentManager, nsIFile, nsIModule*) nsGetModuleProc;
+
+/******************************************************************************
+
+******************************************************************************/
+
+nsresult  NS_InitXPCOM2( nsIServiceManager *result, nsIFile binDirectory,
+	                     nsIDirectoryServiceProvider appFileLocationProvider );
+nsresult  NS_InitXPCOM3( nsIServiceManager *result, nsIFile binDirectory,
+	                     nsIDirectoryServiceProvider appFileLocationProvider,
+	                     nsStaticModuleInfo* staticComponents,
+	                     PRUint32 componentCount );
+
+nsresult  NS_ShutdownXPCOM(nsIServiceManager servMgr);
+nsresult  NS_GetServiceManager(nsIServiceManager *result);
+nsresult  NS_GetComponentManager(nsIComponentManager *result);
+nsresult  NS_GetComponentRegistrar(nsIComponentRegistrar *result);
+nsresult  NS_GetMemoryManager(nsIMemory *result);
+nsresult  NS_NewLocalFile(nsAString* path, PRBool followLinks, nsILocalFile* result);
+nsresult  NS_NewNativeLocalFile(nsACString* path, PRBool followLinks, nsILocalFile* result);
+void *    NS_Alloc(PRSize size);
+void *    NS_Realloc(void *ptr, PRSize size);
+void      NS_Free(void *ptr);
+nsresult  NS_GetDebug(nsIDebug *result);
+nsresult  NS_GetTraceRefcnt(nsITraceRefcnt *result);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/XPCOMInit.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,57 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by Netscape are Copyright (C) 1998-1999
+ * Netscape Communications Corporation.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * IBM
+ * -  Binding to permit interfacing between Mozilla and SWT
+ * -  Copyright (C) 2003, 2006 IBM Corp.  All Rights Reserved.
+ *
+ * Port to the D programming language:
+ *      John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module org.eclipse.swt.internal.mozilla.XPCOMInit;
+
+import org.eclipse.swt.internal.mozilla.Common;
+
+extern(System) {
+
+    align(4):
+
+    struct GREVersionRange {
+        char    *lower;
+        int     lowerInclusive;
+        char    *upper;
+        int     upperInclusive;
+    }
+
+    struct GREProperty {
+        char *property;
+        char *value;
+    } 
+}
+  
+const int PATH_MAX = 4096;
+
+extern(System):
+
+nsresult GRE_GetGREPathWithProperties(GREVersionRange *versions, PRUint32 versionsLength, GREProperty *properties, PRUint32 propertiesLength, char *buffer, PRUint32 buflen);
+nsresult XPCOMGlueStartup(char* xpcomFile);
+nsresult XPCOMGlueShutdown ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/gfxIImageFrame.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,52 @@
+module org.eclipse.swt.internal.mozilla.gfxIImageFrame;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] GFXIIMAGEFRAME_IID_STR = "f6d00ee7-defc-4101-b2dc-e72cf4c37c3c";
+
+const nsIID GFXIIMAGEFRAME_IID= 
+  {0xf6d00ee7, 0xdefc, 0x4101, 
+    [ 0xb2, 0xdc, 0xe7, 0x2c, 0xf4, 0xc3, 0x7c, 0x3c ]};
+
+interface gfxIImageFrame : nsISupports {
+
+
+  static const char[] IID_STR = GFXIIMAGEFRAME_IID_STR;
+  static const nsIID IID = GFXIIMAGEFRAME_IID;
+
+extern(System):
+
+  nsresult Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, gfx_format aFormat, gfx_depth aDepth);
+  nsresult GetMutable(PRBool *aMutable);
+  nsresult SetMutable(PRBool aMutable);
+  nsresult GetX(PRInt32 *aX);
+  nsresult GetY(PRInt32 *aY);
+  nsresult GetWidth(PRInt32 *aWidth);
+  nsresult GetHeight(PRInt32 *aHeight);
+  nsresult GetRect(nsIntRect * rect);
+  nsresult GetFormat(gfx_format *aFormat);
+  nsresult GetNeedsBackground(PRBool *aNeedsBackground);
+  nsresult GetImageBytesPerRow(PRUint32 *aImageBytesPerRow);
+  nsresult GetImageDataLength(PRUint32 *aImageDataLength);
+  nsresult GetImageData(PRUint8 **bits, PRUint32 *length);
+  nsresult SetImageData(PRUint8 *data, PRUint32 length, PRInt32 offset);
+  nsresult LockImageData();
+  nsresult UnlockImageData();
+  nsresult GetAlphaBytesPerRow(PRUint32 *aAlphaBytesPerRow);
+  nsresult GetAlphaDataLength(PRUint32 *aAlphaDataLength);
+  nsresult GetAlphaData(PRUint8 **bits, PRUint32 *length);
+  nsresult SetAlphaData(PRUint8 *data, PRUint32 length, PRInt32 offset);
+  nsresult LockAlphaData();
+  nsresult UnlockAlphaData();
+  nsresult DrawTo(gfxIImageFrame aDst, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
+  nsresult GetTimeout(PRInt32 *aTimeout);
+  nsresult SetTimeout(PRInt32 aTimeout);
+  nsresult GetFrameDisposalMethod(PRInt32 *aFrameDisposalMethod);
+  nsresult SetFrameDisposalMethod(PRInt32 aFrameDisposalMethod);
+  nsresult GetBackgroundColor(gfx_color *aBackgroundColor);
+  nsresult SetBackgroundColor(gfx_color aBackgroundColor);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/imgIContainer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,49 @@
+module org.eclipse.swt.internal.mozilla.imgIContainer;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.gfxIImageFrame;
+import org.eclipse.swt.internal.mozilla.imgIContainerObserver;
+
+const char[] IMGICONTAINER_IID_STR = "1a6290e6-8285-4e10-963d-d001f8d327b8";
+
+const nsIID IMGICONTAINER_IID= 
+  {0x1a6290e6, 0x8285, 0x4e10, 
+    [ 0x96, 0x3d, 0xd0, 0x01, 0xf8, 0xd3, 0x27, 0xb8 ]};
+
+
+interface imgIContainer : nsISupports {
+
+  static const char[] IID_STR = IMGICONTAINER_IID_STR;
+  static const nsIID IID = IMGICONTAINER_IID;
+
+extern(System):
+  nsresult Init(PRInt32 aWidth, PRInt32 aHeight, imgIContainerObserver aObserver);
+  nsresult GetPreferredAlphaChannelFormat(gfx_format *aPreferredAlphaChannelFormat);
+  nsresult GetWidth(PRInt32 *aWidth);
+  nsresult GetHeight(PRInt32 *aHeight);
+  nsresult GetCurrentFrame(gfxIImageFrame  *aCurrentFrame);
+  nsresult GetNumFrames(PRUint32 *aNumFrames);
+
+  enum { kNormalAnimMode = 0 };
+  enum { kDontAnimMode = 1 };
+  enum { kLoopOnceAnimMode = 2 };
+
+  nsresult GetAnimationMode(PRUint16 *aAnimationMode);
+  nsresult SetAnimationMode(PRUint16 aAnimationMode);
+  nsresult GetFrameAt(PRUint32 index, gfxIImageFrame *_retval);
+  nsresult AppendFrame(gfxIImageFrame item);
+  nsresult RemoveFrame(gfxIImageFrame item);
+  nsresult EndFrameDecode(PRUint32 framenumber, PRUint32 timeout);
+  nsresult DecodingComplete();
+  nsresult Clear();
+  nsresult StartAnimation();
+  nsresult StopAnimation();
+  nsresult ResetAnimation();
+  nsresult GetLoopCount(PRInt32 *aLoopCount);
+  nsresult SetLoopCount(PRInt32 aLoopCount);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/imgIContainerObserver.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.imgIContainerObserver;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.imgIContainer;
+import org.eclipse.swt.internal.mozilla.gfxIImageFrame;
+
+const char[] IMGICONTAINEROBSERVER_IID_STR = "53102f15-0f53-4939-957e-aea353ad2700";
+
+const nsIID IMGICONTAINEROBSERVER_IID= 
+  {0x53102f15, 0x0f53, 0x4939, 
+    [ 0x95, 0x7e, 0xae, 0xa3, 0x53, 0xad, 0x27, 0x00 ]};
+
+interface imgIContainerObserver : nsISupports {
+
+  static const char[] IID_STR = IMGICONTAINEROBSERVER_IID_STR;
+  static const nsIID IID = IMGICONTAINEROBSERVER_IID;
+
+extern(System):
+  nsresult FrameChanged(imgIContainer aContainer, gfxIImageFrame aFrame, nsIntRect * aDirtyRect);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsEmbedString.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,91 @@
+module org.eclipse.swt.internal.mozilla.nsEmbedString;
+
+import Utf = tango.text.convert.Utf;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+import XPCOM = org.eclipse.swt.internal.mozilla.XPCOM;
+
+scope class nsEmbedString
+{    
+	this(wchar[] s)
+	{
+		nsresult result;
+		result = NS_StringContainerInit2(&str, s.ptr, s.length, 0);
+		if (XPCOM.NS_FAILED(result)) 
+			throw new Exception("Init string container fail");
+	}
+
+	this()
+	{
+		nsresult result;
+		result = NS_StringContainerInit(&str);
+		if (XPCOM.NS_FAILED(result)) 
+			throw new Exception("Init string container fail");
+	}
+
+	nsAString* opCast()
+	{
+		return cast(nsAString*)&str;
+	}
+
+	wchar[] toString16()
+	{
+		wchar* buffer = null;
+		PRBool terminated;
+		uint len = NS_StringGetData(cast(nsAString*)&str, &buffer, &terminated);
+		return buffer[0 .. len].dup;
+	}
+    
+    char[] toString()
+    {
+        return Utf.toString(this.toString16());
+    }
+    ~this()
+	{
+		NS_StringContainerFinish(&str);
+	}
+private:
+	nsStringContainer str;
+}
+
+
+scope class nsEmbedCString
+{
+	this(char[] s)
+	{
+		nsresult result;
+		result = NS_CStringContainerInit2(&str, s.ptr, s.length, 0);
+		if (XPCOM.NS_FAILED(result)) 
+			throw new Exception("Init string container fail");
+	}
+
+	this()
+	{
+		nsresult result;
+		result = NS_CStringContainerInit(&str);
+		if (XPCOM.NS_FAILED(result)) 
+			throw new Exception("Init string container fail");
+	}
+
+	nsACString* opCast()
+	{
+		return cast(nsACString*)&str;
+	}
+
+	char[] toString()
+	{
+		char* buffer = null;
+		PRBool terminated;
+		uint len = NS_CStringGetData(cast(nsACString*)&str, &buffer, &terminated);
+        return buffer[0 .. len].dup;
+	}
+
+	~this()
+	{
+		NS_CStringContainerFinish(&str);
+	}
+private:
+	nsCStringContainer str;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsError.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,67 @@
+module org.eclipse.swt.internal.mozilla.nsError;
+
+import org.eclipse.swt.internal.mozilla.Common;
+
+/**
+ * @name Standard Module Offset Code. Each Module should identify a unique number
+ *       and then all errors associated with that module become offsets from the
+ *       base associated with that module id. There are 16 bits of code bits for
+ *       each module.
+ */
+
+enum {
+    NS_ERROR_MODULE_XPCOM = 1,
+    NS_ERROR_MODULE_BASE = 2,
+    NS_ERROR_MODULE_GFX = 3,
+    NS_ERROR_MODULE_WIDGET = 4,
+    NS_ERROR_MODULE_CALENDAR = 5,
+    NS_ERROR_MODULE_NETWORK = 6,
+    NS_ERROR_MODULE_PLUGINS = 7,
+    NS_ERROR_MODULE_LAYOUT = 8,
+    NS_ERROR_MODULE_HTMLPARSER = 9,
+    NS_ERROR_MODULE_RDF = 10,
+    NS_ERROR_MODULE_UCONV = 11,
+    NS_ERROR_MODULE_REG = 12,
+    NS_ERROR_MODULE_FILES = 13,
+    NS_ERROR_MODULE_DOM = 14,
+    NS_ERROR_MODULE_IMGLIB = 15,
+    NS_ERROR_MODULE_MAILNEWS = 16,
+    NS_ERROR_MODULE_EDITOR = 17,
+    NS_ERROR_MODULE_XPCONNECT = 18,
+    NS_ERROR_MODULE_PROFILE = 19,
+    NS_ERROR_MODULE_LDAP = 20,
+    NS_ERROR_MODULE_SECURITY = 21,
+    NS_ERROR_MODULE_DOM_XPATH = 22,
+    NS_ERROR_MODULE_DOM_RANGE = 23,
+    NS_ERROR_MODULE_URILOADER = 24,
+    NS_ERROR_MODULE_CONTENT = 25,
+    NS_ERROR_MODULE_PYXPCOM = 26,
+    NS_ERROR_MODULE_XSLT = 27,
+    NS_ERROR_MODULE_IPC = 28,
+    NS_ERROR_MODULE_SVG = 29,
+    NS_ERROR_MODULE_STORAGE = 30,
+    NS_ERROR_MODULE_SCHEMA = 31,
+    NS_ERROR_MODULE_GENERAL = 51,
+    NS_ERROR_SEVERITY_ERROR = 1,
+    NS_ERROR_MODULE_BASE_OFFSET = 0x45,
+}
+
+const nsresult NS_OK = cast(nsresult)0;
+const nsresult NS_ERROR_BASE = cast(nsresult) 0xC1F30000;
+const nsresult NS_ERROR_NOT_INITIALIZED = cast(nsresult)(NS_ERROR_BASE + 1);
+const nsresult NS_ERROR_ALREADY_INITIALIZED = cast(nsresult)(NS_ERROR_BASE + 2);
+const nsresult NS_NOINTERFACE = cast(nsresult)0x80004002L;
+
+alias NS_NOINTERFACE NS_ERROR_NO_INTERFACE;
+
+const nsresult NS_ERROR_INVALID_POINTER = cast(nsresult)0x80004003L;
+
+alias NS_ERROR_INVALID_POINTER NS_ERROR_NULL_POINTER;
+
+const nsresult NS_ERROR_ABORT         = cast(nsresult)0x80004004L;
+const nsresult NS_ERROR_FAILURE       = cast(nsresult)0x80004005L;
+const nsresult NS_ERROR_UNEXPECTED    = cast(nsresult)0x8000ffffL;
+const nsresult NS_ERROR_OUT_OF_MEMORY = cast(nsresult) 0x8007000eL;
+const nsresult NS_ERROR_ILLEGAL_VALUE = cast(nsresult) 0x80070057L;
+
+alias NS_ERROR_ILLEGAL_VALUE NS_ERROR_INVALID_ARG;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAppShell.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIAppShell;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIEventQueue;
+
+const char[] NS_IAPPSHELL_IID_STR = "a0757c31-eeac-11d1-9ec1-00aa002fb821";
+
+const nsIID NS_IAPPSHELL_IID= 
+  {0xa0757c31, 0xeeac, 0x11d1, 
+    [ 0x9e, 0xc1, 0x00, 0xaa, 0x00, 0x2f, 0xb8, 0x21 ]};
+
+interface nsIAppShell : nsISupports {
+  static const char[] IID_STR = NS_IAPPSHELL_IID_STR;
+  static const nsIID IID = NS_IAPPSHELL_IID;
+
+extern(System):
+  nsresult Create(int *argc, char **argv);
+  nsresult Run();
+  nsresult Spinup();
+  nsresult Spindown();
+  nsresult ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen);
+  nsresult GetNativeEvent(PRBool * aRealEvent, void * * aEvent);
+  nsresult DispatchNativeEvent(PRBool aRealEvent, void * aEvent);
+  nsresult Exit();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAtom.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIAtom;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IATOM_IID_STR = "3d1b15b0-93b4-11d1-895b-006008911b81";
+
+const nsIID NS_IATOM_IID= 
+  {0x3d1b15b0, 0x93b4, 0x11d1, 
+    [ 0x89, 0x5b, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81 ]};
+
+interface nsIAtom : nsISupports {
+
+  static const char[] IID_STR = NS_IATOM_IID_STR;
+  static const nsIID IID = NS_IATOM_IID;
+
+extern(System):
+  nsresult ToString(nsAString * _retval);
+  nsresult ToUTF8String(nsACString * _retval);
+  nsresult GetUTF8String(char **aResult);
+  nsresult Equals(nsAString * aString, PRBool *_retval);
+  nsresult EqualsUTF8(nsACString * aString, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthInformation.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+module org.eclipse.swt.internal.mozilla.nsIAuthInformation;
+
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IAUTHINFORMATION_IID_STR =  "0d73639c-2a92-4518-9f92-28f71fea5f20";
+
+const nsIID NS_IAUTHINFORMATION_IID =
+   {0x0d73639c, 0x2a92, 0x4518, 
+    [ 0x9f, 0x92, 0x28, 0xf7, 0x1f, 0xea, 0x5f, 0x20 ] };
+
+interface nsIAuthInformation : nsISupports {
+
+  static const char[] IID_STR = NS_IAUTHINFORMATION_IID_STR;
+  static const nsIID IID = NS_IAUTHINFORMATION_IID;
+
+  enum { AUTH_HOST = 1U }
+  enum { AUTH_PROXY = 2U }
+  enum { NEED_DOMAIN = 4U }
+  enum { ONLY_PASSWORD = 8U }
+
+extern(System):
+  nsresult GetFlags(PRUint32 *aFlags);
+  nsresult GetRealm(nsAString * aRealm);;
+  nsresult GetAuthenticationScheme(nsACString * aAuthenticationScheme);
+  nsresult GetUsername(nsAString * aUsername);
+  nsresult SetUsername(nsAString * aUsername);
+  nsresult GetPassword(nsAString * aPassword);
+  nsresult SetPassword(nsAString * aPassword);
+  nsresult GetDomain(nsAString * aDomain);
+  nsresult SetDomain(nsAString * aDomain);
+
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthPrompt.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+module org.eclipse.swt.internal.mozilla.nsIAuthPrompt;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+// import org.eclipse.swt.internal.mozilla.nsIPrompt;
+
+const char[] NS_IAUTHPROMPT_IID_STR = "2f977d45-5485-11d4-87e2-0010a4e75ef2";
+
+const nsIID NS_IAUTHPROMPT_IID= 
+  {0x2f977d45, 0x5485, 0x11d4, 
+    [ 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 ]};
+
+interface nsIAuthPrompt : nsISupports {
+
+  static const char[] IID_STR = NS_IAUTHPROMPT_IID_STR;
+  static const nsIID IID = NS_IAUTHPROMPT_IID;
+
+  enum { SAVE_PASSWORD_NEVER = 0U };
+  enum { SAVE_PASSWORD_FOR_SESSION = 1U };
+  enum { SAVE_PASSWORD_PERMANENTLY = 2U };
+
+extern(System):
+  nsresult Prompt(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar *passwordRealm, PRUint32 savePassword, PRUnichar *defaultText, PRUnichar **result, PRBool *_retval);
+  nsresult PromptUsernameAndPassword(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar *passwordRealm, PRUint32 savePassword, PRUnichar **user, PRUnichar **pwd, PRBool *_retval);
+  nsresult PromptPassword(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar *passwordRealm, PRUint32 savePassword, PRUnichar **pwd, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIAuthPromptCallback.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+module org.eclipse.swt.internal.mozilla.nsIAuthPromptCallback;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIAuthInformation;
+
+const char[] NS_IAUTHPROMPTCALLBACK_IID_STR = "bdc387d7-2d29-4cac-92f1-dd75d786631d";
+
+const nsIID NS_IAUTHPROMPTCALLBACK_IID= 
+  {0xbdc387d7, 0x2d29, 0x4cac, 
+    [ 0x92, 0xf1, 0xdd, 0x75, 0xd7, 0x86, 0x63, 0x1d ]};
+
+interface nsIAuthPromptCallback : nsISupports {
+
+  static const char[] IID_STR = NS_IAUTHPROMPTCALLBACK_IID_STR;
+  static const nsIID IID = NS_IAUTHPROMPTCALLBACK_IID;
+
+extern(System):
+  nsresult OnAuthAvailable(nsISupports aContext, nsIAuthInformation aAuthInfo);
+  nsresult OnAuthCancelled(nsISupports aContext, PRBool userCancel);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBaseWindow.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,47 @@
+module org.eclipse.swt.internal.mozilla.nsIBaseWindow;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+alias void * nativeWindow;
+
+const char[] NS_IBASEWINDOW_IID_STR = "046bc8a0-8015-11d3-af70-00a024ffc08c";
+
+const nsIID NS_IBASEWINDOW_IID= 
+  {0x046bc8a0, 0x8015, 0x11d3, 
+    [ 0xaf, 0x70, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIBaseWindow : nsISupports {
+
+  static const char[] IID_STR = NS_IBASEWINDOW_IID_STR;
+  static const nsIID IID = NS_IBASEWINDOW_IID;
+
+extern(System):
+  nsresult InitWindow(nativeWindow parentNativeWindow, nsIWidget * parentWidget, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy);
+  nsresult Create();
+  nsresult Destroy();
+  nsresult SetPosition(PRInt32 x, PRInt32 y);
+  nsresult GetPosition(PRInt32 *x, PRInt32 *y);
+  nsresult SetSize(PRInt32 cx, PRInt32 cy, PRBool fRepaint);
+  nsresult GetSize(PRInt32 *cx, PRInt32 *cy);
+  nsresult SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy, PRBool fRepaint);
+  nsresult GetPositionAndSize(PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy);
+  nsresult Repaint(PRBool force);
+  nsresult GetParentWidget(nsIWidget * *aParentWidget);
+  nsresult SetParentWidget(nsIWidget * aParentWidget);
+  nsresult GetParentNativeWindow(nativeWindow *aParentNativeWindow);
+  nsresult SetParentNativeWindow(nativeWindow aParentNativeWindow);
+  nsresult GetVisibility(PRBool *aVisibility);
+  nsresult SetVisibility(PRBool aVisibility);
+  nsresult GetEnabled(PRBool *aEnabled);
+  nsresult SetEnabled(PRBool aEnabled);
+  nsresult GetBlurSuppression(PRBool *aBlurSuppression);
+  nsresult SetBlurSuppression(PRBool aBlurSuppression);
+  nsresult GetMainWidget(nsIWidget * *aMainWidget);
+  nsresult SetFocus();
+  nsresult GetTitle(PRUnichar * *aTitle);
+  nsresult SetTitle(PRUnichar * aTitle);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBinaryInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIBinaryInputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IBINARYINPUTSTREAM_IID_STR = "7b456cb0-8772-11d3-90cf-0040056a906e";
+
+const nsIID NS_IBINARYINPUTSTREAM_IID= 
+  {0x7b456cb0, 0x8772, 0x11d3, 
+    [ 0x90, 0xcf, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e ]};
+
+interface nsIBinaryInputStream : nsIInputStream {
+
+  static const char[] IID_STR = NS_IBINARYINPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IBINARYINPUTSTREAM_IID;
+
+extern(System):
+  nsresult SetInputStream(nsIInputStream aInputStream);
+  nsresult ReadBoolean(PRBool *_retval);
+  nsresult Read8(PRUint8 *_retval);
+  nsresult Read16(PRUint16 *_retval);
+  nsresult Read32(PRUint32 *_retval);
+  nsresult Read64(PRUint64 *_retval);
+  nsresult ReadFloat(float *_retval);
+  nsresult ReadDouble(double *_retval);
+  nsresult ReadCString(nsACString * _retval);
+  nsresult ReadString(nsAString * _retval);
+  nsresult ReadBytes(PRUint32 aLength, char **aString);
+  nsresult ReadByteArray(PRUint32 aLength, PRUint8 **aBytes);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIBinaryOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIBinaryOutputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIOutputStream;
+
+const char[] NS_IBINARYOUTPUTSTREAM_IID_STR = "204ee610-8765-11d3-90cf-0040056a906e";
+
+const nsIID NS_IBINARYOUTPUTSTREAM_IID= 
+  {0x204ee610, 0x8765, 0x11d3, 
+    [ 0x90, 0xcf, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e ]};
+
+interface nsIBinaryOutputStream : nsIOutputStream {
+
+  static const char[] IID_STR = NS_IBINARYOUTPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IBINARYOUTPUTSTREAM_IID;
+
+extern(System):
+  nsresult SetOutputStream(nsIOutputStream aOutputStream);
+  nsresult WriteBoolean(PRBool aBoolean);
+  nsresult Write8(PRUint8 aByte);
+  nsresult Write16(PRUint16 a16);
+  nsresult Write32(PRUint32 a32);
+  nsresult Write64(PRUint64 a64);
+  nsresult WriteFloat(float aFloat);
+  nsresult WriteDouble(double aDouble);
+  nsresult WriteStringZ(char *aString);
+  nsresult WriteWStringZ(PRUnichar *aString);
+  nsresult WriteUtf8Z(PRUnichar *aString);
+  nsresult WriteBytes(char *aString, PRUint32 aLength);
+  nsresult WriteByteArray(PRUint8 *aBytes, PRUint32 aLength);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICancelable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+module org.eclipse.swt.internal.mozilla.nsICancelable;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_ICANCELABLE_IID_STR = "d94ac0a0-bb18-46b8-844e-84159064b0bd";
+
+const nsIID NS_ICANCELABLE_IID= 
+  {0xd94ac0a0, 0xbb18, 0x46b8, 
+    [ 0x84, 0x4e, 0x84, 0x15, 0x90, 0x64, 0xb0, 0xbd ]};
+
+interface nsICancelable : nsISupports {
+
+  static const char[] IID_STR = NS_ICANCELABLE_IID_STR;
+  static const nsIID IID = NS_ICANCELABLE_IID;
+
+extern(System):
+  nsresult Cancel(nsresult aReason);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICategoryManager.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsICategoryManager;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+
+const char[] NS_ICATEGORYMANAGER_IID_STR = "3275b2cd-af6d-429a-80d7-f0c5120342ac";
+
+const nsIID NS_ICATEGORYMANAGER_IID= 
+  {0x3275b2cd, 0xaf6d, 0x429a, 
+    [ 0x80, 0xd7, 0xf0, 0xc5, 0x12, 0x03, 0x42, 0xac ]};
+
+interface nsICategoryManager : nsISupports {
+
+  static const char[] IID_STR = NS_ICATEGORYMANAGER_IID_STR;
+  static const nsIID IID = NS_ICATEGORYMANAGER_IID;
+
+extern(System):
+  nsresult GetCategoryEntry(char *aCategory, char *aEntry, char **_retval);
+  nsresult AddCategoryEntry(char *aCategory, char *aEntry, char *aValue, PRBool aPersist, PRBool aReplace, char **_retval);
+  nsresult DeleteCategoryEntry(char *aCategory, char *aEntry, PRBool aPersist);
+  nsresult DeleteCategory(char *aCategory);
+  nsresult EnumerateCategory(char *aCategory, nsISimpleEnumerator *_retval);
+  nsresult EnumerateCategories(nsISimpleEnumerator *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIChannel.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+module org.eclipse.swt.internal.mozilla.nsIChannel;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsIInterfaceRequestor; 
+import org.eclipse.swt.internal.mozilla.nsIInputStream; 
+import org.eclipse.swt.internal.mozilla.nsIStreamListener;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ICHANNEL_IID_STR = "c63a055a-a676-4e71-bf3c-6cfa11082018";
+const nsIID NS_ICHANNEL_IID= 
+  {0xc63a055a, 0xa676, 0x4e71, 
+    [ 0xbf, 0x3c, 0x6c, 0xfa, 0x11, 0x08, 0x20, 0x18 ]};
+
+interface nsIChannel : nsIRequest {
+
+  static const char[] IID_STR = NS_ICHANNEL_IID_STR;
+  static const nsIID IID = NS_ICHANNEL_IID;
+
+extern(System):
+  nsresult GetOriginalURI(nsIURI  *aOriginalURI);
+  nsresult SetOriginalURI(nsIURI  aOriginalURI);
+  nsresult GetURI(nsIURI  *aURI);
+  nsresult GetOwner(nsISupports  *aOwner);
+  nsresult SetOwner(nsISupports  aOwner);
+
+  nsresult GetNotificationCallbacks(nsIInterfaceRequestor  *aNotificationCallbacks);
+  nsresult SetNotificationCallbacks(nsIInterfaceRequestor  aNotificationCallbacks);
+  nsresult GetSecurityInfo(nsISupports  *aSecurityInfo);
+  nsresult GetContentType(nsACString * aContentType);
+  nsresult SetContentType(nsACString * aContentType);
+  nsresult GetContentCharset(nsACString * aContentCharset);
+  nsresult SetContentCharset(nsACString * aContentCharset);
+  nsresult GetContentLength(PRInt32 *aContentLength);
+  nsresult SetContentLength(PRInt32 aContentLength);
+  nsresult Open(nsIInputStream *_retval);
+  nsresult AsyncOpen(nsIStreamListener aListener, nsISupports aContext);
+
+  enum { LOAD_DOCUMENT_URI = 65536U };
+  enum { LOAD_RETARGETED_DOCUMENT_URI = 131072U };
+  enum { LOAD_REPLACE = 262144U };
+  enum { LOAD_INITIAL_DOCUMENT_URI = 524288U };
+  enum { LOAD_TARGETED = 1048576U };
+  enum { LOAD_CALL_CONTENT_SNIFFERS = 2097152U };
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIChromeEventHandler.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIChromeEventHandler;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent; 
+
+const char[] NS_ICHROMEEVENTHANDLER_IID_STR = "7bc08970-9e6c-11d3-afb2-00a024ffc08c";
+
+const nsIID NS_ICHROMEEVENTHANDLER_IID= 
+  {0x7bc08970, 0x9e6c, 0x11d3, 
+    [ 0xaf, 0xb2, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIChromeEventHandler : nsISupports {
+
+  static const char[] IID_STR = NS_ICHROMEEVENTHANDLER_IID_STR;
+  static const nsIID IID = NS_ICHROMEEVENTHANDLER_IID;
+
+extern(System):
+  nsresult HandleChromeEvent(nsPresContext * aPresContext, nsEvent * aEvent, nsIDOMEvent *aDOMEvent, PRUint32 aFlags, nsEventStatus *aStatus);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICollection.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+module org.eclipse.swt.internal.mozilla.nsICollection;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsISerializable;
+import org.eclipse.swt.internal.mozilla.nsIEnumerator;
+
+const char[] NS_ICOLLECTION_IID_STR = "83b6019c-cbc4-11d2-8cca-0060b0fc14a3";
+
+const nsIID NS_ICOLLECTION_IID= 
+  {0x83b6019c, 0xcbc4, 0x11d2, 
+    [ 0x8c, 0xca, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 ]};
+
+interface nsICollection : nsISerializable {
+
+  static const char[] IID_STR = NS_ICOLLECTION_IID_STR;
+  static const nsIID IID = NS_ICOLLECTION_IID;
+
+extern(System):
+  nsresult Count(PRUint32 *_retval);
+  nsresult GetElementAt(PRUint32 index, nsISupports *_retval);
+  nsresult QueryElementAt(PRUint32 index, nsIID * uuid, void * *result);
+  nsresult SetElementAt(PRUint32 index, nsISupports item);
+  nsresult AppendElement(nsISupports item);
+  nsresult RemoveElement(nsISupports item);
+  nsresult Enumerate(nsIEnumerator *_retval);
+  nsresult Clear();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIComponentManager.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIComponentManager;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIFactory;
+
+const char[] NS_ICOMPONENTMANAGER_IID_STR = "a88e5a60-205a-4bb1-94e1-2628daf51eae";
+
+const nsIID NS_ICOMPONENTMANAGER_IID= 
+  {0xa88e5a60, 0x205a, 0x4bb1, 
+    [ 0x94, 0xe1, 0x26, 0x28, 0xda, 0xf5, 0x1e, 0xae ]};
+
+interface nsIComponentManager : nsISupports {
+  static const char[] IID_STR = NS_ICOMPONENTMANAGER_IID_STR;
+  static const nsIID IID = NS_ICOMPONENTMANAGER_IID;
+
+extern(System):
+  nsresult GetClassObject(nsCID * aClass, nsIID * aIID, void * *result);
+  nsresult GetClassObjectByContractID(char *aContractID, nsIID * aIID, void * *result);
+  nsresult CreateInstance(nsCID * aClass, nsISupports aDelegate, nsIID * aIID, void * *result);
+  nsresult CreateInstanceByContractID(char *aContractID, nsISupports aDelegate, nsIID * aIID, void * *result);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIComponentRegistrar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,34 @@
+module org.eclipse.swt.internal.mozilla.nsIComponentRegistrar;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+import org.eclipse.swt.internal.mozilla.nsIFactory;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+
+const char[] NS_ICOMPONENTREGISTRAR_IID_STR = "2417cbfe-65ad-48a6-b4b6-eb84db174392";
+
+const nsIID NS_ICOMPONENTREGISTRAR_IID= 
+  {0x2417cbfe, 0x65ad, 0x48a6, 
+    [ 0xb4, 0xb6, 0xeb, 0x84, 0xdb, 0x17, 0x43, 0x92 ]};
+
+interface nsIComponentRegistrar : nsISupports {
+  static const char[] IID_STR = NS_ICOMPONENTREGISTRAR_IID_STR;
+  static const nsIID IID = NS_ICOMPONENTREGISTRAR_IID;
+
+extern(System):
+  nsresult AutoRegister(nsIFile aSpec);
+  nsresult AutoUnregister(nsIFile aSpec);
+  nsresult RegisterFactory(nsCID * aClass, char *aClassName, char *aContractID, nsIFactory aFactory);
+  nsresult UnregisterFactory(nsCID * aClass, nsIFactory aFactory);
+  nsresult RegisterFactoryLocation(nsCID * aClass, char *aClassName, char *aContractID, nsIFile aFile, char *aLoaderStr, char *aType);
+  nsresult UnregisterFactoryLocation(nsCID * aClass, nsIFile aFile);
+  nsresult IsCIDRegistered(nsCID * aClass, PRBool *_retval);
+  nsresult IsContractIDRegistered(char *aContractID, PRBool *_retval);
+  nsresult EnumerateCIDs(nsISimpleEnumerator *_retval);
+  nsresult EnumerateContractIDs(nsISimpleEnumerator *_retval);
+  nsresult CIDToContractID(nsCID * aClass, char **_retval);
+  nsresult ContractIDToCID(char *aContractID, nsCID * *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContentViewer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,74 @@
+module org.eclipse.swt.internal.mozilla.nsIContentViewer;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+import org.eclipse.swt.internal.mozilla.nsISHEntry;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ICONTENTVIEWER_IID_STR = "6a7ddb40-8a9e-4576-8ad1-71c5641d8780";
+
+const nsIID NS_ICONTENTVIEWER_IID= 
+  {0x6a7ddb40, 0x8a9e, 0x4576, 
+    [ 0x8a, 0xd1, 0x71, 0xc5, 0x64, 0x1d, 0x87, 0x80 ]};
+
+interface nsIContentViewer : nsISupports {
+
+  static const char[] IID_STR = NS_ICONTENTVIEWER_IID_STR;
+  static const nsIID IID = NS_ICONTENTVIEWER_IID;
+
+extern(System):
+  nsresult Init(nsIWidget * aParentWidget, nsIDeviceContext * aDeviceContext, nsRect * aBounds);
+  nsresult GetContainer(nsISupports  *aContainer);
+  nsresult SetContainer(nsISupports  aContainer);
+  nsresult LoadStart(nsISupports aDoc);
+  nsresult LoadComplete(PRUint32 aStatus);
+  nsresult PermitUnload(PRBool *_retval);
+  nsresult PageHide(PRBool isUnload);
+  nsresult Close(nsISHEntry historyEntry);
+  nsresult Destroy();
+  nsresult Stop();
+  nsresult GetDOMDocument(nsIDOMDocument  *aDOMDocument);
+  nsresult SetDOMDocument(nsIDOMDocument  aDOMDocument);
+  nsresult GetBounds(nsRect * aBounds);
+  nsresult SetBounds(nsRect * aBounds);
+  nsresult GetPreviousViewer(nsIContentViewer  *aPreviousViewer);
+  nsresult SetPreviousViewer(nsIContentViewer  aPreviousViewer);
+  nsresult Move(PRInt32 aX, PRInt32 aY);
+  nsresult Show();
+  nsresult Hide();
+  nsresult GetEnableRendering(PRBool *aEnableRendering);
+  nsresult SetEnableRendering(PRBool aEnableRendering);
+  nsresult GetSticky(PRBool *aSticky);
+  nsresult SetSticky(PRBool aSticky);
+  nsresult RequestWindowClose(PRBool *_retval);
+  nsresult Open(nsISupports aState);
+  nsresult ClearHistoryEntry();
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ICONTENTVIEWER_MOZILLA_1_8_BRANCH_IID_STR = "51341ed4-a3bf-4fd5-ae17-5fd3ec59dcab";
+
+const nsIID NS_ICONTENTVIEWER_MOZILLA_1_8_BRANCH_IID= 
+  {0x51341ed4, 0xa3bf, 0x4fd5, 
+    [ 0xae, 0x17, 0x5f, 0xd3, 0xec, 0x59, 0xdc, 0xab ]};
+
+interface nsIContentViewer_MOZILLA_1_8_BRANCH : nsISupports {
+
+  static const char[] IID_STR = NS_ICONTENTVIEWER_MOZILLA_1_8_BRANCH_IID_STR;
+  static const nsIID IID = NS_ICONTENTVIEWER_MOZILLA_1_8_BRANCH_IID;
+
+extern(System):
+  nsresult OpenWithEntry(nsISupports aState, nsISHEntry aSHEntry);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+module org.eclipse.swt.internal.mozilla.nsIContextMenuListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent; 
+import org.eclipse.swt.internal.mozilla.nsIDOMNode; 
+
+const char[] NS_ICONTEXTMENULISTENER_IID_STR = "3478b6b0-3875-11d4-94ef-0020183bf181";
+
+const nsIID NS_ICONTEXTMENULISTENER_IID= 
+  {0x3478b6b0, 0x3875, 0x11d4, 
+    [ 0x94, 0xef, 0x00, 0x20, 0x18, 0x3b, 0xf1, 0x81 ]};
+
+interface nsIContextMenuListener : nsISupports {
+
+  static const char[] IID_STR = NS_ICONTEXTMENULISTENER_IID_STR;
+  static const nsIID IID = NS_ICONTEXTMENULISTENER_IID;
+
+extern(System):
+  enum { CONTEXT_NONE = 0U };
+  enum { CONTEXT_LINK = 1U };
+  enum { CONTEXT_IMAGE = 2U };
+  enum { CONTEXT_DOCUMENT = 4U };
+  enum { CONTEXT_TEXT = 8U };
+  enum { CONTEXT_INPUT = 16U };
+
+  nsresult OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent aEvent, nsIDOMNode aNode);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIContextMenuListener2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,59 @@
+module org.eclipse.swt.internal.mozilla.nsIContextMenuListener2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode; 
+import org.eclipse.swt.internal.mozilla.imgIContainer;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ICONTEXTMENULISTENER2_IID_STR = "7fb719b3-d804-4964-9596-77cf924ee314";
+
+const nsIID NS_ICONTEXTMENULISTENER2_IID= 
+  {0x7fb719b3, 0xd804, 0x4964, 
+    [ 0x95, 0x96, 0x77, 0xcf, 0x92, 0x4e, 0xe3, 0x14 ]};
+
+interface nsIContextMenuListener2 : nsISupports {
+
+  static const char[] IID_STR = NS_ICONTEXTMENULISTENER2_IID_STR;
+  static const nsIID IID = NS_ICONTEXTMENULISTENER2_IID;
+
+  enum { CONTEXT_NONE = 0U };
+  enum { CONTEXT_LINK = 1U };
+  enum { CONTEXT_IMAGE = 2U };
+  enum { CONTEXT_DOCUMENT = 4U };
+  enum { CONTEXT_TEXT = 8U };
+  enum { CONTEXT_INPUT = 16U };
+  enum { CONTEXT_BACKGROUND_IMAGE = 32U };
+
+extern(System):
+  nsresult OnShowContextMenu(PRUint32 aContextFlags, nsIContextMenuInfo aUtils);
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ICONTEXTMENUINFO_IID_STR = "2f977d56-5485-11d4-87e2-0010a4e75ef2";
+
+const nsIID NS_ICONTEXTMENUINFO_IID= 
+  {0x2f977d56, 0x5485, 0x11d4, 
+    [ 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 ]};
+
+interface nsIContextMenuInfo : nsISupports {
+
+  static const char[] IID_STR = NS_ICONTEXTMENUINFO_IID_STR;
+  static const nsIID IID = NS_ICONTEXTMENUINFO_IID;
+
+extern(System):
+  nsresult GetMouseEvent(nsIDOMEvent  *aMouseEvent);
+  nsresult GetTargetNode(nsIDOMNode  *aTargetNode);
+  nsresult GetAssociatedLink(nsAString * aAssociatedLink);
+  nsresult GetImageContainer(imgIContainer  *aImageContainer);
+  nsresult GetImageSrc(nsIURI  *aImageSrc);
+  nsresult GetBackgroundImageContainer(imgIContainer  *aBackgroundImageContainer);
+  nsresult GetBackgroundImageSrc(nsIURI  *aBackgroundImageSrc);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookie.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+module org.eclipse.swt.internal.mozilla.nsICookie;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRInt32 nsCookieStatus;
+alias PRInt32 nsCookiePolicy;
+
+const char[] NS_ICOOKIE_IID_STR = "e9fcb9a4-d376-458f-b720-e65e7df593bc";
+
+const nsIID NS_ICOOKIE_IID= 
+  {0xe9fcb9a4, 0xd376, 0x458f, 
+    [ 0xb7, 0x20, 0xe6, 0x5e, 0x7d, 0xf5, 0x93, 0xbc ]};
+
+interface nsICookie : nsISupports {
+
+  static const char[] IID_STR = NS_ICOOKIE_IID_STR;
+  static const nsIID IID = NS_ICOOKIE_IID;
+
+extern(System):
+  nsresult GetName(nsACString * aName);
+  nsresult GetValue(nsACString * aValue);
+  nsresult GetIsDomain(PRBool *aIsDomain);
+  nsresult GetHost(nsACString * aHost);
+  nsresult GetPath(nsACString * aPath);
+  nsresult GetIsSecure(PRBool *aIsSecure);
+  nsresult GetExpires(PRUint64 *aExpires);
+
+  enum { STATUS_UNKNOWN = 0 };
+  enum { STATUS_ACCEPTED = 1 };
+  enum { STATUS_DOWNGRADED = 2 };
+  enum { STATUS_FLAGGED = 3 };
+  enum { STATUS_REJECTED = 4 };
+
+  nsresult GetStatus(nsCookieStatus *aStatus);
+
+  enum { POLICY_UNKNOWN = 0 };
+  enum { POLICY_NONE = 1 };
+  enum { POLICY_NO_CONSENT = 2 };
+  enum { POLICY_IMPLICIT_CONSENT = 3 };
+  enum { POLICY_EXPLICIT_CONSENT = 4 };
+  enum { POLICY_NO_II = 5 };
+
+  nsresult GetPolicy(nsCookiePolicy *aPolicy);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookie2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsICookie2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsICookie;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ICOOKIE2_IID_STR = "d3493503-7854-46ed-8284-8af54a847efb";
+
+const nsIID NS_ICOOKIE2_IID= 
+  {0xd3493503, 0x7854, 0x46ed, 
+    [ 0x82, 0x84, 0x8a, 0xf5, 0x4a, 0x84, 0x7e, 0xfb ]};
+
+interface nsICookie2 : nsICookie {
+
+  static const char[] IID_STR = NS_ICOOKIE2_IID_STR;
+  static const nsIID IID = NS_ICOOKIE2_IID;
+
+extern(System):
+  nsresult GetRawHost(nsACString * aRawHost);
+  nsresult GetIsSession(PRBool *aIsSession);
+  nsresult GetExpiry(PRInt64 *aExpiry);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookieManager.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsICookieManager;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ICOOKIEMANAGER_IID_STR = "aaab6710-0f2c-11d5-a53b-0010a401eb10";
+
+const nsIID NS_ICOOKIEMANAGER_IID= 
+  {0xaaab6710, 0x0f2c, 0x11d5, 
+    [ 0xa5, 0x3b, 0x00, 0x10, 0xa4, 0x01, 0xeb, 0x10 ]};
+
+interface nsICookieManager : nsISupports {
+
+  static const char[] IID_STR = NS_ICOOKIEMANAGER_IID_STR;
+  static const nsIID IID = NS_ICOOKIEMANAGER_IID;
+
+extern(System):
+  nsresult RemoveAll();
+  nsresult GetEnumerator(nsISimpleEnumerator  *aEnumerator);
+  nsresult Remove(nsACString * aDomain, nsACString * aName, nsACString * aPath, PRBool aBlocked);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsICookieManager2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsICookieManager2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsICookieManager;
+import org.eclipse.swt.internal.mozilla.nsICookie2;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ICOOKIEMANAGER2_IID_STR = "3e73ff5f-154e-494f-b640-3c654ba2cc2b";
+
+const nsIID NS_ICOOKIEMANAGER2_IID= 
+  {0x3e73ff5f, 0x154e, 0x494f, 
+    [ 0xb6, 0x40, 0x3c, 0x65, 0x4b, 0xa2, 0xcc, 0x2b ]};
+
+interface nsICookieManager2 : nsICookieManager {
+
+  static const char[] IID_STR = NS_ICOOKIEMANAGER2_IID_STR;
+  static const nsIID IID = NS_ICOOKIEMANAGER2_IID;
+
+extern(System):
+  nsresult Add(nsACString * aDomain, nsACString * aPath, nsACString * aName, nsACString * aValue, PRBool aSecure, PRBool aIsSession, PRInt64 aExpiry);
+  nsresult FindMatchingCookie(nsICookie2 aCookie, PRUint32 *aCountFromHost, PRBool *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsID.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,46 @@
+module org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import java.lang.all;
+
+align(1)
+struct nsID
+{
+    PRUint32 m0;
+    PRUint16 m1;
+    PRUint16 m2;
+    PRUint8[8] m3;
+
+	static nsID opCall(String aIDStr)
+	{
+        nsID id;
+        if(aIDStr == null) throw new ParseException();
+        int i = 0;
+        with(id) {
+            for (; i < 8; i++) m0 = (m0 << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16);
+            if (aIDStr.charAt (i) != '-') throw new ParseException ();
+            i++;
+            for (; i < 13; i++) m1 = cast(short)((m1 << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            if (aIDStr.charAt (i) != '-') throw new ParseException ();
+            i++;
+            for (; i < 18; i++) m2 = cast(short)((m2 << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            if (aIDStr.charAt (i) != '-') throw new ParseException ();
+            i++;
+            for (; i < 21; i++) m3[0] = cast(byte)((m3[0] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 23; i++) m3[1] = cast(byte)((m3[1] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            if (aIDStr.charAt (i) != '-') throw new ParseException ();
+            i++;
+            for (; i < 26; i++) m3[2] = cast(byte)((m3[2] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 28; i++) m3[3] = cast(byte)((m3[3] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 30; i++) m3[4] = cast(byte)((m3[4] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 32; i++) m3[5] = cast(byte)((m3[5] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 34; i++) m3[6] = cast(byte)((m3[6] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+            for (; i < 36; i++) m3[7] = cast(byte)((m3[7] << 4) + Integer.parseInt (aIDStr.substring (i, i + 1), 16));
+        }
+        return id;
+	}
+
+}
+
+alias nsID nsCID;
+alias nsID nsIID;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMAbstractView.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMAbstractView;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMDocumentView;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMABSTRACTVIEW_IID_STR = "f51ebade-8b1a-11d3-aae7-0010830123b4";
+
+const nsIID NS_IDOMABSTRACTVIEW_IID= 
+  {0xf51ebade, 0x8b1a, 0x11d3, 
+    [ 0xaa, 0xe7, 0x00, 0x10, 0x83, 0x01, 0x23, 0xb4 ]};
+
+interface nsIDOMAbstractView : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMABSTRACTVIEW_IID_STR;
+  static const nsIID IID = NS_IDOMABSTRACTVIEW_IID;
+
+extern(System):
+  nsresult GetDocument(nsIDOMDocumentView  *aDocument);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMAttr.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMAttr;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMElement;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMATTR_IID_STR = "a6cf9070-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMATTR_IID= 
+  {0xa6cf9070, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMAttr : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMATTR_IID_STR;
+  static const nsIID IID = NS_IDOMATTR_IID;
+
+extern(System):
+  nsresult GetName(nsAString * aName);
+  nsresult GetSpecified(PRBool *aSpecified);
+  nsresult GetValue(nsAString * aValue);
+  nsresult SetValue(nsAString * aValue);
+  nsresult GetOwnerElement(nsIDOMElement  *aOwnerElement);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMBarProp.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMBarProp;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMBARPROP_IID_STR = "9eb2c150-1d56-11d3-8221-0060083a0bcf";
+
+const nsIID NS_IDOMBARPROP_IID= 
+  {0x9eb2c150, 0x1d56, 0x11d3, 
+    [ 0x82, 0x21, 0x00, 0x60, 0x08, 0x3a, 0x0b, 0xcf ]};
+
+interface nsIDOMBarProp : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMBARPROP_IID_STR;
+  static const nsIID IID = NS_IDOMBARPROP_IID;
+
+extern(System):
+  nsresult GetVisible(PRBool *aVisible);
+  nsresult SetVisible(PRBool aVisible);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMCDATASection.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMCDATASection;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMText;
+
+const char[] NS_IDOMCDATASECTION_IID_STR = "a6cf9071-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMCDATASECTION_IID= 
+  {0xa6cf9071, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMCDATASection : nsIDOMText {
+
+extern(System):
+  static const char[] IID_STR = NS_IDOMCDATASECTION_IID_STR;
+  static const nsIID IID = NS_IDOMCDATASECTION_IID;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMCharacterData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMCharacterData;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMCHARACTERDATA_IID_STR = "a6cf9072-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMCHARACTERDATA_IID= 
+  {0xa6cf9072, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMCharacterData : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMCHARACTERDATA_IID_STR;
+  static const nsIID IID = NS_IDOMCHARACTERDATA_IID;
+
+extern(System):
+  nsresult GetData(nsAString * aData);
+  nsresult SetData(nsAString * aData);
+  nsresult GetLength(PRUint32 *aLength);
+  nsresult SubstringData(PRUint32 offset, PRUint32 count, nsAString * _retval);
+  nsresult AppendData(nsAString * arg);
+  nsresult InsertData(PRUint32 offset, nsAString * arg);
+  nsresult DeleteData(PRUint32 offset, PRUint32 count);
+  nsresult ReplaceData(PRUint32 offset, PRUint32 count, nsAString * arg);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMComment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMComment;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMCharacterData;
+
+const char[] NS_IDOMCOMMENT_IID_STR = "a6cf9073-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMCOMMENT_IID= 
+  {0xa6cf9073, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMComment : nsIDOMCharacterData {
+
+extern(System):
+  static const char[] IID_STR = NS_IDOMCOMMENT_IID_STR;
+  static const nsIID IID = NS_IDOMCOMMENT_IID;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDOMImplementation.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMDOMImplementation;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMDocumentType;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMDOMIMPLEMENTATION_IID_STR = "a6cf9074-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMDOMIMPLEMENTATION_IID= 
+  {0xa6cf9074, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMDOMImplementation : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMDOMIMPLEMENTATION_IID_STR;
+  static const nsIID IID = NS_IDOMDOMIMPLEMENTATION_IID;
+
+extern(System):
+  nsresult HasFeature(nsAString * feature, nsAString * version_, PRBool *_retval);
+  nsresult CreateDocumentType(nsAString * qualifiedName, nsAString * publicId, nsAString * systemId, nsIDOMDocumentType *_retval);
+  nsresult CreateDocument(nsAString * namespaceURI, nsAString * qualifiedName, nsIDOMDocumentType doctype, nsIDOMDocument *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocument.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,52 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMNodeList;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocumentType;
+import org.eclipse.swt.internal.mozilla.nsIDOMElement;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocumentFragment;
+import org.eclipse.swt.internal.mozilla.nsIDOMText;
+import org.eclipse.swt.internal.mozilla.nsIDOMComment;
+import org.eclipse.swt.internal.mozilla.nsIDOMCDATASection;
+import org.eclipse.swt.internal.mozilla.nsIDOMProcessingInstruction;
+import org.eclipse.swt.internal.mozilla.nsIDOMDOMImplementation;
+import org.eclipse.swt.internal.mozilla.nsIDOMAttr;
+import org.eclipse.swt.internal.mozilla.nsIDOMEntityReference;
+
+const char[] NS_IDOMDOCUMENT_IID_STR = "a6cf9075-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMDOCUMENT_IID= 
+  {0xa6cf9075, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMDocument : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMDOCUMENT_IID_STR;
+  static const nsIID IID = NS_IDOMDOCUMENT_IID;
+
+extern(System):
+  nsresult GetDoctype(nsIDOMDocumentType  *aDoctype);
+  nsresult GetImplementation(nsIDOMDOMImplementation  *aImplementation);
+  nsresult GetDocumentElement(nsIDOMElement  *aDocumentElement);
+  nsresult CreateElement(nsAString * tagName, nsIDOMElement *_retval);
+  nsresult CreateDocumentFragment(nsIDOMDocumentFragment *_retval);
+  nsresult CreateTextNode(nsAString * data, nsIDOMText *_retval);
+  nsresult CreateComment(nsAString * data, nsIDOMComment *_retval);
+  nsresult CreateCDATASection(nsAString * data, nsIDOMCDATASection *_retval);
+  nsresult CreateProcessingInstruction(nsAString * target, nsAString * data, nsIDOMProcessingInstruction *_retval);
+  nsresult CreateAttribute(nsAString * name, nsIDOMAttr *_retval);
+  nsresult CreateEntityReference(nsAString * name, nsIDOMEntityReference *_retval);
+  nsresult GetElementsByTagName(nsAString * tagname, nsIDOMNodeList *_retval);
+  nsresult ImportNode(nsIDOMNode importedNode, PRBool deep, nsIDOMNode *_retval);
+  nsresult CreateElementNS(nsAString * namespaceURI, nsAString * qualifiedName, nsIDOMElement *_retval);
+  nsresult CreateAttributeNS(nsAString * namespaceURI, nsAString * qualifiedName, nsIDOMAttr *_retval);
+  nsresult GetElementsByTagNameNS(nsAString * namespaceURI, nsAString * localName, nsIDOMNodeList *_retval);
+  nsresult GetElementById(nsAString * elementId, nsIDOMElement *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentFragment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,20 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMDocumentFragment;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+
+const char[] NS_IDOMDOCUMENTFRAGMENT_IID_STR = "a6cf9076-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMDOCUMENTFRAGMENT_IID= 
+  {0xa6cf9076, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMDocumentFragment : nsIDOMNode {
+  static const char[] IID_STR = NS_IDOMDOCUMENTFRAGMENT_IID_STR;
+  static const nsIID IID = NS_IDOMDOCUMENTFRAGMENT_IID;
+
+extern(System):
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentType.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMDocumentType;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMNamedNodeMap;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMDOCUMENTTYPE_IID_STR = "a6cf9077-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMDOCUMENTTYPE_IID= 
+  {0xa6cf9077, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMDocumentType : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMDOCUMENTTYPE_IID_STR;
+  static const nsIID IID = NS_IDOMDOCUMENTTYPE_IID;
+
+extern(System):
+  nsresult GetName(nsAString * aName);
+  nsresult GetEntities(nsIDOMNamedNodeMap  *aEntities);
+  nsresult GetNotations(nsIDOMNamedNodeMap  *aNotations);
+  nsresult GetPublicId(nsAString * aPublicId);
+  nsresult GetSystemId(nsAString * aSystemId);
+  nsresult GetInternalSubset(nsAString * aInternalSubset);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMDocumentView.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMDocumentView;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMAbstractView;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMDOCUMENTVIEW_IID_STR = "1acdb2ba-1dd2-11b2-95bc-9542495d2569";
+
+const nsIID NS_IDOMDOCUMENTVIEW_IID= 
+  {0x1acdb2ba, 0x1dd2, 0x11b2, 
+    [ 0x95, 0xbc, 0x95, 0x42, 0x49, 0x5d, 0x25, 0x69 ]};
+
+interface nsIDOMDocumentView : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMDOCUMENTVIEW_IID_STR;
+  static const nsIID IID = NS_IDOMDOCUMENTVIEW_IID;
+
+extern(System):
+  nsresult GetDefaultView(nsIDOMAbstractView  *aDefaultView);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMElement.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,41 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMElement;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMNodeList;
+import org.eclipse.swt.internal.mozilla.nsIDOMAttr;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMELEMENT_IID_STR = "a6cf9078-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMELEMENT_IID= 
+  {0xa6cf9078, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMElement : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMELEMENT_IID_STR;
+  static const nsIID IID = NS_IDOMELEMENT_IID;
+
+extern(System):
+  nsresult GetTagName(nsAString * aTagName);
+  nsresult GetAttribute(nsAString * name, nsAString * _retval);
+  nsresult SetAttribute(nsAString * name, nsAString * value);
+  nsresult RemoveAttribute(nsAString * name);
+  nsresult GetAttributeNode(nsAString * name, nsIDOMAttr *_retval);
+  nsresult SetAttributeNode(nsIDOMAttr newAttr, nsIDOMAttr *_retval);
+  nsresult RemoveAttributeNode(nsIDOMAttr oldAttr, nsIDOMAttr *_retval);
+  nsresult GetElementsByTagName(nsAString * name, nsIDOMNodeList *_retval);
+  nsresult GetAttributeNS(nsAString * namespaceURI, nsAString * localName, nsAString * _retval);
+  nsresult SetAttributeNS(nsAString * namespaceURI, nsAString * qualifiedName, nsAString * value);
+  nsresult RemoveAttributeNS(nsAString * namespaceURI, nsAString * localName);
+  nsresult GetAttributeNodeNS(nsAString * namespaceURI, nsAString * localName, nsIDOMAttr *_retval);
+  nsresult SetAttributeNodeNS(nsIDOMAttr newAttr, nsIDOMAttr *_retval);
+  nsresult GetElementsByTagNameNS(nsAString * namespaceURI, nsAString * localName, nsIDOMNodeList *_retval);
+  nsresult HasAttribute(nsAString * name, PRBool *_retval);
+  nsresult HasAttributeNS(nsAString * namespaceURI, nsAString * localName, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEntityReference.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMEntityReference;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+
+const char[] NS_IDOMENTITYREFERENCE_IID_STR = "a6cf907a-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMENTITYREFERENCE_IID= 
+  {0xa6cf907a, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMEntityReference : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMENTITYREFERENCE_IID_STR;
+  static const nsIID IID = NS_IDOMENTITYREFERENCE_IID;
+
+extern(System):
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,39 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMEvent;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMEventTarget;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMEVENT_IID_STR = "a66b7b80-ff46-bd97-0080-5f8ae38add32";
+
+const nsIID NS_IDOMEVENT_IID= 
+  {0xa66b7b80, 0xff46, 0xbd97, 
+    [ 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMEvent : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMEVENT_IID_STR;
+  static const nsIID IID = NS_IDOMEVENT_IID;
+
+extern(System):
+  enum { CAPTURING_PHASE = 1U };
+  enum { AT_TARGET = 2U };
+  enum { BUBBLING_PHASE = 3U };
+
+  nsresult GetType(nsAString * aType);
+  nsresult GetTarget(nsIDOMEventTarget  *aTarget);
+  nsresult GetCurrentTarget(nsIDOMEventTarget  *aCurrentTarget);
+  nsresult GetEventPhase(PRUint16 *aEventPhase);
+  nsresult GetBubbles(PRBool *aBubbles);
+  nsresult GetCancelable(PRBool *aCancelable);
+  nsresult GetTimeStamp(DOMTimeStamp *aTimeStamp);
+  nsresult StopPropagation();
+  nsresult PreventDefault();
+  nsresult InitEvent(nsAString * eventTypeArg, PRBool canBubbleArg, PRBool cancelableArg);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventGroup.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMEventGroup;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMEVENTGROUP_IID_STR = "33347bee-6620-4841-8152-36091ae80c7e";
+
+const nsIID NS_IDOMEVENTGROUP_IID= 
+  {0x33347bee, 0x6620, 0x4841, 
+    [ 0x81, 0x52, 0x36, 0x09, 0x1a, 0xe8, 0x0c, 0x7e ]};
+
+interface nsIDOMEventGroup : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMEVENTGROUP_IID_STR;
+  static const nsIID IID = NS_IDOMEVENTGROUP_IID;
+
+extern(System):
+  nsresult IsSameEventGroup(nsIDOMEventGroup other, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMEventListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMEVENTLISTENER_IID_STR = "df31c120-ded6-11d1-bd85-00805f8ae3f4";
+const nsIID NS_IDOMEVENTLISTENER_IID= 
+  {0xdf31c120, 0xded6, 0x11d1, 
+    [ 0xbd, 0x85, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4 ]};
+
+interface nsIDOMEventListener : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMEVENTLISTENER_IID_STR;
+  static const nsIID IID = NS_IDOMEVENTLISTENER_IID;
+
+extern(System):
+  nsresult HandleEvent(nsIDOMEvent event);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMEventTarget.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMEventTarget;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent;
+import org.eclipse.swt.internal.mozilla.nsIDOMEventListener;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMEVENTTARGET_IID_STR = "1c773b30-d1cf-11d2-bd95-00805f8ae3f4";
+
+const nsIID NS_IDOMEVENTTARGET_IID= 
+  {0x1c773b30, 0xd1cf, 0x11d2, 
+    [ 0xbd, 0x95, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4 ]};
+
+//extern(System)
+
+interface nsIDOMEventTarget : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMEVENTTARGET_IID_STR;
+  static const nsIID IID = NS_IDOMEVENTTARGET_IID;
+
+extern(System):
+  nsresult AddEventListener(nsAString * type, nsIDOMEventListener listener, PRBool useCapture);
+  nsresult RemoveEventListener(nsAString * type, nsIDOMEventListener listener, PRBool useCapture);
+  nsresult DispatchEvent(nsIDOMEvent evt, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMKeyEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,148 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMKeyEvent;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMUIEvent;
+import org.eclipse.swt.internal.mozilla.nsIDOMAbstractView;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMKEYEVENT_IID_STR = "028e0e6e-8b01-11d3-aae7-0010838a3123";
+
+const nsIID NS_IDOMKEYEVENT_IID= 
+  {0x028e0e6e, 0x8b01, 0x11d3, 
+    [ 0xaa, 0xe7, 0x00, 0x10, 0x83, 0x8a, 0x31, 0x23 ]};
+
+interface nsIDOMKeyEvent : nsIDOMUIEvent {
+
+  static const char[] IID_STR = NS_IDOMKEYEVENT_IID_STR;
+  static const nsIID IID = NS_IDOMKEYEVENT_IID;
+
+extern(System):
+  enum { DOM_VK_CANCEL = 3U };
+  enum { DOM_VK_HELP = 6U };
+  enum { DOM_VK_BACK_SPACE = 8U };
+  enum { DOM_VK_TAB = 9U };
+  enum { DOM_VK_CLEAR = 12U };
+  enum { DOM_VK_RETURN = 13U };
+  enum { DOM_VK_ENTER = 14U };
+  enum { DOM_VK_SHIFT = 16U };
+  enum { DOM_VK_CONTROL = 17U };
+  enum { DOM_VK_ALT = 18U };
+  enum { DOM_VK_PAUSE = 19U };
+  enum { DOM_VK_CAPS_LOCK = 20U };
+  enum { DOM_VK_ESCAPE = 27U };
+  enum { DOM_VK_SPACE = 32U };
+  enum { DOM_VK_PAGE_UP = 33U };
+  enum { DOM_VK_PAGE_DOWN = 34U };
+  enum { DOM_VK_END = 35U };
+  enum { DOM_VK_HOME = 36U };
+  enum { DOM_VK_LEFT = 37U };
+  enum { DOM_VK_UP = 38U };
+  enum { DOM_VK_RIGHT = 39U };
+  enum { DOM_VK_DOWN = 40U };
+  enum { DOM_VK_PRINTSCREEN = 44U };
+  enum { DOM_VK_INSERT = 45U };
+  enum { DOM_VK_DELETE = 46U };
+  enum { DOM_VK_0 = 48U };
+  enum { DOM_VK_1 = 49U };
+  enum { DOM_VK_2 = 50U };
+  enum { DOM_VK_3 = 51U };
+  enum { DOM_VK_4 = 52U };
+  enum { DOM_VK_5 = 53U };
+  enum { DOM_VK_6 = 54U };
+  enum { DOM_VK_7 = 55U };
+  enum { DOM_VK_8 = 56U };
+  enum { DOM_VK_9 = 57U };
+  enum { DOM_VK_SEMICOLON = 59U };
+  enum { DOM_VK_EQUALS = 61U };
+  enum { DOM_VK_A = 65U };
+  enum { DOM_VK_B = 66U };
+  enum { DOM_VK_C = 67U };
+  enum { DOM_VK_D = 68U };
+  enum { DOM_VK_E = 69U };
+  enum { DOM_VK_F = 70U };
+  enum { DOM_VK_G = 71U };
+  enum { DOM_VK_H = 72U };
+  enum { DOM_VK_I = 73U };
+  enum { DOM_VK_J = 74U };
+  enum { DOM_VK_K = 75U };
+  enum { DOM_VK_L = 76U };
+  enum { DOM_VK_M = 77U };
+  enum { DOM_VK_N = 78U };
+  enum { DOM_VK_O = 79U };
+  enum { DOM_VK_P = 80U };
+  enum { DOM_VK_Q = 81U };
+  enum { DOM_VK_R = 82U };
+  enum { DOM_VK_S = 83U };
+  enum { DOM_VK_T = 84U };
+  enum { DOM_VK_U = 85U };
+  enum { DOM_VK_V = 86U };
+  enum { DOM_VK_W = 87U };
+  enum { DOM_VK_X = 88U };
+  enum { DOM_VK_Y = 89U };
+  enum { DOM_VK_Z = 90U };
+  enum { DOM_VK_CONTEXT_MENU = 93U };
+  enum { DOM_VK_NUMPAD0 = 96U };
+  enum { DOM_VK_NUMPAD1 = 97U };
+  enum { DOM_VK_NUMPAD2 = 98U };
+  enum { DOM_VK_NUMPAD3 = 99U };
+  enum { DOM_VK_NUMPAD4 = 100U };
+  enum { DOM_VK_NUMPAD5 = 101U };
+  enum { DOM_VK_NUMPAD6 = 102U };
+  enum { DOM_VK_NUMPAD7 = 103U };
+  enum { DOM_VK_NUMPAD8 = 104U };
+  enum { DOM_VK_NUMPAD9 = 105U };
+  enum { DOM_VK_MULTIPLY = 106U };
+  enum { DOM_VK_ADD = 107U };
+  enum { DOM_VK_SEPARATOR = 108U };
+  enum { DOM_VK_SUBTRACT = 109U };
+  enum { DOM_VK_DECIMAL = 110U };
+  enum { DOM_VK_DIVIDE = 111U };
+  enum { DOM_VK_F1 = 112U };
+  enum { DOM_VK_F2 = 113U };
+  enum { DOM_VK_F3 = 114U };
+  enum { DOM_VK_F4 = 115U };
+  enum { DOM_VK_F5 = 116U };
+  enum { DOM_VK_F6 = 117U };
+  enum { DOM_VK_F7 = 118U };
+  enum { DOM_VK_F8 = 119U };
+  enum { DOM_VK_F9 = 120U };
+  enum { DOM_VK_F10 = 121U };
+  enum { DOM_VK_F11 = 122U };
+  enum { DOM_VK_F12 = 123U };
+  enum { DOM_VK_F13 = 124U };
+  enum { DOM_VK_F14 = 125U };
+  enum { DOM_VK_F15 = 126U };
+  enum { DOM_VK_F16 = 127U };
+  enum { DOM_VK_F17 = 128U };
+  enum { DOM_VK_F18 = 129U };
+  enum { DOM_VK_F19 = 130U };
+  enum { DOM_VK_F20 = 131U };
+  enum { DOM_VK_F21 = 132U };
+  enum { DOM_VK_F22 = 133U };
+  enum { DOM_VK_F23 = 134U };
+  enum { DOM_VK_F24 = 135U };
+  enum { DOM_VK_NUM_LOCK = 144U };
+  enum { DOM_VK_SCROLL_LOCK = 145U };
+  enum { DOM_VK_COMMA = 188U };
+  enum { DOM_VK_PERIOD = 190U };
+  enum { DOM_VK_SLASH = 191U };
+  enum { DOM_VK_BACK_QUOTE = 192U };
+  enum { DOM_VK_OPEN_BRACKET = 219U };
+  enum { DOM_VK_BACK_SLASH = 220U };
+  enum { DOM_VK_CLOSE_BRACKET = 221U };
+  enum { DOM_VK_QUOTE = 222U };
+  enum { DOM_VK_META = 224U };
+
+  nsresult GetCharCode(PRUint32 *aCharCode);
+  nsresult GetKeyCode(PRUint32 *aKeyCode);
+  nsresult GetAltKey(PRBool *aAltKey);
+  nsresult GetCtrlKey(PRBool *aCtrlKey);
+  nsresult GetShiftKey(PRBool *aShiftKey);
+  nsresult GetMetaKey(PRBool *aMetaKey);
+
+  nsresult InitKeyEvent(nsAString * typeArg, PRBool canBubbleArg, PRBool cancelableArg, nsIDOMAbstractView viewArg, PRBool ctrlKeyArg, PRBool altKeyArg, PRBool shiftKeyArg, PRBool metaKeyArg, PRUint32 keyCodeArg, PRUint32 charCodeArg);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMMouseEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMMouseEvent;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMUIEvent;
+import org.eclipse.swt.internal.mozilla.nsIDOMEventTarget;
+import org.eclipse.swt.internal.mozilla.nsIDOMAbstractView;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMMOUSEEVENT_IID_STR = "ff751edc-8b02-aae7-0010-8301838a3123";
+
+const nsIID NS_IDOMMOUSEEVENT_IID= 
+  {0xff751edc, 0x8b02, 0xaae7, 
+    [ 0x00, 0x10, 0x83, 0x01, 0x83, 0x8a, 0x31, 0x23 ]};
+
+interface nsIDOMMouseEvent : nsIDOMUIEvent {
+
+  static const char[] IID_STR = NS_IDOMMOUSEEVENT_IID_STR;
+  static const nsIID IID = NS_IDOMMOUSEEVENT_IID;
+
+extern(System):
+  nsresult GetScreenX(PRInt32 *aScreenX);
+  nsresult GetScreenY(PRInt32 *aScreenY);
+  nsresult GetClientX(PRInt32 *aClientX);
+  nsresult GetClientY(PRInt32 *aClientY);
+  nsresult GetCtrlKey(PRBool *aCtrlKey);
+  nsresult GetShiftKey(PRBool *aShiftKey);
+  nsresult GetAltKey(PRBool *aAltKey);
+  nsresult GetMetaKey(PRBool *aMetaKey);
+  nsresult GetButton(PRUint16 *aButton);
+  nsresult GetRelatedTarget(nsIDOMEventTarget  *aRelatedTarget);
+
+  nsresult InitMouseEvent(nsAString * typeArg, PRBool canBubbleArg, PRBool cancelableArg, nsIDOMAbstractView viewArg, PRInt32 detailArg, PRInt32 screenXArg, PRInt32 screenYArg, PRInt32 clientXArg, PRInt32 clientYArg, PRBool ctrlKeyArg, PRBool altKeyArg, PRBool shiftKeyArg, PRBool metaKeyArg, PRUint16 buttonArg, nsIDOMEventTarget relatedTargetArg);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNamedNodeMap.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,34 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMNamedNodeMap;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMNAMEDNODEMAP_IID_STR = "a6cf907b-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMNAMEDNODEMAP_IID= 
+  {0xa6cf907b, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMNamedNodeMap : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMNAMEDNODEMAP_IID_STR;
+  static const nsIID IID = NS_IDOMNAMEDNODEMAP_IID;
+
+extern(System):
+  nsresult GetNamedItem(nsAString * name, nsIDOMNode *_retval);
+  nsresult SetNamedItem(nsIDOMNode arg, nsIDOMNode *_retval);
+  nsresult RemoveNamedItem(nsAString * name, nsIDOMNode *_retval);
+  nsresult Item(PRUint32 index, nsIDOMNode *_retval);
+  nsresult GetLength(PRUint32 *aLength);
+  nsresult GetNamedItemNS(nsAString * namespaceURI, nsAString * localName, nsIDOMNode *_retval);
+  nsresult SetNamedItemNS(nsIDOMNode arg, nsIDOMNode *_retval);
+  nsresult RemoveNamedItemNS(nsAString * namespaceURI, nsAString * localName, nsIDOMNode *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNode.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,66 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMNode;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNodeList;
+import org.eclipse.swt.internal.mozilla.nsIDOMNamedNodeMap;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMNODE_IID_STR = "a6cf907c-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMNODE_IID= 
+  {0xa6cf907c, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMNode : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMNODE_IID_STR;
+  static const nsIID IID = NS_IDOMNODE_IID;
+
+extern(System):
+  enum { ELEMENT_NODE = 1U };
+  enum { ATTRIBUTE_NODE = 2U };
+  enum { TEXT_NODE = 3U };
+  enum { CDATA_SECTION_NODE = 4U };
+  enum { ENTITY_REFERENCE_NODE = 5U };
+  enum { ENTITY_NODE = 6U };
+  enum { PROCESSING_INSTRUCTION_NODE = 7U };
+  enum { COMMENT_NODE = 8U };
+  enum { DOCUMENT_NODE = 9U };
+  enum { DOCUMENT_TYPE_NODE = 10U };
+  enum { DOCUMENT_FRAGMENT_NODE = 11U };
+  enum { NOTATION_NODE = 12U };
+
+  nsresult GetNodeName(nsAString * aNodeName);
+  nsresult GetNodeValue(nsAString * aNodeValue);
+  nsresult SetNodeValue(nsAString * aNodeValue);
+  nsresult GetNodeType(PRUint16 *aNodeType);
+  nsresult GetParentNode(nsIDOMNode  *aParentNode);
+  nsresult GetChildNodes(nsIDOMNodeList  *aChildNodes);
+  nsresult GetFirstChild(nsIDOMNode  *aFirstChild);
+  nsresult GetLastChild(nsIDOMNode  *aLastChild);
+  nsresult GetPreviousSibling(nsIDOMNode  *aPreviousSibling);
+  nsresult GetNextSibling(nsIDOMNode  *aNextSibling);
+  nsresult GetAttributes(nsIDOMNamedNodeMap  *aAttributes);
+  nsresult GetOwnerDocument(nsIDOMDocument  *aOwnerDocument);
+  nsresult InsertBefore(nsIDOMNode newChild, nsIDOMNode refChild, nsIDOMNode *_retval);
+  nsresult ReplaceChild(nsIDOMNode newChild, nsIDOMNode oldChild, nsIDOMNode *_retval);
+  nsresult RemoveChild(nsIDOMNode oldChild, nsIDOMNode *_retval);
+  nsresult AppendChild(nsIDOMNode newChild, nsIDOMNode *_retval);
+  nsresult HasChildNodes(PRBool *_retval);
+  nsresult CloneNode(PRBool deep, nsIDOMNode *_retval);
+  nsresult Normalize();
+  nsresult IsSupported(nsAString * feature, nsAString * version_, PRBool *_retval);
+  nsresult GetNamespaceURI(nsAString * aNamespaceURI);
+  nsresult GetPrefix(nsAString * aPrefix);
+  nsresult SetPrefix(nsAString * aPrefix);
+  nsresult GetLocalName(nsAString * aLocalName);
+  nsresult HasAttributes(PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMNodeList.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMNodeList;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMNODELIST_IID_STR = "a6cf907d-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMNODELIST_IID= 
+  {0xa6cf907d, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+//extern(System)
+
+interface nsIDOMNodeList : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMNODELIST_IID_STR;
+  static const nsIID IID = NS_IDOMNODELIST_IID;
+
+extern(System):
+  nsresult Item(PRUint32 index, nsIDOMNode *_retval);
+  nsresult GetLength(PRUint32 *aLength);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMProcessingInstruction.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMProcessingInstruction;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMPROCESSINGINSTRUCTION_IID_STR = "a6cf907f-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMPROCESSINGINSTRUCTION_IID= 
+  {0xa6cf907f, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMProcessingInstruction : nsIDOMNode {
+
+  static const char[] IID_STR = NS_IDOMPROCESSINGINSTRUCTION_IID_STR;
+  static const nsIID IID = NS_IDOMPROCESSINGINSTRUCTION_IID;
+
+  nsresult GetTarget(nsAString * aTarget);
+  nsresult GetData(nsAString * aData);
+  nsresult SetData(nsAString * aData);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMRange.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,55 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMRange;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocumentFragment;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMRANGE_IID_STR = "a6cf90ce-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMRANGE_IID= 
+  {0xa6cf90ce, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMRange : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMRANGE_IID_STR;
+  static const nsIID IID = NS_IDOMRANGE_IID;
+
+extern(System):
+  nsresult GetStartContainer(nsIDOMNode  *aStartContainer);
+  nsresult GetStartOffset(PRInt32 *aStartOffset);
+  nsresult GetEndContainer(nsIDOMNode  *aEndContainer);
+  nsresult GetEndOffset(PRInt32 *aEndOffset);
+  nsresult GetCollapsed(PRBool *aCollapsed);
+  nsresult GetCommonAncestorContainer(nsIDOMNode  *aCommonAncestorContainer);
+  nsresult SetStart(nsIDOMNode refNode, PRInt32 offset);
+  nsresult SetEnd(nsIDOMNode refNode, PRInt32 offset);
+  nsresult SetStartBefore(nsIDOMNode refNode);
+  nsresult SetStartAfter(nsIDOMNode refNode);
+  nsresult SetEndBefore(nsIDOMNode refNode);
+  nsresult SetEndAfter(nsIDOMNode refNode);
+  nsresult Collapse(PRBool toStart);
+  nsresult SelectNode(nsIDOMNode refNode);
+  nsresult SelectNodeContents(nsIDOMNode refNode);
+
+  enum { START_TO_START = 0U };
+  enum { START_TO_END = 1U };
+  enum { END_TO_END = 2U };
+  enum { END_TO_START = 3U };
+
+  nsresult CompareBoundaryPoints(PRUint16 how, nsIDOMRange sourceRange, PRInt16 *_retval);
+  nsresult DeleteContents();
+  nsresult ExtractContents(nsIDOMDocumentFragment *_retval);
+  nsresult CloneContents(nsIDOMDocumentFragment *_retval);
+  nsresult InsertNode(nsIDOMNode newNode);
+  nsresult SurroundContents(nsIDOMNode newParent);
+  nsresult CloneRange(nsIDOMRange *_retval);
+  nsresult ToString(nsAString * _retval);
+  nsresult Detach();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMSerializer;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIOutputStream;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMSERIALIZER_IID_STR = "a6cf9123-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMSERIALIZER_IID= 
+  {0xa6cf9123, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMSerializer : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMSERIALIZER_IID_STR;
+  static const nsIID IID = NS_IDOMSERIALIZER_IID;
+
+extern(System):
+
+  nsresult SerializeToString(nsIDOMNode root, PRUnichar ** _retval);
+  nsresult SerializeToStream(nsIDOMNode root, nsIOutputStream stream, char* charset);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMSerializer_1_7.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMSerializer_1_7;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIOutputStream;
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IDOMSERIALIZER_IID_STR = "9fd4ba15-e67c-4c98-b52c-7715f62c9196";
+
+const nsIID NS_IDOMSERIALIZER_IID= 
+  {0x9fd4ba15, 0xe67c, 0x4c98, 
+    [ 0xb5, 0x2c, 0x77, 0x15, 0xf6, 0x2c, 0x91, 0x96 ]};
+
+interface nsIDOMSerializer_1_7 : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMSERIALIZER_IID_STR;
+  static const nsIID IID = NS_IDOMSERIALIZER_IID;
+
+extern(System):
+  nsresult SerializeToString(nsIDOMNode root, nsAString * _retval);
+  nsresult SerializeToStream(nsIDOMNode root, nsIOutputStream stream, nsACString * charset);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMStorage.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMStorage;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+import org.eclipse.swt.internal.mozilla.nsIDOMStorageItem;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMSTORAGE_IID_STR = "95cc1383-3b62-4b89-aaef-1004a513ef47";
+
+const nsIID NS_IDOMSTORAGE_IID= 
+  {0x95cc1383, 0x3b62, 0x4b89, 
+    [ 0xaa, 0xef, 0x10, 0x04, 0xa5, 0x13, 0xef, 0x47 ]};
+
+interface nsIDOMStorage : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMSTORAGE_IID_STR;
+  static const nsIID IID = NS_IDOMSTORAGE_IID;
+
+extern(System):
+  nsresult GetLength(PRUint32 *aLength);
+  nsresult Key(PRUint32 index, nsAString * _retval);
+  nsresult GetItem(nsAString * key, nsIDOMStorageItem *_retval);
+  nsresult SetItem(nsAString * key, nsAString * data);
+  nsresult RemoveItem(nsAString * key);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMStorageItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMStorageItem;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMSTORAGEITEM_IID_STR = "0cc37c78-4c5f-48e1-adfc-7480b8fe9dc4";
+
+const nsIID NS_IDOMSTORAGEITEM_IID= 
+  {0x0cc37c78, 0x4c5f, 0x48e1, 
+    [ 0xad, 0xfc, 0x74, 0x80, 0xb8, 0xfe, 0x9d, 0xc4 ]};
+
+interface nsIDOMStorageItem : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMSTORAGEITEM_IID_STR;
+  static const nsIID IID = NS_IDOMSTORAGEITEM_IID;
+
+extern(System):
+  nsresult GetSecure(PRBool *aSecure);
+  nsresult SetSecure(PRBool aSecure);
+  nsresult GetValue(nsAString * aValue);
+  nsresult SetValue(nsAString * aValue);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMText.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMText;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMCharacterData;
+
+const char[] NS_IDOMTEXT_IID_STR = "a6cf9082-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMTEXT_IID= 
+  {0xa6cf9082, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMText : nsIDOMCharacterData {
+
+  static const char[] IID_STR = NS_IDOMTEXT_IID_STR;
+  static const nsIID IID = NS_IDOMTEXT_IID;
+
+extern(System):
+  nsresult SplitText(PRUint32 offset, nsIDOMText *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMUIEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMUIEvent;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMEvent;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+import org.eclipse.swt.internal.mozilla.nsIDOMAbstractView;
+
+const char[] NS_IDOMUIEVENT_IID_STR = "a6cf90c3-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMUIEVENT_IID= 
+  {0xa6cf90c3, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMUIEvent : nsIDOMEvent {
+
+  static const char[] IID_STR = NS_IDOMUIEVENT_IID_STR;
+  static const nsIID IID = NS_IDOMUIEVENT_IID;
+
+extern(System):
+  nsresult GetView(nsIDOMAbstractView  *aView);
+  nsresult GetDetail(PRInt32 *aDetail);
+  nsresult InitUIEvent(nsAString * typeArg, PRBool canBubbleArg, PRBool cancelableArg, nsIDOMAbstractView viewArg, PRInt32 detailArg);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,46 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindowCollection;
+import org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+import org.eclipse.swt.internal.mozilla.nsIDOMBarProp;
+import org.eclipse.swt.internal.mozilla.nsISelection;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMWINDOW_IID_STR = "a6cf906b-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMWINDOW_IID= 
+  {0xa6cf906b, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMWindow : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMWINDOW_IID_STR;
+  static const nsIID IID = NS_IDOMWINDOW_IID;
+
+extern(System):
+  nsresult GetDocument(nsIDOMDocument  *aDocument);
+  nsresult GetParent(nsIDOMWindow  *aParent);
+  nsresult GetTop(nsIDOMWindow  *aTop);
+  nsresult GetScrollbars(nsIDOMBarProp  *aScrollbars);
+  nsresult GetFrames(nsIDOMWindowCollection  *aFrames);
+  nsresult GetName(nsAString * aName);
+  nsresult SetName(nsAString * aName);
+  nsresult GetTextZoom(float *aTextZoom);
+  nsresult SetTextZoom(float aTextZoom);
+  nsresult GetScrollX(PRInt32 *aScrollX);
+  nsresult GetScrollY(PRInt32 *aScrollY);
+  nsresult ScrollTo(PRInt32 xScroll, PRInt32 yScroll);
+  nsresult ScrollBy(PRInt32 xScrollDif, PRInt32 yScrollDif);
+  nsresult GetSelection(nsISelection *_retval);
+  nsresult ScrollByLines(PRInt32 numLines);
+  nsresult ScrollByPages(PRInt32 numPages);
+  nsresult SizeToContent();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindow2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMWindow2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+import org.eclipse.swt.internal.mozilla.nsIDOMEventTarget;
+
+const char[] NS_IDOMWINDOW2_IID_STR = "65455132-b96a-40ec-adea-52fa22b1028c";
+
+const nsIID NS_IDOMWINDOW2_IID= 
+  {0x65455132, 0xb96a, 0x40ec, 
+    [ 0xad, 0xea, 0x52, 0xfa, 0x22, 0xb1, 0x02, 0x8c ]};
+
+interface nsIDOMWindow2 : nsIDOMWindow {
+
+  static const char[] IID_STR = NS_IDOMWINDOW2_IID_STR;
+  static const nsIID IID = NS_IDOMWINDOW2_IID;
+
+extern(System):
+  nsresult GetWindowRoot(nsIDOMEventTarget  *aWindowRoot);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDOMWindowCollection.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIDOMWindowCollection;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint64 DOMTimeStamp;
+
+const char[] NS_IDOMWINDOWCOLLECTION_IID_STR = "a6cf906f-15b3-11d2-932e-00805f8add32";
+
+const nsIID NS_IDOMWINDOWCOLLECTION_IID= 
+  {0xa6cf906f, 0x15b3, 0x11d2, 
+    [ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 ]};
+
+interface nsIDOMWindowCollection : nsISupports {
+
+  static const char[] IID_STR = NS_IDOMWINDOWCOLLECTION_IID_STR;
+  static const nsIID IID = NS_IDOMWINDOWCOLLECTION_IID;
+
+extern(System):
+  nsresult GetLength(PRUint32 *aLength);
+  nsresult Item(PRUint32 index, nsIDOMWindow *_retval);
+  nsresult NamedItem(nsAString * name, nsIDOMWindow *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDebug.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIDebug;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IDEBUG_IID_STR = "3bf0c3d7-3bd9-4cf2-a971-33572c503e1e";
+
+const nsIID NS_IDEBUG_IID= 
+  {0x3bf0c3d7, 0x3bd9, 0x4cf2, 
+    [ 0xa9, 0x71, 0x33, 0x57, 0x2c, 0x50, 0x3e, 0x1e ]};
+
+interface nsIDebug : nsISupports {
+  static const char[] IID_STR = NS_IDEBUG_IID_STR;
+  static const nsIID IID = NS_IDEBUG_IID;
+
+extern(System):
+  nsresult Assertion(char *aStr, char *aExpr, char *aFile, PRInt32 aLine);
+  nsresult Warning(char *aStr, char *aFile, PRInt32 aLine);
+  nsresult Break(char *aFile, PRInt32 aLine);
+  nsresult Abort(char *aFile, PRInt32 aLine);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDirectoryService.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,69 @@
+module org.eclipse.swt.internal.mozilla.nsIDirectoryService;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDIRECTORYSERVICEPROVIDER_IID_STR = "bbf8cab0-d43a-11d3-8cc2-00609792278c";
+
+const nsIID NS_IDIRECTORYSERVICEPROVIDER_IID= 
+  {0xbbf8cab0, 0xd43a, 0x11d3, 
+    [ 0x8c, 0xc2, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c ]};
+
+interface nsIDirectoryServiceProvider : nsISupports {
+
+  static const char[] IID_STR = NS_IDIRECTORYSERVICEPROVIDER_IID_STR;
+  static const nsIID IID = NS_IDIRECTORYSERVICEPROVIDER_IID;
+
+extern(System):
+  nsresult GetFile(char *prop, PRBool *persistent, nsIFile *_retval);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDIRECTORYSERVICEPROVIDER2_IID_STR = "2f977d4b-5485-11d4-87e2-0010a4e75ef2";
+
+const nsIID NS_IDIRECTORYSERVICEPROVIDER2_IID= 
+  {0x2f977d4b, 0x5485, 0x11d4, 
+    [ 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 ]};
+
+interface nsIDirectoryServiceProvider2 : nsIDirectoryServiceProvider {
+
+  static const char[] IID_STR = NS_IDIRECTORYSERVICEPROVIDER2_IID_STR;
+  static const nsIID IID = NS_IDIRECTORYSERVICEPROVIDER2_IID;
+
+extern(System):
+  nsresult GetFiles(char *prop, nsISimpleEnumerator *_retval);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDIRECTORYSERVICE_IID_STR = "57a66a60-d43a-11d3-8cc2-00609792278c";
+
+const nsIID NS_IDIRECTORYSERVICE_IID= 
+  {0x57a66a60, 0xd43a, 0x11d3, 
+    [ 0x8c, 0xc2, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c ]};
+
+interface nsIDirectoryService : nsISupports {
+
+  static const char[] IID_STR = NS_IDIRECTORYSERVICE_IID_STR;
+  static const nsIID IID = NS_IDIRECTORYSERVICE_IID;
+
+extern(System):
+  nsresult Init();
+  nsresult RegisterProvider(nsIDirectoryServiceProvider prov);
+  nsresult UnregisterProvider(nsIDirectoryServiceProvider prov);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShell.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,167 @@
+// FIXME; IID's are not consistant with SWT version
+
+module org.eclipse.swt.internal.mozilla.nsIDocShell;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsIChannel;
+import org.eclipse.swt.internal.mozilla.nsIContentViewer;
+import org.eclipse.swt.internal.mozilla.nsIURIContentListener;
+import org.eclipse.swt.internal.mozilla.nsIChromeEventHandler;
+import org.eclipse.swt.internal.mozilla.nsIDocShellLoadInfo;
+import org.eclipse.swt.internal.mozilla.nsIDocumentCharsetInfo;
+import org.eclipse.swt.internal.mozilla.nsIWebNavigation;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+import org.eclipse.swt.internal.mozilla.nsISHEntry;
+import org.eclipse.swt.internal.mozilla.nsISecureBrowserUI;
+import org.eclipse.swt.internal.mozilla.nsIDOMStorage;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDOCSHELL_IID_STR = "69e5de00-7b8b-11d3-af61-00a024ffc08c";
+
+const nsIID NS_IDOCSHELL_IID= 
+  { 0x69e5de00, 0x7b8b, 0x11d3, [0xaf,0x61,0x00,0xa0,0x24,0xff,0xc0,0x8c] };
+interface nsIDocShell : nsISupports {
+
+  static const char[] IID_STR = NS_IDOCSHELL_IID_STR;
+  static const nsIID IID = NS_IDOCSHELL_IID;
+
+extern(System):
+  nsresult LoadURI(nsIURI uri, nsIDocShellLoadInfo loadInfo, PRUint32 aLoadFlags, PRBool firstParty);
+  nsresult LoadStream(nsIInputStream aStream, nsIURI aURI, nsACString * aContentType, nsACString * aContentCharset, nsIDocShellLoadInfo aLoadInfo);
+
+  enum { INTERNAL_LOAD_FLAGS_NONE = 0 };
+  enum { INTERNAL_LOAD_FLAGS_INHERIT_OWNER = 1 };
+  enum { INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER = 2 };
+  enum { INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 4 };
+  enum { INTERNAL_LOAD_FLAGS_FIRST_LOAD = 8 };
+
+  nsresult InternalLoad(nsIURI aURI, nsIURI aReferrer, nsISupports aOwner, PRUint32 aFlags, PRUnichar *aWindowTarget, char *aTypeHint, nsIInputStream aPostDataStream, nsIInputStream aHeadersStream, PRUint32 aLoadFlags, nsISHEntry aSHEntry, PRBool firstParty, nsIDocShell *aDocShell, nsIRequest *aRequest);
+
+  nsresult CreateLoadInfo(nsIDocShellLoadInfo *loadInfo);
+  nsresult PrepareForNewContentModel();
+  nsresult SetCurrentURI(nsIURI aURI);
+  nsresult FirePageHideNotification(PRBool isUnload);
+  nsresult GetPresContext(nsPresContext * *aPresContext);
+  nsresult GetPresShell(nsIPresShell * *aPresShell);
+  nsresult GetEldestPresShell(nsIPresShell * *aEldestPresShell);
+  nsresult GetContentViewer(nsIContentViewer  *aContentViewer);
+  nsresult GetChromeEventHandler(nsIChromeEventHandler  *aChromeEventHandler);
+  nsresult SetChromeEventHandler(nsIChromeEventHandler  aChromeEventHandler);
+  nsresult GetDocumentCharsetInfo(nsIDocumentCharsetInfo  *aDocumentCharsetInfo);
+  nsresult SetDocumentCharsetInfo(nsIDocumentCharsetInfo  aDocumentCharsetInfo);
+  nsresult GetAllowPlugins(PRBool *aAllowPlugins);
+  nsresult SetAllowPlugins(PRBool aAllowPlugins);
+  nsresult GetAllowJavascript(PRBool *aAllowJavascript);
+  nsresult SetAllowJavascript(PRBool aAllowJavascript);
+  nsresult GetAllowMetaRedirects(PRBool *aAllowMetaRedirects);
+  nsresult SetAllowMetaRedirects(PRBool aAllowMetaRedirects);
+  nsresult GetAllowSubframes(PRBool *aAllowSubframes);
+  nsresult SetAllowSubframes(PRBool aAllowSubframes);
+  nsresult GetAllowImages(PRBool *aAllowImages);
+  nsresult SetAllowImages(PRBool aAllowImages);
+
+  enum { ENUMERATE_FORWARDS = 0 };
+  enum { ENUMERATE_BACKWARDS = 1 };
+
+  nsresult GetDocShellEnumerator(PRInt32 aItemType, PRInt32 aDirection, nsISimpleEnumerator *_retval);
+
+  enum { APP_TYPE_UNKNOWN = 0U };
+  enum { APP_TYPE_MAIL = 1U };
+  enum { APP_TYPE_EDITOR = 2U };
+
+  nsresult GetAppType(PRUint32 *aAppType);
+  nsresult SetAppType(PRUint32 aAppType);
+  nsresult GetAllowAuth(PRBool *aAllowAuth);
+  nsresult SetAllowAuth(PRBool aAllowAuth);
+  nsresult GetZoom(float *aZoom);
+  nsresult SetZoom(float aZoom);
+  nsresult GetMarginWidth(PRInt32 *aMarginWidth);
+  nsresult SetMarginWidth(PRInt32 aMarginWidth);
+  nsresult GetMarginHeight(PRInt32 *aMarginHeight);
+  nsresult SetMarginHeight(PRInt32 aMarginHeight);
+  nsresult GetHasFocus(PRBool *aHasFocus);
+  nsresult SetHasFocus(PRBool aHasFocus);
+  nsresult GetCanvasHasFocus(PRBool *aCanvasHasFocus);
+  nsresult SetCanvasHasFocus(PRBool aCanvasHasFocus);
+  nsresult TabToTreeOwner(PRBool forward, PRBool *tookFocus);
+
+  enum { BUSY_FLAGS_NONE = 0U };
+  enum { BUSY_FLAGS_BUSY = 1U };
+  enum { BUSY_FLAGS_BEFORE_PAGE_LOAD = 2U };
+  enum { BUSY_FLAGS_PAGE_LOADING = 4U };
+  enum { LOAD_CMD_NORMAL = 1U };
+  enum { LOAD_CMD_RELOAD = 2U };
+  enum { LOAD_CMD_HISTORY = 4U };
+
+  nsresult GetBusyFlags(PRUint32 *aBusyFlags);
+  nsresult GetLoadType(PRUint32 *aLoadType);
+  nsresult SetLoadType(PRUint32 aLoadType);
+  nsresult IsBeingDestroyed(PRBool *_retval);
+  nsresult GetIsExecutingOnLoadHandler(PRBool *aIsExecutingOnLoadHandler);
+  nsresult GetLayoutHistoryState(nsILayoutHistoryState  *aLayoutHistoryState);
+  nsresult SetLayoutHistoryState(nsILayoutHistoryState  aLayoutHistoryState);
+  nsresult GetShouldSaveLayoutState(PRBool *aShouldSaveLayoutState);
+  nsresult GetSecurityUI(nsISecureBrowserUI  *aSecurityUI);
+  nsresult SetSecurityUI(nsISecureBrowserUI  aSecurityUI);
+  nsresult SuspendRefreshURIs();
+  nsresult ResumeRefreshURIs();
+  nsresult BeginRestore(nsIContentViewer viewer, PRBool top);
+  nsresult FinishRestore();
+  nsresult GetRestoringDocument(PRBool *aRestoringDocument);
+  nsresult GetUseErrorPages(PRBool *aUseErrorPages);
+  nsresult SetUseErrorPages(PRBool aUseErrorPages);
+  nsresult GetPreviousTransIndex(PRInt32 *aPreviousTransIndex);
+  nsresult GetLoadedTransIndex(PRInt32 *aLoadedTransIndex);
+  nsresult HistoryPurged(PRInt32 numEntries);
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDOCSHELL_1_8_IID_STR = "9f0c7461-b9a4-47f6-b88c-421dce1bce66";
+
+const nsIID NS_IDOCSHELL_1_8_IID= 
+    { 0x9f0c7461, 0xb9a4, 0x47f6, 
+       [ 0xb8,0x8c,0x42,0x1d,0xce,0x1b,0xce,0x66 ] }; 
+
+interface nsIDocShell_1_8 : nsIDocShell {
+
+  static const char[] IID_STR = NS_IDOCSHELL_1_8_IID_STR;
+  static const nsIID IID = NS_IDOCSHELL_1_8_IID;
+
+extern(System):
+  nsresult GetSessionStorageForURI(nsIURI uri, nsIDOMStorage *_retval);
+  nsresult AddSessionStorage(nsACString * aDomain, nsIDOMStorage storage);
+  nsresult GetCurrentDocumentChannel(nsIChannel  *aCurrentDocumentChannel);
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDOCSHELL_1_9_IID_STR = "10ed386d-8598-408c-b571-e75ad18edeb0";
+
+const nsIID NS_IDOCSHELL_1_9_IID = 
+    {0x10ed386d, 0x8598, 0x408c, [ 0xb5, 0x71, 0xe7, 0x5a, 0xd1, 0x8e, 0xde, 0xb0 ] };
+
+interface nsIDocShell_1_9 : nsIDocShell_1_8 {
+
+  static const char[] IID_STR = NS_IDOCSHELL_1_9_IID_STR;
+  static const nsIID IID = NS_IDOCSHELL_1_9_IID;
+
+extern(System):
+  nsresult GetSessionStorageForURI(nsIURI uri, nsIDOMStorage *_retval);
+  nsresult AddSessionStorage(nsACString * aDomain, nsIDOMStorage storage);
+  nsresult GetCurrentDocumentChannel(nsIChannel  *aCurrentDocumentChannel);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellLoadInfo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,61 @@
+module org.eclipse.swt.internal.mozilla.nsIDocShellLoadInfo;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+import org.eclipse.swt.internal.mozilla.nsISHEntry;
+
+alias PRInt32 nsDocShellInfoLoadType;
+
+const char[] NS_IDOCSHELLLOADINFO_IID_STR = "4f813a88-7aca-4607-9896-d97270cdf15e";
+
+const nsIID NS_IDOCSHELLLOADINFO_IID= 
+  {0x4f813a88, 0x7aca, 0x4607, 
+    [ 0x98, 0x96, 0xd9, 0x72, 0x70, 0xcd, 0xf1, 0x5e ]};
+
+interface nsIDocShellLoadInfo : nsISupports {
+
+  static const char[] IID_STR = NS_IDOCSHELLLOADINFO_IID_STR;
+  static const nsIID IID = NS_IDOCSHELLLOADINFO_IID;
+
+extern(System):
+  nsresult GetReferrer(nsIURI  *aReferrer);
+  nsresult SetReferrer(nsIURI  aReferrer);
+  nsresult GetOwner(nsISupports  *aOwner);
+  nsresult SetOwner(nsISupports  aOwner);
+  nsresult GetInheritOwner(PRBool *aInheritOwner);
+  nsresult SetInheritOwner(PRBool aInheritOwner);
+
+  enum { loadNormal = 0 };
+  enum { loadNormalReplace = 1 };
+  enum { loadHistory = 2 };
+  enum { loadReloadNormal = 3 };
+  enum { loadReloadBypassCache = 4 };
+  enum { loadReloadBypassProxy = 5 };
+  enum { loadReloadBypassProxyAndCache = 6 };
+  enum { loadLink = 7 };
+  enum { loadRefresh = 8 };
+  enum { loadReloadCharsetChange = 9 };
+  enum { loadBypassHistory = 10 };
+  enum { loadStopContent = 11 };
+  enum { loadStopContentAndReplace = 12 };
+  enum { loadNormalExternal = 13 };
+
+  nsresult GetLoadType(nsDocShellInfoLoadType *aLoadType);
+  nsresult SetLoadType(nsDocShellInfoLoadType aLoadType);
+  nsresult GetSHEntry(nsISHEntry  *aSHEntry);
+  nsresult SetSHEntry(nsISHEntry  aSHEntry);
+  nsresult GetTarget(PRUnichar * *aTarget);
+  nsresult SetTarget(PRUnichar * aTarget);
+  nsresult GetPostDataStream(nsIInputStream  *aPostDataStream);
+  nsresult SetPostDataStream(nsIInputStream  aPostDataStream);
+  nsresult GetHeadersStream(nsIInputStream  *aHeadersStream);
+  nsresult SetHeadersStream(nsIInputStream  aHeadersStream);
+  nsresult GetSendReferrer(PRBool *aSendReferrer);
+  nsresult SetSendReferrer(PRBool aSendReferrer);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellTreeItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,44 @@
+module org.eclipse.swt.internal.mozilla.nsIDocShellTreeItem;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDocShellTreeOwner;
+
+const char[] NS_IDOCSHELLTREEITEM_IID_STR = "7d935d63-6d2a-4600-afb5-9a4f7d68b825";
+
+const nsIID NS_IDOCSHELLTREEITEM_IID= 
+  {0x7d935d63, 0x6d2a, 0x4600, 
+    [ 0xaf, 0xb5, 0x9a, 0x4f, 0x7d, 0x68, 0xb8, 0x25 ]};
+
+interface nsIDocShellTreeItem : nsISupports {
+
+  static const char[] IID_STR = NS_IDOCSHELLTREEITEM_IID_STR;
+  static const nsIID IID = NS_IDOCSHELLTREEITEM_IID;
+
+extern(System):
+  nsresult GetName(PRUnichar * *aName);
+  nsresult SetName(PRUnichar * aName);
+  nsresult NameEquals(PRUnichar *name, PRBool *_retval);
+
+  enum { typeChrome = 0 };
+  enum { typeContent = 1 };
+  enum { typeContentWrapper = 2 };
+  enum { typeChromeWrapper = 3 };
+  enum { typeAll = 2147483647 };
+
+  nsresult GetItemType(PRInt32 *aItemType);
+  nsresult SetItemType(PRInt32 aItemType);
+  nsresult GetParent(nsIDocShellTreeItem  *aParent);
+  nsresult GetSameTypeParent(nsIDocShellTreeItem  *aSameTypeParent);
+  nsresult GetRootTreeItem(nsIDocShellTreeItem  *aRootTreeItem);
+  nsresult GetSameTypeRootTreeItem(nsIDocShellTreeItem  *aSameTypeRootTreeItem);
+  nsresult FindItemWithName(PRUnichar *name, nsISupports aRequestor, nsIDocShellTreeItem aOriginalRequestor, nsIDocShellTreeItem *_retval);
+  nsresult GetTreeOwner(nsIDocShellTreeOwner  *aTreeOwner);
+  nsresult SetTreeOwner(nsIDocShellTreeOwner treeOwner);
+  nsresult GetChildOffset(PRInt32 *aChildOffset);
+  nsresult SetChildOffset(PRInt32 aChildOffset);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocShellTreeOwner.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,55 @@
+module org.eclipse.swt.internal.mozilla.nsIDocShellTreeOwner;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDocShellTreeItem;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDOCSHELLTREEOWNER_IID_STR = "9e508466-5ebb-4618-abfa-9ad47bed0b2e";
+
+const nsIID NS_IDOCSHELLTREEOWNER_IID= 
+  {0x9e508466, 0x5ebb, 0x4618, 
+    [ 0xab, 0xfa, 0x9a, 0xd4, 0x7b, 0xed, 0x0b, 0x2e ]};
+
+interface nsIDocShellTreeOwner : nsISupports {
+
+  static const char[] IID_STR = NS_IDOCSHELLTREEOWNER_IID_STR;
+  static const nsIID IID = NS_IDOCSHELLTREEOWNER_IID;
+
+extern(System):
+  nsresult FindItemWithName(PRUnichar *name, nsIDocShellTreeItem aRequestor, nsIDocShellTreeItem aOriginalRequestor, nsIDocShellTreeItem *_retval);
+  nsresult ContentShellAdded(nsIDocShellTreeItem aContentShell, PRBool aPrimary, PRUnichar *aID);
+  nsresult GetPrimaryContentShell(nsIDocShellTreeItem  *aPrimaryContentShell);
+  nsresult SizeShellTo(nsIDocShellTreeItem shell, PRInt32 cx, PRInt32 cy);
+  nsresult SetPersistence(PRBool aPersistPosition, PRBool aPersistSize, PRBool aPersistSizeMode);
+  nsresult GetPersistence(PRBool *aPersistPosition, PRBool *aPersistSize, PRBool *aPersistSizeMode);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IDOCSHELLTREEOWNER_MOZILLA_1_8_BRANCH_IID_STR = "3c2a6927-e923-4ea8-bbda-a335c768ce4e";
+
+const nsIID NS_IDOCSHELLTREEOWNER_MOZILLA_1_8_BRANCH_IID= 
+  {0x3c2a6927, 0xe923, 0x4ea8, 
+    [ 0xbb, 0xda, 0xa3, 0x35, 0xc7, 0x68, 0xce, 0x4e ]};
+
+interface nsIDocShellTreeOwner_MOZILLA_1_8_BRANCH : nsIDocShellTreeOwner {
+
+  static const char[] IID_STR = NS_IDOCSHELLTREEOWNER_MOZILLA_1_8_BRANCH_IID_STR;
+  static const nsIID IID = NS_IDOCSHELLTREEOWNER_MOZILLA_1_8_BRANCH_IID;
+
+extern(System):
+  nsresult ContentShellAdded2(nsIDocShellTreeItem aContentShell, PRBool aPrimary, PRBool aTargetable, nsAString * aID);
+  nsresult ContentShellRemoved(nsIDocShellTreeItem aContentShell);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDocumentCharsetInfo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsIDocumentCharsetInfo;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIAtom;
+
+const char[] NS_IDOCUMENTCHARSETINFO_IID_STR = "2d40b291-01e1-11d4-9d0e-0050040007b2";
+
+const nsIID NS_IDOCUMENTCHARSETINFO_IID= 
+  {0x2d40b291, 0x01e1, 0x11d4, 
+    [ 0x9d, 0x0e, 0x00, 0x50, 0x04, 0x00, 0x07, 0xb2 ]};
+
+interface nsIDocumentCharsetInfo : nsISupports {
+
+  static const char[] IID_STR = NS_IDOCUMENTCHARSETINFO_IID_STR;
+  static const nsIID IID = NS_IDOCUMENTCHARSETINFO_IID;
+
+extern(System):
+  nsresult GetForcedCharset(nsIAtom  *aForcedCharset);
+  nsresult SetForcedCharset(nsIAtom  aForcedCharset);
+  nsresult GetForcedDetector(PRBool *aForcedDetector);
+  nsresult SetForcedDetector(PRBool aForcedDetector);
+  nsresult GetParentCharset(nsIAtom  *aParentCharset);
+  nsresult SetParentCharset(nsIAtom  aParentCharset);
+  nsresult GetParentCharsetSource(PRInt32 *aParentCharsetSource);
+  nsresult SetParentCharsetSource(PRInt32 aParentCharsetSource);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDownload.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,41 @@
+module org.eclipse.swt.internal.mozilla.nsIDownload;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsITransfer;
+import org.eclipse.swt.internal.mozilla.nsIWebProgressListener;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsIObserver; 
+import org.eclipse.swt.internal.mozilla.nsICancelable;
+import org.eclipse.swt.internal.mozilla.nsIMIMEInfo; 
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+import org.eclipse.swt.internal.mozilla.prtime;
+
+const char[] NS_IDOWNLOAD_IID_STR = "9e1fd9f2-9727-4926-85cd-f16c375bba6d";
+
+const nsIID NS_IDOWNLOAD_IID= 
+  {0x9e1fd9f2, 0x9727, 0x4926, 
+    [ 0x85, 0xcd, 0xf1, 0x6c, 0x37, 0x5b, 0xba, 0x6d ]};
+
+interface nsIDownload : nsISupports {
+
+  static const char[] IID_STR = NS_IDOWNLOAD_IID_STR;
+  static const nsIID IID = NS_IDOWNLOAD_IID;
+
+extern(System):
+  nsresult Init(nsIURI aSource, nsIURI aTarget, nsAString* aDisplayName, nsIMIMEInfo aMIMEInfo, PRTime startTime, PRBool aPersist);
+  nsresult GetSource(nsIURI  *aSource);
+  nsresult GetTarget(nsIURI  *aTarget);
+  nsresult GetPersist(PRBool *aPersist);
+  nsresult GetPercentComplete(PRInt32 *aPercentComplete);
+  nsresult GetDisplayName(PRUnichar * *aDisplayName);
+  nsresult SetDisplayName(PRUnichar* aDisplayName);
+  nsresult GetStartTime(PRInt64 *aStartTime);
+  nsresult GetMIMEInfo(nsIMIMEInfo  *aMIMEInfo);
+  nsresult GetListener(nsIWebProgressListener* aListener);
+  nsresult SetListener(nsIWebProgressListener aListener);
+  nsresult GetObserver(nsIObserver * aObserver);
+  nsresult SetObserver(nsIObserver aObserver);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIDownload_1_8.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+module org.eclipse.swt.internal.mozilla.nsIDownload_1_8;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsITransfer;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsIObserver; 
+import org.eclipse.swt.internal.mozilla.nsICancelable;
+import org.eclipse.swt.internal.mozilla.nsIMIMEInfo; 
+
+const char[] NS_IDOWNLOAD_IID_STR = "9e1fd9f2-9727-4926-85cd-f16c375bba6d";
+
+const nsIID NS_IDOWNLOAD_IID= 
+  {0x9e1fd9f2, 0x9727, 0x4926, 
+    [ 0x85, 0xcd, 0xf1, 0x6c, 0x37, 0x5b, 0xba, 0x6d ]};
+
+interface nsIDownload_1_8 : nsITransfer {
+
+  static const char[] IID_STR = NS_IDOWNLOAD_IID_STR;
+  static const nsIID IID = NS_IDOWNLOAD_IID;
+
+extern(System):
+  nsresult GetTargetFile(nsILocalFile  *aTargetFile);
+  nsresult GetPercentComplete(PRInt32 *aPercentComplete);
+  nsresult GetAmountTransferred(PRUint64 *aAmountTransferred);
+  nsresult GetSize(PRUint64 *aSize);
+  nsresult GetSource(nsIURI  *aSource);
+  nsresult GetTarget(nsIURI  *aTarget);
+  nsresult GetCancelable(nsICancelable  *aCancelable);
+  nsresult GetDisplayName(PRUnichar * *aDisplayName);
+  nsresult GetStartTime(PRInt64 *aStartTime);
+  nsresult GetMIMEInfo(nsIMIMEInfo  *aMIMEInfo);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,33 @@
+module org.eclipse.swt.internal.mozilla.nsIEmbeddingSiteWindow;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IEMBEDDINGSITEWINDOW_IID_STR = "3e5432cd-9568-4bd1-8cbe-d50aba110743";
+
+const nsIID NS_IEMBEDDINGSITEWINDOW_IID= 
+  {0x3e5432cd, 0x9568, 0x4bd1, 
+    [ 0x8c, 0xbe, 0xd5, 0x0a, 0xba, 0x11, 0x07, 0x43 ]};
+
+interface nsIEmbeddingSiteWindow : nsISupports {
+
+  static const char[] IID_STR = NS_IEMBEDDINGSITEWINDOW_IID_STR;
+  static const nsIID IID = NS_IEMBEDDINGSITEWINDOW_IID;
+
+  enum { DIM_FLAGS_POSITION = 1U };
+  enum { DIM_FLAGS_SIZE_INNER = 2U };
+  enum { DIM_FLAGS_SIZE_OUTER = 4U };
+
+extern(System):
+  nsresult SetDimensions(PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy);
+  nsresult GetDimensions(PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy);
+  nsresult SetFocus();
+  nsresult GetVisibility(PRBool *aVisibility);
+  nsresult SetVisibility(PRBool aVisibility);
+  nsresult GetTitle(PRUnichar * *aTitle);
+  nsresult SetTitle(PRUnichar * aTitle);
+  nsresult GetSiteWindow(void * *aSiteWindow);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEmbeddingSiteWindow2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+module org.eclipse.swt.internal.mozilla.nsIEmbeddingSiteWindow2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIEmbeddingSiteWindow;
+
+const char[] NS_IEMBEDDINGSITEWINDOW2_IID_STR = "e932bf55-0a64-4beb-923a-1f32d3661044";
+
+const nsIID NS_IEMBEDDINGSITEWINDOW2_IID= 
+  {0xe932bf55, 0x0a64, 0x4beb, 
+    [ 0x92, 0x3a, 0x1f, 0x32, 0xd3, 0x66, 0x10, 0x44 ]};
+
+interface nsIEmbeddingSiteWindow2 : nsIEmbeddingSiteWindow {
+
+  static const char[] IID_STR = NS_IEMBEDDINGSITEWINDOW2_IID_STR;
+  static const nsIID IID = NS_IEMBEDDINGSITEWINDOW2_IID;
+
+extern(System):
+  nsresult Blur();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEnumerator.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+module org.eclipse.swt.internal.mozilla.nsIEnumerator;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IENUMERATOR_IID_STR = "ad385286-cbc4-11d2-8cca-0060b0fc14a3";
+
+const nsIID NS_IENUMERATOR_IID= 
+  {0xad385286, 0xcbc4, 0x11d2, 
+    [ 0x8c, 0xca, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 ]};
+
+interface nsIEnumerator : nsISupports {
+
+  static const char[] IID_STR = NS_IENUMERATOR_IID_STR;
+  static const nsIID IID = NS_IENUMERATOR_IID;
+
+extern(System):
+  nsresult First();
+  nsresult Next();
+  nsresult CurrentItem(nsISupports *_retval);
+  nsresult IsDone();
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IBIDIRECTIONALENUMERATOR_IID_STR = "75f158a0-cadd-11d2-8cca-0060b0fc14a3";
+
+const nsIID NS_IBIDIRECTIONALENUMERATOR_IID= 
+  {0x75f158a0, 0xcadd, 0x11d2, 
+    [ 0x8c, 0xca, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 ]};
+
+interface nsIBidirectionalEnumerator : nsIEnumerator {
+
+  static const char[] IID_STR = NS_IBIDIRECTIONALENUMERATOR_IID_STR;
+  static const nsIID IID = NS_IBIDIRECTIONALENUMERATOR_IID;
+
+extern(System):
+  nsresult Last();
+  nsresult Prev();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEventQueue.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,38 @@
+module org.eclipse.swt.internal.mozilla.nsIEventQueue;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIEventTarget;
+
+const char[] NS_IEVENTQUEUE_IID_STR = "176afb41-00a4-11d3-9f2a-00400553eef0";
+const nsIID NS_IEVENTQUEUE_IID= 
+  {0x176afb41, 0x00a4, 0x11d3, 
+    [ 0x9f, 0x2a, 0x00, 0x40, 0x05, 0x53, 0xee, 0xf0 ]};
+
+interface nsIEventQueue : nsIEventTarget {
+  static const char[] IID_STR = NS_IEVENTQUEUE_IID_STR;
+  static const nsIID IID = NS_IEVENTQUEUE_IID;
+
+extern(System):
+  nsresult InitEvent(PLEvent * aEvent, void * owner, PLHandleEventProc handler, PLDestroyEventProc destructor);
+  nsresult PostSynchronousEvent(PLEvent * aEvent, void * *aResult);
+  nsresult PendingEvents(PRBool *_retval);
+  nsresult ProcessPendingEvents();
+  nsresult EventLoop();
+  nsresult EventAvailable(PRBool * aResult);
+  nsresult GetEvent(PLEvent * *_retval);
+  nsresult HandleEvent(PLEvent * aEvent);
+  nsresult WaitForEvent(PLEvent * *_retval);
+  PRInt32  GetEventQueueSelectFD();
+  nsresult Init(PRBool aNative);
+  nsresult InitFromPRThread(PRThread * thread, PRBool aNative);
+  nsresult InitFromPLQueue(PLEventQueue * aQueue);
+  nsresult EnterMonitor();
+  nsresult ExitMonitor();
+  nsresult RevokeEvents(void * owner);
+  nsresult GetPLEventQueue(PLEventQueue * *_retval);
+  nsresult IsQueueNative(PRBool *_retval);
+  nsresult StopAcceptingEvents();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIEventTarget.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+module org.eclipse.swt.internal.mozilla.nsIEventTarget;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+const char[] NS_IEVENTTARGET_IID_STR = "ea99ad5b-cc67-4efb-97c9-2ef620a59f2a";
+
+const nsIID NS_IEVENTTARGET_IID= 
+  {0xea99ad5b, 0xcc67, 0x4efb, 
+    [ 0x97, 0xc9, 0x2e, 0xf6, 0x20, 0xa5, 0x9f, 0x2a ]};
+
+interface nsIEventTarget : nsISupports {
+
+  static const char[] IID_STR = NS_IEVENTTARGET_IID_STR;
+  static const nsIID IID = NS_IEVENTTARGET_IID;
+
+extern(System):
+  nsresult PostEvent(PLEvent * aEvent);
+  nsresult IsOnCurrentThread(PRBool *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFactory.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+
+module org.eclipse.swt.internal.mozilla.nsIFactory;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IFACTORY_IID_STR = "00000001-0000-0000-c000-000000000046";
+
+const nsIID NS_IFACTORY_IID= 
+  {0x00000001, 0x0000, 0x0000, 
+    [ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 ]};
+
+interface nsIFactory : nsISupports {
+
+  static const char[] IID_STR = NS_IFACTORY_IID_STR;
+  static const nsIID IID = NS_IFACTORY_IID;
+
+extern(System):
+  nsresult CreateInstance(nsISupports aOuter, nsIID * iid, void * *result);
+  nsresult LockFactory(PRBool lock);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFile.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,69 @@
+module org.eclipse.swt.internal.mozilla.nsIFile;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IFILE_IID_STR = "c8c0a080-0868-11d3-915f-d9d889d48e3c";
+
+const nsIID NS_IFILE_IID= 
+  {0xc8c0a080, 0x0868, 0x11d3, 
+    [ 0x91, 0x5f, 0xd9, 0xd8, 0x89, 0xd4, 0x8e, 0x3c ]};
+
+interface nsIFile : nsISupports {
+  static const char[] IID_STR = NS_IFILE_IID_STR;
+  static const nsIID IID = NS_IFILE_IID;
+
+  enum { NORMAL_FILE_TYPE = 0U };
+  enum { DIRECTORY_TYPE = 1U };
+
+extern(System):
+  nsresult Append(nsAString * node);
+  nsresult AppendNative(nsACString * node);
+  nsresult Normalize();
+  nsresult Create(PRUint32 type, PRUint32 permissions);
+  nsresult GetLeafName(nsAString * aLeafName);
+  nsresult SetLeafName(nsAString * aLeafName);
+  nsresult GetNativeLeafName(nsACString * aNativeLeafName);
+  nsresult SetNativeLeafName(nsACString * aNativeLeafName);
+  nsresult CopyTo(nsIFile newParentDir, nsAString * newName);
+  nsresult CopyToNative(nsIFile newParentDir, nsACString * newName);
+  nsresult CopyToFollowingLinks(nsIFile newParentDir, nsAString * newName);
+  nsresult CopyToFollowingLinksNative(nsIFile newParentDir, nsACString * newName);
+  nsresult MoveTo(nsIFile newParentDir, nsAString * newName);
+  nsresult MoveToNative(nsIFile newParentDir, nsACString * newName);
+  nsresult Remove(PRBool recursive);
+  nsresult GetPermissions(PRUint32 *aPermissions);
+  nsresult SetPermissions(PRUint32 aPermissions);
+  nsresult GetPermissionsOfLink(PRUint32 *aPermissionsOfLink);
+  nsresult SetPermissionsOfLink(PRUint32 aPermissionsOfLink);
+  nsresult GetLastModifiedTime(PRInt64 *aLastModifiedTime);
+  nsresult SetLastModifiedTime(PRInt64 aLastModifiedTime);
+  nsresult GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink);
+  nsresult SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink);
+  nsresult GetFileSize(PRInt64 *aFileSize);
+  nsresult SetFileSize(PRInt64 aFileSize);
+  nsresult GetFileSizeOfLink(PRInt64 *aFileSizeOfLink);
+  nsresult GetTarget(nsAString * aTarget);
+  nsresult GetNativeTarget(nsACString * aNativeTarget);
+  nsresult GetPath(nsAString * aPath);
+  nsresult GetNativePath(nsACString * aNativePath);
+  nsresult Exists(PRBool *_retval);
+  nsresult IsWritable(PRBool *_retval);
+  nsresult IsReadable(PRBool *_retval);
+  nsresult IsExecutable(PRBool *_retval);
+  nsresult IsHidden(PRBool *_retval);
+  nsresult IsDirectory(PRBool *_retval);
+  nsresult IsFile(PRBool *_retval);
+  nsresult IsSymlink(PRBool *_retval);
+  nsresult IsSpecial(PRBool *_retval);
+  nsresult CreateUnique(PRUint32 type, PRUint32 permissions);
+  nsresult Clone(nsIFile *_retval);
+  nsresult Equals(nsIFile inFile, PRBool *_retval);
+  nsresult Contains(nsIFile inFile, PRBool recur, PRBool *_retval);
+  nsresult GetParent(nsIFile  *aParent);
+  nsresult GetDirectoryEntries(nsISimpleEnumerator  *aDirectoryEntries);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFilePicker.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,56 @@
+module org.eclipse.swt.internal.mozilla.nsIFilePicker;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsIFileURL; 
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IFILEPICKER_IID_STR = "c47de916-1dd1-11b2-8141-82507fa02b21";
+
+const nsIID NS_IFILEPICKER_IID= 
+  {0xc47de916, 0x1dd1, 0x11b2, 
+    [ 0x81, 0x41, 0x82, 0x50, 0x7f, 0xa0, 0x2b, 0x21 ]};
+
+interface nsIFilePicker : nsISupports {
+
+  static const char[] IID_STR = NS_IFILEPICKER_IID_STR;
+  static const nsIID IID = NS_IFILEPICKER_IID;
+
+  enum { modeOpen = 0 };
+  enum { modeSave = 1 };
+  enum { modeGetFolder = 2 };
+  enum { modeOpenMultiple = 3 };
+  enum { returnOK = 0 };
+  enum { returnCancel = 1 };
+  enum { returnReplace = 2 };
+  enum { filterAll = 1 };
+  enum { filterHTML = 2 };
+  enum { filterText = 4 };
+  enum { filterImages = 8 };
+  enum { filterXML = 16 };
+  enum { filterXUL = 32 };
+  enum { filterApps = 64 };
+
+extern(System):
+  nsresult Init(nsIDOMWindow parent, nsAString * title, PRInt16 mode);
+  nsresult AppendFilters(PRInt32 filterMask);
+  nsresult AppendFilter(nsAString * title, nsAString * filter);
+  nsresult GetDefaultString(nsAString * aDefaultString);
+  nsresult SetDefaultString(nsAString * aDefaultString);
+  nsresult GetDefaultExtension(nsAString * aDefaultExtension);
+  nsresult SetDefaultExtension(nsAString * aDefaultExtension);
+  nsresult GetFilterIndex(PRInt32 *aFilterIndex);
+  nsresult SetFilterIndex(PRInt32 aFilterIndex);
+  nsresult GetDisplayDirectory(nsILocalFile  *aDisplayDirectory);
+  nsresult SetDisplayDirectory(nsILocalFile  aDisplayDirectory);
+  nsresult GetFile(nsILocalFile  *aFile);
+  nsresult GetFileURL(nsIFileURL  *aFileURL);
+  nsresult GetFiles(nsISimpleEnumerator  *aFiles);
+  nsresult Show(PRInt16 *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFilePicker_1_8.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,56 @@
+module org.eclipse.swt.internal.mozilla.nsIFilePicker_1_8;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsIFileURL; 
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IFILEPICKER_IID_STR = "80faf095-c807-4558-a2cc-185ed70754ea";
+
+const nsIID NS_IFILEPICKER_IID= 
+  {0x80faf095, 0xc807, 0x4558, 
+    [ 0xa2, 0xcc, 0x18, 0x5e, 0xd7, 0x07, 0x54, 0xea ]};
+
+//extern(System)
+interface nsIFilePicker_1_8 : nsISupports {
+
+  static const char[] IID_STR = NS_IFILEPICKER_IID_STR;
+  static const nsIID IID = NS_IFILEPICKER_IID;
+
+  enum { modeOpen = 0 };
+  enum { modeSave = 1 };
+  enum { modeGetFolder = 2 };
+  enum { modeOpenMultiple = 3 };
+  enum { returnOK = 0 };
+  enum { returnCancel = 1 };
+  enum { returnReplace = 2 };
+  enum { filterAll = 1 };
+  enum { filterHTML = 2 };
+  enum { filterText = 4 };
+  enum { filterImages = 8 };
+  enum { filterXML = 16 };
+  enum { filterXUL = 32 };
+  enum { filterApps = 64 };
+
+extern(System):
+  nsresult Init(nsIDOMWindow parent, nsAString * title, PRInt16 mode);
+  nsresult AppendFilters(PRInt32 filterMask);
+  nsresult AppendFilter(nsAString * title, nsAString * filter);
+  nsresult GetDefaultString(nsAString * aDefaultString);
+  nsresult SetDefaultString(nsAString * aDefaultString);
+  nsresult GetDefaultExtension(nsAString * aDefaultExtension);
+  nsresult SetDefaultExtension(nsAString * aDefaultExtension);
+  nsresult GetFilterIndex(PRInt32 *aFilterIndex);
+  nsresult SetFilterIndex(PRInt32 aFilterIndex);
+  nsresult GetDisplayDirectory(nsILocalFile  *aDisplayDirectory);
+  nsresult SetDisplayDirectory(nsILocalFile  aDisplayDirectory);
+  nsresult GetFile(nsILocalFile  *aFile);
+  nsresult GetFileURL(nsIFileURL  *aFileURL);
+  nsresult GetFiles(nsISimpleEnumerator  *aFiles);
+  nsresult Show(PRInt16 *_retval);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIFileURL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIFileURL;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIURL;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+
+const char[] NS_IFILEURL_IID_STR = "d26b2e2e-1dd1-11b2-88f3-8545a7ba7949";
+
+const nsIID NS_IFILEURL_IID= 
+  {0xd26b2e2e, 0x1dd1, 0x11b2, 
+    [ 0x88, 0xf3, 0x85, 0x45, 0xa7, 0xba, 0x79, 0x49 ]};
+
+interface nsIFileURL : nsIURL {
+
+  static const char[] IID_STR = NS_IFILEURL_IID_STR;
+  static const nsIID IID = NS_IFILEURL_IID;
+
+extern(System):
+  nsresult GetFile(nsIFile  *aFile);
+  nsresult SetFile(nsIFile  aFile);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+module org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher;
+
+private import org.eclipse.swt.internal.mozilla.Common;
+private import org.eclipse.swt.internal.mozilla.nsID;
+private import org.eclipse.swt.internal.mozilla.nsISupports;
+private import org.eclipse.swt.internal.mozilla.nsIURI;
+private import org.eclipse.swt.internal.mozilla.nsIMIMEInfo;
+private import org.eclipse.swt.internal.mozilla.nsIFile;
+private import org.eclipse.swt.internal.mozilla.nsIWebProgressListener;
+private import org.eclipse.swt.internal.mozilla.nsStringAPI;
+private import org.eclipse.swt.internal.mozilla.prtime;
+
+const char[] NS_IHELPERAPPLAUNCHER_IID_STR = "9503d0fe-4c9d-11d4-98d0-001083010e9b";
+
+const nsIID NS_IHELPERAPPLAUNCHER_IID= 
+  {0x9503d0fe, 0x4c9d, 0x11d4, 
+    [ 0x98, 0xd0, 0x00, 0x10, 0x83, 0x01, 0x0e, 0x9b ]};
+
+interface nsIHelperAppLauncher : nsISupports {
+
+  static const char[] IID_STR = NS_IHELPERAPPLAUNCHER_IID_STR;
+  static const nsIID IID = NS_IHELPERAPPLAUNCHER_IID;
+
+extern(System):
+  nsresult GetMIMEInfo(nsIMIMEInfo  *aMIMEInfo);
+  nsresult GetSource(nsIURI  *aSource);
+  nsresult GetSuggestedFileName(nsAString * aSuggestedFileName);
+  nsresult SaveToDisk(nsIFile aNewFileLocation, PRBool aRememberThisPreference);
+  nsresult LaunchWithApplication(nsIFile aApplication, PRBool aRememberThisPreference);
+  nsresult Cancel();
+  nsresult SetWebProgressListener(nsIWebProgressListener aWebProgressListener);
+  nsresult CloseProgressWindow();
+  nsresult GetDownloadInfo( nsIURI* aSourceUrl, PRTime* aTimeDownloadStarted, nsIFile* result);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIHelperAppLauncherDialog;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+
+const char[] NS_IHELPERAPPLAUNCHERDIALOG_IID_STR = "d7ebddf0-4c84-11d4-807a-00600811a9c3";
+
+const nsIID NS_IHELPERAPPLAUNCHERDIALOG_IID= 
+  { 0xd7ebddf0, 0x4c84, 0x11d4, [ 0x80,0x7a,0x00,0x60,0x08,0x11,0xa9,0xc3 ]};
+
+interface nsIHelperAppLauncherDialog : nsISupports {
+
+  static const char[] IID_STR = NS_IHELPERAPPLAUNCHERDIALOG_IID_STR;
+  static const nsIID IID = NS_IHELPERAPPLAUNCHERDIALOG_IID;
+
+  enum { REASON_CANTHANDLE = 0U };
+  enum { REASON_SERVERREQUEST = 1U };
+  enum { REASON_TYPESNIFFED = 2U };
+
+extern(System):
+  nsresult Show(nsIHelperAppLauncher aLauncher, nsISupports aContext, PRUint32 aReason);
+  nsresult PromptForSaveToFile(nsIHelperAppLauncher aLauncher, nsISupports aWindowContext, PRUnichar *aDefaultFile, PRUnichar *aSuggestedFileExtension, nsILocalFile *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncherDialog_1_9.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,28 @@
+module org.eclipse.swt.internal.mozilla.nsIHelperAppLauncherDialog_1_9;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher_1_9;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+
+const char[] NS_IHELPERAPPLAUNCHERDIALOG_1_9_IID_STR = "f3704fdc-8ae6-4eba-a3c3-f02958ac0649";
+
+const nsIID NS_IHELPERAPPLAUNCHERDIALOG_1_9_IID= 
+  { 0xf3704fdc, 0x8ae6, 0x4eba, [ 0xa3,0xc3,0xf0,0x29,0x58,0xac,0x06,0x49 ]};
+  
+interface nsIHelperAppLauncherDialog_1_9 : nsISupports {
+
+  static const char[] IID_STR = NS_IHELPERAPPLAUNCHERDIALOG_1_9_IID_STR;
+  static const nsIID IID = NS_IHELPERAPPLAUNCHERDIALOG_1_9_IID;
+
+  enum { REASON_CANTHANDLE = 0U };
+  enum { REASON_SERVERREQUEST = 1U };
+  enum { REASON_TYPESNIFFED = 2U };
+
+extern(System):
+  nsresult Show(nsIHelperAppLauncher_1_9 aLauncher, nsISupports aContext, PRUint32 aReason);
+  nsresult PromptForSaveToFile(nsIHelperAppLauncher_1_9 aLauncher, nsISupports aWindowContext, PRUnichar *aDefaultFile, PRUnichar *aSuggestedFileExtension, PRBool aForcePrompt, nsILocalFile *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_8.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+module org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher_1_8;
+
+private import org.eclipse.swt.internal.mozilla.Common;
+private import org.eclipse.swt.internal.mozilla.nsID;
+private import org.eclipse.swt.internal.mozilla.nsICancelable;
+private import org.eclipse.swt.internal.mozilla.nsIURI;
+private import org.eclipse.swt.internal.mozilla.nsIMIMEInfo;
+private import org.eclipse.swt.internal.mozilla.nsIFile;
+private import org.eclipse.swt.internal.mozilla.nsIWebProgressListener2;
+private import org.eclipse.swt.internal.mozilla.nsStringAPI;
+private import org.eclipse.swt.internal.mozilla.prtime;
+
+const char[] NS_IHELPERAPPLAUNCHER_1_8_IID_STR = "99a0882d-2ff9-4659-9952-9ac531ba5592";
+
+const nsIID NS_IHELPERAPPLAUNCHER_1_8_IID= 
+  {0x99a0882d, 0x2ff9, 0x4659, 
+    [ 0x99, 0x52, 0x9a, 0xc5, 0x31, 0xba, 0x55, 0x92 ]};
+
+interface nsIHelperAppLauncher_1_8 : nsICancelable {
+
+  static const char[] IID_STR = NS_IHELPERAPPLAUNCHER_1_8_IID_STR;
+  static const nsIID IID = NS_IHELPERAPPLAUNCHER_1_8_IID;
+
+extern(System):
+  nsresult GetMIMEInfo(nsIMIMEInfo  *aMIMEInfo);
+  nsresult GetSource(nsIURI  *aSource);
+  nsresult GetSuggestedFileName(nsAString * aSuggestedFileName);
+  nsresult SaveToDisk(nsIFile aNewFileLocation, PRBool aRememberThisPreference);
+  nsresult LaunchWithApplication(nsIFile aApplication, PRBool aRememberThisPreference);
+  nsresult SetWebProgressListener(nsIWebProgressListener2 aWebProgressListener);
+  nsresult CloseProgressWindow();
+  nsresult GetTargetFile(nsIFile  *aTargetFile);
+  nsresult GetTimeDownloadStarted(PRTime *aTimeDownloadStarted);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHelperAppLauncher_1_9.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,35 @@
+module org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher_1_9;
+
+private import org.eclipse.swt.internal.mozilla.Common;
+private import org.eclipse.swt.internal.mozilla.nsID;
+private import org.eclipse.swt.internal.mozilla.nsICancelable;
+private import org.eclipse.swt.internal.mozilla.nsIURI;
+private import org.eclipse.swt.internal.mozilla.nsIMIMEInfo;
+private import org.eclipse.swt.internal.mozilla.nsIFile;
+private import org.eclipse.swt.internal.mozilla.nsIWebProgressListener2;
+private import org.eclipse.swt.internal.mozilla.nsStringAPI;
+private import org.eclipse.swt.internal.mozilla.prtime;
+
+const char[] NS_IHELPERAPPLAUNCHER_1_9_IID_STR = "cc75c21a-0a79-4f68-90e1-563253d0c555";
+
+const nsIID NS_IHELPERAPPLAUNCHER_1_9_IID= 
+  {0xcc75c21a, 0x0a79, 0x4f68, 
+    [ 0x90, 0xe1, 0x56, 0x32, 0x53, 0xd0, 0xc5, 0x55 ]};
+
+interface nsIHelperAppLauncher_1_9 : nsICancelable {
+
+  static const char[] IID_STR = NS_IHELPERAPPLAUNCHER_1_9_IID_STR;
+  static const nsIID IID = NS_IHELPERAPPLAUNCHER_1_9_IID;
+
+extern(System):
+  nsresult GetMIMEInfo(nsIMIMEInfo  *aMIMEInfo);
+  nsresult GetSource(nsIURI *aSource);
+  nsresult GetSuggestedFileName(nsAString * aSuggestedFileName);
+  nsresult SaveToDisk(nsIFile aNewFileLocation, PRBool aRememberThisPreference);
+  nsresult LaunchWithApplication(nsIFile aApplication, PRBool aRememberThisPreference);
+  nsresult SetWebProgressListener(nsIWebProgressListener2 aWebProgressListener);
+  nsresult CloseProgressWindow();
+  nsresult GetTargetFile(nsIFile *aTargetFile);
+  nsresult GetTargetFileIsExecutable(PRBool* aTargetFileIsExecutable);
+  nsresult GetTimeDownloadStarted(PRTime *aTimeDownloadStarted);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIHistoryEntry.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIHistoryEntry;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIURI;
+
+const char[] NS_IHISTORYENTRY_IID_STR = "a41661d4-1417-11d5-9882-00c04fa02f40";
+
+const nsIID NS_IHISTORYENTRY_IID= 
+  {0xa41661d4, 0x1417, 0x11d5, 
+    [ 0x98, 0x82, 0x00, 0xc0, 0x4f, 0xa0, 0x2f, 0x40 ]};
+
+interface nsIHistoryEntry : nsISupports {
+
+  static const char[] IID_STR = NS_IHISTORYENTRY_IID_STR;
+  static const nsIID IID = NS_IHISTORYENTRY_IID;
+
+extern(System):
+  nsresult GetURI(nsIURI  *aURI);
+  nsresult GetTitle(PRUnichar * *aTitle);
+  nsresult GetIsSubFrame(PRBool *aIsSubFrame);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIIOService.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIIOService;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIProtocolHandler;
+import org.eclipse.swt.internal.mozilla.nsIChannel; 
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsIFile; 
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IIOSERVICE_IID_STR = "bddeda3f-9020-4d12-8c70-984ee9f7935e";
+
+const nsIID NS_IIOSERVICE_IID= 
+  {0xbddeda3f, 0x9020, 0x4d12, 
+    [ 0x8c, 0x70, 0x98, 0x4e, 0xe9, 0xf7, 0x93, 0x5e ]};
+
+interface nsIIOService : nsISupports {
+
+  static const char[] IID_STR = NS_IIOSERVICE_IID_STR;
+  static const nsIID IID = NS_IIOSERVICE_IID;
+
+extern(System):
+  nsresult GetProtocolHandler(char *aScheme, nsIProtocolHandler *_retval);
+  nsresult GetProtocolFlags(char *aScheme, PRUint32 *_retval);
+  nsresult NewURI(nsACString * aSpec, char *aOriginCharset, nsIURI aBaseURI, nsIURI *_retval);
+  nsresult NewFileURI(nsIFile aFile, nsIURI *_retval);
+  nsresult NewChannelFromURI(nsIURI aURI, nsIChannel *_retval);
+  nsresult NewChannel(nsACString * aSpec, char *aOriginCharset, nsIURI aBaseURI, nsIChannel *_retval);
+  nsresult GetOffline(PRBool *aOffline);
+  nsresult SetOffline(PRBool aOffline);
+  nsresult AllowPort(PRInt32 aPort, char *aScheme, PRBool *_retval);
+  nsresult ExtractScheme(nsACString * urlString, nsACString * _retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIIOService2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIIOService2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIIOService;
+
+const char[] NS_IIOSERVICE2_IID_STR = "d44fe6d4-ee35-4789-886a-eb8f0554d04e";
+
+const nsIID NS_IIOSERVICE2_IID= 
+  {0xd44fe6d4, 0xee35, 0x4789, 
+    [ 0x88, 0x6a, 0xeb, 0x8f, 0x05, 0x54, 0xd0, 0x4e ]};
+
+interface nsIIOService2 : nsIIOService {
+
+  static const char[] IID_STR = NS_IIOSERVICE2_IID_STR;
+  static const nsIID IID = NS_IIOSERVICE2_IID;
+
+extern(System):
+  nsresult GetManageOfflineStatus(PRBool *aManageOfflineStatus);
+  nsresult SetManageOfflineStatus(PRBool aManageOfflineStatus);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,33 @@
+module org.eclipse.swt.internal.mozilla.nsIInputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+typedef nsresult function(nsIInputStream aInStream,
+	void *aClosure,
+	byte *aFromSegment,
+	PRUint32 aToOffset,
+	PRUint32 aCount,
+	PRUint32 *aWriteCount) nsWriteSegmentFun;
+
+const char[] NS_IINPUTSTREAM_IID_STR = "fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a";
+
+const nsIID NS_IINPUTSTREAM_IID= 
+  {0xfa9c7f6c, 0x61b3, 0x11d4, 
+    [ 0x98, 0x77, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a ]};
+
+interface nsIInputStream : nsISupports {
+
+  static const char[] IID_STR = NS_IINPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IINPUTSTREAM_IID;
+
+extern(System):
+  nsresult Close();
+  nsresult Available(PRUint32 *_retval);
+  nsresult Read(byte * aBuf, PRUint32 aCount, PRUint32 *_retval);
+  nsresult ReadSegments(nsWriteSegmentFun aWriter, void * aClosure, PRUint32 aCount, PRUint32 *_retval);
+  nsresult IsNonBlocking(PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIInterfaceRequestor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+module org.eclipse.swt.internal.mozilla.nsIInterfaceRequestor;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IINTERFACEREQUESTOR_IID_STR = "033a1470-8b2a-11d3-af88-00a024ffc08c";
+
+const nsIID NS_IINTERFACEREQUESTOR_IID= 
+  {0x033a1470, 0x8b2a, 0x11d3, 
+    [ 0xaf, 0x88, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIInterfaceRequestor : nsISupports {
+
+  static const char[] IID_STR = NS_IINTERFACEREQUESTOR_IID_STR;
+  static const nsIID IID = NS_IINTERFACEREQUESTOR_IID;
+
+extern(System):
+  nsresult GetInterface(nsIID * uuid, void * *result);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIJSContextStack.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,72 @@
+module org.eclipse.swt.internal.mozilla.nsIJSContextStack;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IJSCONTEXTSTACK_IID_STR = "c67d8270-3189-11d3-9885-006008962422";
+
+const nsIID NS_IJSCONTEXTSTACK_IID= 
+  {0xc67d8270, 0x3189, 0x11d3, 
+    [ 0x98, 0x85, 0x00, 0x60, 0x08, 0x96, 0x24, 0x22 ]};
+
+interface nsIJSContextStack : nsISupports {
+
+  static const char[] IID_STR = NS_IJSCONTEXTSTACK_IID_STR;
+  static const nsIID IID = NS_IJSCONTEXTSTACK_IID;
+
+extern(System):
+  nsresult GetCount(PRInt32 *aCount);
+  nsresult Peek(JSContext * *_retval);
+  nsresult Pop(JSContext * *_retval);
+  nsresult Push(JSContext * cx);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IJSCONTEXTSTACKITERATOR_IID_STR = "c7e6b7aa-fc12-4ca7-b140-98c38b698961";
+
+const nsIID NS_IJSCONTEXTSTACKITERATOR_IID= 
+  {0xc7e6b7aa, 0xfc12, 0x4ca7, 
+    [ 0xb1, 0x40, 0x98, 0xc3, 0x8b, 0x69, 0x89, 0x61 ]};
+
+interface nsIJSContextStackIterator : nsISupports {
+
+  static const char[] IID_STR = NS_IJSCONTEXTSTACKITERATOR_IID_STR;
+  static const nsIID IID = NS_IJSCONTEXTSTACKITERATOR_IID;
+
+extern(System):
+  nsresult Reset(nsIJSContextStack stack);
+  nsresult Done(PRBool *_retval);
+  nsresult Prev(JSContext * *_retval);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ITHREADJSCONTEXTSTACK_IID_STR = "a1339ae0-05c1-11d4-8f92-0010a4e73d9a";
+
+const nsIID NS_ITHREADJSCONTEXTSTACK_IID= 
+  {0xa1339ae0, 0x05c1, 0x11d4, 
+    [ 0x8f, 0x92, 0x00, 0x10, 0xa4, 0xe7, 0x3d, 0x9a ]};
+
+interface nsIThreadJSContextStack : nsIJSContextStack {
+
+  static const char[] IID_STR = NS_ITHREADJSCONTEXTSTACK_IID_STR;
+  static const nsIID IID = NS_ITHREADJSCONTEXTSTACK_IID;
+
+extern(System):
+  nsresult GetSafeJSContext(JSContext * *aSafeJSContext);
+  nsresult SetSafeJSContext(JSContext * aSafeJSContext);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsILoadGroup.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsILoadGroup;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsIRequestObserver; 
+import org.eclipse.swt.internal.mozilla.nsIInterfaceRequestor;
+
+const char[] NS_ILOADGROUP_IID_STR = "3de0a31c-feaf-400f-9f1e-4ef71f8b20cc";
+
+const nsIID NS_ILOADGROUP_IID= 
+  {0x3de0a31c, 0xfeaf, 0x400f, 
+    [ 0x9f, 0x1e, 0x4e, 0xf7, 0x1f, 0x8b, 0x20, 0xcc ]};
+
+interface nsILoadGroup : nsIRequest {
+
+  static const char[] IID_STR = NS_ILOADGROUP_IID_STR;
+  static const nsIID IID = NS_ILOADGROUP_IID;
+
+extern(System):
+  nsresult GetGroupObserver(nsIRequestObserver  *aGroupObserver);
+  nsresult SetGroupObserver(nsIRequestObserver  aGroupObserver);
+  nsresult GetDefaultLoadRequest(nsIRequest  *aDefaultLoadRequest);
+  nsresult SetDefaultLoadRequest(nsIRequest  aDefaultLoadRequest);
+  nsresult AddRequest(nsIRequest aRequest, nsISupports aContext);
+  nsresult RemoveRequest(nsIRequest aRequest, nsISupports aContext, nsresult aStatus);
+  nsresult GetRequests(nsISimpleEnumerator  *aRequests);
+  nsresult GetActiveCount(PRUint32 *aActiveCount);
+  nsresult GetNotificationCallbacks(nsIInterfaceRequestor  *aNotificationCallbacks);
+  nsresult SetNotificationCallbacks(nsIInterfaceRequestor  aNotificationCallbacks);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsILocalFile.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+module org.eclipse.swt.internal.mozilla.nsILocalFile;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.prlink;
+import org.eclipse.swt.internal.mozilla.prio;
+import org.eclipse.swt.internal.mozilla.prtime;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+import tango.stdc.stdio : FILE;
+
+const char[] NS_ILOCALFILE_IID_STR = "aa610f20-a889-11d3-8c81-000064657374";
+
+const nsIID NS_ILOCALFILE_IID= 
+  {0xaa610f20, 0xa889, 0x11d3, 
+    [ 0x8c, 0x81, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74 ]};
+
+interface nsILocalFile : nsIFile {
+
+    static const char[] IID_STR = NS_ILOCALFILE_IID_STR;
+    static const nsIID IID = NS_ILOCALFILE_IID;
+
+extern(System):
+    nsresult InitWithPath(nsAString * filePath);
+    nsresult InitWithNativePath(nsACString * filePath);
+    nsresult InitWithFile(nsILocalFile aFile);
+    nsresult GetFollowLinks(PRBool *aFollowLinks);
+    nsresult SetFollowLinks(PRBool aFollowLinks);
+    nsresult OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc * *_retval);
+    nsresult OpenANSIFileDesc(char *mode, FILE * *_retval);
+    nsresult Load(PRLibrary * *_retval);
+    nsresult GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable);
+    nsresult AppendRelativePath(nsAString * relativeFilePath);
+    nsresult AppendRelativeNativePath(nsACString * relativeFilePath);
+    nsresult GetPersistentDescriptor(nsACString * aPersistentDescriptor);
+    nsresult SetPersistentDescriptor(nsACString * aPersistentDescriptor);
+    nsresult Reveal();
+    nsresult Launch();
+    nsresult GetRelativeDescriptor(nsILocalFile fromFile, nsACString * _retval);
+    nsresult SetRelativeDescriptor(nsILocalFile fromFile, nsACString * relativeDesc);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIMIMEInfo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,59 @@
+module org.eclipse.swt.internal.mozilla.nsIMIMEInfo;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+import org.eclipse.swt.internal.mozilla.nsIStringEnumerator;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRInt32 nsMIMEInfoHandleAction;
+
+const char[] NS_IMIMEINFO_IID_STR = "1448b42f-cf0d-466e-9a15-64e876ebe857";
+
+const nsIID NS_IMIMEINFO_IID= 
+  {0x1448b42f, 0xcf0d, 0x466e, 
+    [ 0x9a, 0x15, 0x64, 0xe8, 0x76, 0xeb, 0xe8, 0x57 ]};
+
+interface nsIMIMEInfo : nsISupports {
+
+  static const char[] IID_STR = NS_IMIMEINFO_IID_STR;
+  static const nsIID IID = NS_IMIMEINFO_IID;
+
+extern(System):
+  nsresult GetFileExtensions(nsIUTF8StringEnumerator *_retval);
+  nsresult SetFileExtensions(nsACString * aExtensions);
+  nsresult ExtensionExists(nsACString * aExtension, PRBool *_retval);
+  nsresult AppendExtension(nsACString * aExtension);
+  nsresult GetPrimaryExtension(nsACString * aPrimaryExtension);
+  nsresult SetPrimaryExtension(nsACString * aPrimaryExtension);
+  nsresult GetMIMEType(nsACString * aMIMEType);
+  nsresult SetDescription(nsAString * aDescription);
+  nsresult GetMacType(PRUint32 *aMacType);
+  nsresult SetMacType(PRUint32 aMacType);
+  nsresult GetMacCreator(PRUint32 *aMacCreator);
+  nsresult SetMacCreator(PRUint32 aMacCreator);
+  nsresult Equals(nsIMIMEInfo aMIMEInfo, PRBool *_retval);
+  nsresult GetPreferredApplicationHandler(nsIFile  *aPreferredApplicationHandler);
+  nsresult SetPreferredApplicationHandler(nsIFile  aPreferredApplicationHandler);
+  nsresult GetApplicationDescription(nsAString * aApplicationDescription);
+  nsresult SetApplicationDescription(nsAString * aApplicationDescription);
+  nsresult GetHasDefaultHandler(PRBool *aHasDefaultHandler);
+  nsresult GetDefaultDescription(nsAString * aDefaultDescription);
+  nsresult LaunchWithFile(nsIFile aFile);
+
+  enum { saveToDisk = 0 };
+  enum { alwaysAsk = 1 };
+  enum { useHelperApp = 2 };
+  enum { handleInternally = 3 };
+  enum { useSystemDefault = 4 };
+
+  nsresult GetPreferredAction(nsMIMEInfoHandleAction *aPreferredAction);
+  nsresult SetPreferredAction(nsMIMEInfoHandleAction aPreferredAction);
+  nsresult GetAlwaysAskBeforeHandling(PRBool *aAlwaysAskBeforeHandling);
+  nsresult SetAlwaysAskBeforeHandling(PRBool aAlwaysAskBeforeHandling);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIMemory.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIMemory;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IMEMORY_IID_STR = "59e7e77a-38e4-11d4-8cf5-0060b0fc14a3";
+
+const nsIID NS_IMEMORY_IID= 
+  {0x59e7e77a, 0x38e4, 0x11d4, 
+    [ 0x8c, 0xf5, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3 ]};
+
+interface nsIMemory : nsISupports {
+  static const char[] IID_STR = NS_IMEMORY_IID_STR;
+  static const nsIID IID = NS_IMEMORY_IID;
+  
+extern(System):
+  void *    Alloc(size_t size);
+  void *    Realloc(void * ptr, size_t newSize);
+  void      Free(void * ptr);
+  nsresult  HeapMinimize(PRBool immediate);
+  nsresult  IsLowMemory(PRBool *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIModule.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIModule;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIFile; 
+import org.eclipse.swt.internal.mozilla.nsIComponentManager;
+
+const char[] NS_IMODULE_IID_STR = "7392d032-5371-11d3-994e-00805fd26fee";
+
+const nsIID NS_IMODULE_IID= 
+  {0x7392d032, 0x5371, 0x11d3, 
+    [ 0x99, 0x4e, 0x00, 0x80, 0x5f, 0xd2, 0x6f, 0xee ]};
+
+interface nsIModule : nsISupports {
+  static const char[] IID_STR = NS_IMODULE_IID_STR;
+  static const nsIID IID = NS_IMODULE_IID;
+
+extern(System):
+  nsresult GetClassObject(nsIComponentManager aCompMgr, nsCID * aClass, nsIID * aIID, void * *aResult);
+  nsresult RegisterSelf(nsIComponentManager aCompMgr, nsIFile aLocation, char *aLoaderStr, char *aType);
+  nsresult UnregisterSelf(nsIComponentManager aCompMgr, nsIFile aLocation, char *aLoaderStr);
+  nsresult CanUnload(nsIComponentManager aCompMgr, PRBool *_retval);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObjectInputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsIObjectInputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIBinaryInputStream;
+
+const char[] NS_IOBJECTINPUTSTREAM_IID_STR = "6c248606-4eae-46fa-9df0-ba58502368eb";
+
+const nsIID NS_IOBJECTINPUTSTREAM_IID= 
+  {0x6c248606, 0x4eae, 0x46fa, 
+    [ 0x9d, 0xf0, 0xba, 0x58, 0x50, 0x23, 0x68, 0xeb ]};
+
+interface nsIObjectInputStream : nsIBinaryInputStream {
+
+  static const char[] IID_STR = NS_IOBJECTINPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IOBJECTINPUTSTREAM_IID;
+
+extern(System):
+  nsresult ReadObject(PRBool aIsStrongRef, nsISupports *_retval);
+  nsresult ReadID(nsID *aID);
+  char * GetBuffer(PRUint32 aLength, PRUint32 aAlignMask);
+  void PutBuffer(char * aBuffer, PRUint32 aLength);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObjectOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIObjectOutputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIBinaryOutputStream;
+
+const char[] NS_IOBJECTOUTPUTSTREAM_IID_STR = "92c898ac-5fde-4b99-87b3-5d486422094b";
+
+const nsIID NS_IOBJECTOUTPUTSTREAM_IID= 
+  {0x92c898ac, 0x5fde, 0x4b99, 
+    [ 0x87, 0xb3, 0x5d, 0x48, 0x64, 0x22, 0x09, 0x4b ]};
+
+interface nsIObjectOutputStream : nsIBinaryOutputStream {
+
+  static const char[] IID_STR = NS_IOBJECTOUTPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IOBJECTOUTPUTSTREAM_IID;
+
+extern(System):
+  nsresult WriteObject(nsISupports aObject, PRBool aIsStrongRef);
+  nsresult WriteSingleRefObject(nsISupports aObject);
+  nsresult WriteCompoundObject(nsISupports aObject, nsIID * aIID, PRBool aIsStrongRef);
+  nsresult WriteID(nsID * aID);
+  char * GetBuffer(PRUint32 aLength, PRUint32 aAlignMask);
+  void PutBuffer(char * aBuffer, PRUint32 aLength);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObserver.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,22 @@
+module org.eclipse.swt.internal.mozilla.nsIObserver;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IOBSERVER_IID_STR = "db242e01-e4d9-11d2-9dde-000064657374";
+
+const nsIID NS_IOBSERVER_IID= 
+  {0xdb242e01, 0xe4d9, 0x11d2, 
+    [ 0x9d, 0xde, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74 ]};
+
+interface nsIObserver : nsISupports {
+
+  static const char[] IID_STR = NS_IOBSERVER_IID_STR;
+  static const nsIID IID = NS_IOBSERVER_IID;
+
+extern(System):
+  nsresult Observe(nsISupports aSubject, char *aTopic, PRUnichar *aData);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIObserverService.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsIObserverService;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIObserver;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+
+const char[] NS_IOBSERVERSERVICE_IID_STR = "d07f5192-e3d1-11d2-8acd-00105a1b8860";
+
+const nsIID NS_IOBSERVERSERVICE_IID= 
+  {0xd07f5192, 0xe3d1, 0x11d2, 
+    [ 0x8a, 0xcd, 0x00, 0x10, 0x5a, 0x1b, 0x88, 0x60 ]};
+
+interface nsIObserverService : nsISupports {
+
+  static const char[] IID_STR = NS_IOBSERVERSERVICE_IID_STR;
+  static const nsIID IID = NS_IOBSERVERSERVICE_IID;
+
+extern(System):
+  nsresult AddObserver(nsIObserver anObserver, char *aTopic, PRBool ownsWeak);
+  nsresult RemoveObserver(nsIObserver anObserver, char *aTopic);
+  nsresult NotifyObservers(nsISupports aSubject, char *aTopic, PRUnichar *someData);
+  nsresult EnumerateObservers(char *aTopic, nsISimpleEnumerator *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIOutputStream.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIOutputStream;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+
+typedef nsresult function(nsIOutputStream aOutStream,
+	void *aClosure,
+	char *aToSegment,
+	PRUint32 aFromOffset,
+	PRUint32 aCount,
+	PRUint32 *aReadCount) nsReadSegmentFun;
+
+const char[] NS_IOUTPUTSTREAM_IID_STR = "0d0acd2a-61b4-11d4-9877-00c04fa0cf4a";
+
+const nsIID NS_IOUTPUTSTREAM_IID= 
+  {0x0d0acd2a, 0x61b4, 0x11d4, 
+    [ 0x98, 0x77, 0x00, 0xc0, 0x4f, 0xa0, 0xcf, 0x4a ]};
+
+interface nsIOutputStream : nsISupports {
+
+  static const char[] IID_STR = NS_IOUTPUTSTREAM_IID_STR;
+  static const nsIID IID = NS_IOUTPUTSTREAM_IID;
+
+extern(System):
+  nsresult Close();
+  nsresult Flush();
+  nsresult Write(char *aBuf, PRUint32 aCount, PRUint32 *_retval);
+  nsresult WriteFrom(nsIInputStream aFromStream, PRUint32 aCount, PRUint32 *_retval);
+  nsresult WriteSegments(nsReadSegmentFun aReader, void * aClosure, PRUint32 aCount, PRUint32 *_retval);
+  nsresult IsNonBlocking(PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,44 @@
+module org.eclipse.swt.internal.mozilla.nsIPrefBranch;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IPREFBRANCH_IID_STR = "56c35506-f14b-11d3-99d3-ddbfac2ccf65";
+
+const nsIID NS_IPREFBRANCH_IID= 
+  {0x56c35506, 0xf14b, 0x11d3, 
+    [ 0x99, 0xd3, 0xdd, 0xbf, 0xac, 0x2c, 0xcf, 0x65 ]};
+
+interface nsIPrefBranch : nsISupports {
+
+  static const char[] IID_STR = NS_IPREFBRANCH_IID_STR;
+  static const nsIID IID = NS_IPREFBRANCH_IID;
+
+  enum { PREF_INVALID = 0 };
+  enum { PREF_STRING = 32 };
+  enum { PREF_INT = 64 };
+  enum { PREF_BOOL = 128 };
+
+extern(System):
+  nsresult GetRoot(char * *aRoot);
+  nsresult GetPrefType(char *aPrefName, PRInt32 *_retval);
+  nsresult GetBoolPref(char *aPrefName, PRBool *_retval);
+  nsresult SetBoolPref(char *aPrefName, PRInt32 aValue);
+  nsresult GetCharPref(char *aPrefName, char **_retval);
+  nsresult SetCharPref(char *aPrefName, char *aValue);
+  nsresult GetIntPref(char *aPrefName, PRInt32 *_retval);
+  nsresult SetIntPref(char *aPrefName, PRInt32 aValue);
+  nsresult GetComplexValue(char *aPrefName, nsIID * aType, void * *aValue);
+  nsresult SetComplexValue(char *aPrefName, nsIID * aType, nsISupports aValue);
+  nsresult ClearUserPref(char *aPrefName);
+  nsresult LockPref(char *aPrefName);
+  nsresult PrefHasUserValue(char *aPrefName, PRBool *_retval);
+  nsresult PrefIsLocked(char *aPrefName, PRBool *_retval);
+  nsresult UnlockPref(char *aPrefName);
+  nsresult DeleteBranch(char *aStartingAt);
+  nsresult GetChildList(char *aStartingAt, PRUint32 *aCount, char ***aChildArray);
+  nsresult ResetBranch(char *aStartingAt);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefBranch2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIPrefBranch2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIPrefBranch;
+import org.eclipse.swt.internal.mozilla.nsIObserver; 
+
+const char[] NS_IPREFBRANCH2_IID_STR = "74567534-eb94-4b1c-8f45-389643bfc555";
+
+const nsIID NS_IPREFBRANCH2_IID= 
+  {0x74567534, 0xeb94, 0x4b1c, 
+    [ 0x8f, 0x45, 0x38, 0x96, 0x43, 0xbf, 0xc5, 0x55 ]};
+
+interface nsIPrefBranch2 : nsIPrefBranch {
+
+  static const char[] IID_STR = NS_IPREFBRANCH2_IID_STR;
+  static const nsIID IID = NS_IPREFBRANCH2_IID;
+
+extern(System):
+  nsresult AddObserver(char *aDomain, nsIObserver aObserver, PRBool aHoldWeak);
+  nsresult RemoveObserver(char *aDomain, nsIObserver aObserver);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefLocalizedString.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIPrefLocalizedString;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IPREFLOCALIZEDSTRING_IID_STR = "ae419e24-1dd1-11b2-b39a-d3e5e7073802";
+
+const nsIID NS_IPREFLOCALIZEDSTRING_IID= 
+  {0xae419e24, 0x1dd1, 0x11b2, 
+    [ 0xb3, 0x9a, 0xd3, 0xe5, 0xe7, 0x07, 0x38, 0x02 ]};
+
+interface nsIPrefLocalizedString : nsISupports {
+
+  static const char[] IID_STR = NS_IPREFLOCALIZEDSTRING_IID_STR;
+  static const nsIID IID = NS_IPREFLOCALIZEDSTRING_IID;
+
+extern(System):
+  nsresult GetData(PRUnichar * *aData);
+  nsresult SetData(PRUnichar * aData);
+  nsresult ToString(PRUnichar **_retval);
+  nsresult SetDataWithLength(PRUint32 length, PRUnichar *data);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrefService.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIPrefService;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIPrefBranch;
+import org.eclipse.swt.internal.mozilla.nsIFile;
+
+const char[] NS_IPREFSERVICE_IID_STR = "decb9cc7-c08f-4ea5-be91-a8fc637ce2d2";
+
+const nsIID NS_IPREFSERVICE_IID= 
+  {0xdecb9cc7, 0xc08f, 0x4ea5, 
+    [ 0xbe, 0x91, 0xa8, 0xfc, 0x63, 0x7c, 0xe2, 0xd2 ]};
+
+interface nsIPrefService : nsISupports {
+
+  static const char[] IID_STR = NS_IPREFSERVICE_IID_STR;
+  static const nsIID IID = NS_IPREFSERVICE_IID;
+
+extern(System):
+  nsresult ReadUserPrefs(nsIFile aFile);
+  nsresult ResetPrefs();
+  nsresult ResetUserPrefs();
+  nsresult SavePrefFile(nsIFile aFile);
+  nsresult GetBranch(char *aPrefRoot, nsIPrefBranch *_retval);
+  nsresult GetDefaultBranch(char *aPrefRoot, nsIPrefBranch *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIProgressDialog;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDownload;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsIObserver;
+
+const char[] NS_IPROGRESSDIALOG_IID_STR = "88a478b3-af65-440a-94dc-ed9b154d2990";
+
+const nsIID NS_IPROGRESSDIALOG_IID= 
+  {0x88a478b3, 0xaf65, 0x440a, 
+    [ 0x94, 0xdc, 0xed, 0x9b, 0x15, 0x4d, 0x29, 0x90 ]};
+
+interface nsIProgressDialog : nsIDownload {
+
+  static const char[] IID_STR = NS_IPROGRESSDIALOG_IID_STR;
+  static const nsIID IID = NS_IPROGRESSDIALOG_IID;
+
+extern(System):
+  nsresult Open(nsIDOMWindow aParent);
+  nsresult GetCancelDownloadOnClose(PRBool *aCancelDownloadOnClose);
+  nsresult SetCancelDownloadOnClose(PRBool aCancelDownloadOnClose);
+  nsresult GetDialog(nsIDOMWindow  *aDialog);
+  nsresult SetDialog(nsIDOMWindow  aDialog);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProgressDialog_1_8.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+module org.eclipse.swt.internal.mozilla.nsIProgressDialog_1_8;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDownload;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsIObserver;
+import org.eclipse.swt.internal.mozilla.nsIDownload_1_8;
+
+const char[] NS_IPROGRESSDIALOG_IID_STR = "20e790a2-76c6-462d-851a-22ab6cbbe48b";
+
+const nsIID NS_IPROGRESSDIALOG_IID= 
+  {0x20e790a2, 0x76c6, 0x462d, 
+    [ 0x85, 0x1a, 0x22, 0xab, 0x6c, 0xbb, 0xe4, 0x8b ]};
+
+interface nsIProgressDialog_1_8 : nsIDownload_1_8 {
+
+  static const char[] IID_STR = NS_IPROGRESSDIALOG_IID_STR;
+  static const nsIID IID = NS_IPROGRESSDIALOG_IID;
+
+extern(System):
+  nsresult Open(nsIDOMWindow aParent);
+  nsresult GetCancelDownloadOnClose(PRBool *aCancelDownloadOnClose);
+  nsresult SetCancelDownloadOnClose(PRBool aCancelDownloadOnClose);
+  nsresult GetObserver(nsIObserver  *aObserver);
+  nsresult SetObserver(nsIObserver  aObserver);
+  nsresult GetDialog(nsIDOMWindow  *aDialog);
+  nsresult SetDialog(nsIDOMWindow  aDialog);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPrompt.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+module org.eclipse.swt.internal.mozilla.nsIPrompt;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IPROMPT_IID_STR = "a63f70c0-148b-11d3-9333-00104ba0fd40";
+
+const nsIID NS_IPROMPT_IID= 
+  {0xa63f70c0, 0x148b, 0x11d3, 
+    [ 0x93, 0x33, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIPrompt : nsISupports {
+
+  static const char[] IID_STR = NS_IPROMPT_IID_STR;
+  static const nsIID IID = NS_IPROMPT_IID;
+
+extern(System):
+  nsresult Alert(PRUnichar *dialogTitle, PRUnichar *text);
+  nsresult AlertCheck(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar *checkMsg, PRBool *checkValue);
+  nsresult Confirm(PRUnichar *dialogTitle, PRUnichar *text, PRBool *_retval);
+  nsresult ConfirmCheck(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval);
+
+  enum { BUTTON_POS_0 = 1U };
+  enum { BUTTON_POS_1 = 256U };
+  enum { BUTTON_POS_2 = 65536U };
+  enum { BUTTON_TITLE_OK = 1U };
+  enum { BUTTON_TITLE_CANCEL = 2U };
+  enum { BUTTON_TITLE_YES = 3U };
+  enum { BUTTON_TITLE_NO = 4U };
+  enum { BUTTON_TITLE_SAVE = 5U };
+  enum { BUTTON_TITLE_DONT_SAVE = 6U };
+  enum { BUTTON_TITLE_REVERT = 7U };
+  enum { BUTTON_TITLE_IS_STRING = 127U };
+  enum { BUTTON_POS_0_DEFAULT = 0U };
+  enum { BUTTON_POS_1_DEFAULT = 16777216U };
+  enum { BUTTON_POS_2_DEFAULT = 33554432U };
+  enum { BUTTON_DELAY_ENABLE = 67108864U };
+  enum { STD_OK_CANCEL_BUTTONS = 513U };
+
+  nsresult ConfirmEx(PRUnichar *dialogTitle, PRUnichar *text, PRUint32 buttonFlags, PRUnichar *button0Title, PRUnichar *button1Title, PRUnichar *button2Title, PRUnichar *checkMsg, PRBool *checkValue, PRInt32 *_retval);
+  nsresult Prompt(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar **value, PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval);
+  nsresult PromptPassword(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar **password, PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval);
+  nsresult PromptUsernameAndPassword(PRUnichar *dialogTitle, PRUnichar *text, PRUnichar **username, PRUnichar **password, PRUnichar *checkMsg, PRBool *checkValue, PRBool *_retval);
+  nsresult Select(PRUnichar *dialogTitle, PRUnichar *text, PRUint32 count, PRUnichar **selectList, PRInt32 *outSelection, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPromptService.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,51 @@
+module org.eclipse.swt.internal.mozilla.nsIPromptService;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+
+const char[] NS_IPROMPTSERVICE_IID_STR = "1630c61a-325e-49ca-8759-a31b16c47aa5";
+
+const nsIID NS_IPROMPTSERVICE_IID= 
+  {0x1630c61a, 0x325e, 0x49ca, 
+    [ 0x87, 0x59, 0xa3, 0x1b, 0x16, 0xc4, 0x7a, 0xa5 ]};
+
+interface nsIPromptService : nsISupports {
+
+  static const char[] IID_STR = NS_IPROMPTSERVICE_IID_STR;
+  static const nsIID IID = NS_IPROMPTSERVICE_IID;
+
+extern(System):
+  nsresult Alert(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText);
+  nsresult AlertCheck(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUnichar *aCheckMsg, PRBool *aCheckState);
+  nsresult Confirm(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRBool *_retval);
+  nsresult ConfirmCheck(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUnichar *aCheckMsg, PRBool *aCheckState, PRBool *_retval);
+
+  enum { BUTTON_POS_0 = 1U };
+  enum { BUTTON_POS_1 = 256U };
+  enum { BUTTON_POS_2 = 65536U };
+  enum { BUTTON_TITLE_OK = 1U };
+  enum { BUTTON_TITLE_CANCEL = 2U };
+  enum { BUTTON_TITLE_YES = 3U };
+  enum { BUTTON_TITLE_NO = 4U };
+  enum { BUTTON_TITLE_SAVE = 5U };
+  enum { BUTTON_TITLE_DONT_SAVE = 6U };
+  enum { BUTTON_TITLE_REVERT = 7U };
+  enum { BUTTON_TITLE_IS_STRING = 127U };
+  enum { BUTTON_POS_0_DEFAULT = 0U };
+  enum { BUTTON_POS_1_DEFAULT = 16777216U };
+  enum { BUTTON_POS_2_DEFAULT = 33554432U };
+  enum { BUTTON_DELAY_ENABLE = 67108864U };
+  enum { STD_OK_CANCEL_BUTTONS = 513U };
+  enum { STD_YES_NO_BUTTONS = 1027U };
+
+  nsresult ConfirmEx(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUint32 aButtonFlags, PRUnichar *aButton0Title, PRUnichar *aButton1Title, PRUnichar *aButton2Title, PRUnichar *aCheckMsg, PRBool *aCheckState, PRInt32 *_retval);
+  nsresult Prompt(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUnichar **aValue, PRUnichar *aCheckMsg, PRBool *aCheckState, PRBool *_retval);
+  nsresult PromptUsernameAndPassword(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUnichar **aUsername, PRUnichar **aPassword, PRUnichar *aCheckMsg, PRBool *aCheckState, PRBool *_retval);
+  nsresult PromptPassword(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUnichar **aPassword, PRUnichar *aCheckMsg, PRBool *aCheckState, PRBool *_retval);
+  nsresult Select(nsIDOMWindow aParent, PRUnichar *aDialogTitle, PRUnichar *aText, PRUint32 aCount, PRUnichar **aSelectList, PRInt32 *aOutSelection, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIPromptService2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+module org.eclipse.swt.internal.mozilla.nsIPromptService2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsICancelable;
+import org.eclipse.swt.internal.mozilla.nsIChannel;
+import org.eclipse.swt.internal.mozilla.nsIAuthInformation;
+import org.eclipse.swt.internal.mozilla.nsIAuthPromptCallback;
+import org.eclipse.swt.internal.mozilla.nsIPromptService;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+
+const char[] NS_IPROMPTSERVICE2_IID_STR = "cf86d196-dbee-4482-9dfa-3477aa128319";
+
+const nsIID NS_IPROMPTSERVICE2_IID= 
+  {0xcf86d196, 0xdbee, 0x4482, 
+    [ 0x9d, 0xfa, 0x34, 0x77, 0xaa, 0x12, 0x83, 0x19 ]};
+
+interface nsIPromptService2 : nsIPromptService {
+
+  static const char[] IID_STR = NS_IPROMPTSERVICE2_IID_STR;
+  static const nsIID IID = NS_IPROMPTSERVICE2_IID;
+
+extern(System):
+    public nsresult PromptAuth(nsIDOMWindow aParent, nsIChannel aChannel, PRUint32 level, nsIAuthInformation authInfo, PRUnichar* checkboxLabel, PRBool* checkValue, PRBool* _retval);
+
+    public nsresult AsyncPromptAuth(nsIDOMWindow aParent, nsIChannel aChannel, nsIAuthPromptCallback aCallback, nsISupports aContext, PRUint32 level, nsIAuthInformation authInfo, PRUnichar* checkboxLabel, PRBool* checkValue, nsICancelable* _retval);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProperties.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIProperties;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IPROPERTIES_IID_STR = "78650582-4e93-4b60-8e85-26ebd3eb14ca";
+
+const nsIID NS_IPROPERTIES_IID= 
+  {0x78650582, 0x4e93, 0x4b60, 
+    [ 0x8e, 0x85, 0x26, 0xeb, 0xd3, 0xeb, 0x14, 0xca ]};
+
+interface nsIProperties : nsISupports {
+
+  static const char[] IID_STR = NS_IPROPERTIES_IID_STR;
+  static const nsIID IID = NS_IPROPERTIES_IID;
+
+extern(System):
+  nsresult Get(char *prop, nsIID * iid, void * *result);
+  nsresult Set(char *prop, nsISupports value);
+  nsresult Has(char *prop, PRBool *_retval);
+  nsresult Undefine(char *prop);
+  nsresult GetKeys(PRUint32 *count, char ***keys);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIProtocolHandler.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,36 @@
+module org.eclipse.swt.internal.mozilla.nsIProtocolHandler;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsIChannel;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IPROTOCOLHANDLER_IID_STR = "15fd6940-8ea7-11d3-93ad-00104ba0fd40";
+
+const nsIID NS_IPROTOCOLHANDLER_IID= 
+  {0x15fd6940, 0x8ea7, 0x11d3, 
+    [ 0x93, 0xad, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIProtocolHandler : nsISupports {
+
+  static const char[] IID_STR = NS_IPROTOCOLHANDLER_IID_STR;
+  static const nsIID IID = NS_IPROTOCOLHANDLER_IID;
+
+extern(System):
+  nsresult GetScheme(nsACString * aScheme);
+  nsresult GetDefaultPort(PRInt32 *aDefaultPort);
+  nsresult GetProtocolFlags(PRUint32 *aProtocolFlags);
+  nsresult NewURI(nsACString * aSpec, char *aOriginCharset, nsIURI aBaseURI, nsIURI *_retval);
+  nsresult NewChannel(nsIURI aURI, nsIChannel *_retval);
+  nsresult AllowPort(PRInt32 port, char *scheme, PRBool *_retval);
+
+  enum { URI_STD = 0U };
+  enum { URI_NORELATIVE = 1U };
+  enum { URI_NOAUTH = 2U };
+  enum { ALLOWS_PROXY = 4U };
+  enum { ALLOWS_PROXY_HTTP = 8U };
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIRequest.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,45 @@
+module org.eclipse.swt.internal.mozilla.nsIRequest;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsILoadGroup;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+alias PRUint32 nsLoadFlags;
+
+const char[] NS_IREQUEST_IID_STR = "ef6bfbd2-fd46-48d8-96b7-9f8f0fd387fe";
+
+const nsIID NS_IREQUEST_IID= 
+  {0xef6bfbd2, 0xfd46, 0x48d8, 
+    [ 0x96, 0xb7, 0x9f, 0x8f, 0x0f, 0xd3, 0x87, 0xfe ]};
+
+interface nsIRequest : nsISupports {
+
+  static const char[] IID_STR = NS_IREQUEST_IID_STR;
+  static const nsIID IID = NS_IREQUEST_IID;
+
+extern(System):
+  nsresult GetName(nsACString * aName);
+  nsresult IsPending(PRBool *_retval);
+  nsresult GetStatus(nsresult *aStatus);
+  nsresult Cancel(nsresult aStatus);
+  nsresult Suspend();
+  nsresult Resume();
+  nsresult GetLoadGroup(nsILoadGroup  *aLoadGroup);
+  nsresult SetLoadGroup(nsILoadGroup  aLoadGroup);
+  nsresult GetLoadFlags(nsLoadFlags *aLoadFlags);
+  nsresult SetLoadFlags(nsLoadFlags aLoadFlags);
+
+  enum { LOAD_NORMAL = 0U };
+  enum { LOAD_BACKGROUND = 1U };
+  enum { INHIBIT_CACHING = 128U };
+  enum { INHIBIT_PERSISTENT_CACHING = 256U };
+  enum { LOAD_BYPASS_CACHE = 512U };
+  enum { LOAD_FROM_CACHE = 1024U };
+  enum { VALIDATE_ALWAYS = 2048U };
+  enum { VALIDATE_NEVER = 4096U };
+  enum { VALIDATE_ONCE_PER_SESSION = 8192U };
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIRequestObserver.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIRequestObserver;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIRequest; 
+
+const char[] NS_IREQUESTOBSERVER_IID_STR = "fd91e2e0-1481-11d3-9333-00104ba0fd40";
+
+const nsIID NS_IREQUESTOBSERVER_IID= 
+  {0xfd91e2e0, 0x1481, 0x11d3, 
+    [ 0x93, 0x33, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIRequestObserver : nsISupports {
+
+  static const char[] IID_STR = NS_IREQUESTOBSERVER_IID_STR;
+  static const nsIID IID = NS_IREQUESTOBSERVER_IID;
+
+extern(System):
+  nsresult OnStartRequest(nsIRequest aRequest, nsISupports aContext);
+  nsresult OnStopRequest(nsIRequest aRequest, nsISupports aContext, nsresult aStatusCode);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHEntry.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,73 @@
+module org.eclipse.swt.internal.mozilla.nsISHEntry;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIHistoryEntry;
+import org.eclipse.swt.internal.mozilla.nsIContentViewer; 
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsIInputStream; 
+import org.eclipse.swt.internal.mozilla.nsIDocShellTreeItem;
+import org.eclipse.swt.internal.mozilla.nsISupportsArray;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ISHENTRY_IID_STR = "542a98b9-2889-4922-aaf4-02b6056f4136";
+
+const nsIID NS_ISHENTRY_IID= 
+  {0x542a98b9, 0x2889, 0x4922, 
+    [ 0xaa, 0xf4, 0x02, 0xb6, 0x05, 0x6f, 0x41, 0x36 ]};
+
+interface nsISHEntry : nsIHistoryEntry {
+
+  static const char[] IID_STR = NS_ISHENTRY_IID_STR;
+  static const nsIID IID = NS_ISHENTRY_IID;
+
+extern(System):
+  nsresult SetURI(nsIURI aURI);
+  nsresult GetReferrerURI(nsIURI  *aReferrerURI);
+  nsresult SetReferrerURI(nsIURI  aReferrerURI);
+  nsresult GetContentViewer(nsIContentViewer  *aContentViewer);
+  nsresult SetContentViewer(nsIContentViewer  aContentViewer);
+  nsresult GetSticky(PRBool *aSticky);
+  nsresult SetSticky(PRBool aSticky);
+  nsresult GetWindowState(nsISupports  *aWindowState);
+  nsresult SetWindowState(nsISupports  aWindowState);
+  nsresult GetViewerBounds(nsRect * bounds);
+  nsresult SetViewerBounds(nsRect * bounds);
+  nsresult AddChildShell(nsIDocShellTreeItem shell);
+  nsresult ChildShellAt(PRInt32 index, nsIDocShellTreeItem *_retval);
+  nsresult ClearChildShells();
+  nsresult GetRefreshURIList(nsISupportsArray  *aRefreshURIList);
+  nsresult SetRefreshURIList(nsISupportsArray  aRefreshURIList);
+  nsresult SyncPresentationState();
+  nsresult SetTitle(nsAString * aTitle);
+  nsresult GetPostData(nsIInputStream  *aPostData);
+  nsresult SetPostData(nsIInputStream  aPostData);
+  nsresult GetLayoutHistoryState(nsILayoutHistoryState  *aLayoutHistoryState);
+  nsresult SetLayoutHistoryState(nsILayoutHistoryState  aLayoutHistoryState);
+  nsresult GetParent(nsISHEntry  *aParent);
+  nsresult SetParent(nsISHEntry  aParent);
+  nsresult GetLoadType(PRUint32 *aLoadType);
+  nsresult SetLoadType(PRUint32 aLoadType);
+  nsresult GetID(PRUint32 *aID);
+  nsresult SetID(PRUint32 aID);
+  nsresult GetPageIdentifier(PRUint32 *aPageIdentifier);
+  nsresult SetPageIdentifier(PRUint32 aPageIdentifier);
+  nsresult GetCacheKey(nsISupports  *aCacheKey);
+  nsresult SetCacheKey(nsISupports  aCacheKey);
+  nsresult GetSaveLayoutStateFlag(PRBool *aSaveLayoutStateFlag);
+  nsresult SetSaveLayoutStateFlag(PRBool aSaveLayoutStateFlag);
+  nsresult GetExpirationStatus(PRBool *aExpirationStatus);
+  nsresult SetExpirationStatus(PRBool aExpirationStatus);
+  nsresult GetContentType(nsACString * aContentType);
+  nsresult SetContentType(nsACString * aContentType);
+  nsresult SetScrollPosition(PRInt32 x, PRInt32 y);
+  nsresult GetScrollPosition(PRInt32 *x, PRInt32 *y);
+  nsresult Create(nsIURI URI, nsAString * title, nsIInputStream inputStream, nsILayoutHistoryState layoutHistoryState, nsISupports cacheKey, nsACString * contentType);
+  nsresult Clone(nsISHEntry *_retval);
+  nsresult SetIsSubFrame(PRBool aFlag);
+  nsresult GetAnyContentViewer(nsISHEntry *ownerEntry, nsIContentViewer *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHistory.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,34 @@
+module org.eclipse.swt.internal.mozilla.nsISHistory;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIHistoryEntry; 
+import org.eclipse.swt.internal.mozilla.nsISHistoryListener; 
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+
+const char[] NS_ISHISTORY_IID_STR = "7294fe9b-14d8-11d5-9882-00c04fa02f40";
+
+const nsIID NS_ISHISTORY_IID= 
+  {0x7294fe9b, 0x14d8, 0x11d5, 
+    [ 0x98, 0x82, 0x00, 0xc0, 0x4f, 0xa0, 0x2f, 0x40 ]};
+
+interface nsISHistory : nsISupports {
+
+  static const char[] IID_STR = NS_ISHISTORY_IID_STR;
+  static const nsIID IID = NS_ISHISTORY_IID;
+
+extern(System):
+  nsresult GetCount(PRInt32 *aCount);
+  nsresult GetIndex(PRInt32 *aIndex);
+  nsresult GetMaxLength(PRInt32 *aMaxLength);
+  nsresult SetMaxLength(PRInt32 aMaxLength);
+  nsresult GetEntryAtIndex(PRInt32 index, PRBool modifyIndex, nsIHistoryEntry *_retval);
+  nsresult PurgeHistory(PRInt32 numEntries);
+  nsresult AddSHistoryListener(nsISHistoryListener aListener);
+  nsresult RemoveSHistoryListener(nsISHistoryListener aListener);
+  nsresult GetSHistoryEnumerator(nsISimpleEnumerator  *aSHistoryEnumerator);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISHistoryListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsISHistoryListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIURI;
+
+const char[] NS_ISHISTORYLISTENER_IID_STR = "3b07f591-e8e1-11d4-9882-00c04fa02f40";
+
+const nsIID NS_ISHISTORYLISTENER_IID= 
+  {0x3b07f591, 0xe8e1, 0x11d4, 
+    [ 0x98, 0x82, 0x00, 0xc0, 0x4f, 0xa0, 0x2f, 0x40 ]};
+
+interface nsISHistoryListener : nsISupports {
+
+  static const char[] IID_STR = NS_ISHISTORYLISTENER_IID_STR;
+  static const nsIID IID = NS_ISHISTORYLISTENER_IID;
+
+extern(System):
+  nsresult OnHistoryNewEntry(nsIURI aNewURI);
+  nsresult OnHistoryGoBack(nsIURI aBackURI, PRBool *_retval);
+  nsresult OnHistoryGoForward(nsIURI aForwardURI, PRBool *_retval);
+  nsresult OnHistoryReload(nsIURI aReloadURI, PRUint32 aReloadFlags, PRBool *_retval);
+  nsresult OnHistoryGotoIndex(PRInt32 aIndex, nsIURI aGotoURI, PRBool *_retval);
+  nsresult OnHistoryPurge(PRInt32 aNumEntries, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISecureBrowserUI.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,27 @@
+module org.eclipse.swt.internal.mozilla.nsISecureBrowserUI;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ISECUREBROWSERUI_IID_STR = "081e31e0-a144-11d3-8c7c-00609792278c";
+
+const nsIID NS_ISECUREBROWSERUI_IID= 
+  {0x081e31e0, 0xa144, 0x11d3, 
+    [ 0x8c, 0x7c, 0x00, 0x60, 0x97, 0x92, 0x27, 0x8c ]};
+
+interface nsISecureBrowserUI : nsISupports {
+
+  static const char[] IID_STR = NS_ISECUREBROWSERUI_IID_STR;
+  static const nsIID IID = NS_ISECUREBROWSERUI_IID;
+
+extern(System):
+  nsresult Init(nsIDOMWindow window);
+  nsresult GetState(PRUint32 *aState);
+  nsresult GetTooltipText(nsAString * aTooltipText);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISelection.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,43 @@
+module org.eclipse.swt.internal.mozilla.nsISelection;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMNode;
+import org.eclipse.swt.internal.mozilla.nsIDOMRange;
+
+const char[] NS_ISELECTION_IID_STR = "b2c7ed59-8634-4352-9e37-5484c8b6e4e1";
+
+const nsIID NS_ISELECTION_IID= 
+  {0xb2c7ed59, 0x8634, 0x4352, 
+    [ 0x9e, 0x37, 0x54, 0x84, 0xc8, 0xb6, 0xe4, 0xe1 ]};
+
+interface nsISelection : nsISupports {
+
+  static const char[] IID_STR = NS_ISELECTION_IID_STR;
+  static const nsIID IID = NS_ISELECTION_IID;
+
+extern(System):
+  nsresult GetAnchorNode(nsIDOMNode  *aAnchorNode);
+  nsresult GetAnchorOffset(PRInt32 *aAnchorOffset);
+  nsresult GetFocusNode(nsIDOMNode  *aFocusNode);
+  nsresult GetFocusOffset(PRInt32 *aFocusOffset);
+  nsresult GetIsCollapsed(PRBool *aIsCollapsed);
+  nsresult GetRangeCount(PRInt32 *aRangeCount);
+  nsresult GetRangeAt(PRInt32 index, nsIDOMRange *_retval);
+  nsresult Collapse(nsIDOMNode parentNode, PRInt32 offset);
+  nsresult Extend(nsIDOMNode parentNode, PRInt32 offset);
+  nsresult CollapseToStart();
+  nsresult CollapseToEnd();
+  nsresult ContainsNode(nsIDOMNode node, PRBool entirelyContained, PRBool *_retval);
+  nsresult SelectAllChildren(nsIDOMNode parentNode);
+  nsresult AddRange(nsIDOMRange range);
+  nsresult RemoveRange(nsIDOMRange range);
+  nsresult RemoveAllRanges();
+  nsresult DeleteFromDocument();
+  nsresult SelectionLanguageChange(PRBool langRTL);
+  nsresult ToString(PRUnichar **_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISerializable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsISerializable;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIObjectInputStream; 
+import org.eclipse.swt.internal.mozilla.nsIObjectOutputStream;
+
+const char[] NS_ISERIALIZABLE_IID_STR = "91cca981-c26d-44a8-bebe-d9ed4891503a";
+
+const nsIID NS_ISERIALIZABLE_IID= 
+  {0x91cca981, 0xc26d, 0x44a8, 
+    [ 0xbe, 0xbe, 0xd9, 0xed, 0x48, 0x91, 0x50, 0x3a ]};
+
+interface nsISerializable : nsISupports {
+
+  static const char[] IID_STR = NS_ISERIALIZABLE_IID_STR;
+  static const nsIID IID = NS_ISERIALIZABLE_IID;
+
+extern(System):
+  nsresult Read(nsIObjectInputStream aInputStream);
+  nsresult Write(nsIObjectOutputStream aOutputStream);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIServiceManager.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIServiceManager;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_ISERVICEMANAGER_IID_STR = "8bb35ed9-e332-462d-9155-4a002ab5c958";
+const nsIID NS_ISERVICEMANAGER_IID= 
+  {0x8bb35ed9, 0xe332, 0x462d, 
+    [ 0x91, 0x55, 0x4a, 0x00, 0x2a, 0xb5, 0xc9, 0x58 ]};
+
+interface nsIServiceManager : nsISupports {
+
+  static const char[] IID_STR = NS_ISERVICEMANAGER_IID_STR;
+  static const nsIID IID = NS_ISERVICEMANAGER_IID;
+
+extern(System):
+  nsresult GetService(nsCID * aClass, nsIID * aIID, void * *result);
+  nsresult GetServiceByContractID(char *aContractID, nsIID * aIID, void * *result);
+  nsresult IsServiceInstantiated(nsCID * aClass, nsIID * aIID, PRBool *_retval);
+  nsresult IsServiceInstantiatedByContractID(char *aContractID, nsIID * aIID, PRBool *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISimpleEnumerator.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_ISIMPLEENUMERATOR_IID_STR = "d1899240-f9d2-11d2-bdd6-000064657374";
+
+const nsIID NS_ISIMPLEENUMERATOR_IID= 
+  {0xd1899240, 0xf9d2, 0x11d2, 
+    [ 0xbd, 0xd6, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74 ]};
+
+interface nsISimpleEnumerator : nsISupports {
+
+  static const char[] IID_STR = NS_ISIMPLEENUMERATOR_IID_STR;
+  static const nsIID IID = NS_ISIMPLEENUMERATOR_IID;
+
+extern(System):
+  nsresult HasMoreElements(PRBool *_retval);
+  nsresult GetNext(nsISupports *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIStreamListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIStreamListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIRequestObserver;
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+
+const char[] NS_ISTREAMLISTENER_IID_STR = "1a637020-1482-11d3-9333-00104ba0fd40";
+
+const nsIID NS_ISTREAMLISTENER_IID= 
+  {0x1a637020, 0x1482, 0x11d3, 
+    [ 0x93, 0x33, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIStreamListener : nsIRequestObserver {
+
+  static const char[] IID_STR = NS_ISTREAMLISTENER_IID_STR;
+  static const nsIID IID = NS_ISTREAMLISTENER_IID;
+
+extern(System):
+  nsresult OnDataAvailable(nsIRequest aRequest, nsISupports aContext, nsIInputStream aInputStream, PRUint32 aOffset, PRUint32 aCount);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIStringEnumerator.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,50 @@
+module org.eclipse.swt.internal.mozilla.nsIStringEnumerator;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ISTRINGENUMERATOR_IID_STR = "50d3ef6c-9380-4f06-9fb2-95488f7d141c";
+
+const nsIID NS_ISTRINGENUMERATOR_IID= 
+  {0x50d3ef6c, 0x9380, 0x4f06, 
+    [ 0x9f, 0xb2, 0x95, 0x48, 0x8f, 0x7d, 0x14, 0x1c ]};
+
+interface nsIStringEnumerator : nsISupports {
+
+  static const char[] IID_STR = NS_ISTRINGENUMERATOR_IID_STR;
+  static const nsIID IID = NS_ISTRINGENUMERATOR_IID;
+
+extern(System):
+  nsresult HasMore(PRBool *_retval);
+  nsresult GetNext(nsAString * _retval);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IUTF8STRINGENUMERATOR_IID_STR = "9bdf1010-3695-4907-95ed-83d0410ec307";
+
+const nsIID NS_IUTF8STRINGENUMERATOR_IID= 
+  {0x9bdf1010, 0x3695, 0x4907, 
+    [ 0x95, 0xed, 0x83, 0xd0, 0x41, 0x0e, 0xc3, 0x07 ]};
+
+interface nsIUTF8StringEnumerator : nsISupports {
+
+  static const char[] IID_STR = NS_IUTF8STRINGENUMERATOR_IID_STR;
+  static const nsIID IID = NS_IUTF8STRINGENUMERATOR_IID;
+
+extern(System):
+  nsresult HasMore(PRBool *_retval);
+  nsresult GetNext(nsACString * _retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISupports.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,30 @@
+module org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+const char[] NS_ISUPPORTS_IID_STR = "00000000-0000-0000-c000-000000000046";
+
+const nsIID NS_ISUPPORTS_IID= 
+        { 0x00000000, 0x0000, 0x0000, 
+          [ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 ] };
+
+interface IUnknown
+{
+    static const char[] IID_STR = NS_ISUPPORTS_IID_STR;
+    static const nsIID IID = NS_ISUPPORTS_IID;
+
+extern(System):
+    nsresult QueryInterface( nsIID* uuid, void **result);
+
+    nsrefcnt AddRef();
+    nsrefcnt Release();
+}
+
+// WHY WE USE COM's IUnknown for XPCOM:
+//
+// The IUnknown interface is special-cased in D and is specifically designed to be
+// compatible with MS COM.  XPCOM's nsISupports interface is the exact equivalent
+// of IUnknown so we alias it here to take advantage of D's COM support. -JJR
+
+alias IUnknown nsISupports;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsISupportsArray.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+module org.eclipse.swt.internal.mozilla.nsISupportsArray;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsICollection;
+
+typedef PRBool function(nsISupports, void*) nsISupportsArrayEnumFunc;
+
+const char[] NS_ISUPPORTSARRAY_IID_STR = "791eafa0-b9e6-11d1-8031-006008159b5a";
+
+const nsIID NS_ISUPPORTSARRAY_IID= 
+  {0x791eafa0, 0xb9e6, 0x11d1, 
+    [ 0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a ]};
+
+interface nsISupportsArray : nsICollection {
+
+  static const char[] IID_STR = NS_ISUPPORTSARRAY_IID_STR;
+  static const nsIID IID = NS_ISUPPORTSARRAY_IID;
+
+extern(System):
+  PRBool Equals(nsISupportsArray other);
+  nsISupports  ElementAt(PRUint32 aIndex);
+  PRInt32 IndexOf(nsISupports aPossibleElement);
+  PRInt32 IndexOfStartingAt(nsISupports aPossibleElement, PRUint32 aStartIndex);
+  PRInt32 LastIndexOf(nsISupports aPossibleElement);
+  nsresult GetIndexOf(nsISupports aPossibleElement, PRInt32 *_retval);
+  nsresult GetIndexOfStartingAt(nsISupports aPossibleElement, PRUint32 aStartIndex, PRInt32 *_retval);
+  nsresult GetLastIndexOf(nsISupports aPossibleElement, PRInt32 *_retval);
+  PRBool InsertElementAt(nsISupports aElement, PRUint32 aIndex);
+  PRBool ReplaceElementAt(nsISupports aElement, PRUint32 aIndex);
+  PRBool RemoveElementAt(PRUint32 aIndex);
+  PRBool RemoveLastElement(nsISupports aElement);
+  nsresult DeleteLastElement(nsISupports aElement);
+  nsresult DeleteElementAt(PRUint32 aIndex);
+  PRBool AppendElements(nsISupportsArray aElements);
+  nsresult Compact();
+  PRBool EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void * aData);
+  PRBool EnumerateBackwards(nsISupportsArrayEnumFunc aFunc, void * aData);
+  nsresult Clone(nsISupportsArray *_retval);
+  PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
+  PRBool InsertElementsAt(nsISupportsArray aOther, PRUint32 aIndex);
+  PRBool RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount);
+  PRBool SizeTo(PRInt32 aSize);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITooltipListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsITooltipListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_ITOOLTIPLISTENER_IID_STR = "44b78386-1dd2-11b2-9ad2-e4eee2ca1916";
+
+const nsIID NS_ITOOLTIPLISTENER_IID= 
+  {0x44b78386, 0x1dd2, 0x11b2, 
+    [ 0x9a, 0xd2, 0xe4, 0xee, 0xe2, 0xca, 0x19, 0x16 ]};
+
+interface nsITooltipListener : nsISupports {
+
+  static const char[] IID_STR = NS_ITOOLTIPLISTENER_IID_STR;
+  static const nsIID IID = NS_ITOOLTIPLISTENER_IID;
+
+extern(System):
+  nsresult OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, PRUnichar *aTipText);
+  nsresult OnHideTooltip();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITraceRefcnt.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsITraceRefcnt;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_ITRACEREFCNT_IID_STR = "273dc92f-0fe6-4545-96a9-21be77828039";
+
+const nsIID NS_ITRACEREFCNT_IID= 
+  {0x273dc92f, 0x0fe6, 0x4545, 
+    [ 0x96, 0xa9, 0x21, 0xbe, 0x77, 0x82, 0x80, 0x39 ]};
+
+interface nsITraceRefcnt : nsISupports {
+  static const char[] IID_STR = NS_ITRACEREFCNT_IID_STR;
+  static const nsIID IID = NS_ITRACEREFCNT_IID;
+
+extern(System):
+  nsresult LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, char *aTypeName, PRUint32 aInstanceSize);
+  nsresult LogRelease(void * aPtr, nsrefcnt aNewRefcnt, char *aTypeName);
+  nsresult LogCtor(void * aPtr, char *aTypeName, PRUint32 aInstanceSize);
+  nsresult LogDtor(void * aPtr, char *aTypeName, PRUint32 aInstanceSize);
+  nsresult LogAddCOMPtr(void * aPtr, nsISupports aObject);
+  nsresult LogReleaseCOMPtr(void * aPtr, nsISupports aObject);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsITransfer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsITransfer;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.prtime;
+
+import org.eclipse.swt.internal.mozilla.nsIWebProgressListener2;
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsICancelable;
+import org.eclipse.swt.internal.mozilla.nsIMIMEInfo;
+import org.eclipse.swt.internal.mozilla.nsILocalFile;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_ITRANSFER_IID_STR = "23c51569-e9a1-4a92-adeb-3723db82ef7c";
+
+const nsIID NS_ITRANSFER_IID= 
+  {0x23c51569, 0xe9a1, 0x4a92, 
+    [ 0xad, 0xeb, 0x37, 0x23, 0xdb, 0x82, 0xef, 0x7c ]};
+
+interface nsITransfer : nsIWebProgressListener2 {
+
+  static const char[] IID_STR = NS_ITRANSFER_IID_STR;
+  static const nsIID IID = NS_ITRANSFER_IID;
+
+extern(System):
+  nsresult Init(nsIURI aSource, nsIURI aTarget, nsAString * aDisplayName, nsIMIMEInfo aMIMEInfo, PRTime startTime, nsILocalFile aTempFile, nsICancelable aCancelable);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURI.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,48 @@
+module org.eclipse.swt.internal.mozilla.nsIURI;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IURI_IID_STR = "07a22cc0-0ce5-11d3-9331-00104ba0fd40";
+
+const nsIID NS_IURI_IID= 
+  {0x07a22cc0, 0x0ce5, 0x11d3, 
+    [ 0x93, 0x31, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIURI : nsISupports {
+
+  static const char[] IID_STR = NS_IURI_IID_STR;
+  static const nsIID IID = NS_IURI_IID;
+
+extern(System):
+  nsresult GetSpec(nsACString * aSpec);
+  nsresult SetSpec(nsACString * aSpec);
+  nsresult GetPrePath(nsACString * aPrePath);
+  nsresult GetScheme(nsACString * aScheme);
+  nsresult SetScheme(nsACString * aScheme);
+  nsresult GetUserPass(nsACString * aUserPass);
+  nsresult SetUserPass(nsACString * aUserPass);
+  nsresult GetUsername(nsACString * aUsername);
+  nsresult SetUsername(nsACString * aUsername);
+  nsresult GetPassword(nsACString * aPassword);
+  nsresult SetPassword(nsACString * aPassword);
+  nsresult GetHostPort(nsACString * aHostPort);
+  nsresult SetHostPort(nsACString * aHostPort);
+  nsresult GetHost(nsACString * aHost);
+  nsresult SetHost(nsACString * aHost);
+  nsresult GetPort(PRInt32 *aPort);
+  nsresult SetPort(PRInt32 aPort);
+  nsresult GetPath(nsACString * aPath);
+  nsresult SetPath(nsACString * aPath);
+  nsresult Equals(nsIURI other, PRBool *_retval);
+  nsresult SchemeIs(char *scheme, PRBool *_retval);
+  nsresult Clone(nsIURI *_retval);
+  nsresult Resolve(nsACString * relativePath, nsACString * _retval);
+  nsresult GetAsciiSpec(nsACString * aAsciiSpec);
+  nsresult GetAsciiHost(nsACString * aAsciiHost);
+  nsresult GetOriginCharset(nsACString * aOriginCharset);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURIContentListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,33 @@
+module org.eclipse.swt.internal.mozilla.nsIURIContentListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+import org.eclipse.swt.internal.mozilla.nsIStreamListener;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+
+const char[] NS_IURICONTENTLISTENER_IID_STR = "94928ab3-8b63-11d3-989d-001083010e9b";
+
+const nsIID NS_IURICONTENTLISTENER_IID= 
+  {0x94928ab3, 0x8b63, 0x11d3, 
+    [ 0x98, 0x9d, 0x00, 0x10, 0x83, 0x01, 0x0e, 0x9b ]};
+
+interface nsIURIContentListener : nsISupports {
+
+  static const char[] IID_STR = NS_IURICONTENTLISTENER_IID_STR;
+  static const nsIID IID = NS_IURICONTENTLISTENER_IID;
+
+extern(System):
+  nsresult OnStartURIOpen(nsIURI aURI, PRBool *_retval);
+  nsresult DoContent(char *aContentType, PRBool aIsContentPreferred, nsIRequest aRequest, nsIStreamListener *aContentHandler, PRBool *_retval);
+  nsresult IsPreferred(char *aContentType, char **aDesiredContentType, PRBool *_retval);
+  nsresult CanHandleContent(char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType, PRBool *_retval);
+  nsresult GetLoadCookie(nsISupports  *aLoadCookie);
+  nsresult SetLoadCookie(nsISupports  aLoadCookie);
+  nsresult GetParentContentListener(nsIURIContentListener  *aParentContentListener);
+  nsresult SetParentContentListener(nsIURIContentListener  aParentContentListener);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIURL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+module org.eclipse.swt.internal.mozilla.nsIURL;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsIURI;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IURL_IID_STR = "d6116970-8034-11d3-9399-00104ba0fd40";
+
+const nsIID NS_IURL_IID= 
+  {0xd6116970, 0x8034, 0x11d3, 
+    [ 0x93, 0x99, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40 ]};
+
+interface nsIURL : nsIURI {
+
+  static const char[] IID_STR = NS_IURL_IID_STR;
+  static const nsIID IID = NS_IURL_IID;
+
+extern(System):
+  nsresult GetFilePath(nsACString * aFilePath);
+  nsresult SetFilePath(nsACString * aFilePath);
+  nsresult GetParam(nsACString * aParam);
+  nsresult SetParam(nsACString * aParam);
+  nsresult GetQuery(nsACString * aQuery);
+  nsresult SetQuery(nsACString * aQuery);
+  nsresult GetRef(nsACString * aRef);
+  nsresult SetRef(nsACString * aRef);
+  nsresult GetDirectory(nsACString * aDirectory);
+  nsresult SetDirectory(nsACString * aDirectory);
+  nsresult GetFileName(nsACString * aFileName);
+  nsresult SetFileName(nsACString * aFileName);
+  nsresult GetFileBaseName(nsACString * aFileBaseName);
+  nsresult SetFileBaseName(nsACString * aFileBaseName);
+  nsresult GetFileExtension(nsACString * aFileExtension);
+  nsresult SetFileExtension(nsACString * aFileExtension);
+  nsresult GetCommonBaseSpec(nsIURI aURIToCompare, nsACString * _retval);
+  nsresult GetRelativeSpec(nsIURI aURIToCompare, nsACString * _retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWeakReference.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,46 @@
+module org.eclipse.swt.internal.mozilla.nsIWeakReference;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_IWEAKREFERENCE_IID_STR = "9188bc85-f92e-11d2-81ef-0060083a0bcf";
+
+const nsIID NS_IWEAKREFERENCE_IID= 
+  {0x9188bc85, 0xf92e, 0x11d2, 
+    [ 0x81, 0xef, 0x00, 0x60, 0x08, 0x3a, 0x0b, 0xcf ]};
+
+interface nsIWeakReference : nsISupports {
+
+  static const char[] IID_STR = NS_IWEAKREFERENCE_IID_STR;
+  static const nsIID IID = NS_IWEAKREFERENCE_IID;
+
+extern(System):
+  nsresult QueryReferent(nsIID * uuid, void * *result);
+
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+const char[] NS_ISUPPORTSWEAKREFERENCE_IID_STR = "9188bc86-f92e-11d2-81ef-0060083a0bcf";
+
+const nsIID NS_ISUPPORTSWEAKREFERENCE_IID= 
+  {0x9188bc86, 0xf92e, 0x11d2, 
+    [ 0x81, 0xef, 0x00, 0x60, 0x08, 0x3a, 0x0b, 0xcf ]};
+
+interface nsISupportsWeakReference : nsISupports {
+
+  static const char[] IID_STR = NS_ISUPPORTSWEAKREFERENCE_IID_STR;
+  static const nsIID IID = NS_ISUPPORTSWEAKREFERENCE_IID;
+
+extern(System):
+  nsresult GetWeakReference(nsIWeakReference *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowser.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,33 @@
+module org.eclipse.swt.internal.mozilla.nsIWebBrowser;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIWebBrowserChrome; 
+import org.eclipse.swt.internal.mozilla.nsIURIContentListener;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+import org.eclipse.swt.internal.mozilla.nsIWeakReference;
+
+const char[] NS_IWEBBROWSER_IID_STR = "69e5df00-7b8b-11d3-af61-00a024ffc08c";
+
+const nsIID NS_IWEBBROWSER_IID= 
+  {0x69e5df00, 0x7b8b, 0x11d3, 
+    [ 0xaf, 0x61, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIWebBrowser : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBBROWSER_IID_STR;
+  static const nsIID IID = NS_IWEBBROWSER_IID;
+
+extern(System):
+  nsresult AddWebBrowserListener(nsIWeakReference aListener, nsIID * aIID);
+  nsresult RemoveWebBrowserListener(nsIWeakReference aListener, nsIID * aIID);
+  nsresult GetContainerWindow(nsIWebBrowserChrome  *aContainerWindow);
+  nsresult SetContainerWindow(nsIWebBrowserChrome  aContainerWindow);
+  nsresult GetParentURIContentListener(nsIURIContentListener  *aParentURIContentListener);
+  nsresult SetParentURIContentListener(nsIURIContentListener  aParentURIContentListener);
+  nsresult GetContentDOMWindow(nsIDOMWindow  *aContentDOMWindow);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChrome.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,63 @@
+module org.eclipse.swt.internal.mozilla.nsIWebBrowserChrome;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIWebBrowser; 
+
+const char[] NS_IWEBBROWSERCHROME_IID_STR = "ba434c60-9d52-11d3-afb0-00a024ffc08c";
+
+const nsIID NS_IWEBBROWSERCHROME_IID= 
+  {0xba434c60, 0x9d52, 0x11d3, 
+    [ 0xaf, 0xb0, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIWebBrowserChrome : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBBROWSERCHROME_IID_STR;
+  static const nsIID IID = NS_IWEBBROWSERCHROME_IID;
+
+extern(System):
+  enum { STATUS_SCRIPT = 1U };
+  enum { STATUS_SCRIPT_DEFAULT = 2U };
+  enum { STATUS_LINK = 3U };
+
+  nsresult SetStatus(PRUint32 statusType, PRUnichar *status);
+  nsresult GetWebBrowser(nsIWebBrowser  *aWebBrowser);
+  nsresult SetWebBrowser(nsIWebBrowser  aWebBrowser);
+
+  enum { CHROME_DEFAULT = 1U };
+  enum { CHROME_WINDOW_BORDERS = 2U };
+  enum { CHROME_WINDOW_CLOSE = 4U };
+  enum { CHROME_WINDOW_RESIZE = 8U };
+  enum { CHROME_MENUBAR = 16U };
+  enum { CHROME_TOOLBAR = 32U };
+  enum { CHROME_LOCATIONBAR = 64U };
+  enum { CHROME_STATUSBAR = 128U };
+  enum { CHROME_PERSONAL_TOOLBAR = 256U };
+  enum { CHROME_SCROLLBARS = 512U };
+  enum { CHROME_TITLEBAR = 1024U };
+  enum { CHROME_EXTRA = 2048U };
+  enum { CHROME_WITH_SIZE = 4096U };
+  enum { CHROME_WITH_POSITION = 8192U };
+  enum { CHROME_WINDOW_MIN = 16384U };
+  enum { CHROME_WINDOW_POPUP = 32768U };
+  enum { CHROME_WINDOW_RAISED = 33554432U };
+  enum { CHROME_WINDOW_LOWERED = 67108864U };
+  enum { CHROME_CENTER_SCREEN = 134217728U };
+  enum { CHROME_DEPENDENT = 268435456U };
+  enum { CHROME_MODAL = 536870912U };
+  enum { CHROME_OPENAS_DIALOG = 1073741824U };
+  enum { CHROME_OPENAS_CHROME = 2147483648U };
+  enum { CHROME_ALL = 4094U };
+
+  nsresult GetChromeFlags(PRUint32 *aChromeFlags);
+  nsresult SetChromeFlags(PRUint32 aChromeFlags);
+  nsresult DestroyBrowserWindow();
+  nsresult SizeBrowserTo(PRInt32 aCX, PRInt32 aCY);
+  nsresult ShowAsModal();
+  nsresult IsWindowModal(PRBool *_retval);
+  nsresult ExitModalEventLoop(nsresult aStatus);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserChromeFocus.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,23 @@
+module org.eclipse.swt.internal.mozilla.nsIWebBrowserChromeFocus;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+const char[] NS_IWEBBROWSERCHROMEFOCUS_IID_STR = "d2206418-1dd1-11b2-8e55-acddcd2bcfb8";
+
+const nsIID NS_IWEBBROWSERCHROMEFOCUS_IID= 
+  {0xd2206418, 0x1dd1, 0x11b2, 
+    [ 0x8e, 0x55, 0xac, 0xdd, 0xcd, 0x2b, 0xcf, 0xb8 ]};
+
+interface nsIWebBrowserChromeFocus : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBBROWSERCHROMEFOCUS_IID_STR;
+  static const nsIID IID = NS_IWEBBROWSERCHROMEFOCUS_IID;
+
+extern(System):
+  nsresult FocusNextElement();
+  nsresult FocusPrevElement();
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebBrowserFocus.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,31 @@
+module org.eclipse.swt.internal.mozilla.nsIWebBrowserFocus;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsIDOMElement;
+
+const char[] NS_IWEBBROWSERFOCUS_IID_STR = "9c5d3c58-1dd1-11b2-a1c9-f3699284657a";
+
+const nsIID NS_IWEBBROWSERFOCUS_IID= 
+  {0x9c5d3c58, 0x1dd1, 0x11b2, 
+    [ 0xa1, 0xc9, 0xf3, 0x69, 0x92, 0x84, 0x65, 0x7a ]};
+
+interface nsIWebBrowserFocus : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBBROWSERFOCUS_IID_STR;
+  static const nsIID IID = NS_IWEBBROWSERFOCUS_IID;
+
+extern(System):
+  nsresult Activate();
+  nsresult Deactivate();
+  nsresult SetFocusAtFirstElement();
+  nsresult SetFocusAtLastElement();
+  nsresult GetFocusedWindow(nsIDOMWindow  *aFocusedWindow);
+  nsresult SetFocusedWindow(nsIDOMWindow  aFocusedWindow);
+  nsresult GetFocusedElement(nsIDOMElement  *aFocusedElement);
+  nsresult SetFocusedElement(nsIDOMElement  aFocusedElement);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebNavigation.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,59 @@
+module org.eclipse.swt.internal.mozilla.nsIWebNavigation;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMDocument;
+import org.eclipse.swt.internal.mozilla.nsIInputStream;
+import org.eclipse.swt.internal.mozilla.nsISHistory; 
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+
+const char[] NS_IWEBNAVIGATION_IID_STR = "f5d9e7b0-d930-11d3-b057-00a024ffc08c";
+
+const nsIID NS_IWEBNAVIGATION_IID= 
+  {0xf5d9e7b0, 0xd930, 0x11d3, 
+    [ 0xb0, 0x57, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIWebNavigation : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBNAVIGATION_IID_STR;
+  static const nsIID IID = NS_IWEBNAVIGATION_IID;
+
+extern(System):
+  nsresult GetCanGoBack(PRBool *aCanGoBack);
+  nsresult GetCanGoForward(PRBool *aCanGoForward);
+  nsresult GoBack();
+  nsresult GoForward();
+  nsresult GotoIndex(PRInt32 index);
+
+  enum { LOAD_FLAGS_MASK = 65535U };
+  enum { LOAD_FLAGS_NONE = 0U };
+  enum { LOAD_FLAGS_IS_REFRESH = 16U };
+  enum { LOAD_FLAGS_IS_LINK = 32U };
+  enum { LOAD_FLAGS_BYPASS_HISTORY = 64U };
+  enum { LOAD_FLAGS_REPLACE_HISTORY = 128U };
+  enum { LOAD_FLAGS_BYPASS_CACHE = 256U };
+  enum { LOAD_FLAGS_BYPASS_PROXY = 512U };
+  enum { LOAD_FLAGS_CHARSET_CHANGE = 1024U };
+  enum { LOAD_FLAGS_STOP_CONTENT = 2048U };
+  enum { LOAD_FLAGS_FROM_EXTERNAL = 4096U };
+  enum { LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 8192U };
+  enum { LOAD_FLAGS_FIRST_LOAD = 16384U };
+
+  nsresult LoadURI(PRUnichar *aURI, PRUint32 aLoadFlags, nsIURI aReferrer, nsIInputStream aPostData, nsIInputStream aHeaders);
+  nsresult Reload(PRUint32 aReloadFlags);
+
+  enum { STOP_NETWORK = 1U };
+  enum { STOP_CONTENT = 2U };
+  enum { STOP_ALL = 3U };
+
+  nsresult Stop(PRUint32 aStopFlags);
+  nsresult GetDocument(nsIDOMDocument  *aDocument);
+  nsresult GetCurrentURI(nsIURI  *aCurrentURI);
+  nsresult GetReferringURI(nsIURI  *aReferringURI);
+  nsresult GetSessionHistory(nsISHistory  *aSessionHistory);
+  nsresult SetSessionHistory(nsISHistory  aSessionHistory);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebNavigationInfo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,29 @@
+module org.eclipse.swt.internal.mozilla.nsIWebNavigationInfo;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+import org.eclipse.swt.internal.mozilla.nsIWebNavigation;
+import org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+const char[] NS_IWEBNAVIGATIONINFO_IID_STR = "62a93afb-93a1-465c-84c8-0432264229de";
+
+const nsIID NS_IWEBNAVIGATIONINFO_IID= 
+  {0x62a93afb, 0x93a1, 0x465c, 
+    [ 0x84, 0xc8, 0x04, 0x32, 0x26, 0x42, 0x29, 0xde ]};
+
+interface nsIWebNavigationInfo : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBNAVIGATIONINFO_IID_STR;
+  static const nsIID IID = NS_IWEBNAVIGATIONINFO_IID;
+
+extern(System):
+  enum { UNSUPPORTED = 0U };
+  enum { IMAGE = 1U };
+  enum { PLUGIN = 2U };
+  enum { OTHER = 32768U };
+
+  nsresult IsTypeSupported(nsACString * aType, nsIWebNavigation aWebNav, PRUint32 *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgress.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,39 @@
+module org.eclipse.swt.internal.mozilla.nsIWebProgress;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow; 
+import org.eclipse.swt.internal.mozilla.nsIWebProgressListener; 
+
+const char[] NS_IWEBPROGRESS_IID_STR = "570f39d0-efd0-11d3-b093-00a024ffc08c";
+
+const nsIID NS_IWEBPROGRESS_IID= 
+  {0x570f39d0, 0xefd0, 0x11d3, 
+    [ 0xb0, 0x93, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIWebProgress : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBPROGRESS_IID_STR;
+  static const nsIID IID = NS_IWEBPROGRESS_IID;
+
+extern(System):
+  enum { NOTIFY_STATE_REQUEST = 1U };
+  enum { NOTIFY_STATE_DOCUMENT = 2U };
+  enum { NOTIFY_STATE_NETWORK = 4U };
+  enum { NOTIFY_STATE_WINDOW = 8U };
+  enum { NOTIFY_STATE_ALL = 15U };
+  enum { NOTIFY_PROGRESS = 16U };
+  enum { NOTIFY_STATUS = 32U };
+  enum { NOTIFY_SECURITY = 64U };
+  enum { NOTIFY_LOCATION = 128U };
+  enum { NOTIFY_ALL = 255U };
+
+  nsresult AddProgressListener(nsIWebProgressListener aListener, PRUint32 aNotifyMask);
+  nsresult RemoveProgressListener(nsIWebProgressListener aListener);
+  nsresult GetDOMWindow(nsIDOMWindow  *aDOMWindow);
+  nsresult GetIsLoadingDocument(PRBool *aIsLoadingDocument);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,47 @@
+module org.eclipse.swt.internal.mozilla.nsIWebProgressListener;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIWebProgress;
+import org.eclipse.swt.internal.mozilla.nsIRequest; 
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+
+const char[] NS_IWEBPROGRESSLISTENER_IID_STR = "570f39d1-efd0-11d3-b093-00a024ffc08c";
+
+const nsIID NS_IWEBPROGRESSLISTENER_IID= 
+  {0x570f39d1, 0xefd0, 0x11d3, 
+    [ 0xb0, 0x93, 0x00, 0xa0, 0x24, 0xff, 0xc0, 0x8c ]};
+
+interface nsIWebProgressListener : nsISupports {
+
+  static const char[] IID_STR = NS_IWEBPROGRESSLISTENER_IID_STR;
+  static const nsIID IID = NS_IWEBPROGRESSLISTENER_IID;
+
+extern(System):
+  enum { STATE_START = 1U };
+  enum { STATE_REDIRECTING = 2U };
+  enum { STATE_TRANSFERRING = 4U };
+  enum { STATE_NEGOTIATING = 8U };
+  enum { STATE_STOP = 16U };
+  enum { STATE_IS_REQUEST = 65536U };
+  enum { STATE_IS_DOCUMENT = 131072U };
+  enum { STATE_IS_NETWORK = 262144U };
+  enum { STATE_IS_WINDOW = 524288U };
+  enum { STATE_RESTORING = 16777216U };
+  enum { STATE_IS_INSECURE = 4U };
+  enum { STATE_IS_BROKEN = 1U };
+  enum { STATE_IS_SECURE = 2U };
+  enum { STATE_SECURE_HIGH = 262144U };
+  enum { STATE_SECURE_MED = 65536U };
+  enum { STATE_SECURE_LOW = 131072U };
+
+  nsresult OnStateChange(nsIWebProgress aWebProgress, nsIRequest aRequest, PRUint32 aStateFlags, nsresult aStatus);
+  nsresult OnProgressChange(nsIWebProgress aWebProgress, nsIRequest aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress);
+  nsresult OnLocationChange(nsIWebProgress aWebProgress, nsIRequest aRequest, nsIURI aLocation);
+  nsresult OnStatusChange(nsIWebProgress aWebProgress, nsIRequest aRequest, nsresult aStatus, PRUnichar *aMessage);
+  nsresult OnSecurityChange(nsIWebProgress aWebProgress, nsIRequest aRequest, PRUint32 aState);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWebProgressListener2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+module org.eclipse.swt.internal.mozilla.nsIWebProgressListener2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIWebProgressListener;
+import org.eclipse.swt.internal.mozilla.nsIWebProgress;
+import org.eclipse.swt.internal.mozilla.nsIRequest;
+
+const char[] NS_IWEBPROGRESSLISTENER2_IID_STR = "3f24610d-1e1f-4151-9d2e-239884742324";
+
+const nsIID NS_IWEBPROGRESSLISTENER2_IID= 
+  {0x3f24610d, 0x1e1f, 0x4151, 
+    [ 0x9d, 0x2e, 0x23, 0x98, 0x84, 0x74, 0x23, 0x24 ]};
+
+interface nsIWebProgressListener2 : nsIWebProgressListener {
+
+  static const char[] IID_STR = NS_IWEBPROGRESSLISTENER2_IID_STR;
+  static const nsIID IID = NS_IWEBPROGRESSLISTENER2_IID;
+
+extern(System):
+  nsresult OnProgressChange64(nsIWebProgress aWebProgress, nsIRequest aRequest, PRInt64 aCurSelfProgress, PRInt64 aMaxSelfProgress, PRInt64 aCurTotalProgress, PRInt64 aMaxTotalProgress);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,24 @@
+module org.eclipse.swt.internal.mozilla.nsIWindowCreator;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIWebBrowserChrome;
+
+const char[] NS_IWINDOWCREATOR_IID_STR = "30465632-a777-44cc-90f9-8145475ef999";
+
+const nsIID NS_IWINDOWCREATOR_IID= 
+  {0x30465632, 0xa777, 0x44cc, 
+    [ 0x90, 0xf9, 0x81, 0x45, 0x47, 0x5e, 0xf9, 0x99 ]};
+
+interface nsIWindowCreator : nsISupports {
+
+  static const char[] IID_STR = NS_IWINDOWCREATOR_IID_STR;
+  static const nsIID IID = NS_IWINDOWCREATOR_IID;
+
+extern(System):
+  nsresult CreateChromeWindow(nsIWebBrowserChrome parent, PRUint32 chromeFlags, nsIWebBrowserChrome *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowCreator2.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.mozilla.nsIWindowCreator2;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+
+import org.eclipse.swt.internal.mozilla.nsIWindowCreator;
+import org.eclipse.swt.internal.mozilla.nsIURI; 
+import org.eclipse.swt.internal.mozilla.nsIWebBrowserChrome;
+
+const char[] NS_IWINDOWCREATOR2_IID_STR = "f673ec81-a4b0-11d6-964b-eb5a2bf216fc";
+
+const nsIID NS_IWINDOWCREATOR2_IID= 
+  {0xf673ec81, 0xa4b0, 0x11d6, 
+    [ 0x96, 0x4b, 0xeb, 0x5a, 0x2b, 0xf2, 0x16, 0xfc ]};
+
+interface nsIWindowCreator2 : nsIWindowCreator {
+
+  static const char[] IID_STR = NS_IWINDOWCREATOR2_IID_STR;
+  static const nsIID IID = NS_IWINDOWCREATOR2_IID;
+
+extern(System):
+  enum { PARENT_IS_LOADING_OR_RUNNING_TIMEOUT = 1U };
+  nsresult CreateChromeWindow2(nsIWebBrowserChrome parent, PRUint32 chromeFlags, PRUint32 contextFlags, nsIURI uri, PRBool *cancel, nsIWebBrowserChrome *_retval);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsIWindowWatcher.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+module org.eclipse.swt.internal.mozilla.nsIWindowWatcher;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.nsID;
+import org.eclipse.swt.internal.mozilla.nsISupports;
+
+import org.eclipse.swt.internal.mozilla.nsIDOMWindow;
+import org.eclipse.swt.internal.mozilla.nsIObserver; 
+import org.eclipse.swt.internal.mozilla.nsIPrompt; 
+import org.eclipse.swt.internal.mozilla.nsIAuthPrompt;
+import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
+import org.eclipse.swt.internal.mozilla.nsIWebBrowserChrome;
+import org.eclipse.swt.internal.mozilla.nsIWindowCreator; 
+
+const char[] NS_IWINDOWWATCHER_IID_STR = "002286a8-494b-43b3-8ddd-49e3fc50622b";
+
+const nsIID NS_IWINDOWWATCHER_IID= 
+  {0x002286a8, 0x494b, 0x43b3, 
+    [ 0x8d, 0xdd, 0x49, 0xe3, 0xfc, 0x50, 0x62, 0x2b ]};
+
+interface nsIWindowWatcher : nsISupports {
+
+  static const char[] IID_STR = NS_IWINDOWWATCHER_IID_STR;
+  static const nsIID IID = NS_IWINDOWWATCHER_IID;
+
+extern(System):
+  nsresult OpenWindow(nsIDOMWindow aParent, char *aUrl, char *aName, char *aFeatures, nsISupports aArguments, nsIDOMWindow *_retval);
+  nsresult RegisterNotification(nsIObserver aObserver);
+  nsresult UnregisterNotification(nsIObserver aObserver);
+  nsresult GetWindowEnumerator(nsISimpleEnumerator *_retval);
+  nsresult GetNewPrompter(nsIDOMWindow aParent, nsIPrompt *_retval);
+  nsresult GetNewAuthPrompter(nsIDOMWindow aParent, nsIAuthPrompt *_retval);
+  nsresult SetWindowCreator(nsIWindowCreator creator);
+  nsresult GetChromeForWindow(nsIDOMWindow aWindow, nsIWebBrowserChrome *_retval);
+  nsresult GetWindowByName(PRUnichar *aTargetName, nsIDOMWindow aCurrentWindow, nsIDOMWindow *_retval);
+  nsresult GetActiveWindow(nsIDOMWindow  *aActiveWindow);
+  nsresult SetActiveWindow(nsIDOMWindow  aActiveWindow);
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/nsStringAPI.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,191 @@
+module org.eclipse.swt.internal.mozilla.nsStringAPI;
+
+import Utf = tango.text.convert.Utf;
+import org.eclipse.swt.internal.mozilla.Common;
+
+extern (System):
+
+/******************************************************************************
+
+******************************************************************************/
+
+enum
+{
+    NS_STRING_CONTAINER_INIT_DEPEND = 2,
+    NS_STRING_CONTAINER_INIT_ADOPT = 4,
+    NS_STRING_CONTAINER_INIT_SUBSTRING = 8,
+}
+
+nsresult    NS_StringContainerInit ( nsStringContainer *aContainer );
+nsresult    NS_StringContainerInit2( nsStringContainer *aContainer, PRUnichar *aData, PRUint32                                      aDataLength, PRUint32 aFlags );
+void        NS_StringContainerFinish(nsStringContainer *aContainer);
+PRUint32    NS_StringGetData(nsAString *aStr, PRUnichar **aData, PRBool *aTerminated);
+PRUint32    NS_StringGetMutableData(nsAString *aStr, PRUint32 aDataLength, PRUnichar **aData);
+PRUnichar * NS_StringCloneData(nsAString *aStr);
+nsresult    NS_StringSetData(nsAString *aStr, PRUnichar *aData, PRUint32 aDataLength);
+nsresult    NS_StringSetDataRange( nsAString *aStr, PRUint32 aCutOffset, PRUint32 aCutLength,                                     PRUnichar *aData, PRUint32 aDataLength );
+nsresult    NS_StringCopy(nsAString *aDestStr, nsAString *aSrcStr);
+
+/******************************************************************************
+
+******************************************************************************/
+
+enum
+{
+    NS_CSTRING_CONTAINER_INIT_DEPEND = 2,
+    NS_CSTRING_CONTAINER_INIT_ADOPT = 4,
+    NS_CSTRING_CONTAINER_INIT_SUBSTRING = 8,
+}
+
+nsresult    NS_CStringContainerInit( nsCStringContainer *aContainer );
+nsresult    NS_CStringContainerInit2( nsCStringContainer *aContainer, char *aData, PRUint32                                          aDataLength, PRUint32 aFlags );
+void        NS_CStringContainerFinish( nsCStringContainer *aContainer );
+PRUint32    NS_CStringGetData( nsACString *aStr, char **aData, PRBool *aTerminated );
+PRUint32    NS_CStringGetMutableData( nsACString *aStr, PRUint32 aDataLength, char **aData );
+char *      NS_CStringCloneData( nsACString *aStr);
+nsresult    NS_CStringSetData( nsACString *aStr, char *aData, PRUint32 aDataLength );
+nsresult    NS_CStringSetDataRange( nsACString *aStr, PRUint32 aCutOffset, 
+                                    PRUint32 aCutLength, char *aData, PRUint32 aDataLength );
+nsresult    NS_CStringCopy( nsACString *aDestStr, nsACString *aSrcStr );
+
+/******************************************************************************
+
+******************************************************************************/
+
+enum nsCStringEncoding
+{
+    NS_CSTRING_ENCODING_ASCII,
+    NS_CSTRING_ENCODING_UTF8,
+    NS_CSTRING_ENCODING_NATIVE_FILESYSTEM,
+}
+
+nsresult    NS_CStringToUTF16( nsACString *aSource, int aSrcEncoding, nsAString *aDest );
+nsresult    NS_UTF16ToCString( nsAString *aSource, int aDestEncoding, nsACString *aDest );
+
+/******************************************************************************
+
+******************************************************************************/
+
+alias nsAString nsAString_external;
+alias nsACString nsACString_external;
+
+//alias nsAString nsEmbedString;
+//alias nsACString nsEmbedCString;
+
+struct nsAString
+{
+
+    static nsAString opCall(wchar[] s)
+    {
+        nsAString result;
+        NS_StringSetData(&result, cast(PRUnichar*)s, uint.max);
+        return result;
+    }
+
+    static wchar[] toString16( nsAString* str )
+    {
+        wchar* buffer = null;
+		PRBool terminated;
+		uint len = NS_StringGetData(str, &buffer, &terminated);
+		return buffer[0 .. len].dup;
+    }
+    
+    static char[] toString( nsAString* str )
+    {
+        return Utf.toString( nsAString.toString16( str ) );
+    }
+
+  private:
+    void *v;
+}
+
+struct nsACString
+{
+/+
+  static nsACString opCall(char[] s)
+  {
+    nsACString result;
+    NS_CStringSetData(&result, cast(char*)s, uint.max);
+    return result;
+  }
++/
+  private:
+    void *v;
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+struct nsStringContainer// : public nsAString
+{
+private:
+	void* v;
+	void* d1;
+	uint  d2;
+	void* d3;
+}
+
+struct nsCStringContainer// : public nsACString
+{
+private:
+	void* v;
+	void* d1;
+	uint  d2;
+	void* d3;
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+// import mozilla.xpcom.nsDebug;
+
+alias nsString_external     nsString;
+alias nsCString_external    nsCString;
+alias nsDependentString_external nsDependentString;
+alias nsDependentCString_external nsDependentCString;
+alias NS_ConvertASCIItoUTF16_external NS_ConvertASCIItoUTF16;
+alias NS_ConvertUTF8toUTF16_external NS_ConvertUTF8toUTF16;
+alias NS_ConvertUTF16toUTF8_external NS_ConvertUTF16toUTF8;
+alias NS_LossyConvertUTF16toASCII_external NS_LossyConvertUTF16toASCII;
+alias nsGetterCopies_external nsGetterCopies;
+alias nsCGetterCopies_external nsCGetterCopies;
+alias nsDependentSubstring_external nsDependentSubstring;
+alias nsDependentCSubstring_external nsDependentCSubstring;
+
+struct nsString_external{}
+struct nsCString_external{}
+struct nsDependentString_external{}
+struct nsDependentCString_external{}
+struct NS_ConvertASCIItoUTF16_external{}
+struct NS_ConvertUTF8toUTF16_external{}
+struct NS_ConvertUTF16toUTF8_external{}
+struct NS_LossyConvertUTF16toASCII_external{}
+
+/******************************************************************************
+
+******************************************************************************/
+
+struct nsGetterCopies_external
+{
+  private:
+	alias PRUnichar char_type;
+    nsString_external *mString;
+    char_type *mData;
+}
+
+struct nsCGetterCopies_external
+{
+  private:
+	alias char char_type;
+    nsCString_external *mString;
+    char_type *mData;
+}
+
+/******************************************************************************
+
+******************************************************************************/
+
+struct nsDependentSubstring_external{}
+struct nsDependentCSubstring_external{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prinrval.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+module org.eclipse.swt.internal.mozilla.prinrval;
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+import org.eclipse.swt.internal.mozilla.Common;
+
+extern (System):
+
+alias PRUint32 PRIntervalTime;
+
+const PR_INTERVAL_MIN = 1000U;
+const PR_INTERVAL_MAX = 100000U;
+const PR_INTERVAL_NO_WAIT = 0U;
+const PR_INTERVAL_NO_TIMEOUT = 0xffffffffU;
+
+version(NON_XPCOM_GLUE)
+{
+    PRIntervalTime  PR_IntervalNow();
+    PRUint32        PR_TicksPerSecond();
+    PRIntervalTime  PR_SecondsToInterval(PRUint32 seconds);
+    PRIntervalTime  PR_MillisecondsToInterval(PRUint32 milli);
+    PRIntervalTime  PR_MicrosecondsToInterval(PRUint32 micro);
+    PRUint32  PR_IntervalToSeconds(PRIntervalTime ticks);
+    PRUint32  PR_IntervalToMilliseconds(PRIntervalTime ticks);
+    PRUint32  PR_IntervalToMicroseconds(PRIntervalTime ticks);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prio.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,517 @@
+module org.eclipse.swt.internal.mozilla.prio;
+
+import org.eclipse.swt.internal.mozilla.Common;
+import org.eclipse.swt.internal.mozilla.prtime;
+import org.eclipse.swt.internal.mozilla.prinrval;
+
+extern (System):
+
+alias PRIntn PRDescIdentity;
+alias void   PRFilePrivate;
+
+struct PRFileDesc
+{
+    PRIOMethods *methods;
+    PRFilePrivate *secret;
+    PRFileDesc *lower;
+    PRFileDesc *higher;
+    void  function(PRFileDesc *fd)dtor;
+    PRDescIdentity identity;
+}
+
+enum PRTransmitFileFlags
+{
+    PR_TRANSMITFILE_KEEP_OPEN,
+    PR_TRANSMITFILE_CLOSE_SOCKET,
+}
+
+const PR_AF_INET = 2;
+const PR_AF_LOCAL = 1;
+const PR_INADDR_LOOPBACK = 0x7f000001;
+const PR_AF_UNSPEC = 0;
+
+union _N2
+{
+    PRUint8 [16]_S6_u8;
+    PRUint16 [8]_S6_u16;
+    PRUint32 [4]_S6_u32;
+    PRUint64 [2]_S6_u64;
+}
+
+struct PRIPv6Addr
+{
+	struct _N2{
+		union
+		{
+			PRUint8 [16]_S6_u8;
+			PRUint16 [8]_S6_u16;
+			PRUint32 [4]_S6_u32;
+			PRUint64 [2]_S6_u64;
+		}
+	}
+	_N2 _S6_un;
+}
+
+struct _N3
+{
+    PRUint16 family;
+    char [14]data;
+}
+
+struct _N4
+{
+    PRUint16 family;
+    PRUint16 port;
+    PRUint32 ip;
+    char [8]pad;
+}
+
+struct _N5
+{
+    PRUint16 family;
+    PRUint16 port;
+    PRUint32 flowinfo;
+    PRIPv6Addr ip;
+    PRUint32 scope_id;
+}
+
+union PRNetAddr
+{
+    struct _N3
+    {
+        PRUint16 family;
+        char [14]data;
+    }
+    _N3 raw;
+    struct _N4
+    {
+        PRUint16 family;
+        PRUint16 port;
+        PRUint32 ip;
+        char [8]pad;
+    }
+    _N4 inet;
+    struct _N5
+    {
+        PRUint16 family;
+        PRUint16 port;
+        PRUint32 flowinfo;
+        PRIPv6Addr ip;
+        PRUint32 scope_id;
+    }
+    _N5 ipv6;
+}
+
+enum PRSockOption
+{
+    PR_SockOpt_Nonblocking,
+    PR_SockOpt_Linger,
+    PR_SockOpt_Reuseaddr,
+    PR_SockOpt_Keepalive,
+    PR_SockOpt_RecvBufferSize,
+    PR_SockOpt_SendBufferSize,
+    PR_SockOpt_IpTimeToLive,
+    PR_SockOpt_IpTypeOfService,
+    PR_SockOpt_AddMember,
+    PR_SockOpt_DropMember,
+    PR_SockOpt_McastInterface,
+    PR_SockOpt_McastTimeToLive,
+    PR_SockOpt_McastLoopback,
+    PR_SockOpt_NoDelay,
+    PR_SockOpt_MaxSegment,
+    PR_SockOpt_Broadcast,
+    PR_SockOpt_Last,
+}
+
+struct PRLinger
+{
+    PRBool polarity;
+    PRIntervalTime linger;
+}
+
+struct PRMcastRequest
+{
+    PRNetAddr mcaddr;
+    PRNetAddr ifaddr;
+}
+
+union _N6
+{
+    PRUintn ip_ttl;
+    PRUintn mcast_ttl;
+    PRUintn tos;
+    PRBool non_blocking;
+    PRBool reuse_addr;
+    PRBool keep_alive;
+    PRBool mcast_loopback;
+    PRBool no_delay;
+    PRBool broadcast;
+    PRSize max_segment;
+    PRSize recv_buffer_size;
+    PRSize send_buffer_size;
+    PRLinger linger;
+    PRMcastRequest add_member;
+    PRMcastRequest drop_member;
+    PRNetAddr mcast_if;
+}
+
+struct PRSocketOptionData
+{
+    int option;
+    union _N6
+    {
+        PRUintn ip_ttl;
+        PRUintn mcast_ttl;
+        PRUintn tos;
+        PRBool non_blocking;
+        PRBool reuse_addr;
+        PRBool keep_alive;
+        PRBool mcast_loopback;
+        PRBool no_delay;
+        PRBool broadcast;
+        PRSize max_segment;
+        PRSize recv_buffer_size;
+        PRSize send_buffer_size;
+        PRLinger linger;
+        PRMcastRequest add_member;
+        PRMcastRequest drop_member;
+        PRNetAddr mcast_if;
+    }
+    _N6 value;
+}
+
+struct PRIOVec
+{
+    char *iov_base;
+    int iov_len;
+}
+
+enum PRDescType
+{
+    PR_DESC_FILE = 1,
+    PR_DESC_SOCKET_TCP,
+    PR_DESC_SOCKET_UDP,
+    PR_DESC_LAYERED,
+    PR_DESC_PIPE,
+}
+
+enum PRSeekWhence
+{
+    PR_SEEK_SET,
+    PR_SEEK_CUR,
+    PR_SEEK_END,
+}
+
+version(NON_XPCOM_GLUE){
+    int  PR_GetDescType(PRFileDesc *file);
+}
+
+alias PRStatus  function(PRFileDesc *fd)PRCloseFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount)PRReadFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount)PRWriteFN;
+alias PRInt32  function(PRFileDesc *fd)PRAvailableFN;
+alias PRInt64  function(PRFileDesc *fd)PRAvailable64FN;
+alias PRStatus  function(PRFileDesc *fd)PRFsyncFN;
+alias PROffset32  function(PRFileDesc *fd, PROffset32 offset, int how)PRSeekFN;
+alias PROffset64  function(PRFileDesc *fd, PROffset64 offset, int how)PRSeek64FN;
+alias PRStatus  function(PRFileDesc *fd, PRFileInfo *info)PRFileInfoFN;
+alias PRStatus  function(PRFileDesc *fd, PRFileInfo64 *info)PRFileInfo64FN;
+alias PRInt32  function(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout)PRWritevFN;
+alias PRStatus  function(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)PRConnectFN;
+alias PRFileDesc * function(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)PRAcceptFN;
+alias PRStatus  function(PRFileDesc *fd, PRNetAddr *addr)PRBindFN;
+alias PRStatus  function(PRFileDesc *fd, PRIntn backlog)PRListenFN;
+alias PRStatus  function(PRFileDesc *fd, PRIntn how)PRShutdownFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)PRRecvFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout)PRSendFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)PRRecvfromFN;
+alias PRInt32  function(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)PRSendtoFN;
+alias PRInt16  function(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)PRPollFN;
+alias PRInt32  function(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t)PRAcceptreadFN;
+alias PRInt32  function(PRFileDesc *sd, PRFileDesc *fd, void *headers, PRInt32 hlen, int flags, PRIntervalTime t)PRTransmitfileFN;
+alias PRStatus  function(PRFileDesc *fd, PRNetAddr *addr)PRGetsocknameFN;
+alias PRStatus  function(PRFileDesc *fd, PRNetAddr *addr)PRGetpeernameFN;
+alias PRStatus  function(PRFileDesc *fd, PRSocketOptionData *data)PRGetsocketoptionFN;
+alias PRStatus  function(PRFileDesc *fd, PRSocketOptionData *data)PRSetsocketoptionFN;
+alias PRInt32  function(PRFileDesc *networkSocket, PRSendFileData *sendData, int flags, PRIntervalTime timeout)PRSendfileFN;
+alias PRStatus  function(PRFileDesc *fd, PRInt16 out_flags)PRConnectcontinueFN;
+alias PRIntn  function(PRFileDesc *fd)PRReservedFN;
+
+struct PRIOMethods
+{
+    int file_type;
+    PRCloseFN close;
+    PRReadFN read;
+    PRWriteFN write;
+    PRAvailableFN available;
+    PRAvailable64FN available64;
+    PRFsyncFN fsync;
+    PRSeekFN seek;
+    PRSeek64FN seek64;
+    PRFileInfoFN fileInfo;
+    PRFileInfo64FN fileInfo64;
+    PRWritevFN writev;
+    PRConnectFN connect;
+    PRAcceptFN accept;
+    PRBindFN bind;
+    PRListenFN listen;
+    PRShutdownFN shutdown;
+    PRRecvFN recv;
+    PRSendFN send;
+    PRRecvfromFN recvfrom;
+    PRSendtoFN sendto;
+    PRPollFN poll;
+    PRAcceptreadFN acceptread;
+    PRTransmitfileFN transmitfile;
+    PRGetsocknameFN getsockname;
+    PRGetpeernameFN getpeername;
+    PRReservedFN reserved_fn_6;
+    PRReservedFN reserved_fn_5;
+    PRGetsocketoptionFN getsocketoption;
+    PRSetsocketoptionFN setsocketoption;
+    PRSendfileFN sendfile;
+    PRConnectcontinueFN connectcontinue;
+    PRReservedFN reserved_fn_3;
+    PRReservedFN reserved_fn_2;
+    PRReservedFN reserved_fn_1;
+    PRReservedFN reserved_fn_0;
+}
+
+enum PRSpecialFD
+{
+    PR_StandardInput,
+    PR_StandardOutput,
+    PR_StandardError,
+}
+
+version(NON_XPCOM_GLUE)
+{
+    PRFileDesc *    PR_GetSpecialFD(int id);
+    PRDescIdentity  PR_GetUniqueIdentity(char *layer_name);
+    char *          PR_GetNameForIdentity(PRDescIdentity ident);
+    PRDescIdentity  PR_GetLayersIdentity(PRFileDesc *fd);
+    PRFileDesc *    PR_GetIdentitiesLayer(PRFileDesc *fd_stack, PRDescIdentity id);
+    PRIOMethods *   PR_GetDefaultIOMethods();
+    PRFileDesc *    PR_CreateIOLayerStub(PRDescIdentity ident, PRIOMethods *methods);
+    PRFileDesc *    PR_CreateIOLayer(PRFileDesc *fd);
+    PRStatus        PR_PushIOLayer(PRFileDesc *fd_stack, PRDescIdentity id, PRFileDesc *layer);
+    PRFileDesc *    PR_PopIOLayer(PRFileDesc *fd_stack, PRDescIdentity id);
+}
+
+const PR_RDONLY = 0x01;
+const PR_WRONLY = 0x02;
+const PR_RDWR = 0x04;
+const PR_CREATE_FILE = 0x08;
+const PR_APPEND = 0x10;
+const PR_TRUNCATE = 0x20;
+const PR_SYNC = 0x40;
+const PR_EXCL = 0x80;
+
+version(NON_XPCOM_GLUE) {
+    PRFileDesc * PR_Open(char *name, PRIntn flags, PRIntn mode);
+}
+
+const PR_IRWXU = 00700;
+const PR_IRUSR = 00400;
+const PR_IWUSR = 00200;
+const PR_IXUSR = 00100;
+const PR_IRWXG = 00070;
+const PR_IRGRP = 00040;
+const PR_IWGRP = 00020;
+const PR_IXGRP = 00010;
+const PR_IRWXO = 00007;
+const PR_IROTH = 00004;
+const PR_IWOTH = 00002;
+const PR_IXOTH = 00001;
+
+version(NON_XPCOM_GLUE)
+{
+    PRFileDesc *    PR_OpenFile(char *name, PRIntn flags, PRIntn mode);
+    PRStatus        PR_Close(PRFileDesc *fd);
+    PRInt32         PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount);
+    PRInt32         PR_Write(PRFileDesc *fd, void *buf, PRInt32 amount);
+}
+
+const PR_MAX_IOVECTOR_SIZE = 16;
+
+version(NON_XPCOM_GLUE)
+{
+    PRInt32     PR_Writev(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout);
+    PRStatus    PR_Delete(char *name);
+}
+
+enum PRFileType
+{
+    PR_FILE_FILE = 1,
+    PR_FILE_DIRECTORY,
+    PR_FILE_OTHER,
+}
+
+struct PRFileInfo
+{
+    int type;
+    PROffset32 size;
+    PRTime creationTime;
+    PRTime modifyTime;
+}
+
+struct PRFileInfo64
+{
+    int type;
+    PROffset64 size;
+    PRTime creationTime;
+    PRTime modifyTime;
+}
+
+version (NON_XPCOM_GLUE)
+{
+    PRStatus  PR_GetFileInfo(char *fn, PRFileInfo *info);
+    PRStatus  PR_GetFileInfo64(char *fn, PRFileInfo64 *info);
+    PRStatus  PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info);
+    PRStatus  PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info);
+    PRStatus  PR_Rename(char *from, char *to);
+}
+
+enum PRAccessHow
+{
+    PR_ACCESS_EXISTS = 1,
+    PR_ACCESS_WRITE_OK,
+    PR_ACCESS_READ_OK,
+}
+
+version(NON_XPCOM_GLUE)
+{
+    PRStatus    PR_Access(char *name, int how);
+    PROffset32  PR_Seek(PRFileDesc *fd, PROffset32 offset, int whence);
+    PROffset64  PR_Seek64(PRFileDesc *fd, PROffset64 offset, int whence);
+    PRInt32     PR_Available(PRFileDesc *fd);
+    PRInt64     PR_Available64(PRFileDesc *fd);
+    PRStatus    PR_Sync(PRFileDesc *fd);
+}
+
+struct PRDirEntry
+{
+    char *name;
+}
+
+alias void PRDir;
+
+version(NON_XPCOM_GLUE) {
+    PRDir * PR_OpenDir(char *name);
+}
+
+enum PRDirFlags
+{
+    PR_SKIP_NONE,
+    PR_SKIP_DOT,
+    PR_SKIP_DOT_DOT,
+    PR_SKIP_BOTH,
+    PR_SKIP_HIDDEN,
+}
+
+version(NON_XPCOM_GLUE)
+{
+    PRDirEntry *    PR_ReadDir(PRDir *dir, int flags);
+    PRStatus        PR_CloseDir(PRDir *dir);
+    PRStatus        PR_MkDir(char *name, PRIntn mode);
+    PRStatus        PR_MakeDir(char *name, PRIntn mode);
+    PRStatus        PR_RmDir(char *name);
+    PRFileDesc *    PR_NewUDPSocket();
+    PRFileDesc *    PR_NewTCPSocket();
+    PRFileDesc *    PR_OpenUDPSocket(PRIntn af);
+    PRFileDesc *    PR_OpenTCPSocket(PRIntn af);
+    PRStatus        PR_Connect(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout);
+    PRStatus        PR_ConnectContinue(PRFileDesc *fd, PRInt16 out_flags);
+    PRStatus        PR_GetConnectStatus(PRPollDesc *pd);
+    PRFileDesc *    PR_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout);
+    PRStatus        PR_Bind(PRFileDesc *fd, PRNetAddr *addr);
+    PRStatus        PR_Listen(PRFileDesc *fd, PRIntn backlog);
+}
+
+enum PRShutdownHow
+{
+    PR_SHUTDOWN_RCV,
+    PR_SHUTDOWN_SEND,
+    PR_SHUTDOWN_BOTH,
+}
+
+version(NON_XPCOM_GLUE) {
+    PRStatus  PR_Shutdown(PRFileDesc *fd, int how);
+}
+
+const PR_MSG_PEEK = 0x2;
+
+version(NON_XPCOM_GLUE)
+{
+    PRInt32  PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout);
+    PRInt32  PR_Send(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout);
+    PRInt32  PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout);
+    PRInt32  PR_SendTo(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout);
+    PRInt32  PR_TransmitFile(PRFileDesc *networkSocket, PRFileDesc *sourceFile, void *headers, PRInt32 hlen, int flags, PRIntervalTime timeout);
+}
+
+struct PRSendFileData
+{
+    PRFileDesc *fd;
+    PRUint32 file_offset;
+    PRSize file_nbytes;
+    void *header;
+    PRInt32 hlen;
+    void *trailer;
+    PRInt32 tlen;
+}
+
+version(NON_XPCOM_GLUE)
+{
+    PRInt32   PR_SendFile(PRFileDesc *networkSocket, PRSendFileData *sendData, int flags, PRIntervalTime timeout);
+    PRInt32   PR_AcceptRead(PRFileDesc *listenSock, PRFileDesc **acceptedSock, PRNetAddr **peerAddr, void *buf, PRInt32 amount, PRIntervalTime timeout);
+    PRStatus  PR_NewTCPSocketPair(PRFileDesc **fds);
+    PRStatus  PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr);
+    PRStatus  PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr);
+    PRStatus  PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data);
+    PRStatus  PR_SetSocketOption(PRFileDesc *fd, PRSocketOptionData *data);
+    PRStatus  PR_SetFDInheritable(PRFileDesc *fd, PRBool inheritable);
+    PRFileDesc * PR_GetInheritedFD(char *name);
+}
+
+enum PRFileMapProtect
+{
+    PR_PROT_READONLY,
+    PR_PROT_READWRITE,
+    PR_PROT_WRITECOPY,
+}
+
+alias void PRFileMap;
+
+version(NON_XPCOM_GLUE)
+{
+    PRFileMap * PR_CreateFileMap(PRFileDesc *fd, PRInt64 size, int prot);
+    PRInt32     PR_GetMemMapAlignment();
+    void *      PR_MemMap(PRFileMap *fmap, PROffset64 offset, PRUint32 len);
+    PRStatus    PR_MemUnmap(void *addr, PRUint32 len);
+    PRStatus    PR_CloseFileMap(PRFileMap *fmap);
+    PRStatus    PR_CreatePipe(PRFileDesc **readPipe, PRFileDesc **writePipe);
+}
+
+struct PRPollDesc
+{
+    PRFileDesc *fd;
+    PRInt16 in_flags;
+    PRInt16 out_flags;
+}
+
+const PR_POLL_READ = 0x1;
+const PR_POLL_WRITE = 0x2;
+const PR_POLL_EXCEPT = 0x4;
+const PR_POLL_ERR = 0x8;
+const PR_POLL_NVAL = 0x10;
+const PR_POLL_HUP = 0x20;
+
+version(NON_XPCOM_GLUE)
+{
+    PRInt32  PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout);
+    PRFileDesc * PR_NewPollableEvent();
+    PRStatus  PR_DestroyPollableEvent(PRFileDesc *event);
+    PRStatus  PR_SetPollableEvent(PRFileDesc *event);
+    PRStatus  PR_WaitForPollableEvent(PRFileDesc *event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prlink.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,134 @@
+module org.eclipse.swt.internal.mozilla.prlink;
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+import org.eclipse.swt.internal.mozilla.Common;
+
+struct PRStaticLinkTable
+{
+    char *name;
+    void  function()fp;
+}
+
+extern (System):
+
+PRStatus  PR_SetLibraryPath(char *path);
+
+char *  PR_GetLibraryPath();
+char *  PR_GetLibraryName(char *dir, char *lib);
+void    PR_FreeLibraryName(char *mem);
+
+alias void PRLibrary;
+
+PRLibrary * PR_LoadLibrary(char *name);
+
+enum PRLibSpecType
+{
+    PR_LibSpec_Pathname,
+    PR_LibSpec_MacNamedFragment,
+    PR_LibSpec_MacIndexedFragment,
+}
+
+alias void FSSpec;
+
+struct _N3
+{
+    FSSpec *fsspec;
+    char *name;
+}
+
+struct _N4
+{
+    FSSpec *fsspec;
+    PRUint32 index;
+}
+
+union _N2
+{
+    char *pathname;
+    struct _N3
+    {
+        FSSpec *fsspec;
+        char *name;
+    }
+    _N3 mac_named_fragment;
+    struct _N4
+    {
+        FSSpec *fsspec;
+        PRUint32 index;
+    }
+    _N4 mac_indexed_fragment;
+}
+
+struct PRLibSpec
+{
+    int type;
+    union _N2
+    {
+        char *pathname;
+        struct _N3
+        {
+            FSSpec *fsspec;
+            char *name;
+        }
+        _N3 mac_named_fragment;
+        struct _N4
+        {
+            FSSpec *fsspec;
+            PRUint32 index;
+        }
+        _N4 mac_indexed_fragment;
+    }
+    _N2 value;
+}
+
+const PR_LD_LAZY = 0x1;
+const PR_LD_NOW = 0x2;
+const PR_LD_GLOBAL = 0x4;
+const PR_LD_LOCAL = 0x8;
+
+PRLibrary * PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags);
+PRStatus    PR_UnloadLibrary(PRLibrary *lib);
+void *      PR_FindSymbol(PRLibrary *lib, char *name);
+
+alias void  function()PRFuncPtr;
+
+PRFuncPtr   PR_FindFunctionSymbol(PRLibrary *lib, char *name);
+void *      PR_FindSymbolAndLibrary(char *name, PRLibrary **lib);
+PRFuncPtr   PR_FindFunctionSymbolAndLibrary(char *name, PRLibrary **lib);
+PRLibrary * PR_LoadStaticLibrary(char *name, PRStaticLinkTable *table);
+char *      PR_GetLibraryFilePathname(char *name, PRFuncPtr addr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/mozilla/prtime.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,87 @@
+module org.eclipse.swt.internal.mozilla.prtime;
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+import org.eclipse.swt.internal.mozilla.Common;
+
+const PR_MSEC_PER_SEC = 1000U;
+const PR_USEC_PER_SEC = 1000000U;
+const PR_NSEC_PER_SEC = 1000000000U;
+const PR_USEC_PER_MSEC = 1000U;
+const PR_NSEC_PER_MSEC = 1000000U;
+
+extern (System):
+
+alias PRInt64 PRTime;
+
+struct PRTimeParameters
+{
+    PRInt32 tp_gmt_offset;
+    PRInt32 tp_dst_offset;
+}
+
+struct PRExplodedTime
+{
+    PRInt32 tm_usec;
+    PRInt32 tm_sec;
+    PRInt32 tm_min;
+    PRInt32 tm_hour;
+    PRInt32 tm_mday;
+    PRInt32 tm_month;
+    PRInt16 tm_year;
+    PRInt8 tm_wday;
+    PRInt16 tm_yday;
+    PRTimeParameters tm_params;
+}
+
+alias PRTimeParameters  function(PRExplodedTime *gmt)PRTimeParamFn;
+
+version(NON_XPCOM_GLUE)
+{
+    PRTime  PR_Now();
+    void    PR_ExplodeTime(PRTime usecs, PRTimeParamFn params, PRExplodedTime *exploded);
+    PRTime  PR_ImplodeTime(PRExplodedTime *exploded);
+    void    PR_NormalizeTime(PRExplodedTime *exploded, PRTimeParamFn params);
+
+    PRTimeParameters  PR_LocalTimeParameters(PRExplodedTime *gmt);
+    PRTimeParameters  PR_GMTParameters(PRExplodedTime *gmt);
+    PRTimeParameters  PR_USPacificTimeParameters(PRExplodedTime *gmt);
+
+    PRStatus  PR_ParseTimeString(char *string, PRBool default_to_gmt, PRTime *result);
+    PRUint32  PR_FormatTime(char *buf, int buflen, char *fmt, PRExplodedTime *tm);
+    PRUint32  PR_FormatTimeUSEnglish(char *buf, PRUint32 bufSize, char *format, PRExplodedTime *tm);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COM.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,879 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Shawn Liu
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.ole.win32.COM;
+
+
+public import org.eclipse.swt.internal.ole.win32.COMTYPES;
+private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+private import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+private import org.eclipse.swt.internal.ole.win32.EXDISP;
+private import org.eclipse.swt.internal.ole.win32.MSHTMHST;
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.ole.win32.ifs;
+private import org.eclipse.swt.internal.ole.win32.COMAPI;
+import java.lang.all;
+
+private alias org.eclipse.swt.internal.ole.win32.COMAPI COMAPI;
+
+
+public import org.eclipse.swt.internal.win32.OS;
+
+template IIDFromStringT(String g) {
+   static if (g.length == 38)
+     const GUID IIDFromStringT = IIDFromStringT!(g[1..$-1]);
+   else static if (g.length == 36)
+     const GUID IIDFromStringT = {
+        mixin("0x" ~ g[0..8]),
+        mixin("0x" ~ g[9..13]),
+        mixin("0x" ~ g[14..18]),
+        [
+            mixin("0x" ~ g[19..21]),
+            mixin("0x" ~ g[21..23]),
+            mixin("0x" ~ g[24..26]),
+            mixin("0x" ~ g[26..28]),
+            mixin("0x" ~ g[28..30]),
+            mixin("0x" ~ g[30..32]),
+            mixin("0x" ~ g[32..34]),
+            mixin("0x" ~ g[34..36]) ] };
+   else
+     static assert(false, "Incorrect format for GUID. "~g);
+}
+
+
+public class COM : OS {
+
+	//private import std.c.windows.com;
+
+	// all the GUID
+	// GUIDs for Home Page Browser
+
+    /** GUID Constants */
+    public static const GUID IIDJavaBeansBridge = IIDFromStringT!("{8AD9C840-044E-11D1-B3E9-00805F499D93}"); //$NON-NLS-1$
+    public static const GUID IIDShockwaveActiveXControl = IIDFromStringT!("{166B1BCA-3F9C-11CF-8075-444553540000}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorSiteTime = IIDFromStringT!("{6BD2AEFE-7876-45e6-A6E7-3BFCDF6540AA}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorSiteProperty = IIDFromStringT!("{D381A1F4-2326-4f3c-AFB9-B7537DB9E238}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorBaseProperty = IIDFromStringT!("{61E55B0B-2647-47c4-8C89-E736EF15D636}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorSite = IIDFromStringT!("{CDD88AB9-B01D-426E-B0F0-30973E9A074B}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorService = IIDFromStringT!("{BEE283FE-7B42-4FF3-8232-0F07D43ABCF1}"); //$NON-NLS-1$
+    public static const GUID IIDIEditorManager = IIDFromStringT!("{EFDE08C4-BE87-4B1A-BF84-15FC30207180}"); //$NON-NLS-1$
+    public static const GUID IIDIAccessible = IIDFromStringT!("{618736E0-3C3D-11CF-810C-00AA00389B71}"); //$NON-NLS-1$
+    //public static const GUID IIDIAccessibleHandler = IIDFromStringT!("{03022430-ABC4-11D0-BDE2-00AA001A1953}"); //$NON-NLS-1$
+    //public static const GUID IIDIAccessor = IIDFromStringT!("{0C733A8C-2A1C-11CE-ADE5-00AA0044773D}"); //$NON-NLS-1$
+    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 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$
+    //public static const GUID IIDICreateErrorInfo = IIDFromStringT!("{22F03340-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+    //public static const GUID IIDICreateTypeInfo = IIDFromStringT!("{00020405-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDICreateTypeLib = IIDFromStringT!("{00020406-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIDataAdviseHolder = IIDFromStringT!("{00000110-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIDataObject = IIDFromStringT!("{0000010E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIDispatch = IIDFromStringT!("{00020400-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIDocHostUIHandler = IIDFromStringT!("{BD3F23C0-D43E-11CF-893B-00AA00BDCE1A}"); //$NON-NLS-1$
+    public static const GUID IIDIDocHostShowUI = IIDFromStringT!("{C4D244B0-D43E-11CF-893B-00AA00BDCE1A}"); //$NON-NLS-1$
+    public static const GUID IIDIDropSource = IIDFromStringT!("{00000121-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIDropTarget = IIDFromStringT!("{00000122-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumConnectionPoints = IIDFromStringT!("{B196B285-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumConnections = IIDFromStringT!("{B196B287-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    public static const GUID IIDIEnumFORMATETC = IIDFromStringT!("{00000103-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumMoniker = IIDFromStringT!("{00000102-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumOLEVERB = IIDFromStringT!("{00000104-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumSTATDATA = IIDFromStringT!("{00000105-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumSTATSTG = IIDFromStringT!("{0000000D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumString = IIDFromStringT!("{00000101-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIEnumUnknown = IIDFromStringT!("{00000100-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIEnumVARIANT = IIDFromStringT!("{00020404-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIErrorInfo = IIDFromStringT!("{1CF2B120-547D-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+    //public static const GUID IIDIErrorLog = IIDFromStringT!("{3127CA40-446E-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+    //public static const GUID IIDIExternalConnection = IIDFromStringT!("{00000019-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIFont = IIDFromStringT!("{BEF6E002-A874-101A-8BBA-00AA00300CAB}"); //$NON-NLS-1$
+    //public static const GUID IIDIFontDisp = IIDFromStringT!("{BEF6E003-A874-101A-8BBA-00AA00300CAB}"); //$NON-NLS-1$
+    public static const /*GUID*/ String IIDIHTMLDocumentEvents2 = /*IIDFromStringT!(*/"{3050F613-98B5-11CF-BB82-00AA00BDCE0B}"/*)*/;
+    public static const GUID IIDIInternetSecurityManager = IIDFromStringT!("{79eac9ee-baf9-11ce-8c82-00aa004ba90b}"); //$NON-NLS-1$
+    //public static const GUID IIDILockBytes = IIDFromStringT!("{0000000A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIMalloc = IIDFromStringT!("{00000002-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIMallocSpy = IIDFromStringT!("{0000001D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIMarshal = IIDFromStringT!("{00000003-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIMessageFilter = IIDFromStringT!("{00000016-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIMoniker = IIDFromStringT!("{0000000F-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIOleAdviseHolder = IIDFromStringT!("{00000111-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIOleCache = IIDFromStringT!("{0000011E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIOleCache2 = IIDFromStringT!("{00000128-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIOleCacheControl = IIDFromStringT!("{00000129-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleClientSite = IIDFromStringT!("{00000118-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleCommandTarget = IIDFromStringT!("{B722BCCB-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+    public static const GUID IIDIOleContainer = IIDFromStringT!("{0000011B-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleControl = IIDFromStringT!("{B196B288-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    public static const GUID IIDIOleControlSite = IIDFromStringT!("{B196B289-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    public static const GUID IIDIOleDocument = IIDFromStringT!("{B722BCC5-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+    public static const GUID IIDIOleDocumentSite = IIDFromStringT!("{B722BCC7-4E68-101B-A2BC-00AA00404770}"); //$NON-NLS-1$
+    public static const GUID IIDIOleInPlaceActiveObject = IIDFromStringT!("{00000117-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleInPlaceFrame = IIDFromStringT!("{00000116-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleInPlaceObject = IIDFromStringT!("{00000113-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleInPlaceSite = IIDFromStringT!("{00000119-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleInPlaceUIWindow = IIDFromStringT!("{00000115-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIOleItemContainer = IIDFromStringT!("{0000011C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleLink = IIDFromStringT!("{0000011D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleObject = IIDFromStringT!("{00000112-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIOleWindow = IIDFromStringT!("{00000114-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIParseDisplayName = IIDFromStringT!("{0000011A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIPerPropertyBrowsing = IIDFromStringT!("{376BD3AA-3845-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
+    public static const GUID IIDIPersist = IIDFromStringT!("{0000010C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIPersistFile = IIDFromStringT!("{0000010B-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIPersistMemory = IIDFromStringT!("{BD1AE5E0-A6AE-11CE-BD37-504200C10000}"); //$NON-NLS-1$
+    //public static const GUID IIDIPersistPropertyBag = IIDFromStringT!("{37D84F60-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+    public static const GUID IIDIPersistStorage = IIDFromStringT!("{0000010A-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIPersistStream = IIDFromStringT!("{00000109-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIPersistStreamInit = IIDFromStringT!("{7FD52380-4E07-101B-AE2D-08002B2EC713}"); //$NON-NLS-1$
+    //public static const GUID IIDIPicture = IIDFromStringT!("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
+    //public static const GUID IIDIPictureDisp = IIDFromStringT!("{7BF80981-BF32-101A-8BBB-00AA00300CAB}"); //$NON-NLS-1$
+    //public static const GUID IIDIPropertyBag = IIDFromStringT!("{55272A00-42CB-11CE-8135-00AA004BB851}"); //$NON-NLS-1$
+    public static const GUID IIDIPropertyNotifySink = IIDFromStringT!("{9BFBBC02-EFF1-101A-84ED-00AA00341D07}"); //$NON-NLS-1$
+    //public static const GUID IIDIPropertyPage = IIDFromStringT!("{B196B28D-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    //public static const GUID IIDIPropertyPage2 = IIDFromStringT!("{01E44665-24AC-101B-84ED-08002B2EC713}"); //$NON-NLS-1$
+    //public static const GUID IIDIPropertyPageSite = IIDFromStringT!("{B196B28C-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    public static const GUID IIDIProvideClassInfo = IIDFromStringT!("{B196B283-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    public static const GUID IIDIProvideClassInfo2 = IIDFromStringT!("{A6BC3AC0-DBAA-11CE-9DE3-00AA004BB851}"); //$NON-NLS-1$
+    //public static const GUID IIDIPSFactoryBuffer = IIDFromStringT!("{D5F569D0-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+    //public static const GUID IIDIRootStorage = IIDFromStringT!("{00000012-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIROTData = IIDFromStringT!("{F29F6BC0-5021-11CE-AA15-00006901293F}"); //$NON-NLS-1$
+    //public static const GUID IIDIRpcChannelBuffer = IIDFromStringT!("{D5F56B60-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+    //public static const GUID IIDIRpcProxyBuffer = IIDFromStringT!("{D5F56A34-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+    //public static const GUID IIDIRpcStubBuffer = IIDFromStringT!("{D5F56AFC-593B-101A-B569-08002B2DBF7A}"); //$NON-NLS-1$
+    //public static const GUID IIDIRunnableObject = IIDFromStringT!("{00000126-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIRunningObjectTable = IIDFromStringT!("{00000010-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDISimpleFrameSite = IIDFromStringT!("{742B0E01-14E6-101B-914E-00AA00300CAB}"); //$NON-NLS-1$
+    public static const GUID IIDIServiceProvider = IIDFromStringT!("{6d5140c1-7436-11ce-8034-00aa006009fa}"); //$NON-NLS-1$
+    public static const GUID IIDISpecifyPropertyPages = IIDFromStringT!("{B196B28B-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
+    //public static const GUID IIDIStdMarshalInfo = IIDFromStringT!("{00000018-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIStorage = IIDFromStringT!("{0000000B-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIStream = IIDFromStringT!("{0000000C-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDISupportErrorInfo = IIDFromStringT!("{DF0B3D60-548F-101B-8E65-08002B2BD119}"); //$NON-NLS-1$
+    //public static const GUID IIDITypeComp = IIDFromStringT!("{00020403-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDITypeLib = IIDFromStringT!("{00020402-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIUnknown = IIDFromStringT!("{00000000-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    //public static const GUID IIDIViewObject = IIDFromStringT!("{0000010D-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIViewObject2 = IIDFromStringT!("{00000127-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID CGID_DocHostCommandHandler = IIDFromStringT!("{f38bc242-b950-11d1-8918-00c04fc2c836}"); //$NON-NLS-1$
+    public static const GUID CGID_Explorer = IIDFromStringT!("{000214D0-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+
+
+
+	/* Constants */
+    //public static const int ADVF_DATAONSTOP = 64;
+    //public static const int ADVF_NODATA = 1;
+    //public static const int ADVF_ONLYONCE = 2;
+    //public static const int ADVF_PRIMEFIRST = 4;
+    //public static const int ADVFCACHE_FORCEBUILTIN = 16;
+    //public static const int ADVFCACHE_NOHANDLER = 8;
+    //public static const int ADVFCACHE_ONSAVE = 32;
+    public static const int CF_TEXT = 1;
+    public static const int CF_BITMAP = 2;
+    public static const int CF_METAFILEPICT = 3;
+    public static const int CF_SYLK = 4;
+    public static const int CF_DIF = 5;
+    public static const int CF_TIFF = 6;
+    public static const int CF_OEMTEXT = 7;
+    public static const int CF_DIB = 8;
+    public static const int CF_PALETTE = 9;
+    public static const int CF_PENDATA = 10;
+    public static const int CF_RIFF = 11;
+    public static const int CF_WAVE = 12;
+    public static const int CF_UNICODETEXT = 13;
+    public static const int CF_ENHMETAFILE = 14;
+    public static const int CF_HDROP = 15;
+    public static const int CF_LOCALE = 16;
+    public static const int CF_MAX = 17;
+    public static const int CLSCTX_INPROC_HANDLER = 2;
+    public static const int CLSCTX_INPROC_SERVER = 1;
+    public static const int CLSCTX_LOCAL_SERVER = 4;
+    public static const int CLSCTX_REMOTE_SERVER = 16;
+    public static const int CO_E_CLASSSTRING = -2147221005;
+    //public static const int COINIT_APARTMENTTHREADED = 2;
+    //public static const int COINIT_DISABLE_OLE1DDE = 4;
+    //public static const int COINIT_MULTITHREADED = 0;
+    //public static const int COINIT_SPEED_OVER_MEMORY = 8;
+    public static const int DATADIR_GET = 1;
+    public static const int DATADIR_SET = 2;
+    public static const int DISP_E_EXCEPTION = 0x80020009;
+    public static const int DISP_E_MEMBERNOTFOUND = -2147352573;
+    public static const int DISP_E_UNKNOWNINTERFACE = 0x80020001;
+    //public static const int DISPID_AMBIENT_APPEARANCE = -716;
+    //public static const int DISPID_AMBIENT_AUTOCLIP = -715;
+    public static const int DISPID_AMBIENT_BACKCOLOR = -701;
+    //public static const int DISPID_AMBIENT_CHARSET = -727;
+    //public static const int DISPID_AMBIENT_CODEPAGE = -725;
+    //public static const int DISPID_AMBIENT_DISPLAYASDEFAULT = -713;
+    //public static const int DISPID_AMBIENT_DISPLAYNAME = -702;
+    public static const int DISPID_AMBIENT_FONT = -703;
+    public static const int DISPID_AMBIENT_FORECOLOR = -704;
+    public static const int DISPID_AMBIENT_LOCALEID = -705;
+    public static const int DISPID_AMBIENT_MESSAGEREFLECT = -706;
+    public static const int DISPID_AMBIENT_OFFLINEIFNOTCONNECTED = -5501;
+    //public static const int DISPID_AMBIENT_PALETTE = -726;
+    //public static const int DISPID_AMBIENT_RIGHTTOLEFT = -732;
+    //public static const int DISPID_AMBIENT_SCALEUNITS = -707;
+    public static const int DISPID_AMBIENT_SHOWGRABHANDLES = -711;
+    public static const int DISPID_AMBIENT_SHOWHATCHING = -712;
+    public static const int DISPID_AMBIENT_SILENT = -5502;
+    public static const int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714;
+    //public static const int DISPID_AMBIENT_TEXTALIGN = -708;
+    //public static const int DISPID_AMBIENT_TOPTOBOTTOM = -733;
+    //public static const int DISPID_AMBIENT_TRANSFERPRIORITY = -728;
+    public static const int DISPID_AMBIENT_UIDEAD = -710;
+    public static const int DISPID_AMBIENT_USERMODE = -709;
+    public static const int DISPID_BACKCOLOR = -501;
+    public static const int DISPID_FONT = -512;
+    public static const int DISPID_FONT_BOLD = 3;
+    public static const int DISPID_FONT_CHARSET = 8;
+    public static const int DISPID_FONT_ITALIC = 4;
+    public static const int DISPID_FONT_NAME = 0;
+    public static const int DISPID_FONT_SIZE = 2;
+    public static const int DISPID_FONT_STRIKE = 6;
+    public static const int DISPID_FONT_UNDER = 5;
+    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;
+    public static const int DRAGDROP_S_DROP = 0x00040100;
+    public static const int DRAGDROP_S_CANCEL = 0x00040101;
+    public static const int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102;
+    public static const int DROPEFFECT_NONE = 0;
+    public static const int DROPEFFECT_COPY = 1;
+    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;
+    public static const int DVASPECT_CONTENT = 1;
+    //public static const int DVASPECT_DOCPRINT = 8;
+    //public static const int DVASPECT_ICON = 4;
+    //public static const int DVASPECT_THUMBNAIL = 2;
+    public static const int E_FAIL = -2147467259;
+    public static const int E_INVALIDARG = -2147024809;
+    public static const int E_NOINTERFACE = -2147467262;
+    public static const int E_NOTIMPL = -2147467263;
+    public static const int E_NOTSUPPORTED = 0x80040100;
+    //public static const int E_NOTLICENSED = -2147221230;
+    public static const int E_OUTOFMEMORY = -2147024882;
+    //public static const int E_POINTER = -2147467261;
+    public static const int GMEM_FIXED = 0;
+    //public static const int GMEM_MOVABLE = 2;
+    //public static const int GMEM_NODISCARD = 32;
+    public static const int GMEM_ZEROINIT = 64;
+    public static const int GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1;
+    public static const int IMPLTYPEFLAG_FDEFAULT = 1;
+    //public static const int IMPLTYPEFLAG_FDEFAULTVTABLE = 2048;
+    public static const int IMPLTYPEFLAG_FRESTRICTED = 4;
+    public static const int IMPLTYPEFLAG_FSOURCE = 2;
+    public static const int LOCALE_SYSTEM_DEFAULT = 1024;
+    public static const int LOCALE_USER_DEFAULT = 2048;
+    //public static const int MEMCTX_TASK = 1;
+    //public static const int OLEACTIVATEAUTO = 3;
+    //public static const int OLEACTIVATEDOUBLECLICK = 2;
+    //public static const int OLEACTIVATEGETFOCUS = 1;
+    //public static const int OLEACTIVATEMANUAL = 0;
+    //public static const int OLEAUTOMATIC = 0;
+    //public static const int OLECHANGED = 0;
+    public static const int OLECLOSE_NOSAVE = 1;
+    //public static const int OLECLOSE_PROMPTSAVE = 2;
+    public static const int OLECLOSE_SAVEIFDIRTY = 0;
+    //public static const int OLECLOSED = 2;
+    //public static const int OLECONTF_EMBEDDINGS = 1;
+    //public static const int OLECONTF_LINKS = 2;
+    //public static const int OLECONTF_ONLYIFRUNNING = 16;
+    //public static const int OLECONTF_ONLYUSER = 8;
+    //public static const int OLECONTF_OTHERS = 4;
+    //public static const int OLEDEACTIVATEMANUAL = 1;
+    //public static const int OLEDEACTIVATEONLOSEFOCUS = 0;
+    //public static const int OLEDECBORDER = 1;
+    //public static const int OLEDECBORDERANDNIBS = 3;
+    //public static const int OLEDECNIBS = 2;
+    //public static const int OLEDECNONE = 0;
+    //public static const int OLEDISPLAYCONTENT = 0;
+    //public static const int OLEDISPLAYICON = 1;
+    //public static const int OLEEITHER = 2;
+    public static const int OLEEMBEDDED = 1;
+    //public static const int OLEFROZEN = 1;
+    public static const int OLEIVERB_DISCARDUNDOSTATE = -6;
+    //public static const int OLEIVERB_HIDE = -3;
+    public static const int OLEIVERB_INPLACEACTIVATE = -5;
+    //public static const int OLEIVERB_OPEN = -2;
+    public static const int OLEIVERB_PRIMARY = 0;
+    //public static const int OLEIVERB_PROPERTIES = -7;
+    //public static const int OLEIVERB_SHOW = -1;
+    //public static const int OLEIVERB_UIACTIVATE = -4;
+    public static const int OLELINKED = 0;
+    //public static const int OLEMANUAL = 2;
+    //public static const int OLEMISC_ACTIVATEWHENVISIBLE = 256;
+    //public static const int OLEMISC_ACTSLIKEBUTTON = 4096;
+    //public static const int OLEMISC_ACTSLIKELABEL = 8192;
+    //public static const int OLEMISC_ALIGNABLE = 32768;
+    //public static const int OLEMISC_ALWAYSRUN = 2048;
+    //public static const int OLEMISC_CANLINKBYOLE1 = 32;
+    //public static const int OLEMISC_CANTLINKINSIDE = 16;
+    //public static const int OLEMISC_IGNOREACTIVATEWHENVISIBLE = 524288;
+    //public static const int OLEMISC_IMEMODE = 262144;
+    //public static const int OLEMISC_INSERTNOTREPLACE = 4;
+    //public static const int OLEMISC_INSIDEOUT = 128;
+    //public static const int OLEMISC_INVISIBLEATRUNTIME = 1024;
+    //public static const int OLEMISC_ISLINKOBJECT = 64;
+    //public static const int OLEMISC_NOUIACTIVATE = 16384;
+    //public static const int OLEMISC_ONLYICONIC = 2;
+    //public static const int OLEMISC_RECOMPOSEONRESIZE = 1;
+    //public static const int OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512;
+    //public static const int OLEMISC_SETCLIENTSITEFIRST = 131072;
+    //public static const int OLEMISC_SIMPLEFRAME = 65536;
+    //public static const int OLEMISC_STATIC = 8;
+    //public static const int OLEMISC_SUPPORTSMULTILEVELUNDO = 2097152;
+    //public static const int OLEMISC_WANTSTOMENUMERGE = 1048576;
+    //public static const int OLENONE = 3;
+    //public static const int OLERENAMED = 3;
+    //public static const int OLERENDER_ASIS = 3;
+    public static const int OLERENDER_DRAW = 1;
+    //public static const int OLERENDER_FORMAT = 2;
+    //public static const int OLERENDER_NONE = 0;
+    //public static const int OLESAVED = 1;
+    //public static const int OLESIZEAUTOSIZE = 2;
+    //public static const int OLESIZECLIP = 0;
+    //public static const int OLESIZESTRETCH = 1;
+    //public static const int OLESIZEZOOM = 3;
+    //public static const int OLEWHICHMK_CONTAINER = 1;
+    //public static const int OLEWHICHMK_OBJFULL = 3;
+    //public static const int OLEWHICHMK_OBJREL = 2;
+    public static const int S_FALSE = 1;
+    public static const int S_OK = 0;
+    public static const int STG_E_FILENOTFOUND = 0x80030002;
+    public static const int STG_S_CONVERTED = 0x00030200;
+    //public static const int STGC_CONSOLIDATE = 8;
+    //public static const int STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4;
+    public static const int STGC_DEFAULT = 0;
+    //public static const int STGC_ONLYIFCURRENT = 2;
+    //public static const int STGC_OVERWRITE = 1;
+    public static const int STGM_CONVERT = 0x00020000;
+    public static const int STGM_CREATE = 0x00001000;
+    public static const int STGM_DELETEONRELEASE = 0x04000000;
+    public static const int STGM_DIRECT = 0x00000000;
+    public static const int STGM_DIRECT_SWMR = 0x00400000;
+    public static const int STGM_FAILIFTHERE = 0x00000000;
+    public static const int STGM_NOSCRATCH = 0x00100000;
+    public static const int STGM_NOSNAPSHOT = 0x00200000;
+    public static const int STGM_PRIORITY = 0x00040000;
+    public static const int STGM_READ = 0x00000000;
+    public static const int STGM_READWRITE = 0x00000002;
+    public static const int STGM_SHARE_DENY_NONE = 0x00000040;
+    public static const int STGM_SHARE_DENY_READ = 0x00000030;
+    public static const int STGM_SHARE_DENY_WRITE = 0x00000020;
+    public static const int STGM_SHARE_EXCLUSIVE = 0x00000010;
+    public static const int STGM_SIMPLE = 0x08000000;
+    public static const int STGM_TRANSACTED = 0x00010000;
+    public static const int STGM_WRITE = 0x00000001;
+    public static const int STGTY_STORAGE = 1;
+    public static const int STGTY_STREAM = 2;
+    public static const int STGTY_LOCKBYTES = 3;
+    public static const int STGTY_PROPERTY = 4;
+    //public static const int TYMED_ENHMF = 64;
+    //public static const int TYMED_FILE = 2;
+    //public static const int TYMED_GDI = 16;
+    public static const int TYMED_HGLOBAL = 1;
+    //public static const int TYMED_ISTORAGE = 8;
+    //public static const int TYMED_ISTREAM = 4;
+    //public static const int TYMED_MFPICT = 32;
+    //public static const int TYMED_NULL = 0;
+    public static const short DISPATCH_METHOD = 0x1;
+    public static const short DISPATCH_PROPERTYGET = 0x2;
+    public static const short DISPATCH_PROPERTYPUT = 0x4;
+    public static const short DISPATCH_PROPERTYPUTREF = 0x8;
+    //public static const short DISPID_CONSTRUCTOR = -6;
+    //public static const short DISPID_DESTRUCTOR = -7;
+    //public static const short DISPID_EVALUATE = -5;
+    //public static const short DISPID_NEWENUM = -4;
+    public static const short DISPID_PROPERTYPUT = -3;
+    //public static const short DISPID_UNKNOWN = -1;
+    //public static const short DISPID_VALUE = 0;
+    public static const short VT_BOOL = 11;
+    public static const short VT_BSTR = 8;
+    public static const short VT_BYREF = 16384;
+    public static const short VT_CY = 6;
+    public static const short VT_DATE = 7;
+    public static const short VT_DISPATCH = 9;
+    public static const short VT_EMPTY = 0;
+    public static const short VT_ERROR = 10;
+    public static const short VT_I1 = 16;
+    public static const short VT_I2 = 2;
+    public static const short VT_I4 = 3;
+    public static const short VT_I8 = 20;
+    public static const short VT_NULL = 1;
+    public static const short VT_R4 = 4;
+    public static const short VT_R8 = 5;
+    public static const short VT_UI1 = 17;
+    public static const short VT_UI2 = 18;
+    public static const short VT_UI4 = 19;
+    public static const short VT_UNKNOWN = 13;
+    public static const short VT_VARIANT = 12;
+    public static const short VARIANT_TRUE = -1;
+    public static const short VARIANT_FALSE = 0;
+
+
+// alias org.eclipse.swt.internal.ole.win32.comapi.
+// public static GUID* IIDFromString(String lpsz) {
+// 	GUID* lpiid = new GUID();
+// 	if (COM.IIDFromString(Converter.StrToWCHARz(lpsz), lpiid) == COM.S_OK)
+// 		return lpiid;
+// 	return null;
+// }
+
+alias COMAPI.CLSIDFromProgID CLSIDFromProgID;
+alias COMAPI.CLSIDFromString CLSIDFromString;
+alias COMAPI.CoCreateInstance CoCreateInstance;
+alias COMAPI.CoFreeUnusedLibraries CoFreeUnusedLibraries;
+alias COMAPI.CoGetClassObject CoGetClassObject;
+alias COMAPI.CoLockObjectExternal CoLockObjectExternal;
+alias COMAPI.CoTaskMemAlloc CoTaskMemAlloc;
+alias COMAPI.CoTaskMemFree CoTaskMemFree;
+alias COMAPI.CreateStdAccessibleObject CreateStdAccessibleObject;
+alias COMAPI.CreateStreamOnHGlobal CreateStreamOnHGlobal;
+alias COMAPI.DoDragDrop DoDragDrop;
+alias COMAPI.GetClassFile GetClassFile;
+alias COMAPI.IIDFromString IIDFromString;
+alias COMAPI.IsEqualGUID IsEqualGUID;
+alias COMAPI.LresultFromObject LresultFromObject;
+alias COMAPI.OleCreate OleCreate;
+alias COMAPI.OleCreateFromFile OleCreateFromFile;
+alias COMAPI.OleCreatePropertyFrame OleCreatePropertyFrame;
+alias COMAPI.OleDraw OleDraw;
+alias COMAPI.OleFlushClipboard OleFlushClipboard;
+alias COMAPI.OleGetClipboard OleGetClipboard;
+alias COMAPI.OleIsCurrentClipboard OleIsCurrentClipboard;
+alias COMAPI.OleIsRunning OleIsRunning;
+alias COMAPI.OleLoad OleLoad;
+alias COMAPI.OleRun OleRun;
+alias COMAPI.OleSave OleSave;
+alias COMAPI.OleSetClipboard OleSetClipboard;
+alias COMAPI.OleSetContainedObject OleSetContainedObject;
+alias COMAPI.OleSetMenuDescriptor OleSetMenuDescriptor;
+alias COMAPI.OleTranslateColor OleTranslateColor;
+alias COMAPI.ProgIDFromCLSID ProgIDFromCLSID;
+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;
+alias COMAPI.StringFromCLSID StringFromCLSID;
+alias COMAPI.SysAllocString SysAllocString;
+alias COMAPI.SysFreeString SysFreeString;
+alias COMAPI.SysStringByteLen SysStringByteLen;
+alias COMAPI.VariantChangeType VariantChangeType;
+alias COMAPI.VariantClear VariantClear;
+alias COMAPI.VariantCopy VariantCopy;
+alias COMAPI.VariantInit VariantInit;
+alias COMAPI.WriteClassStg WriteClassStg;
+
+/**
+ * <Shawn Liu>
+ * VtbCall partially kept, use VtbCall instead of automation can promote performace
+ * and VtbCall doesn't need prototype of interface declaration
+ */
+
+public static int VtblCall(int fnNumber, void* ppVtbl) {
+	Function1 fn = cast(Function1)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0){
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1){
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2){
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3){
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4){
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5){
+	Function7 fn = cast(Function7)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6){
+	Function8 fn = cast(Function8)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7){
+	Function9 fn = cast(Function9)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+}
+
+/*
+public static int VtblCall(int fnNumber, void* ppVtbl) {
+	Function1 fn = cast(Function1)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0){
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, void* arg0){
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, wchar* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, wchar* arg0, wchar* arg1){
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0, cast(int)arg1);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, wchar* arg0, int arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0, arg1);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, wchar* arg0, int arg1, int arg2, int arg3, int[] arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0, arg1, arg2, arg3, cast(int)cast(int*)arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, wchar* arg0, int arg1, int arg2, int arg3, int arg4, int[] arg5) {
+	Function7 fn = cast(Function7)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)arg0, arg1, arg2, arg3, arg4, cast(int)cast(int*)arg5);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int[] arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)cast(int*)arg0);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int[] arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)cast(int*)arg1);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int[] arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, cast(int)cast(int*)arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int[] arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, cast(int)cast(int*)arg3);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, DVTARGETDEVICE* arg2, SIZE* arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, cast(int)(arg2), cast(int)(arg3));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, GUID* arg2, int arg3, int[] arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, cast(int)(arg2), arg3, cast(int)cast(int*)arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, FORMATETC* arg1, int[] arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1), cast(int)cast(int*)arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, GUID* arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, GUID* arg1, int arg2, int arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1), arg2, arg3);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, GUID* arg1, int arg2, int arg3, DISPPARAMS* arg4, int arg5, EXCEPINFO* arg6, int[] arg7) {
+	Function9 fn = cast(Function9)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1), arg2, arg3, cast(int)(arg4), arg5, cast(int)(arg6), cast(int)cast(int*)arg7);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, STATSTG* arg1, int[] arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1), cast(int)cast(int*)arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, MSG* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, MSG* arg1, int arg2, int arg3, int arg4, RECT* arg5) {
+	Function7 fn = cast(Function7)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1), arg2, arg3, arg4, cast(int)(arg5));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, SIZE* arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)(arg1));
+}
+
+// TODO: the type of BOOL ???
+// conflict with  VtblCall(int, int, int, int);
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, bool arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)arg1);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, CAUUID* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, CONTROLINFO* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, FORMATETC* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, FORMATETC* arg0, STGMEDIUM* arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), cast(int)(arg1));
+}
+// TODO: BOOL type ???
+public static int VtblCall(int fnNumber, void* ppVtbl, FORMATETC* arg0, STGMEDIUM* arg1, int arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), cast(int)(arg1), arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, GUID* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, GUID* arg0, int[] arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), cast(int)cast(int*)arg1);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, GUID* arg0, int arg1, int arg2, int arg3, int[] arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), arg1, arg2, arg3, cast(int)cast(int*)arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, GUID* arg0, int arg1, int arg2, int arg3, int arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), arg1, arg2, arg3, arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, GUID* arg0, int arg1, OLECMD* arg2, OLECMDTEXT* arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), arg1, cast(int)(arg2), cast(int)(arg3));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, LICINFO* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, RECT* arg0, int arg1, int arg2) {
+	Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), arg1, arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, RECT* arg0, RECT* arg1) {
+	Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0), cast(int)(arg1));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, RECT* arg0) {
+	Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, cast(int)(arg0));
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int[] arg1, int[] arg2, int[] arg3, int[] arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)cast(int*)arg1, cast(int)cast(int*)arg2, cast(int)cast(int*)arg3, cast(int)cast(int*)arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int[] arg1, int arg2, int[] arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, cast(int)cast(int*)arg1, arg2, cast(int)cast(int*)arg3);
+}
+
+
+// Start ACCESSIBILITY
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3) {
+	Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4) {
+	Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
+	Function7 fn = cast(Function7)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7) {
+	Function9 fn = cast(Function9)(*cast(int **)ppVtbl)[fnNumber];
+	return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+}
+
+*/
+
+
+public static const int CHILDID_SELF = 0;
+public static const int CO_E_OBJNOTCONNECTED = 0x800401FD;
+
+//public static const int ROLE_SYSTEM_TITLEBAR = 0x1;
+public static const int ROLE_SYSTEM_MENUBAR = 0x2;
+public static const int ROLE_SYSTEM_SCROLLBAR = 0x3;
+//public static const int ROLE_SYSTEM_GRIP = 0x4;
+//public static const int ROLE_SYSTEM_SOUND = 0x5;
+//public static const int ROLE_SYSTEM_CURSOR = 0x6;
+//public static const int ROLE_SYSTEM_CARET = 0x7;
+//public static const int ROLE_SYSTEM_ALERT = 0x8;
+public static const int ROLE_SYSTEM_WINDOW = 0x9;
+public static const int ROLE_SYSTEM_CLIENT = 0xa;
+public static const int ROLE_SYSTEM_MENUPOPUP = 0xb;
+public static const int ROLE_SYSTEM_MENUITEM = 0xc;
+public static const int ROLE_SYSTEM_TOOLTIP = 0xd;
+//public static const int ROLE_SYSTEM_APPLICATION = 0xe;
+//public static const int ROLE_SYSTEM_DOCUMENT = 0xf;
+//public static const int ROLE_SYSTEM_PANE = 0x10;
+//public static const int ROLE_SYSTEM_CHART = 0x11;
+public static const int ROLE_SYSTEM_DIALOG = 0x12;
+//public static const int ROLE_SYSTEM_BORDER = 0x13;
+//public static const int ROLE_SYSTEM_GROUPING = 0x14;
+public static const int ROLE_SYSTEM_SEPARATOR = 0x15;
+public static const int ROLE_SYSTEM_TOOLBAR = 0x16;
+//public static const int ROLE_SYSTEM_STATUSBAR = 0x17;
+public static const int ROLE_SYSTEM_TABLE = 0x18;
+public static const int ROLE_SYSTEM_COLUMNHEADER = 0x19;
+public static const int ROLE_SYSTEM_ROWHEADER = 0x1a;
+//public static const int ROLE_SYSTEM_COLUMN = 0x1b;
+//public static const int ROLE_SYSTEM_ROW = 0x1c;
+public static const int ROLE_SYSTEM_CELL = 0x1d;
+public static const int ROLE_SYSTEM_LINK = 0x1e;
+//public static const int ROLE_SYSTEM_HELPBALLOON = 0x1f;
+//public static const int ROLE_SYSTEM_CHARACTER = 0x20;
+public static const int ROLE_SYSTEM_LIST = 0x21;
+public static const int ROLE_SYSTEM_LISTITEM = 0x22;
+public static const int ROLE_SYSTEM_OUTLINE = 0x23;
+public static const int ROLE_SYSTEM_OUTLINEITEM = 0x24;
+public static const int ROLE_SYSTEM_PAGETAB = 0x25;
+//public static const int ROLE_SYSTEM_PROPERTYPAGE = 0x26;
+//public static const int ROLE_SYSTEM_INDICATOR = 0x27;
+//public static const int ROLE_SYSTEM_GRAPHIC = 0x28;
+public static const int ROLE_SYSTEM_STATICTEXT = 0x29;
+public static const int ROLE_SYSTEM_TEXT = 0x2a;
+public static const int ROLE_SYSTEM_PUSHBUTTON = 0x2b;
+public static const int ROLE_SYSTEM_CHECKBUTTON = 0x2c;
+public static const int ROLE_SYSTEM_RADIOBUTTON = 0x2d;
+public static const int ROLE_SYSTEM_COMBOBOX = 0x2e;
+//public static const int ROLE_SYSTEM_DROPLIST = 0x2f;
+public static const int ROLE_SYSTEM_PROGRESSBAR = 0x30;
+//public static const int ROLE_SYSTEM_DIAL = 0x31;
+//public static const int ROLE_SYSTEM_HOTKEYFIELD = 0x32;
+public static const int ROLE_SYSTEM_SLIDER = 0x33;
+//public static const int ROLE_SYSTEM_SPINBUTTON = 0x34;
+//public static const int ROLE_SYSTEM_DIAGRAM = 0x35;
+//public static const int ROLE_SYSTEM_ANIMATION = 0x36;
+//public static const int ROLE_SYSTEM_EQUATION = 0x37;
+//public static const int ROLE_SYSTEM_BUTTONDROPDOWN = 0x38;
+//public static const int ROLE_SYSTEM_BUTTONMENU = 0x39;
+//public static const int ROLE_SYSTEM_BUTTONDROPDOWNGRID = 0x3a;
+//public static const int ROLE_SYSTEM_WHITESPACE = 0x3b;
+public static const int ROLE_SYSTEM_PAGETABLIST = 0x3c;
+//public static const int ROLE_SYSTEM_CLOCK = 0x3d;
+
+public static const int STATE_SYSTEM_NORMAL = 0;
+//public static const int STATE_SYSTEM_UNAVAILABLE = 0x1;
+public static const int STATE_SYSTEM_SELECTED = 0x2;
+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_INDETERMINATE = STATE_SYSTEM_MIXED;
+public static const int STATE_SYSTEM_READONLY = 0x40;
+public static const int STATE_SYSTEM_HOTTRACKED = 0x80;
+//public static const int STATE_SYSTEM_DEFAULT = 0x100;
+public static const int STATE_SYSTEM_EXPANDED = 0x200;
+public static const int STATE_SYSTEM_COLLAPSED = 0x400;
+public static const int STATE_SYSTEM_BUSY = 0x800;
+//public static const int STATE_SYSTEM_FLOATING = 0x1000;
+//public static const int STATE_SYSTEM_MARQUEED = 0x2000;
+//public static const int STATE_SYSTEM_ANIMATED = 0x4000;
+public static const int STATE_SYSTEM_INVISIBLE = 0x8000;
+public static const int STATE_SYSTEM_OFFSCREEN = 0x10000;
+public static const int STATE_SYSTEM_SIZEABLE = 0x20000;
+//public static const int STATE_SYSTEM_MOVEABLE = 0x40000;
+//public static const int STATE_SYSTEM_SELFVOICING = 0x80000;
+public static const int STATE_SYSTEM_FOCUSABLE = 0x100000;
+public static const int STATE_SYSTEM_SELECTABLE = 0x200000;
+public static const int STATE_SYSTEM_LINKED = 0x400000;
+//public static const int STATE_SYSTEM_TRAVERSED = 0x800000;
+public static const int STATE_SYSTEM_MULTISELECTABLE = 0x1000000;
+//public static const int STATE_SYSTEM_EXTSELECTABLE = 0x2000000;
+//public static const int STATE_SYSTEM_ALERT_LOW = 0x4000000;
+//public static const int STATE_SYSTEM_ALERT_MEDIUM = 0x8000000;
+//public static const int STATE_SYSTEM_ALERT_HIGH = 0x10000000;
+//public static const int STATE_SYSTEM_PROTECTED = 0x20000000;
+//public static const int STATE_SYSTEM_VALID = 0x3fffffff;
+
+/* End ACCESSIBILITY */
+
+}
+
+/**
+ * <Shawn> difference between WCHARzToStr(pwstr, -1) :
+ * BSTRToStr() internally call WCHARzToStr(pwstr, length) with length set,
+ * instead to determine the null ended, this mean BSTRToStr() can get string
+ * which has embedded null characters.
+ */
+// BSTR is aliased to wchar*
+// Note : Free the "bstr" memory if freeTheString is true, default false
+String BSTRToStr( /*BSTR*/ inout wchar* bstr, bool freeTheString = false){
+    if(bstr is null) return null;
+    int size = (SysStringByteLen(bstr) + 1)/wchar.sizeof;
+    String result = WCHARzToStr(bstr, size);
+    if(freeTheString) {
+        // free the string and set ptr to null
+        SysFreeString(bstr);
+        bstr = null;
+    }
+    return result;
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COMAPI.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,284 @@
+/*
+ * All COM APIs required by SWT, all APIs prototype copied from MSDN 2003
+ * don't import this module directly, import std.internal.ole.win32.com instead
+ *
+ * author : Shawn Liu
+ */
+
+
+module org.eclipse.swt.internal.ole.win32.COMAPI;
+
+
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.internal.ole.win32.COMTYPES;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.extras;
+
+extern(Windows){
+
+WINOLEAPI CreateStreamOnHGlobal(
+	HGLOBAL hGlobal,         //Memory handle for the stream object
+	BOOL fDeleteOnRelease,   //Whether to free memory when the object
+					   // is released
+	LPSTREAM * ppstm         //Address of output variable that
+					   // receives the IStream interface pointer
+);
+HRESULT CLSIDFromProgID(
+  LPCOLESTR lpszProgID,
+  LPCLSID pclsid
+);
+HRESULT CLSIDFromString(
+  LPOLESTR lpsz,
+  LPCLSID pclsid
+);
+STDAPI CoCreateInstance(
+  REFCLSID rclsid,
+  LPUNKNOWN pUnkOuter,
+  DWORD dwClsContext,
+  REFIID riid,
+  LPVOID * ppv
+);
+void CoFreeUnusedLibraries();
+STDAPI CoGetClassObject(
+  REFCLSID rclsid,
+  DWORD dwClsContext,
+  COSERVERINFO * pServerInfo,
+  REFIID riid,
+  LPVOID * ppv
+);
+STDAPI CoLockObjectExternal(
+  LPUNKNOWN pUnk,
+  BOOL fLock,
+  BOOL fLastUnlockReleases
+);
+LPVOID CoTaskMemAlloc(
+  ULONG cb
+);
+void CoTaskMemFree(
+  void * pv
+);
+
+WINOLEAPI DoDragDrop(
+  LPDATAOBJECT pDataObject,  //Pointer to the data object
+  LPDROPSOURCE pDropSource,  //Pointer to the source
+  DWORD dwOKEffect,           //Effects allowed by the source
+  DWORD * pdwEffect           //Pointer to effects on the source
+);
+
+WINOLEAPI GetClassFile(
+  LPCWSTR szFileName,
+  CLSID * pclsid
+);
+WINOLEAPI IIDFromString(
+  LPOLESTR lpsz,
+  LPIID lpiid
+);
+BOOL IsEqualGUID(
+  REFGUID rguid1,
+  REFGUID rguid2
+);
+WINOLEAPI OleCreate(
+  REFCLSID rclsid,  //CLSID of embedded object to be created
+  REFIID riid,      //Reference to the identifier of the interface
+                    // used to communicate with new object
+  DWORD renderopt,  //RENDEROPT value indicating cached capabilities
+  FORMATETC * pFormatEtc,
+                    //Pointer to a FORMATETC structure
+  IOleClientSite * pClientSite,
+                    //Pointer to request services from the container
+  LPSTORAGE pStg,  //Pointer to storage for the object
+  void ** ppvObject //Address of output variable that receives the
+                    // interface pointer requested in riid
+);
+WINOLEAPI OleCreateFromFile(
+  REFCLSID rclsid,         //Reserved. Must be CLSID_NULL
+  LPCOLESTR lpszFileName,  //Pointer to full path of file used to
+                           // create object
+  REFIID riid,             //Reference to the identifier of the
+                           // interface to be used to communicate with
+                           // new object
+  DWORD renderopt,         //Value from OLERENDER
+  LPFORMATETC pFormatEtc,  //Pointer to the FORMATETC structure
+  LPOLECLIENTSITE pClientSite,
+                           //Pointer to an interface
+  LPSTORAGE pStg,          //Pointer tothe interface to be used as
+                           // object storage
+  LPVOID * ppvObj       //Address of output variable that
+                           // receives the interface pointer requested
+                           // in riid
+);
+
+STDAPI OleCreatePropertyFrame(
+  HWND hwndOwner,    //Parent window of property sheet dialog box
+  UINT x,            //Horizontal position for dialog box
+  UINT y,            //Vertical position for dialog box
+  LPCOLESTR lpszCaption,
+                     //Pointer to the dialog box caption
+  ULONG cObjects,    //Number of object pointers in lplpUnk
+  LPUNKNOWN * lplpUnk,
+                     //Pointer to the objects for property sheet
+  ULONG cPages,      //Number of property pages in lpPageClsID
+  LPCLSID lpPageClsID,
+                     //Array of CLSIDs for each property page
+  LCID lcid,         //Locale identifier for property sheet locale
+  DWORD dwReserved,  //Reserved
+  LPVOID lpvReserved //Reserved
+);
+WINOLEAPI OleDraw(
+  LPUNKNOWN pUnk,    //Pointer to the view object to be drawn
+  DWORD dwAspect,     //How the object is to be represented
+  HDC hdcDraw,        //Device context on which to draw
+  LPCRECT lprcBounds  //Pointer to the rectangle in which the object
+                      // is drawn
+);
+WINOLEAPI OleFlushClipboard();
+WINOLEAPI OleGetClipboard(
+  LPDATAOBJECT * ppDataObj  //Address of output variable that
+                            // receives the IDataObject interface
+                            // pointer
+);
+WINOLEAPI OleIsCurrentClipboard(
+  LPDATAOBJECT pDataObject  //Pointer to the data object previously
+                             // copied or cut
+);
+BOOL OleIsRunning(
+  LPOLEOBJECT pObject  //Pointer to the interface
+);
+WINOLEAPI OleLoad(
+  LPSTORAGE pStg,   //Pointer to the storage object from which to
+                     // load
+  REFIID riid,       //Reference to the identifier of the interface
+  IOleClientSite * pClientSite,
+                     //Pointer to the client site for the object
+  LPVOID * ppvObj    //Address of output variable that receives the
+                     // interface pointer requested in riid
+);
+WINOLEAPI OleRun(
+  LPUNKNOWN pUnknown  //Pointer to interface on the object
+);
+WINOLEAPI OleSave(
+  LPPERSISTSTORAGE pPS,   //Pointer to the object to be saved
+  LPSTORAGE pStg,         //Pointer to the destination storage to
+                           // which pPS is saved
+  BOOL fSameAsLoad         //Whether the object was loaded from pstg
+                           // or not
+);
+WINOLEAPI OleSetClipboard(
+  LPDATAOBJECT pDataObj  //Pointer to the data object being copied
+                          // or cut
+);
+WINOLEAPI OleSetContainedObject(
+  LPUNKNOWN pUnk,  //Pointer to the interface on the embedded object
+  BOOL fContained  //Indicates if the object is embedded
+);
+WINOLEAPI OleSetMenuDescriptor(
+  HOLEMENU holemenu,      //Handle to the composite menu descriptor
+  HWND hwndFrame,         //Handle to the container's frame window
+  HWND hwndActiveObject,  //Handle to the object's in-place
+                          // activation window
+  LPOLEINPLACEFRAME lpFrame,  //Pointer to the container's frame
+                              // window
+  LPOLEINPLACEACTIVEOBJECT lpActiveObj
+                          //Active in-place object
+);
+STDAPI OleTranslateColor (
+  OLE_COLOR clr,       //Color to be converted into a COLORREF
+  HPALETTE hpal,       //Palette used for conversion
+  COLORREF *pcolorref  //Pointer to the caller's variable that
+                       // receives the converted result
+);
+WINOLEAPI ProgIDFromCLSID(
+  REFCLSID clsid,
+  LPOLESTR * lplpszProgID
+);
+
+WINOLEAPI RegisterDragDrop(
+  HWND hwnd,  //Handle to a window that can accept drops
+  LPDROPTARGET pDropTarget
+              //Pointer to object that is to be target of drop
+);
+void ReleaseStgMedium(
+  STGMEDIUM * pmedium  //Pointer to storage medium to be freed
+);
+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,
+  DWORD reserved,
+  LPSTORAGE* ppstgOpen
+);
+
+WINOLEAPI StgIsStorageFile(
+  WCHAR* pwcsName
+);
+
+HRESULT StgOpenStorage(
+  WCHAR* pwcsName,
+  LPSTORAGE pstgPriority,
+  DWORD grfMode,
+  SNB snbExclude,
+  DWORD reserved,
+  LPSTORAGE * ppstgOpen
+);
+
+WINOLEAPI StringFromCLSID(
+  REFCLSID rclsid,
+  LPOLESTR * ppsz
+);
+BSTR SysAllocString(
+  OLECHAR *  sz
+);
+VOID SysFreeString(
+  BSTR  bstr
+);
+UINT SysStringByteLen(
+  BSTR  bstr
+);
+HRESULT VariantChangeType(
+  VARIANTARG *  pvargDest,
+  VARIANTARG *  pvarSrc,
+  ushort  wFlags,
+  VARTYPE  vt
+);
+
+HRESULT VariantClear(
+  VARIANTARG *  pvarg
+);
+HRESULT VariantCopy(
+  VARIANTARG *  pvargDest,
+  VARIANTARG *  pvargSrc
+);
+VOID VariantInit(
+  VARIANTARG *  pvarg
+);
+WINOLEAPI WriteClassStg(
+  LPSTORAGE pStg,
+  REFCLSID rclsid
+);
+
+STDAPI CreateStdAccessibleObject(
+  HWND hwnd,
+  LONG idObject,
+  REFIID riidInterface,
+  void** ppvObject
+);
+LRESULT LresultFromObject(
+  REFIID riid,
+  WPARAM wParam,
+  LPUNKNOWN pAcc
+);
+
+} // end of comapi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/COMTYPES.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,60 @@
+/*
+ * extra COM types not define in any other modules
+ * don't import this module directly, import std.internal.ole.win32.com instead
+ *
+ * author : Shawn Liu
+ */
+
+module org.eclipse.swt.internal.ole.win32.COMTYPES;
+
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.internal.ole.win32.extras;
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+
+// private import org.eclipse.swt.internal.ole.win32.extras;
+
+
+
+alias IID* LPIID;
+alias HRESULT STDAPI;
+alias DWORD OLE_COLOR;
+
+// for temp use
+// alias void* ComObj;
+
+struct CAUUID {
+    ULONG cElems;
+    GUID* pElems;
+}
+struct CONNECTDATA
+{
+	LPUNKNOWN pUnk;
+	DWORD dwCookie;
+}
+
+struct CONTROLINFO {
+    ULONG  cb;
+    HACCEL hAccel;
+    USHORT cAccel;
+    DWORD  dwFlags;
+}
+
+struct LICINFO {
+    ULONG cbLicInfo;
+    BOOL  fRuntimeKeyAvail;
+    BOOL  fLicVerified;
+}
+
+struct POINTF
+{
+    FLOAT x;
+    FLOAT y;
+}
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/DOCOBJ.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,407 @@
+module org.eclipse.swt.internal.ole.win32.DOCOBJ;
+
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+private import org.eclipse.swt.internal.win32.OS;
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+//private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+
+extern( Windows ) {
+
+alias wchar wchar_t;
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright 1995 - 1998 Microsoft Corporation. All Rights Reserved.
+//
+//  Contents:   OLE Document Object interfaces
+//
+//----------------------------------------------------------------------------
+
+
+/*
+#define HWND        UserHWND
+#define HACCEL      UserHACCEL
+#define HDC         UserHDC
+#define HFONT       UserHFONT
+#define MSG         UserMSG
+#define BSTR        UserBSTR
+#define EXCEPINFO   UserEXCEPINFO
+#define VARIANT     UserVARIANT
+*/
+/*
+interface IOleDocument;
+interface IOleDocumentSite;
+interface IOleDocumentView;
+interface IEnumOleDocumentViews;
+interface IContinueCallback;
+interface IPrint;
+interface IOleCommandTarget;
+  */
+
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IOleDocument interface definition
+//
+//----------------------------------------------------------------------------
+enum DOCMISC {
+                DOCMISC_CANCREATEMULTIPLEVIEWS          = 1,
+                DOCMISC_SUPPORTCOMPLEXRECTANGLES        = 2,
+                DOCMISC_CANTOPENEDIT                        = 4,        // fails the IOleDocumentView::Open  method
+                DOCMISC_NOFILESUPPORT                       = 8,        //  does not support read/writing to a file
+}
+
+interface IOleDocument : IUnknown
+{
+        HRESULT CreateView(IOleInPlaceSite pIPSite,IStream pstm,DWORD dwReserved,IOleDocumentView *ppView);
+
+        HRESULT GetDocMiscStatus(DWORD *pdwStatus);
+
+        HRESULT EnumViews( IEnumOleDocumentViews * ppEnum, IOleDocumentView * ppView);
+}
+alias IOleDocument LPOLEDOCUMENT;
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IOleDocumentSite interface definition
+//
+//----------------------------------------------------------------------------
+interface IOleDocumentSite : IUnknown
+{
+        HRESULT ActivateMe(IOleDocumentView pViewToActivate);
+}
+alias IOleDocumentSite LPOLEDOCUMENTSITE;
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IOleDocumentView interface definition
+//
+//----------------------------------------------------------------------------
+interface IOleDocumentView : IUnknown
+{
+        HRESULT SetInPlaceSite(IOleInPlaceSite pIPSite);
+
+        HRESULT GetInPlaceSite(IOleInPlaceSite * ppIPSite);
+
+        HRESULT GetDocument(IUnknown *ppunk);
+
+        HRESULT SetRect(LPRECT prcView);
+
+        HRESULT GetRect(LPRECT prcView);
+
+        HRESULT SetRectComplex(LPRECT prcView,LPRECT prcHScroll,LPRECT prcVScroll,LPRECT prcSizeBox);
+
+        HRESULT Show(BOOL fShow);
+
+        HRESULT UIActivate(BOOL fUIActivate);
+
+        HRESULT Open();
+
+        HRESULT CloseView(DWORD dwReserved);
+
+        HRESULT SaveViewState(LPSTREAM pstm);
+
+        HRESULT ApplyViewState(LPSTREAM pstm);
+
+        HRESULT Clone(IOleInPlaceSite pIPSiteNew,IOleDocumentView *ppViewNew);
+}
+alias IOleDocumentView LPOLEDOCUMENTVIEW;
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IEnumOleDocumentViews interface definition
+//
+//----------------------------------------------------------------------------
+interface IEnumOleDocumentViews : IUnknown
+{
+        HRESULT Next(
+	ULONG cViews,
+	IOleDocumentView * rgpView,
+		ULONG *pcFetched);
+
+        HRESULT Skip(ULONG cViews);
+
+        HRESULT Reset();
+
+        HRESULT Clone(IEnumOleDocumentViews *ppEnum);
+}
+alias IEnumOleDocumentViews LPENUMOLEDOCUMENTVIEWS;
+
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IContinueCallback interface definition
+//
+//----------------------------------------------------------------------------
+
+interface IContinueCallback : IUnknown
+{
+        HRESULT FContinue();
+
+        HRESULT FContinuePrinting(LONG nCntPrinted,LONG nCurPage, wchar_t * pwszPrintStatus);
+}
+alias IContinueCallback  LPCONTINUECALLBACK;
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IPrint interface definition
+//
+//----------------------------------------------------------------------------
+enum PRINTFLAG
+        {
+                PRINTFLAG_MAYBOTHERUSER         = 1,
+                PRINTFLAG_PROMPTUSER            = 2,
+                PRINTFLAG_USERMAYCHANGEPRINTER  = 4,
+                PRINTFLAG_RECOMPOSETODEVICE     = 8,
+                PRINTFLAG_DONTACTUALLYPRINT     = 16,
+                PRINTFLAG_FORCEPROPERTIES       = 32,
+                PRINTFLAG_PRINTTOFILE           = 64
+        } ;
+
+struct  PAGERANGE
+        {
+                LONG nFromPage;
+                LONG nToPage;
+        }
+
+struct  PAGESET
+        {
+                ULONG   cbStruct;
+                BOOL    fOddPages;
+                BOOL    fEvenPages;
+                ULONG   cPageRange;
+                PAGERANGE[1] rgPages;
+        }
+
+interface IPrint : IUnknown
+{
+
+        HRESULT SetInitialPageNum(LONG nFirstPage);
+
+        HRESULT GetPageInfo(LONG *pnFirstPage,LONG *pcPages);
+
+        HRESULT Print(
+	DWORD grfFlags,
+DVTARGETDEVICE **pptd,
+PAGESET ** ppPageSet,
+STGMEDIUM * pstgmOptions,
+IContinueCallback pcallback,
+LONG nFirstPage,
+LONG *pcPagesPrinted,
+LONG *pnLastPage);
+}
+alias IPrint LPPRINT;
+
+
+//+---------------------------------------------------------------------------
+//
+//  Copyright (C) Microsoft Corporation, 1995-1997.
+//
+//  Contents:    IOleCommandTarget interface definition
+//
+//----------------------------------------------------------------------------
+enum OLECMDF
+        {
+                OLECMDF_SUPPORTED       = 0x00000001,
+                OLECMDF_ENABLED         = 0x00000002,
+                OLECMDF_LATCHED         = 0x00000004,
+                OLECMDF_NINCHED         = 0x00000008,
+        }
+
+
+
+
+struct OLECMD {
+                ULONG   cmdID;
+                DWORD   cmdf;
+        }
+
+struct OLECMDTEXT{
+                DWORD cmdtextf;
+                ULONG cwActual;
+                ULONG cwBuf;    /* size in wide chars of the buffer for text */
+                wchar_t[1] rgwz; /* Array into which callee writes the text */
+}
+
+enum OLECMDTEXTF
+        {
+                OLECMDTEXTF_NONE        = 0,
+                OLECMDTEXTF_NAME        = 1,
+                OLECMDTEXTF_STATUS      = 2,
+        }
+
+enum OLECMDEXECOPT
+        {
+                OLECMDEXECOPT_DODEFAULT         = 0,
+                OLECMDEXECOPT_PROMPTUSER        = 1,
+                OLECMDEXECOPT_DONTPROMPTUSER    = 2,
+                OLECMDEXECOPT_SHOWHELP          = 3
+        }
+enum OLECMDID {
+                OLECMDID_OPEN                           = 1,
+                OLECMDID_NEW                            = 2,
+                OLECMDID_SAVE                           = 3,
+                OLECMDID_SAVEAS                         = 4,
+                OLECMDID_SAVECOPYAS                     = 5,
+                OLECMDID_PRINT                          = 6,
+                OLECMDID_PRINTPREVIEW                   = 7,
+                OLECMDID_PAGESETUP                      = 8,
+                OLECMDID_SPELL                          = 9,
+                OLECMDID_PROPERTIES                     = 10,
+                OLECMDID_CUT                            = 11,
+                OLECMDID_COPY                           = 12,
+                OLECMDID_PASTE                          = 13,
+                OLECMDID_PASTESPECIAL                   = 14,
+                OLECMDID_UNDO                           = 15,
+                OLECMDID_REDO                           = 16,
+                OLECMDID_SELECTALL                      = 17,
+                OLECMDID_CLEARSELECTION                 = 18,
+                OLECMDID_ZOOM                           = 19,
+                OLECMDID_GETZOOMRANGE                   = 20,
+                OLECMDID_UPDATECOMMANDS                 = 21,
+                OLECMDID_REFRESH                        = 22,
+                OLECMDID_STOP                           = 23,
+                OLECMDID_HIDETOOLBARS                   = 24,
+                OLECMDID_SETPROGRESSMAX                 = 25,
+                OLECMDID_SETPROGRESSPOS                 = 26,
+                OLECMDID_SETPROGRESSTEXT                = 27,
+                OLECMDID_SETTITLE                       = 28,
+                OLECMDID_SETDOWNLOADSTATE               = 29,
+                OLECMDID_STOPDOWNLOAD                   = 30,
+                OLECMDID_ONTOOLBARACTIVATED             = 31,
+                OLECMDID_FIND                           = 32,
+                OLECMDID_DELETE                         = 33,
+                OLECMDID_HTTPEQUIV                      = 34,
+                OLECMDID_HTTPEQUIV_DONE                 = 35,
+                OLECMDID_ENABLE_INTERACTION             = 36,
+                OLECMDID_ONUNLOAD                       = 37,
+                OLECMDID_PROPERTYBAG2                   = 38,
+                OLECMDID_PREREFRESH                     = 39
+        }
+
+interface IOleCommandTarget : IUnknown
+{
+
+/* error codes */
+/*
+cpp_quote("#define OLECMDERR_E_FIRST            (OLE_E_LAST+1)")
+cpp_quote("#define OLECMDERR_E_NOTSUPPORTED (OLECMDERR_E_FIRST)")
+cpp_quote("#define OLECMDERR_E_DISABLED         (OLECMDERR_E_FIRST+1)")
+cpp_quote("#define OLECMDERR_E_NOHELP           (OLECMDERR_E_FIRST+2)")
+cpp_quote("#define OLECMDERR_E_CANCELED         (OLECMDERR_E_FIRST+3)")
+cpp_quote("#define OLECMDERR_E_UNKNOWNGROUP     (OLECMDERR_E_FIRST+4)")
+
+cpp_quote("#define MSOCMDERR_E_FIRST OLECMDERR_E_FIRST")
+cpp_quote("#define MSOCMDERR_E_NOTSUPPORTED OLECMDERR_E_NOTSUPPORTED")
+cpp_quote("#define MSOCMDERR_E_DISABLED OLECMDERR_E_DISABLED")
+cpp_quote("#define MSOCMDERR_E_NOHELP OLECMDERR_E_NOHELP")
+cpp_quote("#define MSOCMDERR_E_CANCELED OLECMDERR_E_CANCELED")
+cpp_quote("#define MSOCMDERR_E_UNKNOWNGROUP OLECMDERR_E_UNKNOWNGROUP")
+  */
+        HRESULT QueryStatus(
+					GUID *pguidCmdGroup,
+				ULONG cCmds,
+					OLECMD * prgCmds,
+				OLECMDTEXT *pCmdText);
+
+
+        HRESULT Exec(
+					GUID *pguidCmdGroup,
+					DWORD nCmdID,
+				DWORD nCmdexecopt,
+					VARIANT *pvaIn,
+				VARIANT *pvaOut);
+}
+alias IOleCommandTarget LPOLECOMMANDTARGET;
+/*
+cpp_quote("typedef enum")
+cpp_quote("{")
+cpp_quote("      OLECMDIDF_REFRESH_NORMAL          = 0,")
+cpp_quote("      OLECMDIDF_REFRESH_IFEXPIRED       = 1,")
+cpp_quote("      OLECMDIDF_REFRESH_CONTINUE        = 2,")
+cpp_quote("      OLECMDIDF_REFRESH_COMPLETELY      = 3,")
+cpp_quote("      OLECMDIDF_REFRESH_NO_CACHE        = 4,")
+cpp_quote("      OLECMDIDF_REFRESH_RELOAD          = 5,")
+cpp_quote("      OLECMDIDF_REFRESH_LEVELMASK       = 0x00FF,")
+cpp_quote("      OLECMDIDF_REFRESH_CLEARUSERINPUT  = 0x1000,")
+cpp_quote("      OLECMDIDF_REFRESH_PROMPTIFOFFLINE = 0x2000,")
+cpp_quote("} OLECMDID_REFRESHFLAG;")
+
+cpp_quote("")
+cpp_quote("////////////////////////////////////////////////////////////////////////////")
+cpp_quote("//  Aliases to original office-compatible names")
+cpp_quote("#define IMsoDocument             IOleDocument")
+cpp_quote("#define IMsoDocumentSite         IOleDocumentSite")
+cpp_quote("#define IMsoView                 IOleDocumentView")
+cpp_quote("#define IEnumMsoView             IEnumOleDocumentViews")
+cpp_quote("#define IMsoCommandTarget        IOleCommandTarget")
+cpp_quote("#define LPMSODOCUMENT            LPOLEDOCUMENT")
+cpp_quote("#define LPMSODOCUMENTSITE        LPOLEDOCUMENTSITE")
+cpp_quote("#define LPMSOVIEW                LPOLEDOCUMENTVIEW")
+cpp_quote("#define LPENUMMSOVIEW            LPENUMOLEDOCUMENTVIEWS")
+cpp_quote("#define LPMSOCOMMANDTARGET       LPOLECOMMANDTARGET")
+cpp_quote("#define MSOCMD                   OLECMD")
+cpp_quote("#define MSOCMDTEXT               OLECMDTEXT")
+cpp_quote("#define IID_IMsoDocument         IID_IOleDocument")
+cpp_quote("#define IID_IMsoDocumentSite     IID_IOleDocumentSite")
+cpp_quote("#define IID_IMsoView             IID_IOleDocumentView")
+cpp_quote("#define IID_IEnumMsoView         IID_IEnumOleDocumentViews")
+cpp_quote("#define IID_IMsoCommandTarget    IID_IOleCommandTarget")
+cpp_quote("#define MSOCMDF_SUPPORTED OLECMDF_SUPPORTED")
+cpp_quote("#define MSOCMDF_ENABLED OLECMDF_ENABLED")
+cpp_quote("#define MSOCMDF_LATCHED OLECMDF_LATCHED")
+cpp_quote("#define MSOCMDF_NINCHED OLECMDF_NINCHED")
+cpp_quote("#define MSOCMDTEXTF_NONE OLECMDTEXTF_NONE")
+cpp_quote("#define MSOCMDTEXTF_NAME OLECMDTEXTF_NAME")
+cpp_quote("#define MSOCMDTEXTF_STATUS OLECMDTEXTF_STATUS")
+cpp_quote("#define MSOCMDEXECOPT_DODEFAULT OLECMDEXECOPT_DODEFAULT")
+cpp_quote("#define MSOCMDEXECOPT_PROMPTUSER OLECMDEXECOPT_PROMPTUSER")
+cpp_quote("#define MSOCMDEXECOPT_DONTPROMPTUSER OLECMDEXECOPT_DONTPROMPTUSER")
+cpp_quote("#define MSOCMDEXECOPT_SHOWHELP OLECMDEXECOPT_SHOWHELP")
+cpp_quote("#define MSOCMDID_OPEN OLECMDID_OPEN")
+cpp_quote("#define MSOCMDID_NEW OLECMDID_NEW")
+cpp_quote("#define MSOCMDID_SAVE OLECMDID_SAVE")
+cpp_quote("#define MSOCMDID_SAVEAS OLECMDID_SAVEAS")
+cpp_quote("#define MSOCMDID_SAVECOPYAS OLECMDID_SAVECOPYAS")
+cpp_quote("#define MSOCMDID_PRINT OLECMDID_PRINT")
+cpp_quote("#define MSOCMDID_PRINTPREVIEW OLECMDID_PRINTPREVIEW")
+cpp_quote("#define MSOCMDID_PAGESETUP OLECMDID_PAGESETUP")
+cpp_quote("#define MSOCMDID_SPELL OLECMDID_SPELL")
+cpp_quote("#define MSOCMDID_PROPERTIES OLECMDID_PROPERTIES")
+cpp_quote("#define MSOCMDID_CUT OLECMDID_CUT")
+cpp_quote("#define MSOCMDID_COPY OLECMDID_COPY")
+cpp_quote("#define MSOCMDID_PASTE OLECMDID_PASTE")
+cpp_quote("#define MSOCMDID_PASTESPECIAL OLECMDID_PASTESPECIAL")
+cpp_quote("#define MSOCMDID_UNDO OLECMDID_UNDO")
+cpp_quote("#define MSOCMDID_REDO OLECMDID_REDO")
+cpp_quote("#define MSOCMDID_SELECTALL OLECMDID_SELECTALL")
+cpp_quote("#define MSOCMDID_CLEARSELECTION OLECMDID_CLEARSELECTION")
+cpp_quote("#define MSOCMDID_ZOOM OLECMDID_ZOOM")
+cpp_quote("#define MSOCMDID_GETZOOMRANGE OLECMDID_GETZOOMRANGE")
+
+cpp_quote("EXTERN_C const GUID SID_SContainerDispatch;")
+								*/
+} // extern( Windows)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/EXDISP.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,911 @@
+module org.eclipse.swt.internal.ole.win32.EXDISP;
+//+-------------------------------------------------------------------------
+//
+//  Microsoft Windows
+//  Copyright 1995 - 1998 Microsoft Corporation. All Rights Reserved.
+//
+//--------------------------------------------------------------------------
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+private import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+private import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.WINTYPES;
+
+extern (Windows) {
+
+        enum BrowserNavConstants {
+            navOpenInNewWindow = 0x0001,
+            navNoHistory = 0x0002,
+            navNoReadFromCache = 0x0004,
+            navNoWriteToCache = 0x0008,
+            navAllowAutosearch = 0x0010,
+            navBrowserBar = 0x0020,
+        };
+        enum RefreshConstants {                                         // must map to these in sdk\inc\docobj.h
+            REFRESH_NORMAL     = 0,  //== OLECMDIDF_REFRESH_NORMAL
+            REFRESH_IFEXPIRED  = 1,  //== OLECMDIDF_REFRESH_IFEXPIRED
+            REFRESH_COMPLETELY = 3   //== OLECMDIDF_REFRESH_COMPLETELY
+        };
+
+interface IWebBrowser : IDispatch
+{
+        HRESULT GoBack();
+        HRESULT GoForward();
+        HRESULT GoHome();
+        HRESULT GoSearch();
+
+        HRESULT Navigate( BSTR URL,
+                         VARIANT * Flags,
+                         VARIANT * TargetFrameName,
+                         VARIANT * PostData,
+                         VARIANT * Headers);
+
+        HRESULT Refresh();
+
+        HRESULT Refresh2(VARIANT * Level);
+
+        HRESULT Stop();
+
+        HRESULT Application( IDispatch* ppDisp);
+
+        HRESULT Parent( IDispatch* ppDisp);
+
+        HRESULT Container( IDispatch* ppDisp);
+
+        HRESULT Document( IDispatch* ppDisp);
+
+        HRESULT TopLevelContainer( VARIANT_BOOL* pBool);
+
+        HRESULT Type( BSTR* Type);
+
+        // Window stuff...
+        HRESULT Left( LONG *pl);
+        HRESULT Put_Left( LONG Left);
+        HRESULT Top( LONG *pl);
+        HRESULT Put_Top( LONG Top);
+        HRESULT Width(LONG *pl);
+        HRESULT Put_Width(LONG Width);
+        HRESULT Height(LONG *pl);
+        HRESULT Put_Height(LONG Height);
+
+        // WebBrowser stuff...
+        HRESULT LocationName( BSTR *LocationName);
+
+        HRESULT LocationURL( BSTR * LocationURL);
+
+        HRESULT Busy( VARIANT_BOOL *pBool);
+    }
+
+/* //not sure how to process this
+    dispinterface DWebBrowserEvents
+    {
+        properties:
+        methods:
+        [id(DISPID_BEFORENAVIGATE), helpstring("Fired when a new hyperlink is being navigated to."), helpcontext(0x0000)]
+        void BeforeNavigate([in] BSTR URL, long Flags, BSTR TargetFrameName, VARIANT * PostData, BSTR Headers, [in, out]VARIANT_BOOL * Cancel);
+
+        [id(DISPID_NAVIGATECOMPLETE), helpstring("Fired when the document being navigated to becomes visible and enters the navigation stack."), helpcontext(0x0000)]
+        void NavigateComplete([in] BSTR URL );
+
+        [id(DISPID_STATUSTEXTCHANGE), helpstring("Statusbar text changed."), helpcontext(0x0000)]
+        void StatusTextChange([in]BSTR Text);
+
+        [id(DISPID_PROGRESSCHANGE), helpstring("Fired when download progress is updated."), helpcontext(0x0000)]
+        void ProgressChange([in] long Progress, [in] long ProgressMax);
+
+        [id(DISPID_DOWNLOADCOMPLETE), helpstring("Download of page complete."), helpcontext(0x0000)]
+        void DownloadComplete();
+
+        [id(DISPID_COMMANDSTATECHANGE), helpstring("The enabled state of a command changed"), helpcontext(0x0000)]
+        void CommandStateChange([in] long Command, [in] VARIANT_BOOL Enable);
+
+        [id(DISPID_DOWNLOADBEGIN), helpstring("Download of a page started."), helpcontext(0x000)]
+        void DownloadBegin();
+
+        [id(DISPID_NEWWINDOW), helpstring("Fired when a new window should be created."), helpcontext(0x0000)]
+        void NewWindow([in] BSTR URL, [in] long Flags, [in] BSTR TargetFrameName, [in] VARIANT * PostData, [in] BSTR Headers, [in,out] VARIANT_BOOL * Processed);
+
+        [id(DISPID_TITLECHANGE), helpstring("Document title changed."), helpcontext(0x0000)]
+        void TitleChange([in]BSTR Text);
+
+        [id(DISPID_FRAMEBEFORENAVIGATE), helpstring("Fired when a new hyperlink is being navigated to in a frame."), helpcontext(0x0000)]
+        void FrameBeforeNavigate([in] BSTR URL, long Flags, BSTR TargetFrameName, VARIANT * PostData, BSTR Headers, [in, out]VARIANT_BOOL * Cancel);
+
+        [id(DISPID_FRAMENAVIGATECOMPLETE), helpstring("Fired when a new hyperlink is being navigated to in a frame."), helpcontext(0x0000)]
+        void FrameNavigateComplete([in] BSTR URL );
+
+        [id(DISPID_FRAMENEWWINDOW), helpstring("Fired when a new window should be created."), helpcontext(0x0000)]
+        void FrameNewWindow([in] BSTR URL, [in] long Flags, [in] BSTR TargetFrameName, [in] VARIANT * PostData, [in] BSTR Headers, [in,out] VARIANT_BOOL * Processed);
+
+        // The following are IWebBrowserApp specific:
+        //
+        [id(DISPID_QUIT), helpstring("Fired when application is quiting."), helpcontext(0x0000)]
+        void Quit([in, out] VARIANT_BOOL * Cancel);
+
+        [id(DISPID_WINDOWMOVE), helpstring("Fired when window has been moved."), helpcontext(0x0000)]
+        void WindowMove();
+
+        [id(DISPID_WINDOWRESIZE), helpstring("Fired when window has been sized."), helpcontext(0x0000)]
+        void WindowResize();
+
+        [id(DISPID_WINDOWACTIVATE), helpstring("Fired when window has been activated."), helpcontext(0x0000)]
+        void WindowActivate();
+
+        [id(DISPID_PROPERTYCHANGE), helpstring("Fired when the PutProperty method has been called."), helpcontext(0x0000)]
+        void PropertyChange([in] BSTR Property);
+    }
+   */
+
+    enum CommandStateChangeConstants : uint {
+        CSC_UPDATECOMMANDS  = 0xFFFFFFFF,
+        CSC_NAVIGATEFORWARD = 0x00000001,
+        CSC_NAVIGATEBACK    = 0x00000002,
+    }
+
+    interface IWebBrowserApp : IWebBrowser
+    {
+        HRESULT Quit();
+
+        HRESULT ClientToWindow( int* pcx,  int* pcy);
+
+        HRESULT PutProperty( BSTR Property, VARIANT vtValue);
+        HRESULT GetProperty( BSTR Property, VARIANT *pvtValue);
+
+        HRESULT Name( BSTR* Name);
+
+        HRESULT HWND(LONG *pHWND);
+
+        HRESULT FullName( BSTR* FullName);
+
+        HRESULT Path( BSTR* Path);
+
+        HRESULT Visible( VARIANT_BOOL* pBool);
+        HRESULT Visible( VARIANT_BOOL Value);
+
+        HRESULT StatusBar( VARIANT_BOOL* pBool);
+        HRESULT StatusBar( VARIANT_BOOL Value);
+
+        HRESULT StatusText( BSTR *StatusText);
+        HRESULT StatusText( BSTR StatusText);
+
+        HRESULT ToolBar( int * Value);
+        HRESULT ToolBar( int Value);
+
+        HRESULT MenuBar( VARIANT_BOOL * Value);
+        HRESULT MenuBar( VARIANT_BOOL Value);
+
+        HRESULT FullScreen( VARIANT_BOOL * pbFullScreen);
+        HRESULT FullScreen( VARIANT_BOOL bFullScreen);
+    }
+
+    interface IWebBrowser2 : IWebBrowserApp
+    {
+        HRESULT Navigate2( VARIANT * URL,
+                          VARIANT * Flags,
+                          VARIANT * TargetFrameName,
+                          VARIANT * PostData,
+                          VARIANT * Headers);
+
+
+        HRESULT QueryStatusWB( OLECMDID cmdID,  OLECMDF * pcmdf);
+        HRESULT ExecWB( OLECMDID cmdID,  OLECMDEXECOPT cmdexecopt, VARIANT * pvaIn, VARIANT * pvaOut);
+        HRESULT ShowBrowserBar( VARIANT * pvaClsid,
+                                VARIANT * pvarShow,
+                                VARIANT * pvarSize );
+
+        HRESULT ReadyState(READYSTATE * plReadyState);
+
+        HRESULT Offline(VARIANT_BOOL * pbOffline);
+        HRESULT Offline( VARIANT_BOOL bOffline);
+
+        HRESULT Silent(VARIANT_BOOL * pbSilent);
+        HRESULT Silent(VARIANT_BOOL bSilent);
+
+        HRESULT RegisterAsBrowser(VARIANT_BOOL * pbRegister);
+        HRESULT RegisterAsBrowser(VARIANT_BOOL bRegister);
+
+        HRESULT RegisterAsDropTarget(VARIANT_BOOL * pbRegister);
+        HRESULT RegisterAsDropTarget(VARIANT_BOOL bRegister);
+
+        HRESULT TheaterMode(VARIANT_BOOL * pbRegister);
+        HRESULT TheaterMode(VARIANT_BOOL bRegister);
+
+        HRESULT AddressBar(VARIANT_BOOL * Value);
+        HRESULT AddressBar(VARIANT_BOOL Value);
+
+        HRESULT Resizable(VARIANT_BOOL * Value);
+        HRESULT Resizable(VARIANT_BOOL Value);
+    }
+
+	 /*
+    dispinterface DWebBrowserEvents2
+    {
+        properties:
+        methods:
+        [id(DISPID_STATUSTEXTCHANGE), helpstring("Statusbar text changed."), helpcontext(0x0000)]
+        void StatusTextChange([in]BSTR Text);
+
+        [id(DISPID_PROGRESSCHANGE), helpstring("Fired when download progress is updated."), helpcontext(0x0000)]
+        void ProgressChange([in] long Progress, [in] long ProgressMax);
+
+        [id(DISPID_COMMANDSTATECHANGE), helpstring("The enabled state of a command changed."), helpcontext(0x0000)]
+        void CommandStateChange([in] long Command, [in] VARIANT_BOOL Enable);
+
+        [id(DISPID_DOWNLOADBEGIN), helpstring("Download of a page started."), helpcontext(0x000)]
+        void DownloadBegin();
+
+        [id(DISPID_DOWNLOADCOMPLETE), helpstring("Download of page complete."), helpcontext(0x0000)]
+        void DownloadComplete();
+
+        [id(DISPID_TITLECHANGE), helpstring("Document title changed."), helpcontext(0x0000)]
+        void TitleChange([in] BSTR Text);
+
+        [id(DISPID_PROPERTYCHANGE), helpstring("Fired when the PutProperty method has been called."), helpcontext(0x0000)]
+        void PropertyChange([in] BSTR szProperty);
+
+        // New events for IE40:
+        //
+        [id(DISPID_BEFORENAVIGATE2), helpstring("Fired before navigate occurs in the given WebBrowser (window or frameset element). The processing of this navigation may be modified."), helpcontext(0x0000)]
+        void BeforeNavigate2([in] IDispatch* pDisp,
+                             [in] VARIANT * URL, [in] VARIANT * Flags, [in] VARIANT * TargetFrameName, [in] VARIANT * PostData, [in] VARIANT * Headers,
+                             [in,out] VARIANT_BOOL * Cancel);
+
+        [id(DISPID_NEWWINDOW2), helpstring("A new, hidden, non-navigated WebBrowser window is needed."), helpcontext(0x0000)]
+        void NewWindow2([in, out] IDispatch** ppDisp, [in, out] VARIANT_BOOL * Cancel);
+
+        [id(DISPID_NAVIGATECOMPLETE2), helpstring("Fired when the document being navigated to becomes visible and enters the navigation stack."), helpcontext(0x0000)]
+        void NavigateComplete2([in] IDispatch* pDisp, [in] VARIANT * URL );
+
+        [id(DISPID_DOCUMENTCOMPLETE), helpstring("Fired when the document being navigated to reaches ReadyState_Complete."), helpcontext(0x0000)]
+        void DocumentComplete([in] IDispatch* pDisp, [in] VARIANT * URL );
+
+        [id(DISPID_ONQUIT), helpstring("Fired when application is quiting."), helpcontext(0x0000)]
+        void OnQuit();
+
+        [id(DISPID_ONVISIBLE), helpstring("Fired when the window should be shown/hidden"), helpcontext(0x0000)]
+        void OnVisible([in] VARIANT_BOOL Visible);
+
+        [id(DISPID_ONTOOLBAR), helpstring("Fired when the toolbar  should be shown/hidden"), helpcontext(0x0000)]
+        void OnToolBar([in] VARIANT_BOOL ToolBar);
+
+        [id(DISPID_ONMENUBAR), helpstring("Fired when the menubar should be shown/hidden"), helpcontext(0x0000)]
+        void OnMenuBar([in] VARIANT_BOOL MenuBar);
+
+        [id(DISPID_ONSTATUSBAR), helpstring("Fired when the statusbar should be shown/hidden"), helpcontext(0x0000)]
+        void OnStatusBar([in] VARIANT_BOOL StatusBar);
+
+        [id(DISPID_ONFULLSCREEN), helpstring("Fired when fullscreen mode should be on/off"), helpcontext(0x0000)]
+        void OnFullScreen([in] VARIANT_BOOL FullScreen);
+
+        [id(DISPID_ONTHEATERMODE), helpstring("Fired when theater mode should be on/off"), helpcontext(0x0000)]
+        void OnTheaterMode([in] VARIANT_BOOL TheaterMode);
+    }
+    */
+
+    /*
+
+    [
+        uuid(EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B), // v.1 clsid CLSID_WebBrowser_V1
+        control,
+        helpstring("WebBrowser Control")
+    ]
+    coclass WebBrowser_V1
+    {
+                          interface     IWebBrowser2;
+        [default]         interface     IWebBrowser;
+        [source]          dispinterface DWebBrowserEvents2;
+        [default, source] dispinterface DWebBrowserEvents;
+    }
+
+    [
+        uuid(8856F961-340A-11D0-A96B-00C04FD705A2), // v.2 clsid CLSID_WebBrowser
+        control,
+        helpstring("WebBrowser Control")
+    ]
+    coclass WebBrowser
+    {
+        [default]         interface     IWebBrowser2;
+                          interface     IWebBrowser;
+        [default, source] dispinterface DWebBrowserEvents2;
+        [source]          dispinterface DWebBrowserEvents;
+    }
+
+    [
+        uuid(0002DF01-0000-0000-C000-000000000046), // CLSID_InternetExplorer
+        helpstring("Internet Explorer Application."),
+    ]
+    coclass InternetExplorer
+    {
+        [default]         interface     IWebBrowser2;
+                          interface     IWebBrowserApp;
+        [default, source] dispinterface DWebBrowserEvents2;
+        [source]          dispinterface DWebBrowserEvents;
+    }
+
+	 */
+
+
+    interface IFolderViewOC : IDispatch
+    {
+        HRESULT SetFolderView(IDispatch pdisp);
+    }
+
+    interface DShellFolderViewEvents
+    {
+        void SelectionChanged();
+    }
+
+/*    [
+        uuid(9BA05971-F6A8-11CF-A442-00A0C90A8F39), // CLSID_ShellFolderViewOC
+        helpstring("Shell Folder View Events Router."),
+        hidden
+    ]
+    coclass ShellFolderViewOC
+    {
+        [default]         interface     IFolderViewOC;
+        [default, source] dispinterface DShellFolderViewEvents;
+    }*/
+    enum ShellWindowTypeConstants {
+        SWC_EXPLORER    = 0x0,
+        SWC_BROWSER     = 0x00000001,
+        SWC_3RDPARTY    = 0x00000002,
+        SWC_CALLBACK    = 0x00000004,
+    }
+
+    enum ShellWindowFindWindowOptions {
+        SWFO_NEEDDISPATCH   = 0x00000001,
+        SWFO_INCLUDEPENDING = 0x00000002,
+        SWFO_COOKIEPASSED   = 0x00000004,
+    }
+
+    interface DShellWindowsEvents
+    {
+        void WindowRegistered(LONG lCookie);
+
+        void WindowRevoked(LONG lCookie);
+    }
+
+    interface IShellWindows : IDispatch
+    {
+        //Properties
+        HRESULT Count(LONG *Count);
+
+        HRESULT Item(VARIANT index, IDispatch *Folder);
+
+        HRESULT _NewEnum(IUnknown *ppunk);
+
+        // Some private hidden members to allow shell windows to add and
+        // remove themself from the list.  We mark them hidden to keep
+        // random VB apps from trying to Register...
+        HRESULT Register( IDispatch pid,
+                         LONG hwnd,
+                         int swClass,
+                         LONG *plCookie);
+
+        HRESULT RegisterPending(LONG lThreadId,
+                         VARIANT* pvarloc,     // will hold pidl that is being opened.
+                         VARIANT* pvarlocRoot, // Optional root pidl
+                         int swClass,
+                         LONG *plCookie);
+
+        HRESULT Revoke(LONG lCookie);
+        // As an optimization, each window notifies the new location
+        // only when
+        //  (1) it's being deactivated
+        //  (2) getFullName is called (we overload it to force update)
+        HRESULT OnNavigate(LONG lCookie, VARIANT* pvarLoc);
+        HRESULT OnActivated(LONG lCookie, VARIANT_BOOL fActive);
+        HRESULT FindWindow(VARIANT* pvarLoc,
+                           VARIANT* pvarLocRoot,
+                           int swClass,
+                           LONG * phwnd,
+                            int swfwOptions,
+                           IDispatch* ppdispOut);
+        HRESULT OnCreated(LONG lCookie,IUnknown punk);
+
+        HRESULT ProcessAttachDetach(VARIANT_BOOL fAttach);
+    }
+
+	 /*
+    [
+        uuid(9BA05972-F6A8-11CF-A442-00A0C90A8F39),     // CLSID_ShellWindows
+        helpstring("ShellDispatch Load in Shell Context")
+    ]
+    coclass ShellWindows
+    {
+        [default] interface IShellWindows;
+        [default, source] dispinterface DShellWindowsEvents;
+    }
+    */
+
+    /*
+
+    [
+        uuid(88A05C00-F000-11CE-8350-444553540000), // IID_IShellLinkDual
+        helpstring("Definition of Shell Link IDispatch interface"),
+        oleautomation,
+        dual,
+        odl,
+        hidden,
+    ]
+    interface IShellLinkDual : IDispatch
+    {
+        [propget, helpstring("Get the path of the link")]
+        HRESULT Path([out, retval] BSTR *pbs);
+
+        [propput, helpstring("Set the path of the link")]
+        HRESULT Path([in] BSTR bs);
+
+        [propget, helpstring("Get the description for the link")]
+        HRESULT Description([out, retval] BSTR *pbs);
+
+        [propput, helpstring("Set the description for the link")]
+        HRESULT Description([in] BSTR bs);
+
+        [propget, helpstring("Get the working directory for the link")]
+        HRESULT WorkingDirectory([out, retval] BSTR *pbs);
+
+        [propput, helpstring("Set the working directory for the link")]
+        HRESULT WorkingDirectory([in] BSTR bs);
+
+        [propget, helpstring("Get the arguments for the link")]
+        HRESULT Arguments([out, retval] BSTR *pbs);
+
+        [propput, helpstring("Set the arguments for the link")]
+        HRESULT Arguments([in] BSTR bs);
+
+
+        [propget, helpstring("Get the Hotkey for the link")]
+        HRESULT Hotkey([out, retval] int *piHK);
+
+        [propput, helpstring("Set the Hotkey for the link")]
+        HRESULT Hotkey([in] int iHK);
+
+        [propget, helpstring("Get the Show Command for the link")]
+        HRESULT ShowCommand([out, retval] int *piShowCommand);
+
+        [propput, helpstring("Set the Show Command for the link")]
+        HRESULT ShowCommand([in] int iShowCommand);
+
+        // STDMETHOD(SetRelativePath)(THIS_ LPCSTR pszPathRel, DWORD dwReserved) PURE;
+        //Methods
+        [helpstring("Tell the link to resolve itself")]
+        HRESULT Resolve([in] int fFlags);
+
+        [helpstring("Get the IconLocation for the link")]
+        HRESULT GetIconLocation([out] BSTR *pbs, [out,retval] int *piIcon);
+
+        [helpstring("Set the IconLocation for the link")]
+        HRESULT SetIconLocation([in] BSTR bs, [in] int iIcon);
+
+        [helpstring("Tell the link to save the changes")]
+        HRESULT Save ([in, optional] VARIANT vWhere);
+    }
+
+    [
+        uuid(11219420-1768-11d1-95BE-00609797EA4F), // CLSID_ShellLinkObject
+        helpstring("Shell Link object")
+    ]
+    coclass ShellLinkObject // funny name so we don't conflict with CLSID_ShellLink
+    {
+        [default] interface IShellLinkDual;
+    }
+
+    [
+        uuid(08EC3E00-50B0-11CF-960C-0080C7F4EE85), // IID_FolderItemVerb
+        helpstring("Definition of interface FolderItemVerb"),
+        oleautomation,
+        dual,
+        odl,
+    ]
+    interface FolderItemVerb : IDispatch
+    {
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        [id(0), propget, helpstring("Get display name for item")]
+        HRESULT Name([out, retval] BSTR *pbs);
+
+        [helpstring("Execute the verb")]
+        HRESULT DoIt();
+    }
+
+    [
+        uuid(1F8352C0-50B0-11CF-960C-0080C7F4EE85), // IID_FolderItemVerbs
+        helpstring("Definition of interface FolderItemVerbs"),
+        oleautomation,
+        dual,
+        odl,
+    ]
+    interface FolderItemVerbs : IDispatch
+    {
+        //Properties
+        [propget, helpstring("Get count of open folder windows")]
+        HRESULT Count([out, retval] long *plCount);
+
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        //Methods
+        //Standard Methods
+        [helpstring("Return the specified verb")]
+        HRESULT Item([in,optional] VARIANT index, [out, retval]FolderItemVerb **ppid);
+
+        [id(-4), helpstring("Enumerates the figures")]
+        HRESULT _NewEnum([out, retval] IUnknown **ppunk);
+    }
+
+    interface Folder;   // forward reference
+
+    [
+        uuid(FAC32C80-CBE4-11CE-8350-444553540000), // IID_FolderItem
+        helpstring("Definition of interface FolderItem"),
+        oleautomation,
+        dual,
+        odl,
+    ]
+    interface FolderItem : IDispatch
+    {
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        [id(0), propget, helpstring("Get display name for item")]
+        HRESULT Name([out, retval] BSTR *pbs);
+
+        [id(0), propput, helpstring("Set the name for the item")]
+        HRESULT Name([in] BSTR bs);
+
+        [propget, helpstring("Get the pathname to the item")]
+        HRESULT Path([out, retval]BSTR *pbs);
+
+        [propget, helpstring("If item is link return link object")]
+        HRESULT GetLink([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("If item is a folder return folder object")]
+        HRESULT GetFolder([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Is the item a link?")]
+        HRESULT IsLink([out, retval] VARIANT_BOOL *pb);
+
+        [propget, helpstring("Is the item a Folder?")]
+        HRESULT IsFolder([out, retval] VARIANT_BOOL *pb);
+
+        [propget, helpstring("Is the item a file system object?")]
+        HRESULT IsFileSystem([out, retval] VARIANT_BOOL *pb);
+
+        [propget, helpstring("Is the item browsable?")]
+        HRESULT IsBrowsable([out, retval] VARIANT_BOOL *pb);
+
+        [propget, helpstring("Modification Date?")]
+        HRESULT ModifyDate([out, retval] DATE *pdt);
+
+        [propput, helpstring("Modification Date?")]
+        HRESULT ModifyDate([in] DATE dt);
+
+        [propget, helpstring("Size")]
+        HRESULT Size([out, retval] LONG *pul);
+
+        [propget, helpstring("Type")]
+        HRESULT Type([out, retval] BSTR *pbs);
+
+        [helpstring("Get the list of verbs for the object")]
+        HRESULT Verbs([out, retval] FolderItemVerbs **ppfic);
+
+        [helpstring("Execute a command on the item")]
+        HRESULT InvokeVerb([in,optional] VARIANT vVerb);
+    }
+
+    [
+        uuid(744129E0-CBE5-11CE-8350-444553540000), // IID_FolderItems
+        helpstring("Definition of interface FolderItems"),
+        oleautomation,
+        dual,
+        odl,
+    ]
+    interface FolderItems : IDispatch
+    {
+        //Properties
+        [propget, helpstring("Get count of items in the folder")]
+        HRESULT Count([out, retval] long *plCount);
+
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        //Methods
+        //Standard Methods
+        [helpstring("Return the figure for the given index")]
+        HRESULT Item([in,optional] VARIANT index, [out, retval]FolderItem **ppid);
+
+        [id(-4), helpstring("Enumerates the figures")]
+        HRESULT _NewEnum([out, retval] IUnknown **ppunk);
+    }
+
+    [
+        uuid(BBCBDE60-C3FF-11CE-8350-444553540000), // IID_Folder
+        helpstring("Definition of interface Folder"),
+        oleautomation,
+        dual,
+        odl,
+    ]
+    interface Folder : IDispatch
+    {
+        //Properties
+        [id(0), propget, helpstring("Get the display name for the window")]
+        HRESULT Title([out, retval] BSTR *pbs);
+
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT ParentFolder([out, retval] Folder **ppsf);
+
+        //Methods
+        [helpstring("The collection of Items in folder")]
+        HRESULT Items([out, retval] FolderItems **ppid);
+
+        [helpstring("Parse the name to get an item.")]
+        HRESULT ParseName([in] BSTR bName, [out, retval] FolderItem **ppid);
+
+        [helpstring("Create a new sub folder in this folder.")]
+        HRESULT NewFolder([in] BSTR bName, [in, optional] VARIANT vOptions);
+
+        [helpstring("Move Items to this folder.")]
+        HRESULT MoveHere([in] VARIANT vItem, [in, optional] VARIANT vOptions);
+
+        [helpstring("Copy Items to this folder.")]
+        HRESULT CopyHere([in] VARIANT vItem, [in, optional] VARIANT vOptions);
+
+        [helpstring("Get the details about an item.")]
+        HRESULT GetDetailsOf([in] VARIANT vItem, [in] int iColumn, [out, retval]BSTR *pbs);
+    }
+
+    [
+        uuid(E7A1AF80-4D96-11CF-960C-0080C7F4EE85), // IID_IShellFolderViewDual
+        helpstring("definition of interface IShellFolderViewDual"),
+        oleautomation,
+        hidden,
+        dual,
+        odl,
+    ]
+    interface IShellFolderViewDual : IDispatch
+    {
+        [propget, helpstring("Get Application object")]
+        HRESULT Application([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get the folder being viewed")]
+        HRESULT Folder([out, retval] Folder **ppid);
+
+        [helpstring("The collection of Selected Items in folder")]
+        HRESULT SelectedItems([out, retval] FolderItems **ppid);
+
+        [propget, helpstring("The currently focused item in the folder")]
+        HRESULT FocusedItem([out, retval] FolderItem **ppid);
+
+        [helpstring("Select the item")]
+        HRESULT SelectItem([in]VARIANT *pvfi, [in] int dwFlags);
+
+        [helpstring("Show items menu and return command selected")]
+        HRESULT PopupItemMenu([in]FolderItem *pfi, [in, optional]VARIANT vx, [in, optional]VARIANT vy, [out, retval] BSTR *pbs);
+
+        [propget, helpstring("Returns the scripting automation model."), helpcontext(0x0000)]
+        HRESULT Script([out,retval] IDispatch** ppDisp);
+
+        [propget, helpstring("Returns the view options for showing a folder."), helpcontext(0x0000)]
+        HRESULT ViewOptions([out,retval] long * plViewOptions);
+    }
+
+    [
+        uuid(62112AA1-EBE4-11cf-A5FB-0020AFE7292D),  // CLSID_ShellFolderView
+        helpstring("Shell Folder View Object")
+    ]
+    coclass ShellFolderView
+    {
+        [default] interface IShellFolderViewDual;
+        [source,default] dispinterface DShellFolderViewEvents;
+    }
+
+    typedef
+    [
+        uuid(742A99A0-C77E-11D0-A32C-00A0C91EEDBA),
+        helpstring("Constants for ViewOptions")
+    ]
+    enum ShellFolderViewOptions {
+        [helpstring("Show All Objects")]                        SFVVO_SHOWALLOBJECTS = 0x00000001,
+        [helpstring("Show File Extensions")]                    SFVVO_SHOWEXTENSIONS = 0x00000002,
+        [helpstring("Color encode Compressed files")]           SFVVO_SHOWCOMPCOLOR = 0x00000008,
+        [helpstring("Show System Files")]                       SFVVO_SHOWSYSFILES = 0x00000020,
+        [helpstring("Use Windows 95 UI settings")]              SFVVO_WIN95CLASSIC = 0x00000040,
+        [helpstring("User needs to double click in web View")]  SFVVO_DOUBLECLICKINWEBVIEW = 0x00000080,
+        [helpstring("Is Desktop HTML enabled")]                 SFVVO_DESKTOPHTML = 0x00000200,
+    } ShellFolderViewOptions;
+
+    [
+        uuid(D8F015C0-C278-11CE-A49E-444553540000), // IID_IShellDispatch
+        helpstring("Definition of interface IShellDispatch"),
+        oleautomation,
+        hidden,
+        dual,
+        odl,
+    ]
+    interface IShellDispatch : IDispatch
+    {
+        [propget, helpstring("Get Application object")]
+        HRESULT Application ([out, retval] IDispatch **ppid);
+
+        [propget, helpstring("Get Parent object")]
+        HRESULT Parent([out, retval] IDispatch **ppid);
+
+        //=========================================================
+        // Name Space methods and properties
+
+        [helpstring("Enum the contents of a folder")]
+        HRESULT NameSpace([in] VARIANT vDir, [out, retval] Folder **ppsdf);
+
+        [helpstring("Browse the name space for a Folder")]
+        HRESULT BrowseForFolder([in] long Hwnd,
+            [in] BSTR Title,
+            [in] long Options,
+            [in,optional] VARIANT RootFolder,
+            [out, retval] FOLDER **ppsdf);
+
+        [helpstring("The collection of open folder windows")]
+        HRESULT Windows([out, retval] IDispatch **ppid);
+
+        [helpstring("Open a folder")]
+        HRESULT Open([in] VARIANT vDir);
+
+        [helpstring("Explore a folder")]
+        HRESULT Explore([in] VARIANT vDir);
+
+        [helpstring("Minimize all windows")]
+        HRESULT MinimizeAll(void);
+
+        [helpstring("Undo Minimize All")]
+        HRESULT UndoMinimizeALL(void);
+
+        [helpstring("Bring up the file run")]
+        HRESULT FileRun(void);
+
+        [helpstring("Cascade Windows")]
+        HRESULT CascadeWindows(void);
+
+        [helpstring("Tile windows vertically")]
+        HRESULT TileVertically(void);
+
+        [helpstring("Tile windows horizontally")]
+        HRESULT TileHorizontally(void);
+
+        [helpstring("Exit Windows")]
+        HRESULT ShutdownWindows(void);
+
+        [helpstring("Suspend the pc")]
+        HRESULT Suspend(void);
+
+        [helpstring("Eject the pc")]
+        HRESULT EjectPC(void);
+
+        [helpstring("Bring up the Set time dialog")]
+        HRESULT SetTime(void);
+
+        [helpstring("Handle Tray properties")]
+        HRESULT TrayProperties(void);
+
+        [helpstring("Display shell help")]
+        HRESULT Help(void);
+
+        [helpstring("Find Files")]
+        HRESULT FindFiles(void);
+
+        [helpstring("Find a computer")]
+        HRESULT FindComputer(void);
+
+        [helpstring("Refresh the menu")]
+        HRESULT RefreshMenu(void);
+
+        [helpstring("Run a controlpanelItem")]
+        HRESULT ControlPanelItem([in] BSTR szDir);
+    }
+
+    [
+        uuid(13709620-C279-11CE-A49E-444553540000), // CLSID_Shell
+        helpstring("Shell Object Type Information")
+    ]
+    coclass Shell
+    {
+        [default] interface IShellDispatch;
+    }
+
+    [
+        uuid(0A89A860-D7B1-11CE-8350-444553540000), // CLSID_ShellDispatchInproc
+        helpstring("ShellDispatch Load in Shell Context"),
+        hidden
+    ]
+    coclass ShellDispatchInproc
+    {
+        interface IUnknown;
+    }
+
+    [
+        uuid(1820FED0-473E-11D0-A96C-00C04FD705A2),     // CLSID_WebViewFolderContents
+        hidden
+    ]
+    coclass WebViewFolderContents
+    {
+        [default] interface IShellFolderViewDual;
+        [source,default] dispinterface DShellFolderViewEvents;
+    }
+
+    typedef
+    [
+        uuid(CA31EA20-48D0-11CF-8350-444553540000),
+        helpstring("Constants for Special Folders for open/Explore")
+    ]
+    enum ShellSpecialFolderConstants    {
+        [helpstring("Special Folder DESKTOP")]      ssfDESKTOP = 0x0000,
+        [helpstring("Special Folder PROGRAMS")]     ssfPROGRAMS = 0x0002,
+        [helpstring("Special Folder CONTROLS")]     ssfCONTROLS = 0x0003,
+        [helpstring("Special Folder PRINTERS")]     ssfPRINTERS = 0x0004,
+        [helpstring("Special Folder PERSONAL")]     ssfPERSONAL = 0x0005,
+        [helpstring("Special Folder FAVORITES")]    ssfFAVORITES = 0x0006,
+        [helpstring("Special Folder STARTUP")]      ssfSTARTUP = 0x0007,
+        [helpstring("Special Folder RECENT")]       ssfRECENT = 0x0008,
+        [helpstring("Special Folder SENDTO")]       ssfSENDTO = 0x0009,
+        [helpstring("Special Folder BITBUCKET")]    ssfBITBUCKET = 0x000a,
+        [helpstring("Special Folder STARTMENU")]    ssfSTARTMENU = 0x000b,
+        [helpstring("Special Folder DESKTOPDIRECTORY")]    ssfDESKTOPDIRECTORY = 0x0010,
+        [helpstring("Special Folder DRIVES")]       ssfDRIVES = 0x0011,
+        [helpstring("Special Folder NETWORK")]      ssfNETWORK = 0x0012,
+        [helpstring("Special Folder NETHOOD")]      ssfNETHOOD = 0x0013,
+        [helpstring("Special Folder FONTS")]        ssfFONTS = 0x0014,
+        [helpstring("Special Folder TEMPLATES")]    ssfTEMPLATES = 0x0015,
+    } ShellSpecialFolderConstants;
+
+    [
+        uuid(729FE2F8-1EA8-11d1-8F85-00C04FC2FBE1),     // IID_IShellUIHelper
+        helpstring("Shell UI Helper Control Interface"),
+        oleautomation, dual
+    ]
+    interface IShellUIHelper : IDispatch
+    {
+        [hidden, id(DISPID_RESETFIRSTBOOTMODE)] HRESULT ResetFirstBootMode();
+        [hidden, id(DISPID_RESETSAFEMODE)] HRESULT ResetSafeMode();
+        [hidden, id(DISPID_REFRESHOFFLINEDESKTOP)] HRESULT RefreshOfflineDesktop();
+        [id(DISPID_ADDFAVORITE)] HRESULT AddFavorite([in] BSTR URL, [optional, in] VARIANT *Title);
+        [id(DISPID_ADDCHANNEL)] HRESULT AddChannel([in] BSTR URL);
+        [id(DISPID_ADDDESKTOPCOMPONENT)] HRESULT AddDesktopComponent([in] BSTR URL, [in] BSTR Type,
+            [optional, in] VARIANT *Left,
+            [optional, in] VARIANT *Top,
+            [optional, in] VARIANT *Width,
+            [optional, in] VARIANT *Height);
+        [id(DISPID_ISSUBSCRIBED)] HRESULT IsSubscribed([in] BSTR URL, [out,retval] VARIANT_BOOL* pBool);
+    }
+    [
+        uuid(64AB4BB7-111E-11d1-8F79-00C04FC2FBE1)  // CLSID_ShellUIHelper
+    ]
+    coclass ShellUIHelper
+    {
+        [default] interface IShellUIHelper;
+    }
+*/
+}  // extern (Windows)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/MSHTMHST.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,209 @@
+module org.eclipse.swt.internal.ole.win32.MSHTMHST;
+//+------------------------------------------------------------------------
+//
+//  Microsoft Forms
+//  Copyright 1996 - 1998 Microsoft Corporation.
+//
+//  File:       mshtmhst.idl
+//
+//  Contents:   MSHTML advanced host interfaces
+//
+//-------------------------------------------------------------------------
+
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+import org.eclipse.swt.internal.win32.OS;
+
+//import win32.oleextra;
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+private import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+
+extern( Windows ) {
+/*
+cpp_quote("#define CONTEXT_MENU_DEFAULT        0")
+cpp_quote("#define CONTEXT_MENU_IMAGE          1")
+cpp_quote("#define CONTEXT_MENU_CONTROL        2")
+cpp_quote("#define CONTEXT_MENU_TABLE          3")
+cpp_quote("// in browse mode")
+cpp_quote("#define CONTEXT_MENU_TEXTSELECT     4")
+cpp_quote("#define CONTEXT_MENU_ANCHOR         5")
+cpp_quote("#define CONTEXT_MENU_UNKNOWN        6")
+cpp_quote("//;begin_internal")
+cpp_quote("// These 2 are mapped to IMAGE for the public")
+cpp_quote("#define CONTEXT_MENU_IMGDYNSRC      7")
+cpp_quote("#define CONTEXT_MENU_IMGART         8")
+cpp_quote("#define CONTEXT_MENU_DEBUG          9")
+cpp_quote("//;end_internal")
+
+cpp_quote("#define MENUEXT_SHOWDIALOG           0x1")
+
+cpp_quote("#define DOCHOSTUIFLAG_BROWSER       DOCHOSTUIFLAG_DISABLE_HELP_MENU | DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE ")
+
+import "ocidl.idl";
+import "objidl.idl";
+import "oleidl.idl";
+import "oaidl.idl";
+import "docobj.idl";
+import "mshtml.idl";
+
+cpp_quote("EXTERN_C const GUID CGID_MSHTML;")
+cpp_quote("#define CMDSETID_Forms3 CGID_MSHTML")
+cpp_quote("#define SZ_HTML_CLIENTSITE_OBJECTPARAM L\"{d4db6850-5385-11d0-89e9-00a0c90a90ac}\"")
+#pragma midl_echo("typedef HRESULT STDAPICALLTYPE SHOWHTMLDIALOGFN (HWND hwndParent, IMoniker *pmk, VARIANT *pvarArgIn, TCHAR* pchOptions, VARIANT *pvArgOut);")
+#pragma midl_echo("STDAPI ShowHTMLDialog(                   ")
+#pragma midl_echo("    HWND        hwndParent,              ")
+#pragma midl_echo("    IMoniker *  pMk,                     ")
+#pragma midl_echo("    VARIANT *   pvarArgIn,               ")
+#pragma midl_echo("    TCHAR *     pchOptions,              ")
+#pragma midl_echo("    VARIANT *   pvarArgOut               ")
+#pragma midl_echo("    );                                   ")
+*/
+
+//-------------------------------------------------------------------------
+//  IDocHostUIHandler
+//
+//-------------------------------------------------------------------------
+
+enum DOCHOSTUITYPE {
+        DOCHOSTUITYPE_BROWSE    = 0,
+        DOCHOSTUITYPE_AUTHOR    = 1,
+        BROWSE    = 0,
+        AUTHOR    = 1,
+}
+
+enum DOCHOSTUIDBLCLK {
+        DOCHOSTUIDBLCLK_DEFAULT         = 0,
+        DOCHOSTUIDBLCLK_SHOWPROPERTIES  = 1,
+        DOCHOSTUIDBLCLK_SHOWCODE        = 2,
+
+        DEFAULT         = 0,
+        SHOWPROPERTIES  = 1,
+        SHOWCODE        = 2,
+}
+
+enum DOCHOSTUIFLAG {
+        DOCHOSTUIFLAG_DIALOG            = 1,
+        DOCHOSTUIFLAG_DISABLE_HELP_MENU = 2,
+        DOCHOSTUIFLAG_NO3DBORDER        = 4,
+        DOCHOSTUIFLAG_SCROLL_NO         = 8,
+        DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE = 16,
+        DOCHOSTUIFLAG_OPENNEWWIN        = 32,
+        DOCHOSTUIFLAG_DISABLE_OFFSCREEN = 64,
+        DOCHOSTUIFLAG_FLAT_SCROLLBAR = 128,
+        DOCHOSTUIFLAG_DIV_BLOCKDEFAULT = 256,
+        DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY = 512,
+        DOCHOSTUIFLAG_DISABLE_COOKIE = 1024,
+//
+//  DOCHOSTUIFLAG.name versions
+//
+        DIALOG            = 1,
+        DISABLE_HELP_MENU = 2,
+        NO3DBORDER        = 4,
+        SCROLL_NO         = 8,
+        DISABLE_SCRIPT_INACTIVE = 16,
+        OPENNEWWIN        = 32,
+        DISABLE_OFFSCREEN = 64,
+        FLAT_SCROLLBAR = 128,
+        DIV_BLOCKDEFAULT = 256,
+        ACTIVATE_CLIENTHIT_ONLY = 512,
+        DISABLE_COOKIE = 1024,
+}
+/* polute the global namespace */
+enum {
+        DOCHOSTUITYPE_BROWSE    = 0,
+        DOCHOSTUITYPE_AUTHOR    = 1,
+
+        DOCHOSTUIDBLCLK_DEFAULT         = 0,
+        DOCHOSTUIDBLCLK_SHOWPROPERTIES  = 1,
+        DOCHOSTUIDBLCLK_SHOWCODE        = 2,
+
+       DOCHOSTUIFLAG_DIALOG            = 1,
+        DOCHOSTUIFLAG_DISABLE_HELP_MENU = 2,
+        DOCHOSTUIFLAG_NO3DBORDER        = 4,
+        DOCHOSTUIFLAG_SCROLL_NO         = 8,
+        DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE = 16,
+        DOCHOSTUIFLAG_OPENNEWWIN        = 32,
+        DOCHOSTUIFLAG_DISABLE_OFFSCREEN = 64,
+        DOCHOSTUIFLAG_FLAT_SCROLLBAR = 128,
+        DOCHOSTUIFLAG_DIV_BLOCKDEFAULT = 256,
+        DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY = 512,
+        DOCHOSTUIFLAG_DISABLE_COOKIE = 1024,
+}
+
+struct DOCHOSTUIINFO
+{
+	ULONG cbSize;
+	DWORD dwFlags;
+	DWORD dwDoubleClick;
+}
+
+interface IDocHostUIHandler : IUnknown
+{
+	HRESULT ShowContextMenu( DWORD dwID, POINT* ppt, IUnknown pcmdtReserved, IDispatch pdispReserved);
+	HRESULT GetHostInfo( DOCHOSTUIINFO * pInfo );
+	HRESULT ShowUI( DWORD dwID, IOleInPlaceActiveObject pActiveObject, IOleCommandTarget pCommandTarget, IOleInPlaceFrame pFrame, IOleInPlaceUIWindow pDoc );
+	HRESULT HideUI();
+	HRESULT UpdateUI();
+	HRESULT EnableModeless( BOOL fEnable );
+	HRESULT OnDocWindowActivate( BOOL fActivate );
+	HRESULT OnFrameWindowActivate( BOOL fActivate );
+	HRESULT ResizeBorder(LPRECT prcBorder, IOleInPlaceUIWindow pUIWindow, BOOL fRameWindow );
+	HRESULT TranslateAccelerator( LPMSG lpMsg, GUID * pguidCmdGroup, DWORD nCmdID );
+	HRESULT GetOptionKeyPath( LPOLESTR * pchKey, DWORD dw );
+	HRESULT GetDropTarget( IDropTarget pDropTarget, IDropTarget * ppDropTarget );
+	HRESULT GetExternal( IDispatch * ppDispatch );
+	HRESULT TranslateUrl( DWORD dwTranslate, OLECHAR * pchURLIn, OLECHAR ** ppchURLOut );
+	HRESULT FilterDataObject( IDataObject pDO, IDataObject * ppDORet );
+}
+
+
+//-------------------------------------------------------------------------
+//  ICustomDoc
+//
+//-------------------------------------------------------------------------
+
+interface ICustomDoc : IUnknown
+{
+	HRESULT SetUIHandler( IDocHostUIHandler pUIHandler );
+}
+
+//-------------------------------------------------------------------------
+//  IDocHostShowUI
+//
+//-------------------------------------------------------------------------
+
+interface IDocHostShowUI : IUnknown
+{
+	HRESULT ShowMessage( HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption, DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT * plResult);
+	HRESULT ShowHelp( HWND hwnd, LPOLESTR pszHelpFile, UINT uCommand, DWORD dwData, POINT ptMouse, IDispatch pDispatchObjectHit );
+}
+
+/*
+
+//-------------------------------------------------------------------------
+//  ICSSFilterSite
+//
+//-------------------------------------------------------------------------
+interface ICSSFilterSite : IUnknown
+{
+	HRESULT GetElement( IHTMLElement * ppElem );
+	HRESULT FireOnFilterChangeEvent();
+}
+
+
+//-------------------------------------------------------------------------
+//  ICSSFilter
+//
+//-------------------------------------------------------------------------
+interface ICSSFilter : IUnknown
+{
+	HRESULT SetSite( ICSSFilterSite * pSink );
+	HRESULT OnAmbientPropertyChange( LONG dispid );
+}
+
+*/
+
+} // extern( Windows )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OAIDL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1158 @@
+module org.eclipse.swt.internal.ole.win32.OAIDL;
+
+//+---------------------------------------------------------------------------
+//
+//  Microsoft Windows
+//  Copyright 1992 - 1998 Microsoft Corporation.
+//
+//  File: oaidl.idl
+//
+//----------------------------------------------------------------------------
+
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.ole.win32.Variant;
+
+extern(Windows) {
+
+struct  DECIMAL
+    {
+    USHORT wReserved;
+    BYTE scale;
+    BYTE sign;
+    ULONG Hi32;
+    ulong Lo64;
+    }	;
+
+alias wchar * BSTR;
+struct  FLAGGED_WORD_BLOB
+    {
+    ULONG fFlags;
+    ULONG clSize;
+    ushort[1] asData;
+    }
+
+alias FLAGGED_WORD_BLOB  *wireBSTR;
+
+ struct BYTE_SIZEDARR
+    {
+    ULONG clSize;
+    byte  *pData;
+    }	;
+
+ struct  WORD_SIZEDARR
+    {
+    ULONG clSize;
+    ushort *pData;
+    }	;
+
+struct  DWORD_SIZEDARR
+    {
+    ULONG clSize;
+    ULONG * pData;
+    }	;
+
+struct  HYPER_SIZEDARR
+    {
+    ULONG clSize;
+    long *pData;
+    }
+
+
+enum
+{	VT_EMPTY	= 0,
+	VT_NULL	= 1,
+	VT_I2	= 2,
+	VT_I4	= 3,
+	VT_R4	= 4,
+	VT_R8	= 5,
+	VT_CY	= 6,
+	VT_DATE	= 7,
+	VT_BSTR	= 8,
+	VT_DISPATCH	= 9,
+	VT_ERROR	= 10,
+	VT_BOOL	= 11,
+	VT_VARIANT	= 12,
+	VT_UNKNOWN	= 13,
+	VT_DECIMAL	= 14,
+	VT_I1	= 16,
+	VT_UI1	= 17,
+	VT_UI2	= 18,
+	VT_UI4	= 19,
+	VT_I8	= 20,
+	VT_UI8	= 21,
+	VT_INT	= 22,
+	VT_UINT	= 23,
+	VT_VOID	= 24,
+	VT_HRESULT	= 25,
+	VT_PTR	= 26,
+	VT_SAFEARRAY	= 27,
+	VT_CARRAY	= 28,
+	VT_USERDEFINED	= 29,
+	VT_LPSTR	= 30,
+	VT_LPWSTR	= 31,
+	VT_RECORD	= 36,
+	VT_FILETIME	= 64,
+	VT_BLOB	= 65,
+	VT_STREAM	= 66,
+	VT_STORAGE	= 67,
+	VT_STREAMED_OBJECT	= 68,
+	VT_STORED_OBJECT	= 69,
+	VT_BLOB_OBJECT	= 70,
+	VT_CF	= 71,
+	VT_CLSID	= 72,
+	VT_BSTR_BLOB	= 0xfff,
+	VT_VECTOR	= 0x1000,
+	VT_ARRAY	= 0x2000,
+	VT_BYREF	= 0x4000,
+	VT_RESERVED	= 0x8000,
+	VT_ILLEGAL	= 0xffff,
+	VT_ILLEGALMASKED	= 0xfff,
+	VT_TYPEMASK	= 0xfff
+};
+
+
+/*
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("//  Microsoft Windows")
+cpp_quote("//  Copyright 1992 - 1998 Microsoft Corporation.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+cpp_quote("#if ( _MSC_VER >= 800 )")
+*/
+//cpp_quote("#pragma warning(disable:4201)    /* Nameless struct/union */")
+/*
+cpp_quote("#endif")
+
+#ifndef DO_NO_IMPORTS
+import "objidl.idl";
+#endif
+
+interface ICreateTypeInfo;
+interface ICreateTypeInfo2;
+interface ICreateTypeLib;
+interface ICreateTypeLib2;
+interface IDispatch;
+interface IEnumVARIANT;
+interface ITypeComp;
+interface ITypeInfo;
+interface ITypeInfo2;
+interface ITypeLib;
+interface ITypeLib2;
+interface ITypeChangeEvents;
+interface IErrorInfo;
+interface ICreateErrorInfo;
+interface ISupportErrorInfo;
+interface ITypeFactory;
+interface ITypeMarshal;
+interface IRecordInfo;
+
+
+[
+  version(1.0), pointer_default(unique)
+]
+
+interface IOleAutomationTypes
+{
+
+typedef CY CURRENCY;
+
+// #########################################################################
+//      SAFEARRAY
+// #########################################################################
+*/
+struct SAFEARRAYBOUND {
+    ULONG cElements;
+    LONG  lLbound;
+}
+alias SAFEARRAYBOUND * LPSAFEARRAYBOUND;
+
+struct _wireVARIANT {
+}
+struct _wireBRECORD {
+}
+// Forward references.
+alias _wireVARIANT * wireVARIANT;
+alias _wireBRECORD * wireBRECORD;
+
+struct SAFEARR_BSTR {
+    ULONG Size;
+    wireBSTR * aBstr;
+}
+struct SAFEARR_UNKNOWN {
+    ULONG Size;
+    IUnknown * apUnknown;
+}
+
+struct SAFEARR_DISPATCH {
+    ULONG Size;
+    IDispatch * apDispatch;
+}
+
+struct SAFEARR_VARIANT {
+    ULONG Size;
+    wireVARIANT * aVariant;
+}
+
+struct SAFEARR_BRECORD {
+    ULONG Size;
+    wireBRECORD * aRecord;
+}
+
+struct SAFEARR_HAVEIID {
+    ULONG Size;
+    IUnknown * apUnknown;
+    IID   iid;
+}
+
+enum SF_TYPE {
+    SF_ERROR    = VT_ERROR,
+    SF_I1       = VT_I1,
+    SF_I2       = VT_I2,
+    SF_I4       = VT_I4,
+    SF_I8       = VT_I8,
+    SF_BSTR     = VT_BSTR,
+    SF_UNKNOWN  = VT_UNKNOWN,
+    SF_DISPATCH = VT_DISPATCH,
+    SF_VARIANT  = VT_VARIANT,
+    SF_RECORD   = VT_RECORD,
+    SF_HAVEIID  = VT_UNKNOWN|VT_RESERVED,
+}
+
+union uSAFEARRAY_UNION {
+SAFEARR_BSTR     BstrStr;
+SAFEARR_UNKNOWN  UnknownStr;
+SAFEARR_DISPATCH DispatchStr;
+SAFEARR_VARIANT  VariantStr;
+SAFEARR_BRECORD  RecordStr;
+SAFEARR_HAVEIID  HaveIidStr;
+BYTE_SIZEDARR    ByteStr;
+WORD_SIZEDARR    WordStr;
+DWORD_SIZEDARR   LongStr;
+HYPER_SIZEDARR   HyperStr;
+}
+
+struct SAFEARRAY_UNION {
+	ULONG sfType;
+	uSAFEARRAY_UNION u;
+}
+
+alias SAFEARRAY_UNION SAFEARRAYUNION;
+
+struct wireSAFEARRAY {
+    USHORT cDims;
+    USHORT fFeatures;
+    ULONG  cbElements;
+    ULONG  cLocks;
+    SAFEARRAYUNION uArrayStructs;
+    SAFEARRAYBOUND[1] rgsabound;
+}
+alias wireSAFEARRAY SAFEARRAY ;
+
+alias wireSAFEARRAY * wirePSAFEARRAY;
+
+
+struct tagSAFEARRAY {
+    USHORT cDims;
+    USHORT fFeatures;
+    ULONG  cbElements;
+    ULONG  cLocks;
+    PVOID  pvData;
+    SAFEARRAYBOUND[1] rgsabound;
+}
+
+alias SAFEARRAY * LPSAFEARRAY;
+
+const USHORT FADF_AUTO       = 0x0001;  /* array is allocated on the stack */
+const USHORT FADF_STATIC     = 0x0002;  /* array is staticly allocated */
+const USHORT FADF_EMBEDDED   = 0x0004;  /* array is embedded in a structure */
+const USHORT FADF_FIXEDSIZE  = 0x0010;  /* may not be resized or reallocated */
+const USHORT FADF_RECORD     = 0x0020;  /* an array of records */
+const USHORT FADF_HAVEIID    = 0x0040;  /* with FADF_DISPATCH, FADF_UNKNOWN */
+                                        /* array has an IID for interfaces */
+const USHORT FADF_HAVEVARTYPE= 0x0080;  /* array has a VT type */
+const USHORT FADF_BSTR       = 0x0100;  /* an array of BSTRs */
+const USHORT FADF_UNKNOWN    = 0x0200;  /* an array of IUnknown* */
+const USHORT FADF_DISPATCH   = 0x0400;  /* an array of IDispatch* */
+const USHORT FADF_VARIANT    = 0x0800;  /* an array of VARIANTs */
+const USHORT FADF_RESERVED   = 0xF008;  /* reserved bits */
+
+
+// #########################################################################
+//      VARIANT
+// #########################################################################
+/*
+cpp_quote("#if (__STDC__ && !defined(_FORCENAMELESSUNION)) || defined(NONAMELESSUNION)")
+cpp_quote("#define __VARIANT_NAME_1 n1")
+cpp_quote("#define __VARIANT_NAME_2 n2")
+cpp_quote("#define __VARIANT_NAME_3 n3")
+cpp_quote("#define __VARIANT_NAME_4 brecVal")
+cpp_quote("#else")
+cpp_quote("#define __tagVARIANT")
+cpp_quote("#define __VARIANT_NAME_1")
+cpp_quote("#define __VARIANT_NAME_2")
+cpp_quote("#define __VARIANT_NAME_3")
+cpp_quote("#define __tagBRECORD")
+cpp_quote("#define __VARIANT_NAME_4")
+cpp_quote("#endif")
+*/
+
+/*struct brecVal_t {
+	PVOID         pvRecord;
+	IRecordInfo * pRecInfo;
+}*/
+struct brecVal_t {
+	PVOID         pvRecord;
+	IUnknown * pRecInfo;
+}
+
+alias double DOUBLE;
+alias double DATE;
+alias VARIANT_BOOL _VARIANT_BOOL;
+alias long CY;
+
+
+union n3_t {
+    LONG          lVal;         /* VT_I4                */
+    BYTE          bVal;         /* VT_UI1               */
+    SHORT         iVal;         /* VT_I2                */
+    FLOAT         fltVal;       /* VT_R4                */
+    DOUBLE        dblVal;       /* VT_R8                */
+    VARIANT_BOOL  boolVal;      /* VT_BOOL              */
+    _VARIANT_BOOL BOOLval;         /* (obsolete)           */
+    SCODE         scode;        /* VT_ERROR             */
+    CY            cyVal;        /* VT_CY                */
+    DATE          date;         /* VT_DATE              */
+    BSTR          bstrVal;      /* VT_BSTR              */
+    IUnknown     punkVal;      /* VT_UNKNOWN           */
+    IDispatch    pdispVal;     /* VT_DISPATCH          */
+    SAFEARRAY *   parray;       /* VT_ARRAY             */
+    BYTE *        pbVal;        /* VT_BYREF|VT_UI1      */
+    SHORT *       piVal;        /* VT_BYREF|VT_I2       */
+    LONG *        plVal;        /* VT_BYREF|VT_I4       */
+    FLOAT *       pfltVal;      /* VT_BYREF|VT_R4       */
+    DOUBLE *      pdblVal;      /* VT_BYREF|VT_R8       */
+    VARIANT_BOOL *pboolVal;     /* VT_BYREF|VT_BOOL     */
+    _VARIANT_BOOL *pbool;       /* (obsolete)           */
+    SCODE *       pscode;       /* VT_BYREF|VT_ERROR    */
+    CY *          pcyVal;       /* VT_BYREF|VT_CY       */
+    DATE *        pdate;        /* VT_BYREF|VT_DATE     */
+    BSTR *        pbstrVal;     /* VT_BYREF|VT_BSTR     */
+    IUnknown *   ppunkVal;     /* VT_BYREF|VT_UNKNOWN  */
+    IDispatch *   ppdispVal;    /* VT_BYREF|VT_DISPATCH */
+    SAFEARRAY **  pparray;      /* VT_BYREF|VT_ARRAY    */
+    VARIANT *     pvarVal;      /* VT_BYREF|VT_VARIANT  */
+    PVOID         byref;        /* Generic ByRef        */
+    CHAR          cVal;         /* VT_I1                */
+    USHORT        uiVal;        /* VT_UI2               */
+    ULONG         ulVal;        /* VT_UI4               */
+    INT           intVal;       /* VT_INT               */
+    UINT          uintVal;      /* VT_UINT              */
+    DECIMAL *     pdecVal;      /* VT_BYREF|VT_DECIMAL  */
+    CHAR *        pcVal;        /* VT_BYREF|VT_I1       */
+    USHORT *      puiVal;       /* VT_BYREF|VT_UI2      */
+    ULONG *       pulVal;       /* VT_BYREF|VT_UI4      */
+    INT *         pintVal;      /* VT_BYREF|VT_INT      */
+    UINT *        puintVal;     /* VT_BYREF|VT_UINT     */
+	brecVal_t brecVal;         /* VT_RECORD            */
+}
+
+struct n2_t {
+    VARTYPE vt;
+    WORD    wReserved1;
+    WORD    wReserved2;
+    WORD    wReserved3;
+    n3_t n3;
+};
+union n1_t {
+	n2_t n2;
+    DECIMAL decVal;
+};
+
+// in tango.sys.win32.Types
+/+
+struct VARIANT {
+	n1_t n1;
+
+	VARTYPE vt() { return n1.n2.vt; };
+	void vt(VARTYPE val) { n1.n2.vt = val; }
+	LONG lVal()  { return n1.n2.n3.lVal; }
+	void lVal(LONG val) { return n1.n2.n3.lVal = val; }
+	FLOAT fltVal()  { return n1.n2.n3.fltVal; }
+	void fltVal(FLOAT val) { return n1.n2.n3.fltVal = val; }
+	IDispatch pdispVal() { return n1.n2.n3.pdispVal; }
+	void pdispVal(IDispatch val) { n1.n2.n3.pdispVal = val; }
+	IUnknown punkVal() { return n1.n2.n3.punkVal; }
+	void punkVal(IUnknown val) { n1.n2.n3.punkVal = val; }
+	VARIANT_BOOL boolVal() { return n1.n2.n3.boolVal; }
+	void boolVal(VARIANT_BOOL val) { n1.n2.n3.boolVal = val; }
+	SHORT iVal() { return n1.n2.n3.iVal; }
+	void iVal(SHORT val) { n1.n2.n3.iVal = val; }
+	BSTR bstrVal() { return n1.n2.n3.bstrVal; }
+	void bstrVal(BSTR val) { n1.n2.n3.bstrVal = val; }
+
+};
++/
+
+
+/*
+struct VARIANT {
+	LONG[4] mmmm;
+}
+*/
+alias VARIANT * LPVARIANT;
+alias VARIANT VARIANTARG;
+alias VARIANT * LPVARIANTARG;
+
+/+
+struct _wireBRECORD {
+    ULONG fFlags;
+    ULONG clSize;
+    IRecordInfo pRecInfo;
+    byte * pRecord;
+};
+++++++++++++++++++++/
+
+
+/+
+struct _wireVARIANT {
+    DWORD  clSize;
+    DWORD  rpcReserved;
+    USHORT vt;
+    USHORT wReserved1;
+    USHORT wReserved2;
+    USHORT wReserved3;
+    [switch_type(ULONG), switch_is(vt)] union {
+    [case(VT_I4)]       LONG          lVal;         /* VT_I4                */
+    [case(VT_UI1)]      BYTE          bVal;         /* VT_UI1               */
+    [case(VT_I2)]       SHORT         iVal;         /* VT_I2                */
+    [case(VT_R4)]       FLOAT         fltVal;       /* VT_R4                */
+    [case(VT_R8)]       DOUBLE        dblVal;       /* VT_R8                */
+    [case(VT_BOOL)]     VARIANT_BOOL  boolVal;      /* VT_BOOL              */
+    [case(VT_ERROR)]    SCODE         scode;        /* VT_ERROR             */
+    [case(VT_CY)]       CY            cyVal;        /* VT_CY                */
+    [case(VT_DATE)]     DATE          date;         /* VT_DATE              */
+    [case(VT_BSTR)]     wireBSTR      bstrVal;      /* VT_BSTR              */
+    [case(VT_UNKNOWN)]  IUnknown *    punkVal;      /* VT_UNKNOWN           */
+    [case(VT_DISPATCH)] IDispatch *   pdispVal;     /* VT_DISPATCH          */
+    [case(VT_ARRAY)]    wireSAFEARRAY parray;       /* VT_ARRAY             */
+
+    [case(VT_RECORD, VT_RECORD|VT_BYREF)]
+                        wireBRECORD   brecVal;      /* VT_RECORD            */
+
+    [case(VT_UI1|VT_BYREF)]
+                        BYTE *        pbVal;        /* VT_BYREF|VT_UI1      */
+    [case(VT_I2|VT_BYREF)]
+                        SHORT *       piVal;        /* VT_BYREF|VT_I2       */
+    [case(VT_I4|VT_BYREF)]
+                        LONG *        plVal;        /* VT_BYREF|VT_I4       */
+    [case(VT_R4|VT_BYREF)]
+                        FLOAT *       pfltVal;      /* VT_BYREF|VT_R4       */
+    [case(VT_R8|VT_BYREF)]
+                        DOUBLE *      pdblVal;      /* VT_BYREF|VT_R8       */
+    [case(VT_BOOL|VT_BYREF)]
+                        VARIANT_BOOL *pboolVal;     /* VT_BYREF|VT_BOOL     */
+    [case(VT_ERROR|VT_BYREF)]
+                        SCODE *       pscode;       /* VT_BYREF|VT_ERROR    */
+    [case(VT_CY|VT_BYREF)]
+                        CY *          pcyVal;       /* VT_BYREF|VT_CY       */
+    [case(VT_DATE|VT_BYREF)]
+                        DATE *        pdate;        /* VT_BYREF|VT_DATE     */
+    [case(VT_BSTR|VT_BYREF)]
+                        wireBSTR *    pbstrVal;     /* VT_BYREF|VT_BSTR     */
+    [case(VT_UNKNOWN|VT_BYREF)]
+                        IUnknown **   ppunkVal;     /* VT_BYREF|VT_UNKNOWN  */
+    [case(VT_DISPATCH|VT_BYREF)]
+                        IDispatch **  ppdispVal;    /* VT_BYREF|VT_DISPATCH */
+    [case(VT_ARRAY|VT_BYREF)]
+                        wireSAFEARRAY *pparray;     /* VT_BYREF|VT_ARRAY    */
+    [case(VT_VARIANT|VT_BYREF)]
+                        wireVARIANT * pvarVal;      /* VT_BYREF|VT_VARIANT  */
+
+    [case(VT_I1)]       CHAR          cVal;         /* VT_I1                */
+    [case(VT_UI2)]      USHORT        uiVal;        /* VT_UI2               */
+    [case(VT_UI4)]      ULONG         ulVal;        /* VT_UI4               */
+    [case(VT_INT)]      INT           intVal;       /* VT_INT               */
+    [case(VT_UINT)]     UINT          uintVal;      /* VT_UINT              */
+    [case(VT_DECIMAL)]  DECIMAL       decVal;       /* VT_DECIMAL           */
+
+    [case(VT_BYREF|VT_DECIMAL)]
+                        DECIMAL *     pdecVal;      /* VT_BYREF|VT_DECIMAL  */
+    [case(VT_BYREF|VT_I1)]
+                        CHAR *        pcVal;        /* VT_BYREF|VT_I1       */
+    [case(VT_BYREF|VT_UI2)]
+                        USHORT *      puiVal;       /* VT_BYREF|VT_UI2      */
+    [case(VT_BYREF|VT_UI4)]
+                        ULONG *       pulVal;       /* VT_BYREF|VT_UI4      */
+    [case(VT_BYREF|VT_INT)]
+                        INT *         pintVal;      /* VT_BYREF|VT_INT      */
+    [case(VT_BYREF|VT_UINT)]
+                        UINT *        puintVal;     /* VT_BYREF|VT_UINT     */
+    [case(VT_EMPTY)]    ;                           /* nothing              */
+    [case(VT_NULL)]     ;                           /* nothing              */
+    };
+};
++/
+
+//########################################################################
+//     End of VARIANT & SAFEARRAY
+//########################################################################
+
+
+//TypeInfo stuff.
+
+alias LONG DISPID;
+alias DISPID MEMBERID;
+alias DWORD HREFTYPE;
+
+enum TYPEKIND {
+    TKIND_ENUM = 0,
+    TKIND_RECORD,
+    TKIND_MODULE,
+    TKIND_INTERFACE,
+    TKIND_DISPATCH,
+    TKIND_COCLASS,
+    TKIND_ALIAS,
+    TKIND_UNION,
+    TKIND_MAX                   /* end of enum marker */
+}
+union TD_00{
+        TYPEDESC * lptdesc;
+        ARRAYDESC * lpadesc;
+		  HREFTYPE hreftype;
+};
+
+struct TYPEDESC {
+    TD_00 u;
+    VARTYPE vt;
+}
+
+struct ARRAYDESC {
+    TYPEDESC tdescElem;         /* element type */
+    USHORT cDims;               /* dimension count */
+    SAFEARRAYBOUND[1] rgbounds; /* var len array of bounds */
+}
+
+// parameter description
+struct PARAMDESCEX {
+    ULONG cBytes;               /* size of this structure */
+    VARIANTARG varDefaultValue; /* default value of this parameter */
+}
+alias PARAMDESCEX * LPPARAMDESCEX;
+
+struct PARAMDESC {
+    LPPARAMDESCEX pparamdescex; /* valid if PARAMFLAG_FHASDEFAULT bit is set */
+    USHORT wParamFlags;         /* IN, OUT, etc */
+}
+alias PARAMDESC * LPPARAMDESC;
+
+const USHORT PARAMFLAG_NONE         = 0x00;
+const USHORT PARAMFLAG_FIN          = 0x01;
+const USHORT PARAMFLAG_FOUT         = 0x02;
+const USHORT PARAMFLAG_FLCID        = 0x04;
+const USHORT PARAMFLAG_FRETVAL      = 0x08;
+const USHORT PARAMFLAG_FOPT         = 0x10;
+const USHORT PARAMFLAG_FHASDEFAULT  = 0x20;
+const USHORT PARAMFLAG_FHASCUSTDATA = 0x40;
+
+struct IDLDESC {
+    ULONG dwReserved;
+    USHORT wIDLFlags;           /* IN, OUT, etc */
+}
+alias IDLDESC * LPIDLDESC;
+
+const USHORT IDLFLAG_NONE    = PARAMFLAG_NONE;
+const USHORT IDLFLAG_FIN     = PARAMFLAG_FIN;
+const USHORT IDLFLAG_FOUT    = PARAMFLAG_FOUT;
+const USHORT IDLFLAG_FLCID   = PARAMFLAG_FLCID;
+const USHORT IDLFLAG_FRETVAL = PARAMFLAG_FRETVAL;
+
+
+struct ELEMDESC {    /* a format that MIDL likes */
+    TYPEDESC tdesc;             /* the type of the element */
+    PARAMDESC paramdesc;        /* IDLDESC is a subset of PARAMDESC */
+}
+
+struct TYPEATTR {
+    GUID guid;                  /* the GUID of the TypeInfo */
+    LCID lcid;                  /* locale of member names and doc strings */
+    DWORD dwReserved;
+    MEMBERID memidConstructor;  /* ID of constructor, MEMBERID_NIL if none */
+    MEMBERID memidDestructor;   /* ID of destructor, MEMBERID_NIL if none */
+    LPOLESTR lpstrSchema;
+    ULONG cbSizeInstance;       /* the size of an instance of this type */
+    TYPEKIND typekind;          /* the kind of type this typeinfo describes */
+    WORD cFuncs;                /* number of functions */
+    WORD cVars;                 /* number of variables / data members */
+    WORD cImplTypes;            /* number of implemented interfaces */
+    WORD cbSizeVft;             /* the size of this types virtual func table */
+    WORD cbAlignment;           /* specifies the alignment requirements for
+                                   an instance of this type,
+                                   0 = align on 64k boundary
+                                   1 = byte align
+                                   2 = word align
+                                   4 = dword align... */
+    WORD wTypeFlags;
+    WORD wMajorVerNum;          /* major version number */
+    WORD wMinorVerNum;          /* minor version number */
+    TYPEDESC tdescAlias;        /* if typekind == TKIND_ALIAS this field
+                                   specifies the type for which this type
+                                   is an alias */
+    IDLDESC idldescType;        /* IDL attributes of the described type */
+}
+alias TYPEATTR * LPTYPEATTR;
+
+
+struct DISPPARAMS {
+    VARIANTARG * rgvarg;
+    DISPID * rgdispidNamedArgs;
+    UINT cArgs;
+    UINT cNamedArgs;
+}
+
+struct EXCEPINFO {
+    WORD  wCode;            /* An error code describing the error. */
+    WORD  wReserved;
+    BSTR  bstrSource;       /* A source of the exception */
+    BSTR  bstrDescription;  /* A description of the error */
+    BSTR  bstrHelpFile;     /* Fully qualified drive, path, and file name */
+    DWORD dwHelpContext;    /* help context of topic within the help file */
+    ULONG pvReserved;
+    ULONG pfnDeferredFillIn;
+    SCODE scode;
+}
+/+
+
+cpp_quote("#else /* 0 */")
+cpp_quote("typedef struct tagEXCEPINFO {")
+cpp_quote("    WORD  wCode;")
+cpp_quote("    WORD  wReserved;")
+cpp_quote("    BSTR  bstrSource;")
+cpp_quote("    BSTR  bstrDescription;")
+cpp_quote("    BSTR  bstrHelpFile;")
+cpp_quote("    DWORD dwHelpContext;")
+cpp_quote("    PVOID pvReserved;")
+cpp_quote("    HRESULT (__stdcall *pfnDeferredFillIn)(struct tagEXCEPINFO *);")
+cpp_quote("    SCODE scode;")
+cpp_quote("} EXCEPINFO, * LPEXCEPINFO;")
+cpp_quote("#endif /* 0 */")
++/
+
+enum CALLCONV {
+    CC_FASTCALL = 0,
+    CC_CDECL = 1,
+    CC_MSCPASCAL,
+    CC_PASCAL = CC_MSCPASCAL,
+    CC_MACPASCAL,
+    CC_STDCALL,
+    CC_FPFASTCALL,
+    CC_SYSCALL,
+    CC_MPWCDECL,
+    CC_MPWPASCAL,
+    CC_MAX          /* end of enum marker */
+}
+enum FUNCKIND {
+    FUNC_VIRTUAL,
+    FUNC_PUREVIRTUAL,
+    FUNC_NONVIRTUAL,
+    FUNC_STATIC,
+    FUNC_DISPATCH
+}
+
+enum INVOKEKIND {
+    INVOKE_FUNC = 1,
+    INVOKE_PROPERTYGET = 2,
+    INVOKE_PROPERTYPUT = 4,
+    INVOKE_PROPERTYPUTREF = 8
+}
+
+struct FUNCDESC {
+    MEMBERID memid;
+    SCODE * lprgscode;
+    ELEMDESC * lprgelemdescParam; /* array of param types */
+    FUNCKIND funckind;
+    INVOKEKIND invkind;
+    CALLCONV callconv;
+    SHORT cParams;
+    SHORT cParamsOpt;
+    SHORT oVft;
+    SHORT cScodes;
+    ELEMDESC elemdescFunc;
+    WORD wFuncFlags;
+}
+alias FUNCDESC * LPFUNCDESC;
+
+enum VARKIND {
+    VAR_PERINSTANCE,
+    VAR_STATIC,
+    VAR_CONST,
+    VAR_DISPATCH
+}
+/* IMPLTYPE Flags */
+const USHORT IMPLTYPEFLAG_FDEFAULT      = 0x1;
+const USHORT IMPLTYPEFLAG_FSOURCE       = 0x2;
+const USHORT IMPLTYPEFLAG_FRESTRICTED   = 0x4;
+const USHORT IMPLTYPEFLAG_FDEFAULTVTABLE= 0x8;
+
+union VD_u {
+        /* offset of variable within the instance */
+	ULONG oInst;
+	VARIANT * lpvarValue; /* the value of the constant */
+}
+struct VARDESC {
+    MEMBERID memid;
+    LPOLESTR lpstrSchema;
+    VD_u u;
+    ELEMDESC elemdescVar;
+    WORD     wVarFlags;
+    VARKIND  varkind;
+}
+alias VARDESC * LPVARDESC;
+
+enum TYPEFLAGS {
+    TYPEFLAG_FAPPOBJECT = 0x01,
+    TYPEFLAG_FCANCREATE = 0x02,
+    TYPEFLAG_FLICENSED = 0x04,
+    TYPEFLAG_FPREDECLID = 0x08,
+    TYPEFLAG_FHIDDEN = 0x10,
+    TYPEFLAG_FCONTROL = 0x20,
+    TYPEFLAG_FDUAL = 0x40,
+    TYPEFLAG_FNONEXTENSIBLE = 0x80,
+    TYPEFLAG_FOLEAUTOMATION = 0x100,
+    TYPEFLAG_FRESTRICTED = 0x200,
+    TYPEFLAG_FAGGREGATABLE = 0x400,
+    TYPEFLAG_FREPLACEABLE = 0x800,
+    TYPEFLAG_FDISPATCHABLE = 0x1000,
+    TYPEFLAG_FREVERSEBIND = 0x2000
+}
+
+enum FUNCFLAGS {
+    FUNCFLAG_FRESTRICTED = 0x1,
+    FUNCFLAG_FSOURCE = 0x2,
+    FUNCFLAG_FBINDABLE = 0x4,
+    FUNCFLAG_FREQUESTEDIT = 0x8,
+    FUNCFLAG_FDISPLAYBIND = 0x10,
+    FUNCFLAG_FDEFAULTBIND = 0x20,
+    FUNCFLAG_FHIDDEN = 0x40,
+    FUNCFLAG_FUSESGETLASTERROR = 0x80,
+    FUNCFLAG_FDEFAULTCOLLELEM = 0x100,
+    FUNCFLAG_FUIDEFAULT = 0x200,
+    FUNCFLAG_FNONBROWSABLE = 0x400,
+    FUNCFLAG_FREPLACEABLE = 0x800,
+    FUNCFLAG_FIMMEDIATEBIND = 0x1000
+}
+
+enum VARFLAGS {
+    VARFLAG_FREADONLY = 0x1,
+    VARFLAG_FSOURCE = 0x2,
+    VARFLAG_FBINDABLE = 0x4,
+    VARFLAG_FREQUESTEDIT = 0x8,
+    VARFLAG_FDISPLAYBIND = 0x10,
+    VARFLAG_FDEFAULTBIND = 0x20,
+    VARFLAG_FHIDDEN = 0x40,
+    VARFLAG_FRESTRICTED = 0x80,
+    VARFLAG_FDEFAULTCOLLELEM = 0x100,
+    VARFLAG_FUIDEFAULT = 0x200,
+    VARFLAG_FNONBROWSABLE = 0x400,
+    VARFLAG_FREPLACEABLE = 0x800,
+    VARFLAG_FIMMEDIATEBIND = 0x1000
+}
+
+struct CLEANLOCALSTORAGE {
+    IUnknown pInterface;      /* interface that is responsible for storage */
+    PVOID pStorage;             /* the storage being managed by interface */
+    DWORD flags;                /* which interface, what storage */
+}
+
+struct CUSTDATAITEM {
+    GUID guid;           /* guid identifying this custom data item */
+    VARIANTARG varValue; /* value of this custom data item */
+}
+alias CUSTDATAITEM * LPCUSTDATAITEM;
+
+struct CUSTDATA {
+    DWORD cCustData;            /* number of custom data items in rgCustData */
+    LPCUSTDATAITEM prgCustData;
+                                /* array of custom data items */
+}
+alias CUSTDATA * LPCUSTDATA;
+
+
+interface ICreateTypeInfo: IUnknown
+{
+    HRESULT SetGuid( REFGUID guid );
+    HRESULT SetTypeFlags( UINT uTypeFlags );
+    HRESULT SetDocString( LPOLESTR pStrDoc );
+    HRESULT SetHelpContext( DWORD dwHelpContext);
+    HRESULT SetVersion( WORD wMajorVerNum, WORD wMinorVerNum );
+    HRESULT AddRefTypeInfo( ITypeInfo pTInfo, HREFTYPE * phRefType );
+    HRESULT AddFuncDesc( UINT index, FUNCDESC * pFuncDesc            );
+    HRESULT AddImplType( UINT index, HREFTYPE hRefType             );
+    HRESULT SetImplTypeFlags( UINT index, INT implTypeFlags            );
+    HRESULT SetAlignment( WORD cbAlignment             );
+    HRESULT SetSchema( LPOLESTR pStrSchema            );
+    HRESULT AddVarDesc( UINT index, VARDESC * pVarDesc            );
+    HRESULT SetFuncAndParamNames( UINT index, LPOLESTR * rgszNames, UINT cNames );
+    HRESULT SetVarName( UINT index, LPOLESTR szName         );
+    HRESULT SetTypeDescAlias( TYPEDESC * pTDescAlias    );
+    HRESULT DefineFuncAsDllEntry( UINT index,LPOLESTR szDllName,LPOLESTR szProcName            );
+    HRESULT SetFuncDocString( UINT index, LPOLESTR szDocString            );
+    HRESULT SetVarDocString(UINT index,LPOLESTR szDocString            );
+    HRESULT SetFuncHelpContext(UINT index,DWORD dwHelpContext            );
+    HRESULT SetVarHelpContext(UINT index,DWORD dwHelpContext            );
+    HRESULT SetMops(UINT index,BSTR bstrMops            );
+    HRESULT SetTypeIdldesc(IDLDESC * pIdlDesc            );
+    HRESULT LayOut();
+}
+alias ICreateTypeInfo LPCREATETYPEINFO;
+
+interface ICreateTypeInfo2: ICreateTypeInfo
+{
+	HRESULT DeleteFuncDesc(UINT index);
+	HRESULT DeleteFuncDescByMemId(MEMBERID memid,INVOKEKIND invKind);
+	HRESULT DeleteVarDesc(UINT index);
+	HRESULT DeleteVarDescByMemId(MEMBERID memid);
+	HRESULT DeleteImplType(UINT index);
+	HRESULT SetCustData(REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetFuncCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetParamCustData(UINT indexFunc,UINT indexParam,REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetVarCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetImplTypeCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetHelpStringContext(ULONG dwHelpStringContext);
+	HRESULT SetFuncHelpStringContext(UINT index,ULONG dwHelpStringContext);
+	HRESULT SetVarHelpStringContext(UINT index,ULONG dwHelpStringContext);
+	HRESULT Invalidate();
+	HRESULT SetName(LPOLESTR szName);
+}
+alias ICreateTypeInfo2 LPCREATETYPEINFO2;
+
+interface ICreateTypeLib : IUnknown
+{
+	HRESULT CreateTypeInfo(LPOLESTR szName,TYPEKIND tkind,ICreateTypeInfo * ppCTInfo);
+	HRESULT SetName(LPOLESTR szName);
+	HRESULT SetVersion(WORD wMajorVerNum,WORD wMinorVerNum);
+	HRESULT SetGuid(REFGUID guid);
+	HRESULT SetDocString( LPOLESTR szDoc);
+	HRESULT SetHelpFileName(LPOLESTR szHelpFileName);
+	HRESULT SetHelpContext(DWORD dwHelpContext);
+	HRESULT SetLcid(LCID lcid);
+	HRESULT SetLibFlags(UINT uLibFlags);
+	HRESULT SaveAllChanges();
+}
+alias ICreateTypeLib LPCREATETYPELIB;
+
+interface ICreateTypeLib2 : ICreateTypeLib
+{
+	HRESULT DeleteTypeInfo(LPOLESTR szName);
+	HRESULT SetCustData(REFGUID guid,VARIANT * pVarVal);
+	HRESULT SetHelpStringContext(ULONG dwHelpStringContext);
+	HRESULT SetHelpStringDll(LPOLESTR szFileName);
+}
+
+interface IDispatch : IUnknown
+{
+HRESULT GetTypeInfoCount(UINT * pctinfo);
+HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo);
+HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId);
+HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr);
+}
+alias IDispatch LPDISPATCH;
+const DISPID DISPID_UNKNOWN = cast(DISPID)-1;
+const DISPID DISPID_VALUE = cast(DISPID)0;
+const DISPID DISPID_PROPERTYPUT = cast(DISPID)-3;
+const DISPID DISPID_NEWENUM = cast(DISPID)-4;
+const DISPID DISPID_EVALUATE = cast(DISPID)-5;
+const DISPID DISPID_CONSTRUCTOR = cast(DISPID)-6;
+const DISPID DISPID_DESTRUCTOR = cast(DISPID)-7;
+const DISPID DISPID_COLLECT = cast(DISPID)-8;
+
+/+++++++++++++++++++++++++++++++++++++++
+
+[
+    object,
+    uuid(00020404-0000-0000-C000-000000000046),
+    pointer_default(unique)
+]
+
+interface IEnumVARIANT : IUnknown
+{
+    typedef [unique] IEnumVARIANT* LPENUMVARIANT;
+
+    [local]
+    HRESULT Next(
+                [in] ULONG celt,
+                [out, size_is(celt), length_is(*pCeltFetched)] VARIANT * rgVar,
+                [out] ULONG * pCeltFetched
+            );
+
+    [call_as(Next)]
+    HRESULT RemoteNext(
+                [in] ULONG celt,
+                [out, size_is(celt), length_is(*pCeltFetched)] VARIANT * rgVar,
+                [out] ULONG * pCeltFetched
+            );
+
+    HRESULT Skip(
+                [in] ULONG celt
+            );
+
+    HRESULT Reset(
+            );
+
+    HRESULT Clone(
+                [out] IEnumVARIANT ** ppEnum
+            );
+}
+
+
++/
+enum DESCKIND {
+        DESCKIND_NONE = 0,
+        DESCKIND_FUNCDESC,
+        DESCKIND_VARDESC,
+        DESCKIND_TYPECOMP,
+        DESCKIND_IMPLICITAPPOBJ,
+        DESCKIND_MAX
+}
+
+
+union BINDPTR {
+        FUNCDESC  * lpfuncdesc;
+        VARDESC   * lpvardesc;
+        ITypeComp lptcomp;
+}
+alias BINDPTR * LPBINDPTR;
+
+interface ITypeComp : IUnknown
+{
+
+    HRESULT Bind(LPOLESTR szName,ULONG lHashVal,WORD wFlags,
+ITypeInfo * ppTInfo,DESCKIND * pDescKind,BINDPTR * pBindPtr
+            );
+
+
+    HRESULT BindType( LPOLESTR szName,ULONG lHashVal,
+						ITypeInfo * ppTInfo,
+						ITypeComp * ppTComp
+            );
+
+}
+
+interface ITypeInfo : IUnknown
+{
+    HRESULT GetTypeAttr(TYPEATTR ** ppTypeAttr);
+    HRESULT GetTypeComp( ITypeComp * ppTComp );
+    HRESULT GetFuncDesc( UINT index, FUNCDESC ** ppFuncDesc );
+    HRESULT GetVarDesc( UINT index,VARDESC ** ppVarDesc);
+    HRESULT GetNames(MEMBERID memid,BSTR * rgBstrNames,UINT cMaxNames,UINT * pcNames);
+    HRESULT GetRefTypeOfImplType(UINT index,HREFTYPE * pRefType);
+    HRESULT GetImplTypeFlags(UINT index,INT * pImplTypeFlags);
+    HRESULT GetIDsOfNames(LPOLESTR * rgszNames,UINT cNames,MEMBERID * pMemId);
+    HRESULT Invoke(PVOID pvInstance,MEMBERID memid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr);
+    HRESULT GetDocumentation(MEMBERID memid,BSTR * pBstrName,BSTR * pBstrDocString,DWORD * pdwHelpContext,BSTR * pBstrHelpFile);
+    HRESULT GetDllEntry(MEMBERID memid,INVOKEKIND invKind,BSTR * pBstrDllName,BSTR * pBstrName,WORD * pwOrdinal);
+    HRESULT GetRefTypeInfo(HREFTYPE hRefType,ITypeInfo * ppTInfo);
+    HRESULT AddressOfMember(MEMBERID memid,INVOKEKIND invKind,PVOID * ppv);
+    HRESULT CreateInstance(IUnknown pUnkOuter,REFIID riid,PVOID * ppvObj);
+    HRESULT GetMops(MEMBERID memid,BSTR * pBstrMops);
+    HRESULT GetContainingTypeLib( ITypeLib ** ppTLib,UINT * pIndex);
+    void ReleaseTypeAttr(TYPEATTR * pTypeAttr );
+    void ReleaseFuncDesc( FUNCDESC * pFuncDesc  );
+    void ReleaseVarDesc(VARDESC * pVarDesc            );
+}
+alias ITypeInfo LPTYPEINFO;
+
+interface ITypeInfo2 : ITypeInfo
+{
+	HRESULT GetTypeKind(TYPEKIND * pTypeKind);
+	HRESULT GetTypeFlags(ULONG * pTypeFlags);
+	HRESULT GetFuncIndexOfMemId(MEMBERID memid,INVOKEKIND invKind,UINT * pFuncIndex);
+	HRESULT GetVarIndexOfMemId(MEMBERID memid,UINT * pVarIndex);
+	HRESULT GetCustData(REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetFuncCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetParamCustData(UINT indexFunc,UINT indexParam,REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetVarCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetImplTypeCustData(UINT index,REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetDocumentation2(MEMBERID memid,LCID lcid,BSTR *pbstrHelpString,DWORD *pdwHelpStringContext,BSTR *pbstrHelpStringDll);
+	HRESULT GetAllCustData(CUSTDATA * pCustData);
+	HRESULT GetAllFuncCustData(UINT index,CUSTDATA * pCustData);
+	HRESULT GetAllParamCustData(UINT indexFunc,UINT indexParam,CUSTDATA * pCustData);
+	HRESULT GetAllVarCustData(UINT index,CUSTDATA * pCustData);
+	HRESULT GetAllImplTypeCustData(UINT index,CUSTDATA * pCustData);
+}
+
+alias ITypeInfo2 LPTYPEINFO2;
+
+enum SYSKIND {
+        SYS_WIN16 = 0,
+        SYS_WIN32,
+        SYS_MAC
+}
+
+enum LIBFLAGS {
+        LIBFLAG_FRESTRICTED = 0x01,
+        LIBFLAG_FCONTROL = 0x02,
+        LIBFLAG_FHIDDEN = 0x04,
+        LIBFLAG_FHASDISKIMAGE = 0x08
+}
+
+struct TLIBATTR {
+        GUID guid;
+        LCID lcid;
+        SYSKIND syskind;
+        WORD wMajorVerNum;
+        WORD wMinorVerNum;
+        WORD wLibFlags;
+}
+alias TLIBATTR * LPTLIBATTR;
+
+interface ITypeLib : IUnknown
+{
+    UINT GetTypeInfoCount(
+            );
+
+    HRESULT GetTypeInfo(
+	UINT index,
+ITypeInfo * ppTInfo
+            );
+
+HRESULT GetTypeInfoType(
+	UINT index,
+	TYPEKIND * pTKind
+            );
+
+   HRESULT GetTypeInfoOfGuid(
+	REFGUID guid,
+	ITypeInfo * ppTinfo
+            );
+
+    HRESULT GetLibAttr(
+			TLIBATTR ** ppTLibAttr
+);
+
+    HRESULT GetTypeComp(ITypeComp * ppTComp            );
+
+    HRESULT GetDocumentation(INT index,BSTR * pBstrName,BSTR * pBstrDocString,DWORD * pdwHelpContext,BSTR * pBstrHelpFile
+            );
+
+    HRESULT IsName(LPOLESTR szNameBuf,ULONG lHashVal,BOOL * pfName
+            );
+
+    HRESULT FindName(
+			LPOLESTR szNameBuf,
+			ULONG lHashVal,
+			ITypeInfo * ppTInfo,
+			MEMBERID * rgMemId,
+			USHORT * pcFound
+	);
+
+    void ReleaseTLibAttr(		TLIBATTR * pTLibAttr            );
+}
+
+alias ITypeLib  LPTYPELIB;
+
+interface ITypeLib2 : ITypeLib
+{
+	HRESULT GetCustData(REFGUID guid,VARIANT * pVarVal);
+	HRESULT GetLibStatistics(ULONG * pcUniqueNames,ULONG * pcchUniqueNames);
+	HRESULT GetDocumentation2(INT index,LCID lcid,BSTR *pbstrHelpString,DWORD *pdwHelpStringContext,BSTR *pbstrHelpStringDll);
+	HRESULT GetAllCustData(CUSTDATA * pCustData);
+}
+alias ITypeLib2 LPTYPELIB2;
+
+enum CHANGEKIND {
+        CHANGEKIND_ADDMEMBER,
+        CHANGEKIND_DELETEMEMBER,
+        CHANGEKIND_SETNAMES,
+        CHANGEKIND_SETDOCUMENTATION,
+        CHANGEKIND_GENERAL,
+        CHANGEKIND_INVALIDATE,
+        CHANGEKIND_CHANGEFAILED,
+        CHANGEKIND_MAX,
+        ADDMEMBER    = CHANGEKIND_ADDMEMBER,
+        DELETEMEMBER = CHANGEKIND_DELETEMEMBER,
+        SETNAMES     = CHANGEKIND_SETNAMES,
+        SETDOCUMENTATION = CHANGEKIND_SETDOCUMENTATION,
+        GENERAL          = CHANGEKIND_GENERAL,
+        INVALIDATE       = CHANGEKIND_INVALIDATE,
+        CHANGEFAILED     = CHANGEKIND_CHANGEFAILED,
+        MAX       = CHANGEKIND_MAX
+}
+
+interface ITypeChangeEvents: IUnknown
+{
+    // notification messages used by the dynamic typeinfo protocol.
+    HRESULT RequestTypeChange(CHANGEKIND changeKind,ITypeInfo pTInfoBefore,LPOLESTR pStrName,INT * pfCancel);
+    HRESULT AfterTypeChange(CHANGEKIND changeKind,ITypeInfo pTInfoAfter,LPOLESTR pStrName);
+}
+alias ITypeChangeEvents LPTYPECHANGEEVENTS;
+
+interface IErrorInfo: IUnknown
+{
+	HRESULT GetGUID( GUID * pGUID );
+	HRESULT GetSource(BSTR * pBstrSource);
+	HRESULT GetDescription(BSTR * pBstrDescription);
+	HRESULT GetHelpFile(BSTR * pBstrHelpFile);
+	HRESULT GetHelpContext(DWORD * pdwHelpContext);
+}
+alias IErrorInfo LPERRORINFO;
+
+interface ICreateErrorInfo: IUnknown
+{
+	HRESULT SetGUID(REFGUID rguid);
+	HRESULT SetSource(LPOLESTR szSource);
+	HRESULT SetDescription(LPOLESTR szDescription);
+	HRESULT SetHelpFile(LPOLESTR szHelpFile);
+	HRESULT SetHelpContext(DWORD dwHelpContext);
+}
+alias ICreateErrorInfo LPCREATEERRORINFO;
+
+interface ISupportErrorInfo: IUnknown
+{
+	HRESULT InterfaceSupportsErrorInfo(REFIID riid);
+}
+alias ISupportErrorInfo LPSUPPORTERRORINFO;
+
+interface ITypeFactory : IUnknown
+{
+	HRESULT CreateFromTypeInfo(ITypeInfo pTypeInfo,REFIID riid, IUnknown *ppv);
+}
+
+interface ITypeMarshal : IUnknown
+{
+    HRESULT Size(PVOID pvType,DWORD dwDestContext,PVOID pvDestContext,ULONG * pSize);
+    HRESULT Marshal(PVOID pvType,DWORD dwDestContext,PVOID pvDestContext,ULONG cbBufferLength,BYTE  * pBuffer,ULONG * pcbWritten);
+    HRESULT Unmarshal(PVOID pvType,DWORD dwFlags,ULONG cbBufferLength,BYTE  * pBuffer,ULONG * pcbRead);
+    HRESULT Free(PVOID pvType);
+}
+
+
+interface IRecordInfo: IUnknown
+{
+	HRESULT RecordInit(PVOID pvNew);
+	HRESULT RecordClear(PVOID pvExisting);
+	HRESULT RecordCopy(PVOID pvExisting,PVOID pvNew);
+	HRESULT GetGuid(GUID * pguid);
+	HRESULT GetName(BSTR * pbstrName);
+	HRESULT GetSize(ULONG * pcbSize);
+	HRESULT GetTypeInfo(ITypeInfo * ppTypeInfo);
+	HRESULT GetField(PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField);
+	HRESULT GetFieldNoCopy(PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField,PVOID * ppvDataCArray);
+	HRESULT PutField(ULONG wFlags,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField);
+	HRESULT PutFieldNoCopy(ULONG wFlags,PVOID pvData,LPCOLESTR szFieldName,VARIANT * pvarField);
+	HRESULT GetFieldNames(ULONG * pcNames,BSTR * rgBstrNames);
+	BOOL IsMatchingType(IRecordInfo pRecordInfo);
+	PVOID RecordCreate();
+	HRESULT RecordCreateCopy(PVOID pvSource,PVOID * ppvDest);
+	HRESULT RecordDestroy(PVOID pvRecord);
+}
+alias IRecordInfo LPRECORDINFO;
+
+} // extern(WIndows);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OBJIDL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2744 @@
+module org.eclipse.swt.internal.ole.win32.OBJIDL;
+//+-------------------------------------------------------------------------
+//
+//  Microsoft Windows
+//  Copyright (C) Microsoft Corporation, 1992-1997.
+//
+//  File: objidl.idl
+//
+//--------------------------------------------------------------------------
+
+
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.win32.WINTYPES;
+// private import std.c.windows.windows;
+// private import std.c.windows.com;
+// private import org.eclipse.swt.internal.win32.os;
+
+
+/* *NEED* to port wtypes.h */
+
+extern( Windows ) {
+
+
+
+
+//#ifndef DO_NO_IMPORTS
+//import "unknwn.idl";
+//import "wtypes.idl";
+//#endif
+
+enum SRVINFO
+{
+    SRVINFO_F_COSERVERINFO = 0,
+    SRVINFO_F_COSERVERINFO2 = 1
+}
+
+struct COSERVERINFO
+{
+    DWORD             dwReserved1;
+    LPWSTR            pwszName;
+    COAUTHINFO *      pAuthInfo;
+    DWORD             dwReserved2;
+}
+
+struct COSERVERINFO2 {
+    DWORD           dwFlags;
+    LPWSTR          pwszName;
+    COAUTHINFO*     pAuthInfo;
+    IUnknown*       ppCall;
+    LPWSTR          pwszCodeURL;
+    DWORD           dwFileVersionMS;
+    DWORD           dwFileVersionLS;
+    LPWSTR          pwszContentType;
+}
+
+
+/****************************************************************************
+ *  Component Object Interfaces
+ ****************************************************************************/
+
+interface IMarshal : IUnknown
+{
+	HRESULT GetUnmarshalClass( REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid );
+	HRESULT GetMarshalSizeMax( REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize );
+	HRESULT MarshalInterface( IStream pStm, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags );
+	HRESULT UnmarshalInterface( IStream pStm, REFIID riid, void **ppv );
+	HRESULT ReleaseMarshalData( IStream pStm );
+	HRESULT DisconnectObject( DWORD dwReserved );
+}
+alias IMarshal LPMARSHAL;
+
+interface IMalloc : IUnknown
+{
+	void * Alloc( ULONG cb );
+	void * Realloc( void * pv, ULONG cb );
+	void   Free( void * pv );
+	ULONG  GetSize( void * pv );
+	int    DidAlloc( void * pv );
+	void   HeapMinimize();
+}
+alias IMalloc LPMALLOC;
+
+interface IMallocSpy : IUnknown
+{
+	ULONG   PreAlloc( ULONG cbRequest );
+	void  * PostAlloc( void * pActual );
+	void  * PreFree( void *pRequest, BOOL  fSpyed );
+	void    PostFree( BOOL  fSpyed );
+	ULONG   PreRealloc( void   *pRequest, ULONG   cbRequest, void **ppNewRequest, BOOL    fSpyed );
+	void  * PostRealloc( void *pActual, BOOL  fSpyed );
+	void  * PreGetSize( void *pRequest, BOOL  fSpyed );
+	ULONG   PostGetSize( ULONG cbActual, BOOL  fSpyed );
+	void  * PreDidAlloc( void * pRequest, BOOL  fSpyed );
+	int    PostDidAlloc( void *pRequest, BOOL  fSpyed, int   fActual );
+	void  PreHeapMinimize();
+	void  PostHeapMinimize();
+}
+alias IMallocSpy LPMALLOCSPY;
+
+interface IStdMarshalInfo : IUnknown
+{
+	HRESULT GetClassForHandler( DWORD dwDestContext, void *pvDestContext, CLSID *pClsid );
+}
+alias IStdMarshalInfo LPSTDMARSHALINFO;
+
+    // bit flags for IExternalConnection
+enum EXTCONN
+{
+	EXTCONN_STRONG      = 0x0001,   // strong connection
+	EXTCONN_WEAK        = 0x0002,   // weak connection (table, container)
+	EXTCONN_CALLABLE    = 0x0004,   // table .vs. callable
+}
+
+interface IExternalConnection : IUnknown
+{
+    // *** IExternalConnection methods ***
+	DWORD AddConnection( DWORD extconn, DWORD reserved );
+	DWORD ReleaseConnection( DWORD extconn, DWORD reserved, BOOL  fLastReleaseCloses );
+}
+alias IExternalConnection LPEXTERNALCONNECTION;
+
+
+struct MULTI_QI
+{
+	const IID  *pIID; // pass this one in
+	IUnknown   pItf; // get these out (you must set to NULL before calling)
+	HRESULT     hr;
+}
+
+interface IMultiQI : IUnknown
+{
+    HRESULT QueryMultipleInterfaces( ULONG      cMQIs, MULTI_QI  *pMQIs );
+}
+alias IMultiQI LPMULTIQI;
+
+interface IEnumUnknown : IUnknown
+{
+	HRESULT Next( ULONG celt, IUnknown * rgelt, ULONG *pceltFetched);
+	HRESULT Skip( ULONG celt );
+	HRESULT Reset();
+	HRESULT Clone( IEnumUnknown * ppenum );
+}
+alias IEnumUnknown LPENUMUNKNOWN;
+
+
+
+/****************************************************************************
+ *  Binding Interfaces
+ ****************************************************************************/
+
+struct BIND_OPTS {
+    DWORD       cbStruct;       //  sizeof(BIND_OPTS)
+    DWORD       grfFlags;
+    DWORD       grfMode;
+    DWORD       dwTickCountDeadline;
+}
+alias BIND_OPTS * LPBIND_OPTS;
+
+struct BIND_OPTS2 {
+    DWORD           cbStruct;       //  sizeof(BIND_OPTS2)
+    DWORD           grfFlags;
+    DWORD           grfMode;
+    DWORD           dwTickCountDeadline;
+    DWORD           dwTrackFlags;
+    DWORD           dwClassContext;
+    LCID            locale;
+    COSERVERINFO *  pServerInfo;
+}
+alias BIND_OPTS2 * LPBIND_OPTS2;
+
+enum BIND_FLAGS
+{
+	BIND_MAYBOTHERUSER = 1,
+	BIND_JUSTTESTEXISTENCE = 2
+}
+
+interface IBindCtx : IUnknown
+{
+	HRESULT RegisterObjectBound( IUnknown  punk );
+	HRESULT RevokeObjectBound( IUnknown punk );
+	HRESULT ReleaseBoundObjects();
+	HRESULT SetBindOptions( BIND_OPTS * pbindopts );
+	HRESULT GetBindOptions( BIND_OPTS * pbindopts );
+	HRESULT GetRunningObjectTable( IRunningObjectTable * pprot );
+	HRESULT RegisterObjectParam( LPOLESTR pszKey, IUnknown punk );
+	HRESULT GetObjectParam( LPOLESTR pszKey, IUnknown * ppunk );
+	HRESULT EnumObjectParam( IEnumString * ppenum );
+	HRESULT RevokeObjectParam( LPOLESTR pszKey );
+}
+alias IBindCtx LPBC;
+alias IBindCtx LPBINDCTX;
+
+interface IEnumMoniker : IUnknown
+{
+	HRESULT Next( ULONG celt, IMoniker * rgelt, ULONG *pceltFetched );
+	HRESULT Skip( ULONG celt );
+	HRESULT Reset();
+	HRESULT Clone( IEnumMoniker * ppenum );
+}
+alias IEnumMoniker LPENUMMONIKER;
+
+interface IRunnableObject : IUnknown
+{
+	HRESULT GetRunningClass( LPCLSID lpClsid );
+	HRESULT Run( LPBINDCTX pbc );
+	BOOL IsRunning();
+	HRESULT LockRunning( BOOL fLock, BOOL fLastUnlockCloses );
+	HRESULT SetContainedObject( BOOL fContained );
+}
+alias IRunnableObject LPRUNNABLEOBJECT;
+
+interface IRunningObjectTable : IUnknown
+{
+	HRESULT Register( DWORD grfFlags, IUnknown punkObject, IMoniker pmkObjectName, DWORD *pdwRegister );
+	HRESULT Revoke ( DWORD dwRegister );
+	HRESULT IsRunning( IMoniker pmkObjectName );
+	HRESULT GetObject( IMoniker pmkObjectName, IUnknown * ppunkObject );
+	HRESULT NoteChangeTime( DWORD dwRegister, FILETIME *pfiletime );
+	HRESULT GetTimeOfLastChange( IMoniker  pmkObjectName, FILETIME *pfiletime );
+	HRESULT EnumRunning( IEnumMoniker * ppenumMoniker );
+}
+alias IRunningObjectTable LPRUNNINGOBJECTTABLE;
+
+interface IPersist : IUnknown
+{
+	HRESULT GetClassID( CLSID * pClassID );
+}
+alias IPersist LPPERSIST;
+
+interface IPersistStream : IPersist
+{
+	HRESULT IsDirty(  );
+	HRESULT Load( IStream pStm );
+	HRESULT Save( IStream pStm, BOOL fClearDirty );
+	HRESULT GetSizeMax( ULARGE_INTEGER *pcbSize );
+}
+alias IPersistStream LPPERSISTSTREAM;
+
+    // system moniker types; returned from IsSystemMoniker.
+enum MKSYS
+{
+	MKSYS_NONE = 0,
+	MKSYS_GENERICCOMPOSITE = 1,
+	MKSYS_FILEMONIKER = 2,
+	MKSYS_ANTIMONIKER = 3,
+	MKSYS_ITEMMONIKER = 4,
+	MKSYS_POINTERMONIKER = 5,
+    //  MKSYS_URLMONIKER = 6,
+	MKSYS_CLASSMONIKER = 7
+}
+
+enum MKREDUCE
+{
+	MKRREDUCE_ONE           =   3<<16,
+	MKRREDUCE_TOUSER        =   2<<16,
+	MKRREDUCE_THROUGHUSER   =   1<<16,
+	MKRREDUCE_ALL           =   0
+}
+
+interface IMoniker : IPersistStream
+{
+	HRESULT BindToObject( IBindCtx pbc, IMoniker pmkToLeft, REFIID riidResult, void **ppvResult );
+	HRESULT BindToStorage( IBindCtx pbc, IMoniker pmkToLeft, REFIID riid, void * ppvObj );
+	HRESULT Reduce( IBindCtx pbc, DWORD dwReduceHowFar, IMoniker * ppmkToLeft, IMoniker * ppmkReduced );
+	HRESULT ComposeWith( IMoniker pmkRight, BOOL fOnlyIfNotGeneric, IMoniker * ppmkComposite );
+	HRESULT Enum( BOOL fForward, IEnumMoniker * ppenumMoniker );
+	HRESULT IsEqual( IMoniker pmkOtherMoniker );
+	HRESULT Hash( DWORD *pdwHash );
+	HRESULT IsRunning( IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning );
+	HRESULT GetTimeOfLastChange( IBindCtx pbc, IMoniker pmkToLeft, FILETIME *pFileTime );
+	HRESULT Inverse( IMoniker * ppmk );
+	HRESULT CommonPrefixWith( IMoniker pmkOther, IMoniker * ppmkPrefix );
+	HRESULT RelativePathTo( IMoniker pmkOther, IMoniker * ppmkRelPath );
+	HRESULT GetDisplayName( IBindCtx pbc, IMoniker pmkToLeft, LPOLESTR *ppszDisplayName );
+	HRESULT ParseDisplayName( IBindCtx pbc, IMoniker pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten,	IMoniker * ppmkOut );
+	HRESULT IsSystemMoniker( DWORD * pdwMksys );
+}
+alias IMoniker LPMONIKER;
+
+interface IROTData : IUnknown
+{
+	HRESULT GetComparisonData( byte * pbData, ULONG cbMax, ULONG *pcbData );
+}
+
+interface IEnumString : IUnknown
+{
+	HRESULT Next( ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched );
+	HRESULT Skip( ULONG celt );
+	HRESULT Reset();
+	HRESULT Clone( IEnumString * ppenum );
+}
+alias IEnumString LPENUMSTRING;
+
+
+/****************************************************************************
+ *  Structured Storage Interfaces
+ ****************************************************************************/
+
+interface ISequentialStream : IUnknown
+{
+	HRESULT Read( void *pv, ULONG cb, ULONG *pcbRead );
+	HRESULT Write( void *pv, ULONG cb, ULONG *pcbWritten );
+}
+
+    /* Storage stat buffer */
+struct STATSTG
+{
+        LPOLESTR pwcsName;
+        DWORD type;
+        ULARGE_INTEGER cbSize;
+        FILETIME mtime;
+        FILETIME ctime;
+        FILETIME atime;
+        DWORD grfMode;
+        DWORD grfLocksSupported;
+        CLSID clsid;
+        DWORD grfStateBits;
+    DWORD reserved;
+}
+
+    /* Storage element types */
+enum STGTY
+{
+	STGTY_STORAGE   = 1,
+	STGTY_STREAM    = 2,
+	STGTY_LOCKBYTES = 3,
+	STGTY_PROPERTY  = 4
+}
+
+enum STREAM_SEEK
+{
+        STREAM_SEEK_SET = 0,
+        STREAM_SEEK_CUR = 1,
+        STREAM_SEEK_END = 2
+}
+
+enum LOCKTYPE
+{
+        LOCK_WRITE      = 1,
+        LOCK_EXCLUSIVE  = 2,
+        LOCK_ONLYONCE   = 4
+}
+
+interface IStream : ISequentialStream
+{
+	HRESULT Seek( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition );
+	HRESULT SetSize( ULARGE_INTEGER libNewSize );
+	HRESULT CopyTo( IStream pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);
+	HRESULT Commit( DWORD grfCommitFlags );
+	HRESULT Revert();
+	HRESULT LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType );
+	HRESULT UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType );
+	HRESULT Stat( STATSTG *pstatstg, DWORD grfStatFlag);
+	HRESULT Clone( IStream * ppstm );
+}
+alias IStream LPSTREAM;
+
+interface IEnumSTATSTG : IUnknown
+{
+	HRESULT Next( ULONG celt, STATSTG *rgelt, ULONG *pceltFetched );
+	HRESULT Skip( ULONG celt );
+	HRESULT Reset();
+	HRESULT Clone( IEnumSTATSTG * ppenum );
+}
+alias IEnumSTATSTG LPENUMSTATSTG;
+
+struct RemSNB
+{
+	ULONG ulCntStr;
+	ULONG ulCntChar;
+	OLECHAR rgString[];
+}
+alias RemSNB * wireSNB;
+alias OLECHAR ** SNB;
+
+interface IStorage : IUnknown
+{
+	HRESULT CreateStream( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream * ppstm);
+   HRESULT OpenStream( OLECHAR *pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream * ppstm);
+   HRESULT CreateStorage( OLECHAR *pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStorage * ppstg);
+   HRESULT OpenStorage( OLECHAR *pwcsName, IStorage pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage * ppstg );
+   HRESULT CopyTo( DWORD ciidExclude, IID *rgiidExclude, SNB snbExclude, IStorage pstgDest );
+	HRESULT MoveElementTo( OLECHAR * pwcsName, IStorage pstgDest, OLECHAR *pwcsNewName, DWORD grfFlags );
+	HRESULT Commit( DWORD grfCommitFlags );
+	HRESULT Revert();
+	HRESULT EnumElements( DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG * ppenum);
+	HRESULT DestroyElement( OLECHAR * pwcsName );
+	HRESULT RenameElement( OLECHAR *pwcsOldName, OLECHAR *pwcsNewName );
+	HRESULT SetElementTimes( OLECHAR * pwcsName, FILETIME * pctime, FILETIME *patime, FILETIME *pmtime );
+	HRESULT SetClass( REFCLSID clsid );
+	HRESULT SetStateBits( DWORD grfStateBits, DWORD grfMask );
+	HRESULT Stat( STATSTG *pstatstg, DWORD grfStatFlag );
+}
+alias IStorage LPSTORAGE;
+
+interface IPersistFile : IPersist
+{
+	HRESULT IsDirty();
+	HRESULT Load(LPCOLESTR pszFileName,DWORD dwMode);
+	HRESULT Save(LPCOLESTR pszFileName,BOOL fRemember);
+	HRESULT SaveCompleted(LPCOLESTR pszFileName);
+	HRESULT GetCurFile(LPOLESTR *ppszFileName );
+}
+alias IPersistFile LPPERSISTFILE;
+
+interface IPersistStorage : IPersist
+{
+	HRESULT IsDirty();
+	HRESULT InitNew(IStorage pStg);
+	HRESULT Load(IStorage pStg);
+	HRESULT Save(IStorage pStgSave,BOOL fSameAsLoad);
+	HRESULT SaveCompleted(IStorage pStgNew);
+	HRESULT HandsOffStorage();
+}
+alias IPersistStorage LPPERSISTSTORAGE;
+
+interface ILockBytes : IUnknown
+{
+    HRESULT ReadAt(
+ULARGE_INTEGER ulOffset,
+void *pv,
+ULONG cb,
+ULONG *pcbRead);
+
+    HRESULT WriteAt(
+ULARGE_INTEGER ulOffset,
+void  *pv,
+ULONG cb,
+ULONG *pcbWritten);
+
+HRESULT Flush();
+
+HRESULT SetSize(
+ULARGE_INTEGER cb);
+
+    HRESULT LockRegion(
+ULARGE_INTEGER libOffset,
+ULARGE_INTEGER cb,
+DWORD dwLockType);
+
+    HRESULT UnlockRegion(
+ULARGE_INTEGER libOffset,
+ULARGE_INTEGER cb,
+DWORD dwLockType);
+
+    HRESULT Stat(
+STATSTG *pstatstg,
+DWORD grfStatFlag);
+}
+alias ILockBytes LPLOCKBYTES;
+
+struct DVTARGETDEVICE {
+        DWORD tdSize;
+        WORD tdDriverNameOffset;
+        WORD tdDeviceNameOffset;
+        WORD tdPortNameOffset;
+        WORD tdExtDevmodeOffset;
+BYTE[1] tdData;
+}
+
+typedef CLIPFORMAT LPCLIPFORMAT;
+
+struct FORMATETC {
+        CLIPFORMAT cfFormat;
+DVTARGETDEVICE * ptd;
+        DWORD dwAspect;
+        LONG lindex;
+        DWORD tymed;
+}
+alias FORMATETC *LPFORMATETC;
+
+interface IEnumFORMATETC : IUnknown
+{
+    HRESULT Next(
+ULONG celt,
+        FORMATETC *rgelt,
+ULONG *pceltFetched);
+
+    HRESULT Skip(
+ULONG celt);
+
+    HRESULT Reset();
+
+    HRESULT Clone(
+IEnumFORMATETC * ppenum);
+}
+alias IEnumFORMATETC LPENUMFORMATETC;
+
+    //Advise Flags
+enum ADVF
+{
+        ADVF_NODATA = 1,
+        ADVF_PRIMEFIRST = 2,
+        ADVF_ONLYONCE = 4,
+        ADVF_DATAONSTOP = 64,
+        ADVFCACHE_NOHANDLER = 8,
+        ADVFCACHE_FORCEBUILTIN = 16,
+        ADVFCACHE_ONSAVE = 32
+}
+
+    // Stats for data; used by several enumerations and by at least one
+    // implementation of IDataAdviseHolder; if a field is not used, it
+    // will be NULL.
+
+struct STATDATA
+{                              // field used by:
+	FORMATETC formatetc;       // EnumAdvise, EnumData (cache), EnumFormats
+	DWORD advf;                // EnumAdvise, EnumData (cache)
+	IAdviseSink pAdvSink; // EnumAdvise
+	DWORD dwConnection;        // EnumAdvise
+}
+alias STATDATA * LPSTATDATA;
+
+interface IEnumSTATDATA : IUnknown
+{
+    HRESULT Next(
+ULONG celt,
+        STATDATA *rgelt,
+ULONG *pceltFetched);
+
+
+    HRESULT Skip(
+ULONG celt);
+
+    HRESULT Reset();
+
+    HRESULT Clone(
+IEnumSTATDATA * ppenum);
+}
+alias IEnumSTATDATA LPENUMSTATDATA;
+
+interface IRootStorage : IUnknown
+{
+    HRESULT SwitchToFile( LPOLESTR pszFile    );
+}
+alias IRootStorage LPROOTSTORAGE;
+
+
+/****************************************************************************
+ *  Notification Interfaces
+ ****************************************************************************/
+
+enum TYMED {
+        TYMED_HGLOBAL = 1,
+        TYMED_FILE = 2,
+        TYMED_ISTREAM = 4,
+        TYMED_ISTORAGE = 8,
+        TYMED_GDI = 16,
+        TYMED_MFPICT = 32,
+        TYMED_ENHMF = 64,
+        TYMED_NULL = 0
+}
+
+struct RemSTGMEDIUM {
+        DWORD tymed;
+        DWORD dwHandleType;
+        ULONG pData;
+        ULONG pUnkForRelease;
+        ULONG cbData;
+        byte[1] data;
+}
+
+union UNION_u {
+	HBITMAP hBitmap;
+	HMETAFILEPICT hMetaFilePict;
+	HENHMETAFILE hEnhMetaFile;
+	HGLOBAL hGlobal;
+	LPOLESTR lpszFileName;
+	IStream pstm;
+	IStorage pstg;
+}
+/*
+struct uSTGMEDIUM {
+	DWORD tymed;
+	UNION_u u;
+	IUnknown pUnkForRelease;
+}
+*/
+// <Shawn Liu> modified
+struct uSTGMEDIUM {
+	DWORD tymed;
+	void* unionField;
+	IUnknown pUnkForRelease;
+}
+
+
+enum {
+	OBJ_PEN             =1,
+	OBJ_BRUSH           =2,
+	OBJ_DC              =3,
+	OBJ_METADC          =4,
+	OBJ_PAL             =5,
+	OBJ_FONT            =6,
+	OBJ_BITMAP          =7,
+	OBJ_REGION          =8,
+	OBJ_METAFILE        =9,
+	OBJ_MEMDC           =10,
+	OBJ_EXTPEN          =11,
+	OBJ_ENHMETADC       =12,
+	OBJ_ENHMETAFILE     =13
+}
+union __MIDL_IAdviseSink_0002
+{
+		wireHBITMAP hBitmap;
+		wireHPALETTE hPalette;
+		wireHGLOBAL hGeneric;
+}
+
+struct GDI_OBJECT
+{
+	DWORD ObjectType;
+   __MIDL_IAdviseSink_0002 u;
+}
+
+union __MIDL_IAdviseSink_0003
+{
+			wireHMETAFILEPICT hMetaFilePict;
+			wireHENHMETAFILE hHEnhMetaFile;
+			GDI_OBJECT  *hGdiHandle;
+			wireHGLOBAL hGlobal;
+			LPOLESTR lpszFileName;
+			BYTE_BLOB  *pstm;
+			BYTE_BLOB  *pstg;
+}
+
+struct  userSTGMEDIUM
+{
+   DWORD tymed;
+   __MIDL_IAdviseSink_0003 u;
+	IUnknown pUnkForRelease;
+}
+
+alias userSTGMEDIUM *wireSTGMEDIUM;
+alias uSTGMEDIUM STGMEDIUM;
+alias userSTGMEDIUM *wireASYNC_STGMEDIUM;
+alias STGMEDIUM ASYNC_STGMEDIUM;
+alias STGMEDIUM *LPSTGMEDIUM;
+
+struct  userFLAG_STGMEDIUM
+{
+    LONG ContextFlags;
+    LONG fPassOwnership;
+	userSTGMEDIUM Stgmed;
+}
+
+alias userFLAG_STGMEDIUM *wireFLAG_STGMEDIUM;
+
+struct  FLAG_STGMEDIUM
+{
+	LONG ContextFlags;
+	LONG fPassOwnership;
+	STGMEDIUM Stgmed;
+}
+
+
+interface IAdviseSink : IUnknown
+{
+    void OnDataChange(FORMATETC *pFormatetc,STGMEDIUM *pStgmed);
+    void OnViewChange(DWORD dwAspect,LONG lindex);
+    void OnRename(IMoniker pmk);
+    void OnSave();
+    void OnClose();
+}
+alias IAdviseSink LPADVISESINK;
+
+interface IAdviseSink2 : IAdviseSink
+{
+    void OnLinkSrcChange( IMoniker pmk );
+}
+alias IAdviseSink2 LPADVISESINK2;
+
+
+enum DATADIR
+{
+	DATADIR_GET = 1,
+	DATADIR_SET = 2
+}
+
+interface IDataObject : IUnknown
+{
+
+    HRESULT GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
+
+    HRESULT GetDataHere( FORMATETC *pformatetc, STGMEDIUM *pmedium);
+
+    HRESULT QueryGetData(	FORMATETC *pformatetc);
+
+    HRESULT GetCanonicalFormatEtc(
+			FORMATETC *pformatectIn,
+			FORMATETC *pformatetcOut);
+
+    HRESULT SetData(
+		FORMATETC *pformatetc,
+		STGMEDIUM *pmedium,
+			BOOL fRelease);
+
+    HRESULT EnumFormatEtc(
+			DWORD dwDirection,
+			IEnumFORMATETC * ppenumFormatEtc);
+
+    HRESULT DAdvise(
+		FORMATETC *pformatetc,
+		DWORD advf,
+		IAdviseSink pAdvSink,
+		DWORD *pdwConnection);
+
+    HRESULT DUnadvise(DWORD dwConnection);
+
+    HRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise);
+
+}
+alias IDataObject LPDATAOBJECT;
+
+interface IDataAdviseHolder : IUnknown
+{
+    HRESULT Advise
+    (
+	IDataObject pDataObject,
+	FORMATETC *pFetc,
+	DWORD advf,
+	IAdviseSink pAdvise,
+	DWORD *pdwConnection
+    );
+
+    HRESULT Unadvise
+    (
+	DWORD dwConnection
+    );
+
+    HRESULT EnumAdvise
+    (
+IEnumSTATDATA * ppenumAdvise
+    );
+
+    HRESULT SendOnDataChange
+    (
+		IDataObject pDataObject,
+		DWORD dwReserved,
+		DWORD advf
+    );
+
+}
+alias IDataAdviseHolder LPDATAADVISEHOLDER;
+
+
+// call type used by IMessageFilter::HandleIncomingMessage
+enum CALLTYPE
+{
+    CALLTYPE_TOPLEVEL = 1,      // toplevel call - no outgoing call
+    CALLTYPE_NESTED   = 2,      // callback on behalf of previous outgoing call - should always handle
+    CALLTYPE_ASYNC    = 3,      // aysnchronous call - can NOT be rejected
+    CALLTYPE_TOPLEVEL_CALLPENDING = 4,  // new toplevel call with new LID
+    CALLTYPE_ASYNC_CALLPENDING    = 5   // async call - can NOT be rejected
+}
+
+// status of server call - returned by IMessageFilter::HandleIncomingCall
+// and passed to  IMessageFilter::RetryRejectedCall
+enum SERVERCALL
+{
+    SERVERCALL_ISHANDLED    = 0,
+    SERVERCALL_REJECTED     = 1,
+    SERVERCALL_RETRYLATER   = 2
+}
+
+// Pending type indicates the level of nesting
+enum PENDINGTYPE
+{
+    PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+    PENDINGTYPE_NESTED   = 2  // nested call
+}
+
+// return values of MessagePending
+enum PENDINGMSG
+{
+    PENDINGMSG_CANCELCALL  = 0, // cancel the outgoing call
+    PENDINGMSG_WAITNOPROCESS  = 1, // wait for the return and don't dispatch the message
+    PENDINGMSG_WAITDEFPROCESS = 2  // wait and dispatch the message
+
+}
+
+// additional interface information about the incoming call
+struct INTERFACEINFO
+{
+    IUnknown    pUnk;      // the pointer to the object
+    IID         iid;        // interface id
+    WORD        wMethod;    // interface method
+}
+alias INTERFACEINFO *LPINTERFACEINFO;
+
+
+interface IMessageFilter : IUnknown
+{
+
+    DWORD HandleInComingCall
+    (
+DWORD dwCallType,
+HTASK htaskCaller,
+DWORD dwTickCount,
+LPINTERFACEINFO lpInterfaceInfo
+    );
+
+    DWORD RetryRejectedCall
+    (
+HTASK htaskCallee,
+DWORD dwTickCount,
+DWORD dwRejectType
+    );
+
+    DWORD MessagePending
+    (
+HTASK htaskCallee,
+DWORD dwTickCount,
+DWORD dwPendingType
+    );
+}
+alias IMessageFilter LPMESSAGEFILTER;
+
+
+
+/****************************************************************************
+ *  Object Remoting Interfaces
+ ****************************************************************************/
+/*
+interface IRpcChannelBuffer : IUnknown
+{
+
+    typedef unsigned long RPCOLEDATAREP;
+
+    typedef struct tagRPCOLEMESSAGE
+    {
+        void             *reserved1;
+        RPCOLEDATAREP     dataRepresentation;
+        void             *Buffer;
+        ULONG             cbBuffer;
+        ULONG             iMethod;
+        void             *reserved2[5];
+        ULONG             rpcFlags;
+    } RPCOLEMESSAGE;
+
+    typedef RPCOLEMESSAGE *PRPCOLEMESSAGE;
+
+    HRESULT GetBuffer
+    (
+        [in] RPCOLEMESSAGE *pMessage,
+        [in] REFIID riid
+    );
+
+    HRESULT SendReceive
+    (
+        [in,out] RPCOLEMESSAGE *pMessage,
+        [out] ULONG *pStatus
+    );
+
+    HRESULT FreeBuffer
+    (
+        [in] RPCOLEMESSAGE *pMessage
+    );
+
+    HRESULT GetDestCtx
+    (
+        [out] DWORD *pdwDestContext,
+        [out] void **ppvDestContext
+    );
+
+    HRESULT IsConnected
+    (
+        void
+    );
+
+}
+
+[
+    local,
+    object,
+    uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf)
+]
+interface IRpcChannelBuffer2 : IRpcChannelBuffer
+{
+
+    HRESULT GetProtocolVersion
+    (
+        [in,out] DWORD *pdwVersion
+    );
+}
+
+[
+    local,
+    object,
+    uuid(25B15600-0115-11d0-BF0D-00AA00B8DFD2)
+]
+interface IRpcChannelBuffer3 : IRpcChannelBuffer2
+{
+
+    HRESULT Send
+    (
+        [in,out] RPCOLEMESSAGE *pMsg,
+        [out]    ULONG *pulStatus
+    );
+
+    HRESULT Receive
+    (
+        [in,out] RPCOLEMESSAGE *pMsg,
+        [in]     ULONG ulSize,
+        [out]    ULONG *pulStatus
+    );
+
+    HRESULT Cancel
+    (
+        [in] RPCOLEMESSAGE *pMsg
+    );
+
+    HRESULT GetCallContext
+    (
+        [in]  RPCOLEMESSAGE *pMsg,
+        [in]  REFIID riid,
+        [out] void **pInterface
+    );
+
+    HRESULT GetDestCtxEx
+    (
+        [in] RPCOLEMESSAGE *pMsg,
+        [out] DWORD *pdwDestContext,
+        [out] void **ppvDestContext
+    );
+
+    HRESULT GetState
+    (
+        [in]  RPCOLEMESSAGE   *pMsg,
+        [out] DWORD           *pState
+    );
+
+    HRESULT RegisterAsync
+    (
+        [in] RPCOLEMESSAGE *pMsg,
+        [in] IAsyncManager *pAsyncMgr
+    );
+
+}
+
+
+[
+    local,
+    object,
+    uuid(D5F56A34-593B-101A-B569-08002B2DBF7A)
+]
+interface IRpcProxyBuffer : IUnknown
+{
+
+    HRESULT Connect
+    (
+        [in, unique] IRpcChannelBuffer *pRpcChannelBuffer
+    );
+
+    void Disconnect
+    (
+        void
+    );
+
+}
+
+[
+    local,
+    object,
+    uuid(D5F56AFC-593B-101A-B569-08002B2DBF7A)
+]
+interface IRpcStubBuffer : IUnknown
+{
+
+    HRESULT Connect
+    (
+        [in] IUnknown *pUnkServer
+    );
+
+    void Disconnect();
+
+    HRESULT Invoke
+    (
+        [in] RPCOLEMESSAGE *_prpcmsg,
+        [in] IRpcChannelBuffer *_pRpcChannelBuffer
+    );
+
+    IRpcStubBuffer *IsIIDSupported
+    (
+        [in] REFIID riid
+    );
+
+    ULONG CountRefs
+    (
+        void
+    );
+
+    HRESULT DebugServerQueryInterface
+    (
+        void **ppv
+    );
+
+    void DebugServerRelease
+    (
+        void *pv
+    );
+
+}
+
+
+
+[
+    local,
+    object,
+    uuid(D5F569D0-593B-101A-B569-08002B2DBF7A)
+]
+interface IPSFactoryBuffer : IUnknown
+{
+
+    HRESULT CreateProxy
+    (
+        [in] IUnknown *pUnkOuter,
+        [in] REFIID riid,
+        [out] IRpcProxyBuffer **ppProxy,
+        [out] void **ppv
+    );
+
+    HRESULT CreateStub
+    (
+        [in] REFIID riid,
+        [in, unique] IUnknown *pUnkServer,
+        [out] IRpcStubBuffer **ppStub
+    );
+}
+
+cpp_quote( "#if  (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM" )
+cpp_quote( "// This interface is only valid on Windows NT 4.0" )
+
+// This structure contains additional data for hooks.  As a backward
+// compatability hack, the entire structure is passed in place of the
+// RIID parameter on all hook methods.  Thus the IID must be the first
+// parameter.  As a forward compatability hack the second field is the
+// current size of the structure.
+typedef struct SChannelHookCallInfo
+{
+    IID               iid;
+    DWORD             cbSize;
+    GUID              uCausality;
+    DWORD             dwServerPid;
+    DWORD             iMethod;
+    void             *pObject;
+} SChannelHookCallInfo;
+
+[
+    local,
+    object,
+    uuid(1008c4a0-7613-11cf-9af1-0020af6e72f4)
+]
+interface IChannelHook : IUnknown
+{
+    void ClientGetSize(
+        [in]  REFGUID uExtent,
+        [in]  REFIID  riid,
+        [out] ULONG  *pDataSize );
+
+    void ClientFillBuffer(
+        [in]      REFGUID uExtent,
+        [in]      REFIID  riid,
+        [in, out] ULONG  *pDataSize,
+        [in]      void   *pDataBuffer );
+
+    void ClientNotify(
+        [in] REFGUID uExtent,
+        [in] REFIID  riid,
+        [in] ULONG   cbDataSize,
+        [in] void   *pDataBuffer,
+        [in] DWORD   lDataRep,
+        [in] HRESULT hrFault );
+
+    void ServerNotify(
+        [in] REFGUID uExtent,
+        [in] REFIID  riid,
+        [in] ULONG   cbDataSize,
+        [in] void   *pDataBuffer,
+        [in] DWORD   lDataRep );
+
+    void ServerGetSize(
+        [in]  REFGUID uExtent,
+        [in]  REFIID  riid,
+        [in]  HRESULT hrFault,
+        [out] ULONG  *pDataSize );
+
+    void ServerFillBuffer(
+        [in]      REFGUID uExtent,
+        [in]      REFIID  riid,
+        [in, out] ULONG  *pDataSize,
+        [in]      void   *pDataBuffer,
+        [in]      HRESULT hrFault );
+};
+
+cpp_quote( "#endif //DCOM" )
+*/
+
+/****************************************************************************
+ *  Property Storage Interfaces
+ ****************************************************************************/
+
+ /*
+interface IPropertyStorage;
+interface IEnumSTATPROPSTG;
+interface IEnumSTATPROPSETSTG;
+
+[
+    object,
+    uuid(00000138-0000-0000-C000-000000000046),
+    pointer_default(unique)
+]
+
+interface IPropertyStorage : IUnknown
+{
+
+    cpp_quote("")
+    cpp_quote("// Well-known Property Set Format IDs")
+    extern const FMTID FMTID_SummaryInformation;
+    extern const FMTID FMTID_DocSummaryInformation;
+    extern const FMTID FMTID_UserDefinedProperties;
+
+    cpp_quote("")
+    cpp_quote("// Flags for IPropertySetStorage::Create")
+    const DWORD PROPSETFLAG_DEFAULT = 0;
+    const DWORD PROPSETFLAG_NONSIMPLE = 1;
+    const DWORD PROPSETFLAG_ANSI = 2;
+    cpp_quote("// This flag is only supported on StgCreatePropStg & StgOpenPropStg")
+    const DWORD PROPSETFLAG_UNBUFFERED = 4;
+
+    typedef [unique] IPropertyStorage * LPPROPERTYSTORAGE;
+
+    typedef struct tagPROPVARIANT PROPVARIANT;
+
+    #define TYPEDEF_CA(type, name) \
+        typedef struct tag##name\
+        {\
+            ULONG   cElems;\
+            [size_is( cElems )]\
+            type *  pElems;\
+        } name
+
+    TYPEDEF_CA(unsigned char,       CAUB);
+    TYPEDEF_CA(short,               CAI);
+    TYPEDEF_CA(USHORT,              CAUI);
+    TYPEDEF_CA(long,                CAL);
+    TYPEDEF_CA(ULONG,               CAUL);
+    TYPEDEF_CA(float,               CAFLT);
+    TYPEDEF_CA(double,              CADBL);
+    TYPEDEF_CA(CY,                  CACY);
+    TYPEDEF_CA(DATE,                CADATE);
+    TYPEDEF_CA(BSTR,                CABSTR);
+    TYPEDEF_CA(BSTRBLOB,            CABSTRBLOB);
+    TYPEDEF_CA(VARIANT_BOOL,        CABOOL);
+    TYPEDEF_CA(SCODE,               CASCODE);
+    TYPEDEF_CA(PROPVARIANT,         CAPROPVARIANT);
+    TYPEDEF_CA(LARGE_INTEGER,       CAH);
+    TYPEDEF_CA(ULARGE_INTEGER,      CAUH);
+    TYPEDEF_CA(LPSTR,               CALPSTR);
+    TYPEDEF_CA(LPWSTR,              CALPWSTR);
+    TYPEDEF_CA(FILETIME,            CAFILETIME);
+    TYPEDEF_CA(CLIPDATA,            CACLIPDATA);
+    TYPEDEF_CA(CLSID,               CACLSID);
+
+cpp_quote("// Disable the warning about the obsolete member named 'bool'")
+cpp_quote("// 'bool', 'true', 'false', 'mutable', 'explicit', & 'typename'")
+cpp_quote("// are reserved keywords")
+cpp_quote("#pragma warning(disable:4237)")
+
+    struct tagPROPVARIANT
+    {
+        VARTYPE vt;
+        WORD    wReserved1;
+        WORD    wReserved2;
+        WORD    wReserved3;
+        [switch_is((unsigned short) (vt & 0x1fff))] union
+        {
+            [case(VT_EMPTY, VT_NULL)]
+                ;
+            [case(VT_UI1)]
+                UCHAR               bVal;
+            [case(VT_I2)]
+                short               iVal;
+            [case(VT_UI2)]
+                USHORT              uiVal;
+            [case(VT_BOOL)]
+                VARIANT_BOOL        boolVal;
+            [case(VT_ILLEGAL)]  // obsolete field name; use boolVal
+                _VARIANT_BOOL        bool;
+            [case(VT_I4)]
+                long                lVal;
+            [case(VT_UI4)]
+                ULONG               ulVal;
+            [case(VT_R4)]
+                float               fltVal;
+            [case(VT_ERROR)]
+                SCODE               scode;
+            [case(VT_I8)]
+                LARGE_INTEGER       hVal;
+            [case(VT_UI8)]
+                ULARGE_INTEGER      uhVal;
+            [case(VT_R8)]
+                double              dblVal;
+            [case(VT_CY)]
+                CY                  cyVal;
+            [case(VT_DATE)]
+                DATE                date;
+            [case(VT_FILETIME)]
+                FILETIME            filetime;
+            [case(VT_CLSID)]
+                CLSID *             puuid;
+            [case(VT_BLOB, VT_BLOB_OBJECT)]
+                BLOB                blob;
+            [case(VT_CF)]
+                CLIPDATA            *pclipdata;
+            [case(VT_STREAM, VT_STREAMED_OBJECT)]
+                IStream *           pStream;
+            [case(VT_STORAGE, VT_STORED_OBJECT)]
+                IStorage *          pStorage;
+            [case(VT_BSTR)]
+                BSTR                bstrVal;
+            [case(VT_BSTR_BLOB)]        // System use only
+                BSTRBLOB            bstrblobVal;
+            [case(VT_LPSTR)]
+                LPSTR               pszVal;
+            [case(VT_LPWSTR)]
+                LPWSTR              pwszVal;
+            [case(VT_UI1|VT_VECTOR)]
+                CAUB                caub;
+            [case(VT_I2|VT_VECTOR)]
+                CAI                 cai;
+            [case(VT_UI2|VT_VECTOR)]
+                CAUI                caui;
+            [case(VT_BOOL|VT_VECTOR)]
+                CABOOL              cabool;
+            [case(VT_I4|VT_VECTOR)]
+                CAL                 cal;
+            [case(VT_UI4|VT_VECTOR)]
+                CAUL                caul;
+            [case(VT_R4|VT_VECTOR)]
+                CAFLT               caflt;
+            [case(VT_ERROR|VT_VECTOR)]
+                CASCODE             cascode;
+            [case(VT_I8|VT_VECTOR)]
+                CAH                 cah;
+            [case(VT_UI8|VT_VECTOR)]
+                CAUH                cauh;
+            [case(VT_R8|VT_VECTOR)]
+                CADBL               cadbl;
+            [case(VT_CY|VT_VECTOR)]
+                CACY                cacy;
+            [case(VT_DATE|VT_VECTOR)]
+                CADATE              cadate;
+            [case(VT_FILETIME|VT_VECTOR)]
+                CAFILETIME          cafiletime;
+            [case(VT_CLSID|VT_VECTOR)]
+                CACLSID             cauuid;
+            [case(VT_CF|VT_VECTOR)]
+                CACLIPDATA          caclipdata;
+            [case(VT_BSTR|VT_VECTOR)]
+                CABSTR              cabstr;
+            [case(VT_BSTR_BLOB|VT_VECTOR)]  // System use only
+                CABSTRBLOB          cabstrblob;
+            [case(VT_LPSTR|VT_VECTOR)]
+                CALPSTR             calpstr;
+            [case(VT_LPWSTR|VT_VECTOR)]
+                CALPWSTR            calpwstr;
+            [case(VT_VARIANT|VT_VECTOR)]
+                CAPROPVARIANT       capropvar;
+        };
+    };
+
+    typedef struct tagPROPVARIANT * LPPROPVARIANT;
+
+    cpp_quote("// Reserved global Property IDs")
+    const PROPID PID_DICTIONARY         = 0x00000000;
+    const PROPID PID_CODEPAGE           = 0x00000001;
+    const PROPID PID_FIRST_USABLE       = 0x00000002;
+    const PROPID PID_FIRST_NAME_DEFAULT = 0x00000fff;
+    const PROPID PID_LOCALE             = 0x80000000;
+    const PROPID PID_MODIFY_TIME        = 0x80000001;
+    const PROPID PID_SECURITY           = 0x80000002;
+    const PROPID PID_ILLEGAL            = 0xffffffff;
+
+
+    cpp_quote("// Property IDs for the SummaryInformation Property Set")
+    cpp_quote("")
+    cpp_quote("#define PIDSI_TITLE               0x00000002L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_SUBJECT             0x00000003L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_AUTHOR              0x00000004L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_KEYWORDS            0x00000005L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_COMMENTS            0x00000006L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_TEMPLATE            0x00000007L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_LASTAUTHOR          0x00000008L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_REVNUMBER           0x00000009L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_EDITTIME            0x0000000aL  // VT_FILETIME (UTC)")
+    cpp_quote("#define PIDSI_LASTPRINTED         0x0000000bL  // VT_FILETIME (UTC)")
+    cpp_quote("#define PIDSI_CREATE_DTM          0x0000000cL  // VT_FILETIME (UTC)")
+    cpp_quote("#define PIDSI_LASTSAVE_DTM        0x0000000dL  // VT_FILETIME (UTC)")
+    cpp_quote("#define PIDSI_PAGECOUNT           0x0000000eL  // VT_I4")
+    cpp_quote("#define PIDSI_WORDCOUNT           0x0000000fL  // VT_I4")
+    cpp_quote("#define PIDSI_CHARCOUNT           0x00000010L  // VT_I4")
+    cpp_quote("#define PIDSI_THUMBNAIL           0x00000011L  // VT_CF")
+    cpp_quote("#define PIDSI_APPNAME             0x00000012L  // VT_LPSTR")
+    cpp_quote("#define PIDSI_DOC_SECURITY        0x00000013L  // VT_I4")
+
+    const ULONG PRSPEC_INVALID = 0xffffffff;
+    const ULONG PRSPEC_LPWSTR = 0;
+    const ULONG PRSPEC_PROPID = 1;
+
+    typedef struct tagPROPSPEC
+    {
+
+        ULONG   ulKind;
+        [switch_is(ulKind)] union
+        {
+            [case(PRSPEC_PROPID)]
+                PROPID      propid;
+            [case(PRSPEC_LPWSTR)]
+                LPOLESTR    lpwstr;
+            [default] ;
+        } ;
+
+    } PROPSPEC;
+
+    typedef struct tagSTATPROPSTG
+    {
+
+        LPOLESTR    lpwstrName;
+        PROPID      propid;
+        VARTYPE     vt;
+
+    } STATPROPSTG;
+
+    cpp_quote("// Macros for parsing the OS Version of the Property Set Header")
+    cpp_quote("#define PROPSETHDR_OSVER_KIND(dwOSVer)      HIWORD( (dwOSVer) )")
+    cpp_quote("#define PROPSETHDR_OSVER_MAJOR(dwOSVer)     LOBYTE(LOWORD( (dwOSVer) ))")
+    cpp_quote("#define PROPSETHDR_OSVER_MINOR(dwOSVer)     HIBYTE(LOWORD( (dwOSVer) ))")
+    cpp_quote("#define PROPSETHDR_OSVERSION_UNKNOWN        0xFFFFFFFF")
+
+
+    typedef struct tagSTATPROPSETSTG
+    {
+
+        FMTID       fmtid;
+        CLSID       clsid;
+        DWORD       grfFlags;
+        FILETIME    mtime;
+        FILETIME    ctime;
+        FILETIME    atime;
+        DWORD       dwOSVersion;
+
+    } STATPROPSETSTG;
+
+
+    // When this IDL file is used for "IProp.dll" (the
+    // standalone property set DLL), we must have local
+    // and remotable routines (call_as routines are used
+    // to remove BSTRs, which are not remotable with some
+    // RPC run-times).
+    //
+    // For the remotable routines, we must use pointer
+    // parameters (e.g. "*rgspec" rather than "rgspec[]")
+    // so that the MIDL 2.0 compiler will generate an
+    // interpereted proxy/stub, rather than inline.
+
+#ifdef IPROPERTY_DLL
+    [local]
+#endif
+    HRESULT ReadMultiple(
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          rgpspec[],
+        [out, size_is(cpspec)]
+                PROPVARIANT             rgpropvar[]
+        );
+
+#ifdef IPROPERTY_DLL
+    [call_as(ReadMultiple)]
+    HRESULT RemoteReadMultiple(
+        [out]   BOOL                    *pfBstrPresent,
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          *rgpspec,
+        [out, size_is(cpspec)]
+                PROPVARIANT             *rgpropvar
+        );
+#endif
+
+#ifdef IPROPERTY_DLL
+    [local]
+#endif
+    HRESULT WriteMultiple(
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          rgpspec[],
+        [in, size_is(cpspec)]
+                const PROPVARIANT       rgpropvar[],
+        [in]    PROPID                  propidNameFirst
+        );
+
+#ifdef IPROPERTY_DLL
+    [call_as(WriteMultiple)]
+    HRESULT RemoteWriteMultiple(
+        [in]    BOOL                    fBstrPresent,
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          *rgpspec,
+        [in, size_is(cpspec)]
+                const PROPVARIANT       *rgpropvar,
+        [in]    PROPID                  propidNameFirst
+        );
+#endif
+
+#ifdef IPROPERTY_DLL
+    [local]
+#endif
+    HRESULT DeleteMultiple(
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          rgpspec[]
+        );
+
+#ifdef IPROPERTY_DLL
+    [call_as(DeleteMultiple)]
+    HRESULT RemoteDeleteMultiple(
+        [in]    ULONG                   cpspec,
+        [in, size_is(cpspec)]
+                const PROPSPEC          *rgpspec
+        );
+#endif
+
+    HRESULT ReadPropertyNames(
+        [in]    ULONG                   cpropid,
+        [in, size_is(cpropid)]
+                const PROPID            rgpropid[],
+        [out, size_is(cpropid)]
+                LPOLESTR                rglpwstrName[]
+        );
+
+    HRESULT WritePropertyNames(
+        [in]    ULONG                   cpropid,
+        [in, size_is(cpropid)]
+                const PROPID            rgpropid[],
+        [in, size_is(cpropid)]
+                const LPOLESTR          rglpwstrName[]
+        );
+
+    HRESULT DeletePropertyNames(
+        [in]    ULONG                   cpropid,
+        [in, size_is(cpropid)]
+                const PROPID            rgpropid[]
+        );
+
+    HRESULT Commit(
+        [in]    DWORD                   grfCommitFlags
+        );
+
+    HRESULT Revert();
+
+    HRESULT Enum(
+        [out]   IEnumSTATPROPSTG **     ppenum
+        );
+
+    HRESULT SetTimes(
+        [in]    FILETIME const *        pctime,
+        [in]    FILETIME const *        patime,
+        [in]    FILETIME const *        pmtime
+        );
+
+    HRESULT SetClass(
+        [in]    REFCLSID                clsid
+        );
+
+    HRESULT Stat(
+        [out]   STATPROPSETSTG *        pstatpsstg
+        );
+}
+
+[
+    object,
+    uuid(0000013A-0000-0000-C000-000000000046),
+    pointer_default(unique)
+]
+
+interface IPropertySetStorage : IUnknown
+{
+
+    typedef [unique] IPropertySetStorage * LPPROPERTYSETSTORAGE;
+
+    HRESULT Create(
+        [in]    REFFMTID                rfmtid,
+        [in, unique]
+                const CLSID *           pclsid,
+        [in]    DWORD                   grfFlags,
+        [in]    DWORD                   grfMode,
+        [out]   IPropertyStorage **     ppprstg
+        );
+
+    HRESULT Open(
+        [in]    REFFMTID                rfmtid,
+        [in]    DWORD                   grfMode,
+        [out]   IPropertyStorage **     ppprstg
+        );
+
+    HRESULT Delete(
+        [in]    REFFMTID                rfmtid
+        );
+
+    HRESULT Enum(
+        [out]   IEnumSTATPROPSETSTG **  ppenum
+        );
+
+}
+
+
+[
+    object,
+    uuid(00000139-0000-0000-C000-000000000046),
+    pointer_default(unique)
+]
+
+interface IEnumSTATPROPSTG : IUnknown
+{
+
+    typedef [unique] IEnumSTATPROPSTG * LPENUMSTATPROPSTG;
+
+    [local]
+    HRESULT Next(
+        [in]    ULONG                   celt,
+        [out, size_is(celt), length_is(*pceltFetched)]
+                STATPROPSTG *           rgelt,
+        [out]   ULONG *                 pceltFetched
+        );
+
+    [call_as(Next)]
+    HRESULT RemoteNext(
+        [in]    ULONG                   celt,
+        [out, size_is(celt), length_is(*pceltFetched)]
+                STATPROPSTG *           rgelt,
+        [out]   ULONG *                 pceltFetched
+        );
+
+    HRESULT Skip(
+        [in]    ULONG                   celt
+        );
+
+    HRESULT Reset();
+
+    HRESULT Clone(
+        [out]   IEnumSTATPROPSTG **     ppenum
+        );
+}
+
+
+[
+    object,
+    uuid(0000013B-0000-0000-C000-000000000046),
+    pointer_default(unique)
+]
+
+interface IEnumSTATPROPSETSTG : IUnknown
+{
+
+    typedef [unique] IEnumSTATPROPSETSTG * LPENUMSTATPROPSETSTG;
+
+    [local]
+    HRESULT Next(
+        [in]    ULONG                   celt,
+        [out, size_is(celt), length_is(*pceltFetched)]
+                STATPROPSETSTG *        rgelt,
+        [out]   ULONG *                 pceltFetched
+        );
+
+    [call_as(Next)]
+    HRESULT RemoteNext(
+        [in]    ULONG                   celt,
+        [out, size_is(celt), length_is(*pceltFetched)]
+                STATPROPSETSTG *        rgelt,
+        [out]   ULONG *                 pceltFetched
+        );
+
+    HRESULT Skip(
+        [in]    ULONG                   celt
+        );
+
+    HRESULT Reset();
+
+    HRESULT Clone(
+        [out]   IEnumSTATPROPSETSTG **  ppenum
+        );
+}
+
+
+cpp_quote("WINOLEAPI PropVariantCopy ( PROPVARIANT * pvarDest, const PROPVARIANT * pvarSrc );")
+cpp_quote("WINOLEAPI PropVariantClear ( PROPVARIANT * pvar );")
+cpp_quote("WINOLEAPI FreePropVariantArray ( ULONG cVariants, PROPVARIANT * rgvars );")
+
+cpp_quote("")
+cpp_quote("#define _PROPVARIANTINIT_DEFINED_")
+cpp_quote("#   ifdef __cplusplus")
+cpp_quote("inline void PropVariantInit ( PROPVARIANT * pvar )")
+cpp_quote("{")
+cpp_quote("    memset ( pvar, 0, sizeof(PROPVARIANT) );")
+cpp_quote("}")
+cpp_quote("#   else")
+cpp_quote("#   define PropVariantInit(pvar) memset ( pvar, 0, sizeof(PROPVARIANT) )")
+cpp_quote("#   endif")
+cpp_quote("")
+
+cpp_quote("")
+cpp_quote("#ifndef _STGCREATEPROPSTG_DEFINED_")
+cpp_quote("WINOLEAPI StgCreatePropStg( IUnknown* pUnk, REFFMTID fmtid, const CLSID *pclsid, DWORD grfFlags, DWORD dwReserved, IPropertyStorage **ppPropStg );")
+cpp_quote("WINOLEAPI StgOpenPropStg( IUnknown* pUnk, REFFMTID fmtid, DWORD grfFlags, DWORD dwReserved, IPropertyStorage **ppPropStg );")
+cpp_quote("WINOLEAPI StgCreatePropSetStg( IStorage *pStorage, DWORD dwReserved, IPropertySetStorage **ppPropSetStg);")
+
+cpp_quote("")
+cpp_quote("#define CCH_MAX_PROPSTG_NAME    31")
+cpp_quote("WINOLEAPI FmtIdToPropStgName( const FMTID *pfmtid, LPOLESTR oszName );" )
+cpp_quote("WINOLEAPI PropStgNameToFmtId( const LPOLESTR oszName, FMTID *pfmtid );" )
+cpp_quote("#endif")
+
+	*/
+
+/****************************************************************************
+ *  Connection Point Interfaces
+ ****************************************************************************/
+ /*
+#ifdef __INCLUDE_CPIFS
+interface IConnectionPointContainer;
+interface IConnectionPoint;
+interface IEnumConnections;
+interface IEnumConnectionPoints;
+
+[
+    object,
+    uuid(B196B286-BAB4-101A-B69C-00AA00341D07),
+    pointer_default(unique)
+]
+interface IConnectionPoint : IUnknown
+{
+    typedef IConnectionPoint * PCONNECTIONPOINT;
+    typedef IConnectionPoint * LPCONNECTIONPOINT;
+
+    HRESULT GetConnectionInterface
+    (
+        [out]           IID * piid
+    );
+
+    HRESULT GetConnectionPointContainer
+    (
+        [out]           IConnectionPointContainer ** ppCPC
+    );
+
+    HRESULT Advise
+    (
+        [in]    IUnknown * pUnkSink,
+        [out]   DWORD *    pdwCookie
+    );
+
+    HRESULT Unadvise
+    (
+        [in]    DWORD dwCookie
+    );
+
+    HRESULT EnumConnections
+    (
+        [out]   IEnumConnections ** ppEnum
+    );
+}
+
+[
+    object,
+    uuid(B196B284-BAB4-101A-B69C-00AA00341D07),
+    pointer_default(unique)
+]
+interface IConnectionPointContainer : IUnknown
+{
+    typedef IConnectionPointContainer * PCONNECTIONPOINTCONTAINER;
+    typedef IConnectionPointContainer * LPCONNECTIONPOINTCONTAINER;
+
+    HRESULT EnumConnectionPoints
+    (
+        [out]   IEnumConnectionPoints ** ppEnum
+    );
+
+    HRESULT FindConnectionPoint
+    (
+        [in]    REFIID riid,
+        [out]   IConnectionPoint ** ppCP
+    );
+}
+
+
+[
+    object,
+    uuid(B196B287-BAB4-101A-B69C-00AA00341D07),
+    pointer_default(unique)
+]
+interface IEnumConnections : IUnknown
+{
+    typedef IEnumConnections * PENUMCONNECTIONS;
+    typedef IEnumConnections * LPENUMCONNECTIONS;
+
+    typedef struct tagCONNECTDATA
+    {
+        IUnknown *  pUnk;
+        DWORD       dwCookie;
+    } CONNECTDATA;
+
+    typedef struct tagCONNECTDATA * PCONNECTDATA;
+    typedef struct tagCONNECTDATA * LPCONNECTDATA;
+
+    [local]
+    HRESULT Next(
+        [in]                        ULONG           cConnections,
+        [out,
+         size_is(cConnections),
+         length_is(*lpcFetched)]    CONNECTDATA *   rgcd,
+        [out]                       ULONG *         lpcFetched
+    );
+
+    [call_as(Next)]
+    HRESULT RemoteNext(
+        [in]                            ULONG           cConnections,
+        [out,
+         size_is(cConnections),
+         length_is(*lpcFetched)]        CONNECTDATA *   rgcd,
+        [out]                           ULONG *         lpcFetched
+    );
+
+    HRESULT Skip
+    (
+        [in]    ULONG cConnections
+    );
+
+    HRESULT Reset
+    (
+        void
+    );
+
+    HRESULT Clone
+    (
+        [out]   IEnumConnections ** ppEnum
+    );
+}
+
+
+[
+    object,
+    uuid(B196B285-BAB4-101A-B69C-00AA00341D07),
+    pointer_default(unique)
+]
+interface IEnumConnectionPoints : IUnknown
+{
+    typedef IEnumConnectionPoints * PENUMCONNECTIONPOINTS;
+    typedef IEnumConnectionPoints * LPENUMCONNECTIONPOINTS;
+
+    [local]
+    HRESULT Next(
+        [in]                        ULONG               cConnections,
+        [out,
+         size_is(cConnections),
+         length_is(*lpcFetched)]    IConnectionPoint ** rgpcn,
+        [out]                       ULONG *             lpcFetched
+    );
+
+    [call_as(Next)]
+    HRESULT RemoteNext(
+        [in]                        ULONG               cConnections,
+        [out,
+         size_is(cConnections),
+         length_is(*lpcFetched)]    IConnectionPoint ** rgpcn,
+        [out]                       ULONG *             lpcFetched
+    );
+
+    HRESULT Skip
+    (
+        [in]    ULONG   cConnections
+    );
+
+    HRESULT Reset
+    (
+        void
+    );
+
+    HRESULT Clone
+    (
+        [out]   IEnumConnectionPoints **    ppEnum
+    );
+}
+#endif // __INCLUDE_CPIFS
+
+
+cpp_quote( "#if  (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM" )
+cpp_quote( "// This interface is only valid on Windows NT 4.0" )
+
+[
+    local,
+    object,
+    uuid(0000013D-0000-0000-C000-000000000046)
+]
+interface IClientSecurity : IUnknown
+{
+
+    typedef struct tagSOLE_AUTHENTICATION_SERVICE
+    {
+        DWORD    dwAuthnSvc;
+        DWORD    dwAuthzSvc;
+        OLECHAR *pPrincipalName;
+        HRESULT  hr;
+    } SOLE_AUTHENTICATION_SERVICE;
+
+    typedef SOLE_AUTHENTICATION_SERVICE *PSOLE_AUTHENTICATION_SERVICE;
+
+    typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES
+    {
+        EOAC_NONE           = 0x0,
+        EOAC_MUTUAL_AUTH    = 0x1,
+        EOAC_CLOAKING       = 0x10,
+
+        // These are only valid for CoInitializeSecurity
+        EOAC_SECURE_REFS    = 0x2,
+        EOAC_ACCESS_CONTROL = 0x4,
+        EOAC_APPID          = 0x8
+    } EOLE_AUTHENTICATION_CAPABILITIES;
+
+    HRESULT QueryBlanket
+    (
+        [in]  IUnknown                *pProxy,
+        [out] DWORD                   *pAuthnSvc,
+        [out] DWORD                   *pAuthzSvc,
+        [out] OLECHAR                **pServerPrincName,
+        [out] DWORD                   *pAuthnLevel,
+        [out] DWORD                   *pImpLevel,
+        [out] void                   **pAuthInfo,
+        [out] DWORD                   *pCapabilites
+    );
+
+    HRESULT SetBlanket
+    (
+        [in] IUnknown                 *pProxy,
+        [in] DWORD                     AuthnSvc,
+        [in] DWORD                     AuthzSvc,
+        [in] OLECHAR                  *pServerPrincName,
+        [in] DWORD                     AuthnLevel,
+        [in] DWORD                     ImpLevel,
+        [in] void                     *pAuthInfo,
+        [in] DWORD                     Capabilities
+    );
+
+    HRESULT CopyProxy
+    (
+        [in]  IUnknown  *pProxy,
+        [out] IUnknown **ppCopy
+    );
+}
+
+[
+    local,
+    object,
+    uuid(0000013E-0000-0000-C000-000000000046)
+]
+interface IServerSecurity : IUnknown
+{
+    HRESULT QueryBlanket
+    (
+        [out] DWORD    *pAuthnSvc,
+        [out] DWORD    *pAuthzSvc,
+        [out] OLECHAR **pServerPrincName,
+        [out] DWORD    *pAuthnLevel,
+        [out] DWORD    *pImpLevel,
+        [out] void    **pPrivs,
+        [out] DWORD    *pCapabilities
+    );
+
+    HRESULT ImpersonateClient();
+
+    HRESULT RevertToSelf();
+
+    BOOL IsImpersonating();
+}
+
+[
+    object,
+    uuid(00000140-0000-0000-C000-000000000046)
+]
+
+interface IClassActivator : IUnknown
+{
+    HRESULT GetClassObject(
+        [in] REFCLSID rclsid,
+        [in] DWORD dwClassContext,
+        [in] LCID locale,
+        [in] REFIID riid,
+        [out, iid_is(riid)] void **ppv);
+}
+
+
+[
+object,
+local,
+uuid(00000144-0000-0000-C000-000000000046),
+oleautomation
+]
+interface IRpcOptions : IUnknown
+{
+    HRESULT Set([in] IUnknown * pPrx,
+                [in] DWORD dwProperty,
+                [in] DWORD dwValue);
+
+    HRESULT Query([in] IUnknown * pPrx,
+                  [in] DWORD dwProperty,
+                  [out] DWORD * pdwValue);
+
+    HRESULT CopyProxy([in] IUnknown * punkProxy,
+                      [out] IUnknown ** ppunkCopy);
+}
+
+enum {COMBND_RPCSTRINGS = 0x01};  // flag indicating arBndInfo is the
+                                  // Rpc string bindings to be used.
+
+[
+object,
+local,
+uuid(00000148-0000-0000-C000-000000000046)
+]
+interface IComBinding : IUnknown
+{
+  HRESULT InitBinding([in]    DWORD    dwEndpointFlags,
+                      [in]    DWORD    dwNICFlags,
+                      [in]    DWORD    mbzReserved1,
+                      [in]    DWORD    mbzReserved2,
+                      [in]    LPOLESTR pszBinding
+	              );
+
+  HRESULT QueryBinding([out]    LPDWORD    pdwEndpointFlags,
+                       [out]    LPDWORD    pdwNICFlags,
+                       [out]    LPDWORD    mbzReserved1,
+                       [out]    LPDWORD    mbzReserved2,
+                       [out]    LPOLESTR  *ppszBinding
+	              );
+
+
+}
+
+
+
+
+cpp_quote( "#endif //DCOM" )
+
+
+[
+    object,
+    uuid(99caf010-415e-11cf-8814-00aa00b569f5),
+    pointer_default(unique)
+]
+
+interface IFillLockBytes: IUnknown
+{
+    [local]
+    HRESULT FillAppend
+    (
+        [in, size_is(cb)] void const *pv,
+        [in] ULONG cb,
+        [out] ULONG *pcbWritten
+    );
+
+    [call_as(FillAppend)]
+    HRESULT _stdcall RemoteFillAppend(
+        [in, size_is(cb)] byte const *pv,
+        [in] ULONG cb,
+        [out] ULONG *pcbWritten);
+
+    [local]
+    HRESULT FillAt
+    (
+        [in] ULARGE_INTEGER ulOffset,
+        [in, size_is(cb)] void const *pv,
+        [in] ULONG cb,
+        [out] ULONG *pcbWritten
+    );
+
+    [call_as(FillAt)]
+    HRESULT _stdcall RemoteFillAt(
+        [in] ULARGE_INTEGER ulOffset,
+        [in, size_is(cb)] byte const *pv,
+        [in] ULONG cb,
+        [out] ULONG *pcbWritten);
+
+    HRESULT SetFillSize
+    (
+        [in] ULARGE_INTEGER ulSize
+    );
+
+    HRESULT Terminate
+    (
+        [in] BOOL bCanceled
+    );
+}
+
+
+[
+    object,
+    uuid(a9d758a0-4617-11cf-95fc-00aa00680db4),
+    pointer_default(unique)
+]
+
+interface IProgressNotify: IUnknown
+{
+    HRESULT OnProgress
+    (
+        [in] DWORD dwProgressCurrent,
+        [in] DWORD dwProgressMaximum,
+        [in] BOOL  fAccurate,
+        [in] BOOL  fOwner
+    );
+}
+
+
+[
+    local,
+    object,
+    uuid(0e6d4d90-6738-11cf-9608-00aa00680db4),
+    pointer_default(unique)
+]
+
+interface ILayoutStorage: IUnknown
+{
+        typedef struct tagStorageLayout
+        {
+            DWORD LayoutType;
+            OLECHAR *pwcsElementName;
+            LARGE_INTEGER cOffset;
+            LARGE_INTEGER cBytes;
+        } StorageLayout;
+
+        HRESULT __stdcall LayoutScript
+        (
+            [in] StorageLayout *pStorageLayout,
+            [in] DWORD nEntries,
+            [in] DWORD glfInterleavedFlag
+        );
+        HRESULT __stdcall BeginMonitor(void);
+
+        HRESULT __stdcall EndMonitor(void);
+
+        HRESULT __stdcall ReLayoutDocfile
+        (
+            [in] OLECHAR *pwcsNewDfName
+        );
+
+        HRESULT __stdcall ReLayoutDocfileOnILockBytes
+        (
+            [in] ILockBytes *pILockBytes
+        );
+
+
+}
+
+[
+ uuid(00000022-0000-0000-C000-000000000046),
+ version(1.0),
+ pointer_default(unique)
+  , object
+]
+
+interface ISurrogate : IUnknown
+{
+    typedef [unique] ISurrogate* LPSURROGATE;
+
+        HRESULT LoadDllServer(
+                [in] REFCLSID           Clsid);
+        HRESULT FreeSurrogate();
+}
+
+
+[
+    local,
+    object,
+    uuid(00000146-0000-0000-C000-000000000046)
+]
+interface IGlobalInterfaceTable : IUnknown
+{
+    typedef [unique] IGlobalInterfaceTable *LPGLOBALINTERFACETABLE;
+
+    HRESULT RegisterInterfaceInGlobal
+    (
+        [in]  IUnknown *pUnk,
+        [in]  REFIID    riid,
+        [out] DWORD    *pdwCookie
+    );
+
+    HRESULT RevokeInterfaceFromGlobal
+    (
+        [in] DWORD      dwCookie
+    );
+
+    HRESULT GetInterfaceFromGlobal
+    (
+        [in]  DWORD          dwCookie,
+        [in]  REFIID         riid,
+        [out, iid_is(riid)] void **ppv
+    );
+};
+
+
+[
+    object,
+    uuid(0e6d4d92-6738-11cf-9608-00aa00680db4),
+    pointer_default(unique)
+]
+
+interface IDirectWriterLock : IUnknown
+{
+
+    HRESULT WaitForWriteAccess ([in] DWORD dwTimeout);
+
+    HRESULT ReleaseWriteAccess ();
+
+    HRESULT HaveWriteAccess ();
+
+}
+
+[
+    object,
+    uuid(00000023-0000-0000-C000-000000000046)
+]
+
+interface ISynchronize : IUnknown
+{
+    HRESULT Wait([in] DWORD dwMilliseconds);
+    HRESULT Signal();
+    HRESULT Reset();
+}
+
+[
+ local,
+ object,
+ uuid(00000025-0000-0000-C000-000000000046)
+]
+interface ISynchronizeMutex : ISynchronize
+{
+    HRESULT ReleaseMutex();
+}
+
+[
+ local,
+ object,
+ uuid(00000024-0000-0000-C000-000000000046)
+]
+interface IAsyncSetup : IUnknown
+{
+    HRESULT GetAsyncManager( [in]  REFIID           riid,
+                             [in]  IUnknown        *pOuter,
+                             [in]  DWORD            dwFlags,
+                             [out] IUnknown       **ppInner,
+                             [out] IAsyncManager  **ppAsyncMgr );
+}
+
+[
+ local,
+ object,
+ uuid(00000029-0000-0000-C000-000000000046)
+]
+
+interface ICancelMethodCalls : IUnknown
+{
+    typedef [unique] ICancelMethodCalls *LPCANCELMETHODCALLS;
+
+    HRESULT Cancel          (void);
+    HRESULT TestCancel      (void);
+    HRESULT SetCancelTimeout([in] ULONG ulSeconds);
+}
+
+[
+ local,
+ object,
+ uuid(0000002A-0000-0000-C000-000000000046)
+]
+interface IAsyncManager : IUnknown
+{
+    typedef enum tagDCOM_CALL_STATE
+    {
+        DCOM_NONE           = 0x0,
+        DCOM_CALL_COMPLETE  = 0x1,
+        DCOM_CALL_CANCELED  = 0x2,
+    } DCOM_CALL_STATE;
+
+    HRESULT CompleteCall  ( [in] HRESULT Result );
+    HRESULT GetCallContext( [in] REFIID riid, [out] void **pInterface );
+    HRESULT GetState      ( [out] ULONG *pulStateFlags);
+}
+
+[
+ local,
+ object,
+ uuid(0000002B-0000-0000-C000-000000000046)
+]
+interface IWaitMultiple : IUnknown
+{
+    HRESULT WaitMultiple  ( [in] DWORD timeout, [out] ISynchronize **pSync );
+    HRESULT AddSynchronize( [in] ISynchronize *pSync );
+}
+
+[
+ local,
+ object,
+ uuid(0000002C-0000-0000-C000-000000000046)
+]
+interface ISynchronizeEvent : IUnknown
+{
+    HRESULT GetEvent( [out] HANDLE *pEvent );
+}
+
+[
+ object,
+ uuid(00000026-0000-0000-C000-000000000046)
+]
+interface IUrlMon : IUnknown
+{
+    HRESULT AsyncGetClassBits(
+        [in]         REFCLSID   rclsid,
+        [in, unique] LPCWSTR    pszTYPE,
+        [in, unique] LPCWSTR    pszExt,
+        [in]         DWORD      dwFileVersionMS,
+        [in]         DWORD      dwFileVersionLS,
+        [in, unique] LPCWSTR    pszCodeBase,
+        [in]         IBindCtx * pbc,
+        [in]         DWORD      dwClassContext,
+        [in]         REFIID     riid,
+        [in]         DWORD      flags);
+}
+
+//----------------------------------------------------------------------------
+// The Class Store Access Interface.
+//----------------------------------------------------------------------------
+[
+  object,
+  uuid(00000190-0000-0000-C000-000000000046)
+]
+interface IClassAccess : IUnknown
+{
+
+// This is the most common method to access the Class Container.
+// It queries the Class Store for implementations for a specific
+// Class Id.
+// If a matching implementation is available for the object type,
+// client architecture, locale and class context a pointer to the
+// binary is returned along with other package info in the [out] parameter
+// pPackageInfo.
+//
+// If the binary needs to be downloaded to the local machine, it is
+// done as a part of this.
+//
+    HRESULT   GetClassInfo(
+          [in]    REFCLSID          clsid,             // Class ID
+          [in]    QUERYCONTEXT      QryContext,        // Query Attributes
+          [out]   PACKAGEINFO   *   pPackageInfo
+    );
+
+//
+// GetClassSpecInfo is same as GetClassInfo except for it takes in
+//  any Class Specifier , CLSID or File Ext, or ProgID or MIME type.
+//
+    HRESULT   GetClassSpecInfo(
+          [in]    uCLSSPEC      *   pClassSpec,        // Class Spec (CLSID/Ext/MIME)
+          [in]    QUERYCONTEXT      QryContext,        // Query Attributes
+          [out]   PACKAGEINFO   *   pPackageInfo
+    );
+
+
+//
+// GetInstallablePackages is used by CoGetPublishedAppInfo
+// to provide list of published apps from the class store that are
+// available for installation.
+//
+
+typedef struct tagPUBLISHEDINFOLIST {
+        DWORD            cPublApps;
+        [size_is(cPublApps), unique] PUBLISHEDAPPINFO    *pPublAppInfo;
+} PUBLISHEDINFOLIST;
+
+    HRESULT   GetInstallablePackages (
+          [in]    DWORD               Count,
+          [out]   PUBLISHEDINFOLIST   *pInfoList
+    );
+
+}
+
+[
+  object,
+  uuid(00000192-0000-0000-C000-000000000046)
+]
+interface IClassRefresh : IUnknown
+{
+//
+// GetUpgrades is called to check if the Class Store has
+// newer versions for any of a list of CLSIDs. The client calls this
+// with a list of CLSIDs that were installed from the Class Container.
+//
+
+typedef struct tagPACKAGEINFOLIST {
+        DWORD            cPackInfo;
+        [size_is(cPackInfo), unique] PACKAGEINFO    *pPackageInfo;
+} PACKAGEINFOLIST;
+
+    HRESULT   GetUpgrades (
+        [in]    ULONG                   cClasses,
+        [in, size_is(cClasses)] CLSID   *pClassList,     // CLSIDs Installed
+        [in]    CSPLATFORM              Platform,
+        [in]    LCID                    Locale,
+        [out]   PACKAGEINFOLIST         *pPackageInfoList);
+
+//
+// CommitUpgrades is called to notify the Class Store that
+// the newer versions were successfully installed and that the update sequence
+// can be moved forward.
+//
+
+    HRESULT   CommitUpgrades ();
+}
+
+
+//----------------------------------------------------------------------------
+// The Class Store Admin Interface.
+//----------------------------------------------------------------------------
+
+typedef struct tagCLASSDETAIL {
+               CLSID                Clsid;
+               LPOLESTR             pszDesc;
+               LPOLESTR             pszIconPath;
+               CLSID                TreatAsClsid;
+               CLSID                AutoConvertClsid;
+               DWORD                cFileExt;
+               [size_is(cFileExt)] LPOLESTR  *prgFileExt;
+               LPOLESTR             pMimeType;
+               LPOLESTR             pDefaultProgId;
+               DWORD                cOtherProgId;
+               [size_is(cOtherProgId)] LPOLESTR  *prgOtherProgId;
+} CLASSDETAIL;
+
+//+---------------------------------------------------------------------------
+//    Contents:        Enum Interfaces for Class Store
+//----------------------------------------------------------------------------
+cpp_quote("#ifndef _LPCSADMNENUM_DEFINED")
+cpp_quote("#define _LPCSADMNENUM_DEFINED")
+
+//
+//  IEnumPackage
+//  ============
+//
+
+[
+  object,
+  uuid(00000193-0000-0000-C000-000000000046)
+]
+interface IEnumPackage : IUnknown
+{
+
+//---- Next()
+
+    HRESULT Next(
+        [in]        ULONG celt,
+        [out, size_is(celt), length_is(*pceltFetched)] PACKAGEDETAIL *rgelt,
+        [out]       ULONG *pceltFetched);
+
+//
+//    celt             number of elements to be fetched.
+//    rgelt            array of PackageDetail structures.
+//    pceltFetched     elements actually fetched.
+//
+// Returns:
+//        S_OK
+//        S_FALSE            (Not enough elements to be fetched.)
+//        E_INVALIDARG
+//        E_FAIL
+//        CS_E_INVALID_VERSION (Class Container is corrupted
+//                              OR is of a version that is no more supported)
+//        E_OUTOFMEMORY
+//
+//    on errors
+//        *pceltFetched = 0
+//
+
+
+//---- Skip()
+
+    HRESULT Skip(
+        [in]        ULONG celt);
+
+//
+//    celt            number of elements to be skipped.
+//
+// Returns:
+//        S_OK
+//        S_FALSE            (Not enough elements to be skipped.)
+//        E_FAIL
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+
+
+//---- Reset()
+
+    HRESULT Reset();
+
+//
+// Returns:
+//        S_OK
+//
+
+
+//---- Clone()
+
+    HRESULT Clone(
+        [out]       IEnumPackage **ppenum);
+
+//
+// Returns:
+//        S_OK
+//        E_FAIL
+//        E_INVALIDARG
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+
+
+}
+
+
+//
+//  IEnumClass
+//  ==========
+//
+
+[
+  object,
+  uuid(00000194-0000-0000-C000-000000000046)
+]
+
+interface IEnumClass : IUnknown
+{
+//---- Next()
+
+    HRESULT Next(
+        [in]        ULONG celt,
+        [out, size_is(celt), length_is(*pceltFetched)] CLASSDETAIL *rgelt,
+        [out]       ULONG *pceltFetched);
+
+//
+//    celt             number of elements to be fetched.
+//    rgelt            array of CLASSDETAIL structures.
+//    pceltFetched     elements actually fetched.
+//
+// Returns:
+//        S_OK
+//        S_FALSE            (Not enough elements to be fetched.)
+//        E_INVALIDARG
+//        E_FAIL
+//        CS_E_INVALID_VERSION (Class Container is corrupted
+//                              OR is of a version that is no more supported)
+//        E_OUTOFMEMORY
+//
+//    on errors
+//        *pceltFetched = 0
+//
+
+//---- Skip()
+
+    HRESULT Skip(
+        [in]        ULONG celt);
+
+//
+//    celt            number of elements to be skipped.
+//
+// Returns:
+//        S_OK
+//        S_FALSE            (Not enough elements to be skipped.)
+//        E_FAIL
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+
+//---- Reset()
+
+    HRESULT Reset();
+
+//
+// Returns:
+//        S_OK
+//
+
+
+//---- Clone()
+
+    HRESULT Clone(
+        [out]       IEnumClass **ppenum);
+
+//
+// Returns:
+//        S_OK
+//        E_FAIL
+//        E_INVALIDARG
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+
+
+
+}
+cpp_quote("#endif")
+
+//
+//  IClassAdmin
+//  ===========
+//
+
+
+[
+  object,
+  uuid(00000191-0000-0000-C000-000000000046)
+]
+interface IClassAdmin : IUnknown
+{
+
+// ::NewClass
+// -----------
+// Stores a new Class Definition in the Class Store
+// Corresponds to HKCR/{CLSID} in registry
+// [In] - CLSID
+//                Class Name
+//                TreatAs CLSID (NULL GUID if no TreatAs)
+//                AutoConvert CLSID (NULL GUID if no AutoConvert)
+//                File Extension (NULL if no association)
+//                Mime Type (NULL if no association)
+//                Default ProgId (NULL if no association)
+//                Other ProgIds
+//                TypelibID
+//                Icon Path (NULL if none).
+//
+// Returns - S_OK
+//                     E_ALREADY_EXISTS
+//                     E_INVALIDARG
+//
+    HRESULT    NewClass (
+        [in]        CLASSDETAIL *pClassDetail
+        );
+
+// ::DeleteClass
+// -----------
+// Removes a Class Definition from the Class Store
+// [In] - CLSID
+
+    HRESULT    DeleteClass (
+        [in]        REFCLSID      guidClsId
+        );
+
+
+// ::NewInterface
+// --------------
+// Stores a new Interface Definition in the Class Store
+// Corresponds to HKCR/{IID} in registry
+// [In] - IID
+//                Interface Name
+//                Proxy-Stub CLSID (NULL GUID if no ProxyStub)
+//                TypeLib GUID (NULL GUID if no TypeLib)
+//
+// Returns - S_OK
+//                     E_ALREADY_EXISTS
+//                     E_INVALID_ARG
+//
+    HRESULT    NewInterface (
+        [in]        REFIID      iid,
+        [in, unique] LPOLESTR   pszDesc,
+        [in]        REFCLSID    psclsid,
+        [in]        REFCLSID    typelibid
+        );
+
+// ::DeleteInterface
+// -----------
+// Removes an Interface Definition from the Class Store
+// [In] - IID
+
+    HRESULT    DeleteInterface (
+        [in]        REFIID      iid
+        );
+
+
+// ::NewPackage
+// ------------
+// Stores a new application package in the Class Store
+// May Correspond to HKCR/{CLSID}/LocalServer32 likes in registry
+//
+// Returns - S_OK
+//                     E_ALREADY_EXISTS
+//                     E_INVALIDARG
+//
+    HRESULT    NewPackage (
+        [in]        PACKAGEDETAIL *pPackageDetail
+        );
+
+
+// ::DeletePackage
+// -----------
+// Removes a package from the Class Store
+// [In] - PackageName
+
+    HRESULT    DeletePackage (
+        [in]        LPOLESTR       pszPackageName
+        );
+
+// ::GetClassesEnum()
+//
+// Returns the clsid enumerator
+// for browsing classes defined in the class store.
+//
+// Returns:
+//        S_OK
+//        E_INVALIDARG
+//        E_FAIL
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+//
+//
+//  The value of the enumerator is NULL for all the error conditions.
+//
+
+    HRESULT    GetClassesEnum(
+        [out]       IEnumClass **ppIEnumClass
+    );
+
+
+
+// ::GetPackagesEnum()
+//
+//        Getting the Package enumerator from the classstore.
+//
+//        guidClsid:    All the apps that implements the clsid.
+//                        ignored if NULLGUID.
+//        Vendor:       All the apps provided by a given Vendor.
+//                        ignored if NULL.
+//
+//        ppIEnumPackage: NULL if there is any error.
+//
+// Returns:
+//        S_OK
+//        E_INVALIDARG
+//        E_FAIL
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+//
+// The value of the enumerator is NULL for all the error conditions.
+//
+
+    HRESULT    GetPackagesEnum(
+        [in]         REFCLSID         guidClsid,
+        [in, unique] LPOLESTR         pszVendor,
+        [in]         CSPLATFORM       Platform,
+        [in]         DWORD            dwContext,
+        [in]         LCID             Locale,
+        [out]        IEnumPackage    **ppIEnumPackage
+        );
+
+
+// ::GetClassDetails()
+//
+// Get all the class details given the clsid.
+//
+//    [in]      guidClsID    class ID (guid)
+//    [out]     CLASSDETAIL     *pClassDetail
+//
+// Returns:
+//        S_OK
+//        E_INVALIDARG
+//        E_FAIL
+//        E_NOTFOUND            (no such class)
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+//
+//
+
+
+
+    HRESULT    GetClassDetails (
+        [in]        REFCLSID            guidClsId,
+        [out]       CLASSDETAIL         *pClassDetail
+        );
+
+
+// ::GetIidDetails()
+//
+//    [IN]
+//        iid            IID (guid)
+//    [OUT]
+//        pszDesc         Description
+//        psClsid         Proxy Stub Class ID
+//        pTypeLibId      libid
+//
+// Returns:
+//        S_OK
+//        E_INVALIDARG
+//        E_FAIL
+//        E_NOTFOUND
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+//
+//
+
+    HRESULT GetIidDetails (
+        [in]        REFIID           iid,
+        [out]       LPOLESTR        *ppszDesc,
+        [out]       CLSID           *psClsid,
+        [out]       CLSID           *pTypeLibId
+        );
+
+// ::GetPackageDetails()
+//
+// Get all the Package details given packagename.
+//
+//    [IN]
+//          PackageName: Name of the package
+//    [OUT]
+//          pPackageDetail  Package Detail
+//
+// Returns:
+//        S_OK
+//        E_INVALIDARG
+//        E_FAIL
+//        E_NOTFOUND            (no such class)
+//        E_ACCESSDENIED
+//        E_OUTOFMEMORY
+//
+//
+
+
+    HRESULT    GetPackageDetails (
+        [in]        LPOLESTR             pszPackageName,
+        [out]       PACKAGEDETAIL       *pPackageDetail
+        );
+}
+
+cpp_quote("#if ( _MSC_VER >= 800 )")
+cpp_quote("#pragma warning(default:4201)")
+cpp_quote("#endif")
+
+	*/
+
+} // extern (Windows)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/OLEIDL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,479 @@
+module org.eclipse.swt.internal.ole.win32.OLEIDL;
+//+-------------------------------------------------------------------------
+//
+//  Microsoft Windows
+//  Copyright (C) Microsoft Corporation, 1992-1997.
+//
+//  File: oadvhr.idl
+//
+//--------------------------------------------------------------------------
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.internal.ole.win32.extras;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+
+extern( Windows ) {
+//interface IOleInPlaceActiveObject;
+//interface IEnumOLEVERB;
+
+interface IOleAdviseHolder : IUnknown
+{
+    HRESULT Advise( IAdviseSink pAdvise, DWORD * pdwConnection );
+    HRESULT Unadvise( DWORD dwConnection );
+    HRESULT EnumAdvise ( IEnumSTATDATA ppenumAdvise );
+    HRESULT SendOnRename( IMoniker pmk );
+    HRESULT SendOnSave();
+    HRESULT SendOnClose();
+}
+alias IOleAdviseHolder LPOLEADVISEHOLDER;
+
+interface IOleCache : IUnknown
+{
+    HRESULT Cache( FORMATETC *pformatetc, DWORD advf, DWORD * pdwConnection );
+    HRESULT Uncache( DWORD dwConnection );
+    HRESULT EnumCache( IEnumSTATDATA * ppenumSTATDATA );
+    HRESULT InitCache( IDataObject pDataObject );
+    HRESULT SetData( FORMATETC * pformatetc, STGMEDIUM * pmedium, BOOL fRelease );
+}
+alias IOleCache LPOLECACHE;
+
+interface IOleCache2 : IOleCache
+{
+    // Cache update Flags
+/*
+    const DWORD UPDFCACHE_NODATACACHE   =       0x00000001;
+    const DWORD UPDFCACHE_ONSAVECACHE   =       0x00000002;
+    const DWORD UPDFCACHE_ONSTOPCACHE   =       0x00000004;
+    const DWORD UPDFCACHE_NORMALCACHE   =       0x00000008;
+    const DWORD UPDFCACHE_IFBLANK       =       0x00000010;
+    const DWORD UPDFCACHE_ONLYIFBLANK   =       0x80000000;
+
+    const DWORD UPDFCACHE_IFBLANKORONSAVECACHE  =
+                    (UPDFCACHE_IFBLANK | UPDFCACHE_ONSAVECACHE);
+    const DWORD UPDFCACHE_ALL                   =
+                    ((DWORD)(~(UPDFCACHE_ONLYIFBLANK)));
+    const DWORD UPDFCACHE_ALLBUTNODATACACHE     =
+                    (UPDFCACHE_ALL & ((DWORD)(~UPDFCACHE_NODATACACHE)));
+
+
+    // IOleCache2::DiscardCache options
+    typedef [v1_enum] enum tagDISCARDCACHE
+    {
+        DISCARDCACHE_SAVEIFDIRTY =  0,  // Save all dirty cache before discarding
+        DISCARDCACHE_NOSAVE      =  1   // Don't save dirty caches before
+                                    // discarding
+    } DISCARDCACHE;
+*/
+
+    HRESULT UpdateCache( LPDATAOBJECT pDataObject, DWORD grfUpdf, LPVOID pReserved );
+
+//    [call_as(UpdateCache)]
+//    HRESULT RemoteUpdateCache( LPDATAOBJECT pDataObject, DWORD grfUpdf, DWORD pReserved );
+    HRESULT DiscardCache( DWORD dwDiscardOptions );
+}
+alias IOleCache2 LPOLECACHE2;
+
+interface IOleCacheControl : IUnknown
+{
+    HRESULT OnRun( LPDATAOBJECT pDataObject );
+    HRESULT OnStop();
+}
+alias IOleCacheControl LPOLECACHECONTROL;
+
+interface IParseDisplayName : IUnknown
+{
+    HRESULT ParseDisplayName( IBindCtx pbc, LPOLESTR pszDisplayName, ULONG * pchEaten, IMoniker * ppmkOut );
+}
+alias IParseDisplayName LPPARSEDISPLAYNAME;
+
+interface IOleContainer : IParseDisplayName
+{
+	HRESULT EnumObjects( DWORD grfFlags, IEnumUnknown * ppenum );
+	HRESULT LockContainer( BOOL fLock );
+}
+alias IOleContainer LPOLECONTAINER;
+
+
+interface IOleClientSite : IUnknown
+{
+	HRESULT SaveObject();
+	HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk );
+	HRESULT GetContainer( IOleContainer * ppContainer );
+	HRESULT ShowObject();
+	HRESULT OnShowWindow( BOOL fShow );
+	HRESULT RequestNewObjectLayout();
+}
+alias IOleClientSite LPOLECLIENTSITE;
+
+enum OLEGETMONIKER
+{
+	OLEGETMONIKER_ONLYIFTHERE = 1,
+	OLEGETMONIKER_FORCEASSIGN = 2,
+	OLEGETMONIKER_UNASSIGN    = 3,
+	OLEGETMONIKER_TEMPFORUSER = 4
+}
+
+enum OLEWHICHMK
+{
+	OLEWHICHMK_CONTAINER = 1,
+	OLEWHICHMK_OBJREL    = 2,
+	OLEWHICHMK_OBJFULL   = 3
+}
+
+enum USERCLASSTYPE
+{
+        USERCLASSTYPE_FULL    = 1,
+        USERCLASSTYPE_SHORT   = 2,
+        USERCLASSTYPE_APPNAME = 3,
+}
+
+enum OLEMISC
+{
+        OLEMISC_RECOMPOSEONRESIZE           = 0x00000001,
+        OLEMISC_ONLYICONIC                  = 0x00000002,
+        OLEMISC_INSERTNOTREPLACE            = 0x00000004,
+        OLEMISC_STATIC                      = 0x00000008,
+        OLEMISC_CANTLINKINSIDE              = 0x00000010,
+        OLEMISC_CANLINKBYOLE1               = 0x00000020,
+        OLEMISC_ISLINKOBJECT                = 0x00000040,
+        OLEMISC_INSIDEOUT                   = 0x00000080,
+        OLEMISC_ACTIVATEWHENVISIBLE         = 0x00000100,
+        OLEMISC_RENDERINGISDEVICEINDEPENDENT= 0x00000200,
+        OLEMISC_INVISIBLEATRUNTIME          = 0x00000400,
+        OLEMISC_ALWAYSRUN                   = 0x00000800,
+        OLEMISC_ACTSLIKEBUTTON              = 0x00001000,
+        OLEMISC_ACTSLIKELABEL               = 0x00002000,
+        OLEMISC_NOUIACTIVATE                = 0x00004000,
+        OLEMISC_ALIGNABLE                   = 0x00008000,
+        OLEMISC_SIMPLEFRAME                 = 0x00010000,
+        OLEMISC_SETCLIENTSITEFIRST          = 0x00020000,
+        OLEMISC_IMEMODE                     = 0x00040000,
+        OLEMISC_IGNOREACTIVATEWHENVISIBLE   = 0x00080000,
+        OLEMISC_WANTSTOMENUMERGE            = 0x00100000,
+        OLEMISC_SUPPORTSMULTILEVELUNDO      = 0x00200000
+}
+
+enum OLECLOSE
+{
+	OLECLOSE_SAVEIFDIRTY = 0,
+	OLECLOSE_NOSAVE      = 1,
+	OLECLOSE_PROMPTSAVE  = 2,
+	SAVEIFDIRTY = 0,
+	NOSAVE      = 1,
+	PROMPTSAVE  = 2
+}
+
+interface IOleObject : IUnknown
+{
+	HRESULT SetClientSite( IOleClientSite pClientSite );
+	HRESULT GetClientSite( IOleClientSite * ppClientSite );
+	HRESULT SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj );
+	HRESULT Close( DWORD dwSaveOption );
+	HRESULT SetMoniker( DWORD dwWhichMoniker, IMoniker pmk );
+	HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk );
+	HRESULT InitFromData( IDataObject pDataObject, BOOL fCreation, DWORD dwReserved );
+	HRESULT GetClipboardData( DWORD dwReserved, IDataObject * ppDataObject );
+	HRESULT DoVerb( LONG iVerb, LPMSG lpmsg, IOleClientSite pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect );
+	HRESULT EnumVerbs( IEnumOLEVERB * ppEnumOleVerb );
+	HRESULT Update();
+	HRESULT IsUpToDate();
+	HRESULT GetUserClassID( CLSID * pClsid );
+	HRESULT GetUserType( DWORD dwFormOfType, LPOLESTR * pszUserType );
+	HRESULT SetExtent( DWORD dwDrawAspect, SIZEL * psizel );
+	HRESULT GetExtent( DWORD dwDrawAspect, SIZEL * psizel );
+	HRESULT Advise( IAdviseSink pAdvSink, DWORD * pdwConnection );
+	HRESULT Unadvise( DWORD dwConnection );
+	HRESULT EnumAdvise( IEnumSTATDATA * ppenumAdvise );
+	HRESULT GetMiscStatus( DWORD dwAspect, DWORD *pdwStatus );
+	HRESULT SetColorScheme( LOGPALETTE *pLogpal );
+}
+alias IOleObject LPOLEOBJECT;
+
+enum OLERENDER
+{
+	OLERENDER_NONE   = 0,
+	OLERENDER_DRAW   = 1,
+	OLERENDER_FORMAT = 2,
+	OLERENDER_ASIS   = 3,
+	NONE   = 0,
+	DRAW   = 1,
+	FORMAT = 2,
+	ASIS   = 3
+}
+alias OLERENDER * LPOLERENDER;
+
+interface IOLETypes
+{
+}
+    /****** OLE value types ***********************************************/
+    /* rendering options */
+    /****** Clipboard Data structures *****************************************/
+    struct OBJECTDESCRIPTOR
+    {
+       ULONG    cbSize;              // Size of structure in bytes
+       CLSID    clsid;               // CLSID of data being transferred
+       DWORD    dwDrawAspect;        // Display aspect of the object
+                                     //     normally DVASPECT_CONTENT or ICON.
+                                     //     dwDrawAspect will be 0 (which is NOT
+                                     //     DVASPECT_CONTENT) if the copier or
+                                     //     dragsource didn't draw the object to
+                                     //     begin with.
+       SIZEL    sizel;               // size of the object in HIMETRIC
+                                     //    sizel is opt.: will be (0,0) for apps
+                                     //    which don't draw the object being
+                                     //    transferred
+       POINTL   pointl;              // Offset in HIMETRIC units from the
+                                     //    upper-left corner of the obj where the
+                                     //    mouse went down for the drag.
+                                     //    NOTE: y coordinates increase downward.
+                                     //          x coordinates increase to right
+                                     //    pointl is opt.; it is only meaningful
+                                     //    if object is transfered via drag/drop.
+                                     //    (0, 0) if mouse position is unspecified
+                                     //    (eg. when obj transfered via clipboard)
+       DWORD    dwStatus;            // Misc. status flags for object. Flags are
+                                     //    defined by OLEMISC enum. these flags
+                                     //    are as would be returned
+                                     //    by IOleObject::GetMiscStatus.
+       DWORD    dwFullUserTypeName;  // Offset from beginning of structure to
+                                     //    null-terminated string that specifies
+                                     //    Full User Type Name of the object.
+                                     //    0 indicates string not present.
+       DWORD    dwSrcOfCopy;         // Offset from beginning of structure to
+                                     //    null-terminated string that specifies
+                                     //    source of the transfer.
+                                     //    dwSrcOfCOpy is normally implemented as
+                                     //    the display name of the temp-for-user
+                                     //    moniker which identifies the source of
+                                     //    the data.
+                                     //    0 indicates string not present.
+                                     //    NOTE: moniker assignment is NOT forced.
+                                     //    see IOleObject::GetMoniker(
+                                     //                OLEGETMONIKER_TEMPFORUSER)
+
+     /* variable sized string data may appear here */
+
+    }
+	 alias OBJECTDESCRIPTOR  LINKSRCDESCRIPTOR;
+	 alias OBJECTDESCRIPTOR  * POBJECTDESCRIPTOR;
+	 alias OBJECTDESCRIPTOR  * LPOBJECTDESCRIPTOR;
+	 alias OBJECTDESCRIPTOR  * PLINKSRCDESCRIPTOR;
+	 alias OBJECTDESCRIPTOR  * LPLINKSRCDESCRIPTOR;
+
+
+interface IOleWindow : IUnknown
+{
+    HRESULT GetWindow( HWND * phwnd );
+    HRESULT ContextSensitiveHelp( BOOL fEnterMode );
+}
+alias IOleWindow LPOLEWINDOW;
+enum OLEUPDATE
+{
+	OLEUPDATE_ALWAYS=1,
+	OLEUPDATE_ONCALL=3
+}
+alias OLEUPDATE * LPOLEUPDATE;
+alias OLEUPDATE * POLEUPDATE;
+
+    // for IOleLink::BindToSource
+enum OLELINKBIND
+{
+	OLELINKBIND_EVENIFCLASSDIFF = 1,
+}
+
+interface IOleLink : IUnknown
+{
+    /* Link update options */
+	HRESULT SetUpdateOptions( DWORD dwUpdateOpt );
+	HRESULT GetUpdateOptions( DWORD * pdwUpdateOpt );
+	HRESULT SetSourceMoniker( IMoniker pmk, REFCLSID rclsid );
+	HRESULT GetSourceMoniker( IMoniker * ppmk );
+	HRESULT SetSourceDisplayName( LPCOLESTR pszStatusText );
+	HRESULT GetSourceDisplayName( LPOLESTR * ppszDisplayName );
+	HRESULT BindToSource( DWORD bindflags, IBindCtx pbc );
+	HRESULT BindIfRunning();
+	HRESULT GetBoundSource( IUnknown * ppunk );
+	HRESULT UnbindSource();
+	HRESULT Update( IBindCtx pbc );
+}
+alias IOleLink LPOLELINK;
+
+enum BINDSPEED
+{
+	BINDSPEED_INDEFINITE    = 1,
+	BINDSPEED_MODERATE      = 2,
+	BINDSPEED_IMMEDIATE     = 3
+}
+
+enum OLECONTF
+{
+	OLECONTF_EMBEDDINGS     = 1,
+	OLECONTF_LINKS          = 2,
+	OLECONTF_OTHERS         = 4,
+	OLECONTF_ONLYUSER       = 8,
+	OLECONTF_ONLYIFRUNNING  = 16
+}
+
+interface IOleItemContainer : IOleContainer
+{
+	HRESULT GetObject( LPOLESTR pszItem, DWORD dwSpeedNeeded, IBindCtx pbc, REFIID riid, void **ppvObject);
+	HRESULT GetObjectStorage( LPOLESTR pszItem, IBindCtx pbc, REFIID riid, void **ppvStorage);
+	HRESULT IsRunning(LPOLESTR pszItem);
+}
+alias IOleItemContainer LPOLEITEMCONTAINER;
+
+alias RECT BORDERWIDTHS;
+alias LPRECT LPBORDERWIDTHS;
+alias LPCRECT LPCBORDERWIDTHS;
+
+interface IOleInPlaceUIWindow : IOleWindow
+{
+	HRESULT GetBorder( LPRECT lprectBorder );
+	HRESULT RequestBorderSpace( LPCBORDERWIDTHS pborderwidths );
+	HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths );
+	HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName );
+}
+alias IOleInPlaceUIWindow LPOLEINPLACEUIWINDOW;
+
+interface IOleInPlaceActiveObject : IOleWindow
+{
+	HRESULT TranslateAccelerator( LPMSG lpmsg );
+	HRESULT OnFrameWindowActivate( BOOL fActivate );
+	HRESULT OnDocWindowActivate( BOOL fActivate );
+	HRESULT ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow pUIWindow, BOOL fFrameWindow );
+	HRESULT EnableModeless ( BOOL fEnable );
+}
+alias IOleInPlaceActiveObject LPOLEINPLACEACTIVEOBJECT;
+
+struct OLEINPLACEFRAMEINFO          // OleInPlaceFrameInfo
+{
+    UINT    cb;
+    BOOL    fMDIApp;
+    HWND    hwndFrame;
+    HACCEL  haccel;
+    UINT    cAccelEntries;
+}
+alias OLEINPLACEFRAMEINFO * LPOLEINPLACEFRAMEINFO;
+
+
+struct OLEMENUGROUPWIDTHS
+{
+    LONG    width[6];
+}
+alias OLEMENUGROUPWIDTHS * LPOLEMENUGROUPWIDTHS;
+
+alias HGLOBAL HOLEMENU;
+
+interface IOleInPlaceFrame : IOleInPlaceUIWindow
+{
+HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths );
+HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject );
+HRESULT RemoveMenus( HMENU hmenuShared );
+HRESULT SetStatusText( LPCOLESTR pszStatusText );
+HRESULT EnableModeless( BOOL fEnable );
+HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID );
+}
+alias IOleInPlaceFrame LPOLEINPLACEFRAME;
+
+interface IOleInPlaceObject : IOleWindow
+{
+	HRESULT InPlaceDeactivate();
+	HRESULT UIDeactivate();
+	HRESULT SetObjectRects( LPCRECT lprcPosRect, LPCRECT lprcClipRect );
+	HRESULT ReactivateAndUndo();
+}
+alias IOleInPlaceObject LPOLEINPLACEOBJECT;
+
+interface IOleInPlaceSite : IOleWindow
+{
+	HRESULT CanInPlaceActivate();
+	HRESULT OnInPlaceActivate();
+	HRESULT OnUIActivate();
+	HRESULT GetWindowContext( IOleInPlaceFrame * ppFrame, IOleInPlaceUIWindow * ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo );
+	HRESULT Scroll( SIZE scrollExtant );
+	HRESULT OnUIDeactivate( BOOL fUndoable );
+	HRESULT OnInPlaceDeactivate();
+	HRESULT DiscardUndoState();
+	HRESULT DeactivateAndUndo();
+	HRESULT OnPosRectChange( LPCRECT lprcPosRect );
+}
+alias IOleInPlaceSite LPOLEINPLACESITE;
+
+interface IContinue : IUnknown
+{
+    HRESULT FContinue();
+}
+
+interface IViewObject : IUnknown
+{
+	HRESULT Draw( DWORD dwDrawAspect, LONG lindex, void * pvAspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL (*pfnContinue)(DWORD dwContinue), DWORD dwContinue );
+	HRESULT GetColorSet( DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet );
+	HRESULT Freeze( DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze );
+	HRESULT Unfreeze( DWORD dwFreeze );
+	HRESULT SetAdvise( DWORD aspects, DWORD advf, IAdviseSink pAdvSink );
+	HRESULT GetAdvise( DWORD * pAspects, DWORD * pAdvf, IAdviseSink * ppAdvSink );
+}
+alias IViewObject LPVIEWOBJECT;
+
+interface IViewObject2 : IViewObject
+{
+	HRESULT GetExtent( DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE* ptd, LPSIZEL lpsizel );
+}
+alias IViewObject2 LPVIEWOBJECT2;
+
+interface IDropSource : IUnknown
+{
+	HRESULT QueryContinueDrag( BOOL fEscapePressed, DWORD grfKeyState );
+	HRESULT GiveFeedback( DWORD dwEffect );
+}
+alias IDropSource LPDROPSOURCE;
+
+const DWORD MK_ALT = 0x0020;
+const DWORD DROPEFFECT_NONE = 0;
+const DWORD DROPEFFECT_COPY = 1;
+const DWORD DROPEFFECT_MOVE = 2;
+const DWORD DROPEFFECT_LINK = 4;
+const DWORD DROPEFFECT_SCROLL = 0x80000000;
+const DWORD DD_DEFSCROLLINSET = 11;
+const DWORD DD_DEFSCROLLDELAY = 50;
+const DWORD DD_DEFSCROLLINTERVAL = 50;
+const DWORD DD_DEFDRAGDELAY = 200;
+const DWORD DD_DEFDRAGMINDIST = 2;
+
+interface IDropTarget : IUnknown
+{
+	HRESULT DragEnter( IDataObject pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect );
+	HRESULT DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect );
+	HRESULT DragLeave();
+	HRESULT Drop(IDataObject pDataObj,DWORD grfKeyState,POINTL pt,DWORD *pdwEffect);
+}
+alias IDropTarget LPDROPTARGET;
+
+struct OLEVERB {
+        LONG    lVerb;
+        LPOLESTR  lpszVerbName;
+        DWORD   fuFlags;
+        DWORD grfAttribs;
+}
+alias OLEVERB * LPOLEVERB;
+
+// Bitwise verb attributes used in OLEVERB.grfAttribs
+enum OLEVERBATTRIB // bitwise
+{
+	OLEVERBATTRIB_NEVERDIRTIES = 1,
+	OLEVERBATTRIB_ONCONTAINERMENU = 2,
+	NEVERDIRTIES = 1,
+	ONCONTAINERMENU = 2
+}
+
+interface IEnumOLEVERB : IUnknown
+{
+	HRESULT Next( ULONG celt, LPOLEVERB rgelt, ULONG * pceltFetched );
+	HRESULT Skip( ULONG celt );
+	HRESULT Reset();
+	HRESULT Clone( IEnumOLEVERB * ppenum );
+}
+alias IEnumOLEVERB LPENUMOLEVERB;
+
+} /* extern(Windows) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/extras.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,279 @@
+module org.eclipse.swt.internal.ole.win32.extras;
+
+//
+// extra bits form here and there to bring the com alias inline with MS
+// to ease the porting.
+//
+
+//public import std.c.windows.com;
+//public import std.c.windows.windows;
+import org.eclipse.swt.internal.win32.WINTYPES;
+// private import org.eclipse.swt.internal.ole.win32.comtypes;
+alias WCHAR OLECHAR;
+alias OLECHAR *LPOLESTR;
+alias OLECHAR *LPCOLESTR;
+
+enum
+{
+    rmm = 23,   // OLE 2 version number info
+    rup = 639,
+}
+
+enum : int
+{
+    S_OK = 0,
+    S_FALSE = 0x00000001,
+    NOERROR = 0,
+    E_NOTIMPL     = cast(int)0x80004001,
+    E_NOINTERFACE = cast(int)0x80004002,
+    E_POINTER     = cast(int)0x80004003,
+    E_ABORT       = cast(int)0x80004004,
+    E_FAIL        = cast(int)0x80004005,
+    E_HANDLE      = cast(int)0x80070006,
+    CLASS_E_NOAGGREGATION = cast(int)0x80040110,
+    E_OUTOFMEMORY = cast(int)0x8007000E,
+    E_INVALIDARG  = cast(int)0x80070057,
+    E_UNEXPECTED  = cast(int)0x8000FFFF,
+}
+
+// in tango types.di
+// struct GUID {          // size is 16
+//     align(1):
+//     DWORD Data1;
+//     WORD  Data2;
+//     WORD  Data3;
+//     BYTE  Data4[8];
+// }
+
+enum
+{
+    CLSCTX_INPROC_SERVER    = 0x1,
+    CLSCTX_INPROC_HANDLER   = 0x2,
+    CLSCTX_LOCAL_SERVER = 0x4,
+    CLSCTX_INPROC_SERVER16  = 0x8,
+    CLSCTX_REMOTE_SERVER    = 0x10,
+    CLSCTX_INPROC_HANDLER16 = 0x20,
+    CLSCTX_INPROC_SERVERX86 = 0x40,
+    CLSCTX_INPROC_HANDLERX86 = 0x80,
+
+    CLSCTX_INPROC = (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER),
+    CLSCTX_ALL = (CLSCTX_INPROC_SERVER| CLSCTX_INPROC_HANDLER| CLSCTX_LOCAL_SERVER),
+    CLSCTX_SERVER = (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER),
+}
+
+alias GUID IID;
+alias GUID CLSID;
+
+extern (C)
+{
+    extern IID IID_IUnknown;
+    extern IID IID_IClassFactory;
+    extern IID IID_IMarshal;
+    extern IID IID_IMallocSpy;
+    extern IID IID_IStdMarshalInfo;
+    extern IID IID_IExternalConnection;
+    extern IID IID_IMultiQI;
+    extern IID IID_IEnumUnknown;
+    extern IID IID_IBindCtx;
+    extern IID IID_IEnumMoniker;
+    extern IID IID_IRunnableObject;
+    extern IID IID_IRunningObjectTable;
+    extern IID IID_IPersist;
+    extern IID IID_IPersistStream;
+    extern IID IID_IMoniker;
+    extern IID IID_IROTData;
+    extern IID IID_IEnumString;
+    extern IID IID_ISequentialStream;
+    extern IID IID_IStream;
+    extern IID IID_IEnumSTATSTG;
+    extern IID IID_IStorage;
+    extern IID IID_IPersistFile;
+    extern IID IID_IPersistStorage;
+    extern IID IID_ILockBytes;
+    extern IID IID_IEnumFORMATETC;
+    extern IID IID_IEnumSTATDATA;
+    extern IID IID_IRootStorage;
+    extern IID IID_IAdviseSink;
+    extern IID IID_IAdviseSink2;
+    extern IID IID_IDataObject;
+    extern IID IID_IDataAdviseHolder;
+    extern IID IID_IMessageFilter;
+    extern IID IID_IRpcChannelBuffer;
+    extern IID IID_IRpcProxyBuffer;
+    extern IID IID_IRpcStubBuffer;
+    extern IID IID_IPSFactoryBuffer;
+    extern IID IID_IPropertyStorage;
+    extern IID IID_IPropertySetStorage;
+    extern IID IID_IEnumSTATPROPSTG;
+    extern IID IID_IEnumSTATPROPSETSTG;
+    extern IID IID_IFillLockBytes;
+    extern IID IID_IProgressNotify;
+    extern IID IID_ILayoutStorage;
+    extern IID GUID_NULL;
+    extern IID IID_IRpcChannel;
+    extern IID IID_IRpcStub;
+    extern IID IID_IStubManager;
+    extern IID IID_IRpcProxy;
+    extern IID IID_IProxyManager;
+    extern IID IID_IPSFactory;
+    extern IID IID_IInternalMoniker;
+    extern IID IID_IDfReserved1;
+    extern IID IID_IDfReserved2;
+    extern IID IID_IDfReserved3;
+    extern IID IID_IStub;
+    extern IID IID_IProxy;
+    extern IID IID_IEnumGeneric;
+    extern IID IID_IEnumHolder;
+    extern IID IID_IEnumCallback;
+    extern IID IID_IOleManager;
+    extern IID IID_IOlePresObj;
+    extern IID IID_IDebug;
+    extern IID IID_IDebugStream;
+    extern IID IID_StdOle;
+    extern IID IID_ICreateTypeInfo;
+    extern IID IID_ICreateTypeInfo2;
+    extern IID IID_ICreateTypeLib;
+    extern IID IID_ICreateTypeLib2;
+    extern IID IID_IDispatch;
+    extern IID IID_IEnumVARIANT;
+    extern IID IID_ITypeComp;
+    extern IID IID_ITypeInfo;
+    extern IID IID_ITypeInfo2;
+    extern IID IID_ITypeLib;
+    extern IID IID_ITypeLib2;
+    extern IID IID_ITypeChangeEvents;
+    extern IID IID_IErrorInfo;
+    extern IID IID_ICreateErrorInfo;
+    extern IID IID_ISupportErrorInfo;
+    extern IID IID_IOleAdviseHolder;
+    extern IID IID_IOleCache;
+    extern IID IID_IOleCache2;
+    extern IID IID_IOleCacheControl;
+    extern IID IID_IParseDisplayName;
+    extern IID IID_IOleContainer;
+    extern IID IID_IOleClientSite;
+    extern IID IID_IOleObject;
+    extern IID IID_IOleWindow;
+    extern IID IID_IOleLink;
+    extern IID IID_IOleItemContainer;
+    extern IID IID_IOleInPlaceUIWindow;
+    extern IID IID_IOleInPlaceActiveObject;
+    extern IID IID_IOleInPlaceFrame;
+    extern IID IID_IOleInPlaceObject;
+    extern IID IID_IOleInPlaceSite;
+    extern IID IID_IContinue;
+    extern IID IID_IViewObject;
+    extern IID IID_IViewObject2;
+    extern IID IID_IDropSource;
+    extern IID IID_IDropTarget;
+    extern IID IID_IEnumOLEVERB;
+}
+
+extern (Windows) export {
+    DWORD   CoBuildVersion();
+
+    int StringFromGUID2(GUID *rguid, LPOLESTR lpsz, int cbMax);
+
+    /* init/uninit */
+
+    HRESULT CoInitialize(LPVOID pvReserved);
+    void    CoUninitialize();
+    DWORD   CoGetCurrentProcess();
+
+
+    HRESULT CoCreateInstance(CLSID *rclsid, IUnknown UnkOuter,
+                        DWORD dwClsContext, IID* riid, void* ppv);
+
+    //HINSTANCE CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
+    void    CoFreeLibrary(HINSTANCE hInst);
+    void    CoFreeAllLibraries();
+    void    CoFreeUnusedLibraries();
+
+    interface IUnknown {
+        HRESULT QueryInterface(IID* riid, void** pvObject);
+        ULONG AddRef();
+        ULONG Release();
+    }
+
+    interface IClassFactory : IUnknown {
+        HRESULT CreateInstance(IUnknown UnkOuter, IID* riid, void** pvObject);
+        HRESULT LockServer(BOOL fLock);
+    }
+
+}
+
+
+alias IUnknown LPUNKNOWN;
+alias IClassFactory LPCLASSFACTORY;
+
+//alias LPRECT LPCRECT; /* D has no consts */
+struct COAUTHINFO{}
+//alias DWORD LCID;
+alias PDWORD PLCID;
+//typedef GUID CLSID;
+//alias CLSID * LPCLSID;
+alias GUID *REFGUID;
+
+//alias IID *REFIID;
+
+alias CLSID *REFCLSID;
+
+//typedef FMTID  *REFFMTID;
+union __MIDL_IWinTypes_0001
+{
+DWORD dwValue;
+wchar *pwszName;
+}
+struct  userCLIPFORMAT
+{
+    long fContext;
+	__MIDL_IWinTypes_0001 u;
+}
+
+alias userCLIPFORMAT *wireCLIPFORMAT;
+
+alias WORD CLIPFORMAT;
+
+alias void * HMETAFILEPICT;
+// typeless hack
+alias void * wireHGLOBAL;
+alias void * wireHBITMAP;
+alias void * wireHPALETTE;
+alias void * wireHENHMETAFILE;
+alias void * wireHMETAFILE;
+alias void * wireHMETAFILEPICT;
+
+struct BYTE_BLOB {
+   ULONG clSize;
+	byte[1] abData;
+}
+
+alias BYTE_BLOB *UP_BYTE_BLOB;
+
+struct  WORD_BLOB
+{
+	ULONG clSize;
+	ushort[1] asData;
+}
+
+alias WORD_BLOB *UP_WORD_BLOB;
+
+struct  DWORD_BLOB
+{
+    ULONG clSize;
+	ULONG[1] alData;
+}
+alias DWORD_BLOB *UP_DWORD_BLOB;
+alias ushort VARTYPE;
+alias short VARIANT_BOOL;
+
+// all the st
+enum READYSTATE
+    {	READYSTATE_UNINITIALIZED	= 0,
+	READYSTATE_LOADING	= 1,
+	READYSTATE_LOADED	= 2,
+	READYSTATE_INTERACTIVE	= 3,
+	READYSTATE_COMPLETE	= 4
+}
+
+alias HANDLE HTASK;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/ole/win32/ifs.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,257 @@
+/*
+ * extra interface not define in any other modules, copied from MSDN 2003
+ * don't import this module directly, import std.internal.ole.win32.com instead
+ *
+ * author : Shawn Liu
+ */
+
+module org.eclipse.swt.internal.ole.win32.ifs;
+
+private import org.eclipse.swt.SWT;
+private import org.eclipse.swt.internal.win32.WINTYPES;
+private import org.eclipse.swt.internal.ole.win32.COM;
+//private import std.c.windows.windows;
+//private import std.c.windows.com;
+private import org.eclipse.swt.internal.ole.win32.COMTYPES;
+private import org.eclipse.swt.internal.ole.win32.OAIDL;
+private import org.eclipse.swt.internal.ole.win32.OBJIDL;
+private import org.eclipse.swt.internal.ole.win32.OLEIDL;
+private import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+private import org.eclipse.swt.internal.ole.win32.EXDISP;
+private import org.eclipse.swt.internal.ole.win32.MSHTMHST;
+private import org.eclipse.swt.internal.ole.win32.extras;
+
+
+interface IAccessible : IDispatch {
+//	int GetTypeInfoCount(int pctinfo);
+//	int GetTypeInfo(THIS_ UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo);
+//	int GetIDsOfNames - not implemented
+//	int Invoke - not implemented
+	HRESULT get_accParent(LPDISPATCH* ppdispParent);
+	HRESULT get_accChildCount(LONG* pcountChildren);
+	HRESULT get_accChild(VARIANT varChildID, LPDISPATCH* ppdispChild);
+	HRESULT get_accName(VARIANT varID, BSTR* pszName);
+	HRESULT get_accValue(VARIANT varID, BSTR* pszValue);
+	HRESULT get_accDescription(VARIANT varID,BSTR* pszDescription);
+	HRESULT get_accRole(VARIANT varID, VARIANT* pvarRole);
+	HRESULT get_accState(VARIANT varID, VARIANT* pvarState);
+	HRESULT get_accHelp(VARIANT varID, BSTR* pszHelp);
+	HRESULT get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild, LONG* pidTopic);
+	HRESULT get_accKeyboardShortcut(VARIANT varID, BSTR* pszKeyboardShortcut);
+	HRESULT get_accFocus(VARIANT* pvarID);
+	HRESULT get_accSelection(VARIANT* pvarChildren);
+	HRESULT get_accDefaultAction(VARIANT varID,BSTR* pszDefaultAction);
+	HRESULT accSelect(LONG flagsSelect, VARIANT varID);
+	HRESULT accLocation(LONG* pxLeft, LONG* pyTop, LONG* pcxWidth, LONG* pcyHeight, VARIANT varID);
+	HRESULT accNavigate(LONG navDir, VARIANT varStart, VARIANT* pvarEnd);
+	HRESULT accHitTest(LONG xLeft,  LONG yTop, VARIANT* pvarID);
+	HRESULT accDoDefaultAction(VARIANT varID);
+	HRESULT put_accName(VARIANT varID, BSTR* szName);
+	HRESULT put_accValue(VARIANT varID, BSTR* szValue);
+}
+alias IAccessible LPACCESSIBLE;
+
+interface IClassFactory2 : IClassFactory
+{
+	HRESULT GetLicInfo(LICINFO * pLicInfo);
+	HRESULT RequestLicKey(DWORD dwReserved, BSTR * pbstrKey);
+	HRESULT CreateInstanceLic(LPUNKNOWN pUnkOuter, LPUNKNOWN pUnkReserved, REFIID riid, BSTR bstrKey, void ** ppvObject);
+}
+alias IClassFactory2 LPCLASSFACTORY2;
+
+
+interface IConnectionPoint : IUnknown
+{
+	HRESULT GetConnectionInterface(IID * pIID);
+	HRESULT GetConnectionPointContainer(LPCONNECTIONPOINTCONTAINER * ppCPC);
+	HRESULT Advise(LPUNKNOWN pUnk, DWORD * pdwCookie);
+	HRESULT Unadvise(DWORD dwCookie);
+	HRESULT EnumConnections(LPENUMCONNECTIONS * ppEnum);
+}
+alias IConnectionPoint LPCONNECTIONPOINT;
+
+
+interface IConnectionPointContainer : IUnknown
+{
+	HRESULT EnumConnectionPoints(LPENUMCONNECTIONPOINTS * ppEnum);
+	HRESULT FindConnectionPoint(REFIID riid, LPCONNECTIONPOINT * ppCP);
+}
+alias IConnectionPointContainer LPCONNECTIONPOINTCONTAINER;
+
+interface IEnumConnectionPoints : IUnknown
+{
+	HRESULT Next(ULONG celt, LPCONNECTIONPOINT * rgelt, ULONG * pceltFetched);
+	HRESULT Skip(ULONG celt);
+	HRESULT Reset();
+	HRESULT Clone(LPENUMCONNECTIONPOINTS * ppenum);
+}
+alias IEnumConnectionPoints LPENUMCONNECTIONPOINTS;
+
+interface IEnumConnections : IUnknown {
+	HRESULT Next(ULONG cConnections, CONNECTDATA ** rgpcd, ULONG * pcFetched);
+	HRESULT Skip(ULONG cConnections);
+	HRESULT Reset();
+	HRESULT Clone(LPENUMCONNECTIONS * ppEnum);
+}alias IEnumConnections LPENUMCONNECTIONS;
+
+interface IEnumVARIANT : IUnknown {
+    HRESULT Next(ULONG celt, VARIANT *rgelt, ULONG *pceltFetched);
+    HRESULT Skip(ULONG celt);
+    HRESULT Reset();
+    HRESULT Clone(LPENUMVARIANT * ppenum);
+}
+alias IEnumVARIANT LPENUMVARIANT;
+
+
+interface IInternetSecurityManager : IUnknown {
+	HRESULT SetSecuritySite(LPINTERNETSECURITYMGRSITE pSite);
+	HRESULT GetSecuritySite(LPINTERNETSECURITYMGRSITE *ppSite);
+	HRESULT MapUrlToZone(LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags);
+	HRESULT GetSecurityId(LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved);
+	HRESULT ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved);
+	HRESULT QueryCustomPolicy(LPCWSTR pwszUrl, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwReserved);
+	HRESULT SetZoneMapping(DWORD dwZone, LPCWSTR lpszPattern, DWORD dwFlags);
+	HRESULT GetZoneMappings(DWORD dwZone, LPENUMSTRING * ppenumString, DWORD dwFlags);
+}
+interface IInternetSecurityMgrSite : IUnknown {
+	HRESULT EnableModeless(BOOL fEnable);
+	HRESULT GetWindow(HWND *phwnd);
+}
+alias IInternetSecurityMgrSite LPINTERNETSECURITYMGRSITE;
+
+interface IOleControl : IUnknown
+{
+	HRESULT GetControlInfo(CONTROLINFO* pCI);
+	HRESULT OnMnemonic(LPMSG pMsg);
+	HRESULT OnAmbientPropertyChange(DISPID dispID);
+	HRESULT FreezeEvents(BOOL bFreeze);
+}
+alias IOleControl LPOLECONTROL;
+
+
+interface IOleControlSite : IUnknown {
+	HRESULT OnControlInfoChanged();
+	HRESULT LockInPlaceActive(
+	  BOOL fLock  //Indicates whether to ensure the active state
+	);
+	HRESULT GetExtendedControl(
+	  LPDISPATCH* ppDisp  //Address of output variable that receives the
+	                  // IDispatch interface pointer
+	);
+	HRESULT TransformCoords(
+	  POINTL* pPtlHimetric ,  //Address of POINTL structure
+	  POINTF* pPtfContainer ,  //Address of POINTF structure
+	  DWORD dwFlags           //Flags indicating the exact conversion
+	);
+	HRESULT TranslateAccelerator(
+	  LPMSG pMsg ,        //Pointer to the structure
+	  DWORD grfModifiers  //Flags describing the state of the keys
+	);
+	HRESULT OnFocus(
+	  BOOL fGotFocus  //Indicates whether the control gained focus
+	);
+	HRESULT ShowPropertyFrame();
+}
+alias IOleControlSite LPOLECONTROLSITE;
+
+
+interface IPersistStreamInit : IPersist {
+	HRESULT IsDirty();
+	HRESULT Load(LPSTREAM pStm);
+	HRESULT Save(LPSTREAM pStm, BOOL fClearDirty);
+	HRESULT GetSizeMax(ULARGE_INTEGER * pcbSize);
+	HRESULT InitNew();
+}
+
+interface IPropertyNotifySink : IUnknown {
+	HRESULT OnChanged(DISPID dispID);
+	HRESULT OnRequestEdit(DISPID dispID);
+}
+alias IPropertyNotifySink LPPROPERTYNOTIFYSINK;
+
+interface IProvideClassInfo : IUnknown
+{
+	HRESULT GetClassInfo(LPTYPEINFO * ppTI);
+}
+alias IProvideClassInfo LPPROVIDECLASSINFO;
+
+interface IProvideClassInfo2 : IProvideClassInfo
+{
+	HRESULT GetGUID(DWORD dwGuidKind, GUID * pGUID);
+}
+alias IProvideClassInfo2 LPPROVIDECLASSINFO2;
+
+
+/*
+interface IDocHostUIHandler : IUnknown
+{
+	int ShowContextMenu( int dwID, POINT* ppt, ComObj pcmdtReserved, ComObj pdispReserved);
+	int GetHostInfo( int pInfo );
+	int ShowUI( int dwID, ComObj pActiveObject, ComObj pCommandTarget, ComObj pFrame, ComObj pDoc );
+	int HideUI();
+	int UpdateUI();
+	int EnableModeless( int fEnable );
+	int OnDocWindowActivate( int fActivate );
+	int OnFrameWindowActivate( int fActivate );
+	int ResizeBorder( RECT* prcBorder, ComObj pUIWindow, int fRameWindow );
+	int TranslateAccelerator( int lpMsg, int pguidCmdGroup, int nCmdID );
+	int GetOptionKeyPath( int  pchKey, int dw );
+	int GetDropTarget( ComObj pDropTarget, ComObj* ppDropTarget );
+	int GetExternal( ComObj** ppDispatch );
+	int TranslateUrl( int dwTranslate, int pchURLIn, int ppchURLOut );
+	int FilterDataObject( ComObj pDO, ComObj* ppDORet );
+}
+
+interface IDocHostShowUI : IUnknown
+{
+	int ShowMessage( HWND hwnd, wchar* lpstrText, int lpstrCaption, int dwType, int lpstrHelpFile, int dwHelpContext, int plResult);
+	int ShowHelp( HWND hwnd, int pszHelpFile, int uCommand, int dwData, long ptMouse, ComObj pDispatchObjectHit );
+}
+*/
+interface IServiceProvider : IUnknown {
+	HRESULT QueryService(REFGUID guidService, REFIID riid, void **ppv);
+}
+alias IServiceProvider LPSERVICEPROVIDER;
+
+interface ISpecifyPropertyPages : IUnknown {
+	HRESULT GetPages(
+  		CAUUID *pPages  //Pointer to structure
+	);
+}
+alias ISpecifyPropertyPages LPSPECIFYPROPERTYPAGES;
+
+
+
+
+
+
+
+/*
+interface IEnumFORMATETC : IEnumXXXX {}
+
+
+interface IDataObject : IUnknown {
+	int GetData(int pFormatetc, int pmedium);
+	int GetDataHere(FORMATETC* pFormatetc, STGMEDIUM* pmedium);
+	int QueryGetData(FORMATETC* pFormatetc);
+	int GetCanonicalFormatEtc(int pFormatetcIn, int pFormatetcOut);
+	int SetData(int pFormatetc, int pmedium, int fRelease);
+	int EnumFormatEtc(int dwDirection, int ppenumFormatetc);
+	int DAdvise(int pFormatetc, int advf, int pAdvSink, int pdwConnection);
+	int DUnadvise(int dwConnection);
+	int EnumDAdvise(ComObj* ppenumAdvise);
+}
+
+interface IDropSource : IUnknown {
+	int QueryContinueDrag(int fEscapePressed, int grfKeyState);
+	int GiveFeedback(int dwEffect);
+}
+
+interface IDropTarget : IUnknown {
+	// NOTE : POINT* is splited to pt_x, pt_y
+	int DragEnter(ComObj pDataObject, int grfKeyState, int pt_x, int pt_y, int pdwEffect);
+	int DragOver(int grfKeyState, int pt_x,	int pt_y, int pdwEffect);
+	int DragLeave();
+	int Drop(ComObj pDataObject, int grfKeyState, int pt_x, int pt_y, int pdwEffect);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/opengl/win32/WGL.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D Programming Language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module org.eclipse.swt.internal.opengl.win32.WGL;
+
+import org.eclipse.swt.internal.Library;
+import org.eclipse.swt.internal.Platform;
+
+private import org.eclipse.swt.internal.win32.WINAPI;
+private import org.eclipse.swt.internal.opengl.win32.native;
+    
+public class WGL : Platform { 
+
+public:
+    enum : int {
+        WGL_FONT_LINES      = 0,
+        WGL_FONT_POLYGONS   = 1,
+    
+    /* LAYERPLANEDESCRIPTOR flags */
+        LPD_DOUBLEBUFFER        = 0x00000001,
+        LPD_STEREO              = 0x00000002,
+        LPD_SUPPORT_GDI         = 0x00000010,
+        LPD_SUPPORT_OPENGL      = 0x00000020,
+        LPD_SHARE_DEPTH         = 0x00000040,
+        LPD_SHARE_STENCIL       = 0x00000080,
+        LPD_SHARE_ACCUM         = 0x00000100,
+        LPD_SWAP_EXCHANGE       = 0x00000200,
+        LPD_SWAP_COPY           = 0x00000400,
+        LPD_TRANSPARENT         = 0x00001000,
+    
+        LPD_TYPE_RGBA        = 0,
+        LPD_TYPE_COLORINDEX  = 1,
+    
+    /* wglSwapLayerBuffers flags */
+        WGL_SWAP_MAIN_PLANE     = 0x00000001,
+        WGL_SWAP_OVERLAY1       = 0x00000002,
+        WGL_SWAP_OVERLAY2       = 0x00000004,
+        WGL_SWAP_OVERLAY3       = 0x00000008,
+        WGL_SWAP_OVERLAY4       = 0x00000010,
+        WGL_SWAP_OVERLAY5       = 0x00000020,
+        WGL_SWAP_OVERLAY6       = 0x00000040,
+        WGL_SWAP_OVERLAY7       = 0x00000080,
+        WGL_SWAP_OVERLAY8       = 0x00000100,
+        WGL_SWAP_OVERLAY9       = 0x00000200,
+        WGL_SWAP_OVERLAY10      = 0x00000400,
+        WGL_SWAP_OVERLAY11      = 0x00000800,
+        WGL_SWAP_OVERLAY12      = 0x00001000,
+        WGL_SWAP_OVERLAY13      = 0x00002000,
+        WGL_SWAP_OVERLAY14      = 0x00004000,
+        WGL_SWAP_OVERLAY15      = 0x00008000,
+        WGL_SWAP_UNDERLAY1      = 0x00010000,
+        WGL_SWAP_UNDERLAY2      = 0x00020000,
+        WGL_SWAP_UNDERLAY3      = 0x00040000,
+        WGL_SWAP_UNDERLAY4      = 0x00080000,
+        WGL_SWAP_UNDERLAY5      = 0x00100000,
+        WGL_SWAP_UNDERLAY6      = 0x00200000,
+        WGL_SWAP_UNDERLAY7      = 0x00400000,
+        WGL_SWAP_UNDERLAY8      = 0x00800000,
+        WGL_SWAP_UNDERLAY9      = 0x01000000,
+        WGL_SWAP_UNDERLAY10     = 0x02000000,
+        WGL_SWAP_UNDERLAY11     = 0x04000000,
+        WGL_SWAP_UNDERLAY12     = 0x08000000,
+        WGL_SWAP_UNDERLAY13     = 0x10000000,
+        WGL_SWAP_UNDERLAY14     = 0x20000000,
+        WGL_SWAP_UNDERLAY15     = 0x40000000,
+    
+    /* pixel types */
+        PFD_TYPE_RGBA        = 0,
+        PFD_TYPE_COLORINDEX  = 1,
+    
+    /* layer types */
+        PFD_MAIN_PLANE       = 0,
+        PFD_OVERLAY_PLANE    = 1,
+        PFD_UNDERLAY_PLANE   = -1,
+    
+    /* PIXELFORMATDESCRIPTOR flags */
+        PFD_DOUBLEBUFFER            = 0x00000001,
+        PFD_STEREO                  = 0x00000002,
+        PFD_DRAW_TO_WINDOW          = 0x00000004,
+        PFD_DRAW_TO_BITMAP          = 0x00000008,
+        PFD_SUPPORT_GDI             = 0x00000010,
+        PFD_SUPPORT_OPENGL          = 0x00000020,
+        PFD_GENERIC_FORMAT          = 0x00000040,
+        PFD_NEED_PALETTE            = 0x00000080,
+        PFD_NEED_SYSTEM_PALETTE     = 0x00000100,
+        PFD_SWAP_EXCHANGE           = 0x00000200,
+        PFD_SWAP_COPY               = 0x00000400,
+        PFD_SWAP_LAYER_BUFFERS      = 0x00000800,
+        PFD_GENERIC_ACCELERATED     = 0x00001000,
+        PFD_SUPPORT_DIRECTDRAW      = 0x00002000,
+    
+    /* PIXELFORMATDESCRIPTOR flags for use in ChoosePixelFormat only */
+        PFD_DEPTH_DONTCARE          = 0x20000000,
+        PFD_DOUBLEBUFFER_DONTCARE   = 0x40000000,
+        PFD_STEREO_DONTCARE         = 0x80000000
+    }
+
+    alias .ChoosePixelFormat            ChoosePixelFormat;
+    alias .DescribePixelFormat          DescribePixelFormat;
+    alias .GetPixelFormat               GetPixelFormat;
+    alias .SetPixelFormat               SetPixelFormat;
+    alias .SwapBuffers                  SwapBuffers;
+    
+    alias .wglCopyContext               wglCopyContext;
+    alias .wglCreateContext             wglCreateContext;
+    alias .wglCreateLayerContext        wglCreateLayerContext;
+    alias .wglDeleteContext             wglDeleteContext;
+    alias .wglGetCurrentContext         wglGetCurrentContext;
+    alias .wglGetCurrentDC              wglGetCurrentDC;
+    alias .wglGetProcAddress            wglGetProcAddress;
+    alias .wglMakeCurrent               wglMakeCurrent;
+    alias .wglShareLists                wglShareLists;
+    alias .wglDescribeLayerPlane        wglDescribeLayerPlane;
+    alias .wglSetLayerPaletteEntries    wglSetLayerPaletteEntries;
+    alias .wglGetLayerPaletteEntries    wglGetLayerPaletteEntries;
+    alias .wglRealizeLayerPalette       wglRealizeLayerPalette;
+    alias .wglSwapLayerBuffers          wglSwapLayerBuffers;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/opengl/win32/native.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,26 @@
+module org.eclipse.swt.internal.opengl.win32.native;
+
+private import org.eclipse.swt.internal.win32.WINTYPES;
+
+extern (Windows):
+
+int     ChoosePixelFormat( HDC, PIXELFORMATDESCRIPTOR* );
+int     DescribePixelFormat( HDC, int, UINT, PIXELFORMATDESCRIPTOR* );
+int     GetPixelFormat( HDC );
+BOOL    SetPixelFormat( HDC, int, PIXELFORMATDESCRIPTOR* );
+BOOL    SwapBuffers( HDC );
+
+BOOL    wglCopyContext(HGLRC, HGLRC, UINT);
+HGLRC   wglCreateContext(HDC);
+HGLRC   wglCreateLayerContext(HDC, int);
+BOOL    wglDeleteContext(HGLRC);
+BOOL    wglDescribeLayerPlane(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+HGLRC   wglGetCurrentContext();
+HDC     wglGetCurrentDC();
+int     wglGetLayerPaletteEntries(HDC, int, int, int, COLORREF*);
+FARPROC wglGetProcAddress(LPCSTR);
+BOOL    wglMakeCurrent(HDC, HGLRC);
+BOOL    wglRealizeLayerPalette(HDC, int, BOOL);
+int     wglSetLayerPaletteEntries(HDC, int, int, int, COLORREF*);
+BOOL    wglShareLists(HGLRC, HGLRC);
+BOOL    wglSwapLayerBuffers(HDC, UINT);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/OS.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3830 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.internal.win32.OS;
+
+public import org.eclipse.swt.internal.win32.WINTYPES;
+version(TANGOSVN){
+    private import org.eclipse.swt.internal.win32.WINAPI;
+    alias org.eclipse.swt.internal.win32.WINAPI DWTWINAPI;
+    private import tango.sys.win32.UserGdi;
+    alias tango.sys.win32.UserGdi WINAPI;
+}
+else{
+    private import org.eclipse.swt.internal.win32.WINAPI;
+    alias org.eclipse.swt.internal.win32.WINAPI WINAPI;
+    alias org.eclipse.swt.internal.win32.WINAPI DWTWINAPI;
+}
+
+import org.eclipse.swt.internal.C;
+import org.eclipse.swt.internal.Library;
+import java.lang.all;
+import tango.sys.SharedLib : SharedLib;
+import tango.sys.Common : SysError;
+static import tango.stdc.stdlib;
+
+import tango.stdc.string : memset, strlen;
+import tango.stdc.stringz : toString16z;
+import tango.text.convert.Utf : toString16;
+//import tango.io.device.File;
+
+
+import tango.io.Console;
+void trace(int line ){
+    getDwtLogger.trace( "OS {}", line );
+}
+
+// declare of Callback functions
+extern (Windows)
+{
+alias int function() Function0;
+alias int function(void*) Function1;
+alias int function(void*, int) Function2;
+alias int function(void*, int, int) Function3;
+alias int function(void*, int, int, int) Function4;
+alias int function(void*, int, int, int, int) Function5;
+alias int function(void*, int, int, int, int, int) Function6;
+alias int function(void*, int, int, int, int, int, int) Function7;
+alias int function(void*, int, int, int, int, int, int, int) Function8;
+alias int function(void*, int, int, int, int, int, int, int, int) Function9;
+}
+
+
+/*
+Compile time versions
+    ANSI
+    WinCE
+
+    OS.IsUnicode
+    OS.IsWinCE
+
+    OS.IsHPC
+
+    OS.IsSP
+    OS.IsPPC
+    OS.IsWin95
+    OS.IsWinNT
+
+*/
+
+public class LDWTRESULT {
+    public int value;
+    // initalize ONE and ZERO in static OS.this();
+    public static LDWTRESULT ONE;
+    public static LDWTRESULT ZERO;
+    public this (int value) { this.value = value; }
+}
+
+
+public class OS : C {
+
+    struct Symbol {
+        char[] name;
+        void** symbol;
+        int major;
+        int minor;
+    }
+    static void loadLib( Symbol[] symbols, char[] libname ){
+        if (auto lib = SharedLib.load(libname)) {
+            foreach( inout s; symbols ){
+                if( OS.WIN32_VERSION >= OS.VERSION( s.major, s.minor )){
+                    *s.symbol = lib.getSymbol( s.name.ptr );
+                    if( s.symbol is null ){
+                        getDwtLogger.error( "{}: Symbol '{}' not found", libname, s.name );
+                    }
+                }
+            }
+        } else {
+            getDwtLogger.error( "Could not load the library {}", libname );
+        }
+    }
+
+    public static HINSTANCE GetLibraryHandle(){
+        //PORTING_FIXME: GetLibraryHandle
+        // is the hInstance of the DLL or null, if not a DLL.
+        // At the moment SWT is statically linked but this needs to be fixed
+        return null;
+    }
+
+    // macro from winnt.h
+    public static int PRIMARYLANGID( int lgid ){
+        return lgid & 0x3FF;
+    }
+
+    public static int LVITEM_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 1 )) ? LVITEM.sizeof : 40;
+    }
+    public static int MENUITEMINFO_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 0 )) ? MENUITEMINFO.sizeof : 44;
+    }
+    public static int NMLVCUSTOMDRAW_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 1 )) ? NMLVCUSTOMDRAW.sizeof : 60;
+    }
+    public static int NMLVDISPINFO_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 1 )) ? NMLVDISPINFO.sizeof : 52;
+    }
+    public static int OPENFILENAME_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 0 )) ? OPENFILENAME.sizeof : 76;
+    }
+    public static int TOOLINFO_sizeof(){
+        return ( !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION( 5, 1 )) ? TOOLINFO.sizeof : 44;
+    }
+//     private static int getNOTIFYICONDATAA_V2_SIZE (){
+//         // hm, NOTIFYICONDATAA.dwInfoFlags.offsetof did not compile
+//         return IsWinCE ? NOTIFYICONDATAA.sizeof : cast(int)(&(cast(NOTIFYICONDATAA*)null).dwInfoFlags) + int.sizeof;
+//     }
+//
+//     private static int getNOTIFYICONDATAW_V2_SIZE (){
+//         return IsWinCE ? NOTIFYICONDATAW.sizeof : cast(int)(&(cast(NOTIFYICONDATAW*)null).dwInfoFlags) + int.sizeof;
+//     }
+// kernel32 winxp/vista
+public static extern(Windows) {
+HANDLE function( ACTCTX* pActCtx ) CreateActCtx;
+BOOL function( HACTCTX hActCtx, uint* lpCookie ) ActivateActCtx;
+LANGID function() GetSystemDefaultUILanguage;
+BOOL function(
+    LANGUAGEGROUP_ENUMPROC pLangGroupEnumProc, // callback function
+    DWORD dwFlags,                             // language groups
+    LONG_PTR  lParam                           // callback parameter
+)EnumSystemLanguageGroupsA;
+BOOL function(
+    LANGUAGEGROUP_ENUMPROC pLangGroupEnumProc, // callback function
+    DWORD dwFlags,                             // language groups
+    LONG_PTR  lParam                           // callback parameter
+)EnumSystemLanguageGroupsW;
+BOOL function(
+    LOCALE_ENUMPROC lpLocaleEnumProc, // callback function
+    DWORD dwFlags                     // locales
+)EnumSystemLocalesA;
+BOOL function(
+    LOCALE_ENUMPROC lpLocaleEnumProc, // callback function
+    DWORD dwFlags                     // locales
+)EnumSystemLocalesW;
+}
+
+    /*
+    * SWT Windows flags
+    */
+    public static BOOL IsWin32s;
+    public static BOOL IsWin95;
+    public static BOOL IsWinNT;
+
+    version(WinCE) {
+        public const static BOOL IsWinCE = true;
+        public static const BOOL IsHPC   = false; //todo
+    }
+    else {
+        public const static BOOL IsWinCE = false;
+        public static const BOOL IsHPC   = false;
+    }
+
+    public static const BOOL IsPPC = false;
+
+    // PORTING_FIXME, is it Windows WFSP?
+    public static const BOOL IsSP = false;
+
+    public static const BOOL IsDBLocale;
+
+    version(ANSI) {
+        public const BOOL IsUnicode = false;
+    }else{
+        public const BOOL IsUnicode = true;
+    }
+
+    public static const int WIN32_MAJOR, WIN32_MINOR, WIN32_VERSION;
+    public static const int COMCTL32_MAJOR, COMCTL32_MINOR, COMCTL32_VERSION;
+    public static const int SHELL32_MAJOR, SHELL32_MINOR, SHELL32_VERSION;
+
+    public static const char[] NO_MANIFEST = "org.eclipse.swt.internal.win32.OS.NO_MANIFEST";
+
+
+    /*
+    * Flags for Window API GetVersionEx()
+    */
+    public static const int VER_PLATFORM_WIN32s = 0;
+    public static const int VER_PLATFORM_WIN32_WINDOWS = 1;
+    public static const int VER_PLATFORM_WIN32_NT = 2;
+    public static const int VER_PLATFORM_WIN32_CE = 3;
+
+    /* Forward references */
+    public static const int HEAP_ZERO_MEMORY = 0x8;
+    public static const int ACTCTX_FLAG_RESOURCE_NAME_VALID    = 0x00000008;
+    public static const int ACTCTX_FLAG_SET_PROCESS_DEFAULT    = 0x00000010;
+    public static const int ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x00000020;
+    public static const int ACTCTX_FLAG_OVERRIDEMANIFEST_VALID = 0x00000100;
+    public static const TCHAR* MANIFEST_RESOURCE_ID = cast(TCHAR*)1;
+    public static const int SM_DBCSENABLED = 0x2A;
+    public static const int SM_IMMENABLED = 0x52;
+    public static const int LANG_KOREAN = 0x12;
+    public static const int MAX_PATH = 260;
+
+//     static this(){
+//         NOTIFYICONDATAA_V2_SIZE = getNOTIFYICONDATAA_V2_SIZE ();
+//         NOTIFYICONDATAW_V2_SIZE = getNOTIFYICONDATAW_V2_SIZE ();
+//         NOTIFYICONDATA_V2_SIZE = IsUnicode ? getNOTIFYICONDATAW_V2_SIZE : getNOTIFYICONDATAA_V2_SIZE;
+//         OSVERSIONINFO info;
+//         IsWin32s = (info.dwPlatformId is VER_PLATFORM_WIN32s);
+//         IsWin95 = (info.dwPlatformId is VER_PLATFORM_WIN32_WINDOWS);
+//         IsWinNT = (info.dwPlatformId is VER_PLATFORM_WIN32_NT);
+//         //IsSP_ = false;
+//         //IsPPC_ = false;
+//         //IsHPC = false;
+//         IsDBLocale = false;
+//         WIN32_MAJOR = info.dwMajorVersion;
+//         WIN32_MINOR = info.dwMinorVersion;
+//         WIN32_VERSION = VERSION (WIN32_MAJOR, WIN32_MINOR);
+//         //IsUnicode = !IsWin32s && !IsWin95;
+//         DLLVERSIONINFO dvi;
+//         COMCTL32_MAJOR = dvi.dwMajorVersion;
+//         COMCTL32_MINOR = dvi.dwMinorVersion;
+//         COMCTL32_VERSION = VERSION (COMCTL32_MAJOR, COMCTL32_MINOR);
+//         SHELL32_MAJOR = dvi.dwMajorVersion;
+//         SHELL32_MINOR = dvi.dwMinorVersion;
+//         SHELL32_VERSION = VERSION (SHELL32_MAJOR, SHELL32_MINOR);
+//     }
+
+    /* Get the Windows version and the flags */
+    public static this() {
+        LDWTRESULT.ONE = new LDWTRESULT(1);
+        LDWTRESULT.ZERO = new LDWTRESULT(0);
+        /*
+        * Try the UNICODE version of GetVersionEx first
+        * and then the ANSI version.  The UNICODE version
+        * is present on all versions of Windows but is not
+        * implemented on Win95/98/ME.
+        *
+        * NOTE: The value of OSVERSIONINFO.sizeof cannot
+        * be static final because it relies on the Windows
+        * platform version to be initialized and IsUnicode
+        * has not been calculated.  It must be initialized
+        * here, after the platform is determined in order
+        * for the value to be correct.
+        */
+        OSVERSIONINFO info;
+        info.dwOSVersionInfoSize = OSVERSIONINFO.sizeof;
+        if(!OS.GetVersionEx(&info)){
+            MessageBoxA(null,
+                    _PCHAR!("SWT Unicode version applications can't run in a non-Unicode platform !"),
+                    _PCHAR!("Error"),
+                    MB_OK|MB_ICONERROR);
+            tango.stdc.stdlib.exit(-1);
+        }
+        //OSVERSIONINFO info = new OSVERSIONINFOW ();
+        //info.dwOSVersionInfoSize = OSVERSIONINFOW.sizeof;
+        //if (!OS.GetVersionExW ((OSVERSIONINFOW)info)) {
+        //    info = new OSVERSIONINFOA ();
+        //    info.dwOSVersionInfoSize = OSVERSIONINFOA.sizeof;
+        //    OS.GetVersionExA ((OSVERSIONINFOA)info);
+        //}
+        //OSVERSIONINFO.sizeof = info.dwOSVersionInfoSize;
+
+        IsWin32s = (info.dwPlatformId is VER_PLATFORM_WIN32s);
+        IsWin95 = (info.dwPlatformId is VER_PLATFORM_WIN32_WINDOWS);
+        IsWinNT = (info.dwPlatformId is VER_PLATFORM_WIN32_NT);
+        //PORTING_CHANGE: made by version
+        //IsWinCE = (info.dwPlatformId is VER_PLATFORM_WIN32_CE);
+        //PORTING_CHANGE: made by version
+        //IsSP  = IsSP();
+        //PORTING_CHANGE: made by version
+        //IsPPC = IsPPC();
+        version(WinCE) {
+            IsHPC = IsWinCE && !IsPPC && !IsSP;
+        }
+        WIN32_MAJOR = info.dwMajorVersion;
+        WIN32_MINOR = info.dwMinorVersion;
+        WIN32_VERSION = VERSION (WIN32_MAJOR, WIN32_MINOR);
+
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
+            loadLib( Symbols_Kernel32, `Kernel32.dll` );
+        }
+
+        //PORTING_CHANGE: made by version
+        //IsUnicode = !IsWin32s && !IsWin95;
+
+        /* Load the manifest to force the XP Theme */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            //enableVisualStyles();
+        }
+
+        // when to load uxtheme
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            loadLib( Symbols_UxTheme, `UxTheme.dll` );
+        }
+        if (OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            loadLib( Symbols_CoreImm, `Coreimm.dll` );
+        }
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
+            loadLib( Symbols_User32, `User32.dll` );
+        }
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 0)) {
+            loadLib( Symbols_Imm32, `Imm32.dll` );
+        }
+
+        /* Make the process DPI aware for Windows Vista */
+        if (OS.WIN32_VERSION >= OS.VERSION (6, 0)) OS.SetProcessDPIAware ();
+
+        /* Get the DBCS flag */
+        BOOL dbcsEnabled = OS.GetSystemMetrics (SM_DBCSENABLED) !is 0;
+        BOOL immEnabled = OS.GetSystemMetrics (SM_IMMENABLED) !is 0;
+        IsDBLocale = dbcsEnabled || immEnabled;
+
+        /*
+        * Bug in Windows.  On Korean Windows XP when the Text
+        * Services Framework support for legacy applications
+        * is enabled, certain legacy calls segment fault.
+        * For example, when ImmSetCompositionWindow() is used
+        * to move the composition window outside of the client
+        * area, Windows crashes.  The fix is to disable legacy
+        * support.
+        *
+        * Note: The bug is fixed in Service Pack 2.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION is OS.VERSION (5, 1)) {
+            short langID = OS.GetSystemDefaultUILanguage ();
+            short primaryLang = OS.PRIMARYLANGID (langID);
+            if (primaryLang is LANG_KOREAN) {
+                OSVERSIONINFOEX infoex;
+                infoex.dwOSVersionInfoSize = OSVERSIONINFOEX.sizeof;
+                GetVersionEx (cast(OSVERSIONINFO*) &infoex );
+                if (infoex.wServicePackMajor < 2) {
+                    OS.ImmDisableTextFrameService (0);
+                }
+            }
+        }
+
+        /* Get the COMCTL32.DLL version */
+        DLLVERSIONINFO dvi;
+        dvi.cbSize = DLLVERSIONINFO.sizeof;
+        dvi.dwMajorVersion = 4;
+        dvi.dwMinorVersion = 0;
+        //PORTING_CHANGE: comctl is loaded automatically
+        //TCHAR lpLibFileName = new TCHAR (0, "comctl32.dll", true); //$NON-NLS-1$
+        //int /*long*/ hModule = OS.LoadLibrary (lpLibFileName);
+        if (auto lib = SharedLib.load( `comctl32.dll`) ) {
+            char[] name = "DllGetVersion\0"; //$NON-NLS-1$
+            void* DllGetVersion = lib.getSymbol(name.ptr);
+            if (DllGetVersion !is null){
+                alias extern(Windows) void function(DLLVERSIONINFO*) TDllVersion;
+                TDllVersion f = cast( TDllVersion )DllGetVersion;
+                f(&dvi);
+            }
+            lib.unload();
+        }
+        COMCTL32_MAJOR = dvi.dwMajorVersion;
+        COMCTL32_MINOR = dvi.dwMinorVersion;
+        COMCTL32_VERSION = VERSION (COMCTL32_MAJOR, COMCTL32_MINOR);
+
+        /* Get the Shell32.DLL version */
+        dvi = DLLVERSIONINFO.init;
+        dvi.cbSize = DLLVERSIONINFO.sizeof;
+        dvi.dwMajorVersion = 4;
+        //TCHAR lpLibFileName = new TCHAR (0, "Shell32.dll", true); //$NON-NLS-1$
+        //int /*long*/ hModule = OS.LoadLibrary (lpLibFileName);
+        if ( auto lib = SharedLib.load( `Shell32.dll`)) {
+            char[] name = "DllGetVersion\0"; //$NON-NLS-1$
+            void* DllGetVersion = lib.getSymbol(name.ptr);
+            if (DllGetVersion !is null){
+                alias extern(Windows) void function(DLLVERSIONINFO*) TDllVersion;
+                TDllVersion f = cast( TDllVersion )DllGetVersion;
+                f(&dvi);
+            }
+            lib.unload();
+        }
+        SHELL32_MAJOR = dvi.dwMajorVersion;
+        SHELL32_MINOR = dvi.dwMinorVersion;
+        SHELL32_VERSION = VERSION (SHELL32_MAJOR, SHELL32_MINOR);
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    public static void enableVisualStyles() {
+        void printError( char[] msg ){
+            char[] winMsg = SysError.lastMsg();
+            char[2000] buf;
+            getDwtLogger.error("{}: {}", msg, CodePage.from( winMsg, buf ) );
+        }
+        TCHAR[] buffer = new TCHAR[ MAX_PATH ];
+        buffer[] = 0;
+        HANDLE hModule = OS.GetLibraryHandle ();
+        while (OS.GetModuleFileName (hModule, buffer.ptr, buffer.length ) is buffer.length ) {
+            buffer.length = buffer.length + MAX_PATH;
+            buffer[] = 0;
+        }
+        auto hHeap = OS.GetProcessHeap ();
+        int byteCount = buffer.length * TCHAR.sizeof;
+        TCHAR* pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+
+        ACTCTX pActCtx;
+        pActCtx.cbSize = ACTCTX.sizeof;
+        pActCtx.dwFlags = 0
+            | ACTCTX_FLAG_RESOURCE_NAME_VALID
+            | ACTCTX_FLAG_SET_PROCESS_DEFAULT
+            ;
+        pActCtx.lpSource = pszText;
+        pActCtx.lpApplicationName = pszText;
+        pActCtx.lpResourceName = MANIFEST_RESOURCE_ID;
+        HANDLE hActCtx = OS.CreateActCtx (&pActCtx);
+        if (hActCtx is INVALID_HANDLE_VALUE){
+            printError("CreateActCtx failed, hence theme support will not be available\n"
+                    "Please check for:\n"
+                    " - missing link option -L/su:windows:5 or -L/su:console:5\n"
+                    " - missing link option -L/rc:org.eclipse.swt\n"
+                    " - resource file 'org.eclipse.swt.res' was not accessible by linker\n"
+                    );
+        }
+        else{
+            ULONG_PTR ulpActivationCookie;
+            if (!OS.ActivateActCtx(hActCtx, &ulpActivationCookie)){
+                printError("ActivateActCtx failed" );
+            }
+        }
+
+        if (pszText !is null){
+            OS.HeapFree (hHeap, 0, pszText);
+        }
+
+        /*
+        * NOTE:  A single activation context is created and activated
+        * for the entire lifetime of the program.  It is deactivated
+        * and released by Windows when the program exits.
+        */
+    }
+
+    /**************************************************************************
+
+    **************************************************************************/
+
+    /* Flag used on WinCE */
+
+    static const int SYS_COLOR_INDEX_FLAG = OS.IsWinCE ? 0x40000000 : 0x0;
+
+    /*
+    * NOTE:  There is a bug in JVM 1.2 where loading
+    * a class with a large number of constants causes
+    * a segment fault to occur sometime later after
+    * the class is loaded.  The fix is to break the
+    * class up into a hierarchy of classes that each
+    * contain a smaller number of constants.  This
+    * fix is not necessary at this time but is required
+    * when all constants are uncommented.  We have not
+    * done the research to determine the limit.
+    */
+
+    /* Constants */
+    public static const int ABS_DOWNDISABLED = 8;
+    public static const int ABS_DOWNHOT = 6;
+    public static const int ABS_DOWNNORMAL = 5;
+    public static const int ABS_DOWNPRESSED = 7;
+    public static const int ABS_LEFTDISABLED = 12;
+    public static const int ABS_LEFTHOT = 10;
+    public static const int ABS_LEFTNORMAL = 9;
+    public static const int ABS_LEFTPRESSED = 11;
+    public static const int ABS_RIGHTDISABLED = 16;
+    public static const int ABS_RIGHTHOT = 14;
+    public static const int ABS_RIGHTNORMAL = 13;
+    public static const int ABS_RIGHTPRESSED = 15;
+    public static const int ABS_UPDISABLED = 4;
+    public static const int ABS_UPHOT = 2;
+    public static const int ABS_UPNORMAL = 1;
+    public static const int ABS_UPPRESSED = 3;
+    public static const int AC_SRC_OVER = 0;
+    public static const int AC_SRC_ALPHA = 1;
+//  public static const int ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x00000008;
+//  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;
+    public static const int ASSOCSTR_FRIENDLYDOCNAME = 3;
+    public static const int AW_SLIDE = 0x00040000;
+    public static const int AW_ACTIVATE = 0x00020000;
+    public static const int AW_BLEND = 0x00080000;
+    public static const int AW_HIDE = 0x00010000;
+    public static const int AW_CENTER = 0x00000010;
+    public static const int AW_HOR_POSITIVE = 0x00000001;
+    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;
+    public static const int BCM_GETNOTE = BCM_FIRST + 0xa;
+    public static const int BCM_GETNOTELENGTH = BCM_FIRST + 0xb;
+    public static const int BCM_SETIMAGELIST = BCM_FIRST + 0x2;
+    public static const int BCM_SETNOTE = BCM_FIRST + 0x9;
+    public static const int BDR_RAISEDOUTER = 0x0001;
+    public static const int BDR_SUNKENOUTER = 0x0002;
+    public static const int BDR_RAISEDINNER = 0x0004;
+    public static const int BDR_SUNKENINNER = 0x0008;
+    public static const int BDR_OUTER = 0x0003;
+    public static const int BDR_INNER = 0x000c;
+    public static const int BDR_RAISED = 0x0005;
+    public static const int BDR_SUNKEN = 0x000a;
+    public static const int BFFM_INITIALIZED = 0x1;
+    public static const int BFFM_SETSELECTION = IsUnicode ? 0x467 : 0x466;
+    public static const int BFFM_VALIDATEFAILED = IsUnicode ? 0x4 : 0x3;
+    public static const int BFFM_VALIDATEFAILEDW = 0x4;
+    public static const int BFFM_VALIDATEFAILEDA = 0x3;
+    public static const int BF_ADJUST = 0x2000;
+    public static const int BF_LEFT = 0x0001;
+    public static const int BF_TOP = 0x0002;
+    public static const int BF_RIGHT = 0x0004;
+    public static const int BF_BOTTOM = 0x0008;
+    public static const int BF_RECT = (BF_LEFT | BF_TOP | BF_RIGHT | BF_BOTTOM);
+    public static const int BIF_EDITBOX = 0x10;
+    public static const int BIF_NEWDIALOGSTYLE = 0x40;
+    public static const int BIF_RETURNONLYFSDIRS = 0x1;
+    public static const int BIF_VALIDATE = 0x20;
+    public static const int BITSPIXEL = 0xc;
+    public static const int BI_BITFIELDS = 3;
+    public static const int BI_RGB = 0;
+    public static const int BLACKNESS = 0x42;
+    public static const int BLACK_BRUSH = 4;
+    public static const int BUTTON_IMAGELIST_ALIGN_LEFT = 0;
+    public static const int BUTTON_IMAGELIST_ALIGN_RIGHT = 1;
+    public static const int BUTTON_IMAGELIST_ALIGN_CENTER = 4;
+    public static const int BM_CLICK = 0xf5;
+    public static const int BM_GETCHECK = 0xf0;
+    public static const int BM_SETCHECK = 0xf1;
+    public static const int BM_SETIMAGE = 0xf7;
+    public static const int BM_SETSTYLE = 0xf4;
+    public static const int BN_CLICKED = 0x0;
+    public static const int BN_DOUBLECLICKED = 0x5;
+    public static const int BPBF_COMPATIBLEBITMAP = 0;
+    public static const int BPBF_DIB = 1;
+    public static const int BPBF_TOPDOWNDIB = 2;
+    public static const int BPBF_TOPDOWNMONODIB = 3;
+    public static const int BPPF_ERASE = 0x0001;
+    public static const int BPPF_NOCLIP = 0x0002;
+    public static const int BPPF_NONCLIENT = 0x0004;
+    public static const int BP_PUSHBUTTON = 1;
+    public static const int BP_RADIOBUTTON = 2;
+    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;
+    public static const int BS_COMMANDLINK =  0xe;
+    public static const int BS_DEFPUSHBUTTON = 0x1;
+    public static const int BS_FLAT = 0x8000;
+    public static const int BS_GROUPBOX = 0x7;
+    public static const int BS_ICON = 0x40;
+    public static const int BS_LEFT = 0x100;
+    public static const int BS_NOTIFY = 0x4000;
+    public static const int BS_OWNERDRAW = 0xb;
+    public static const int BS_PATTERN = 0x3;
+    public static const int BS_PUSHBUTTON = 0x0;
+    public static const int BS_PUSHLIKE = 0x1000;
+    public static const int BS_RADIOBUTTON = 0x4;
+    public static const int BS_RIGHT = 0x200;
+    public static const int BS_SOLID = 0x0;
+    public static const int BTNS_AUTOSIZE = 0x10;
+    public static const int BTNS_BUTTON = 0x0;
+    public static const int BTNS_CHECK = 0x2;
+    public static const int BTNS_CHECKGROUP = 0x6;
+    public static const int BTNS_DROPDOWN = 0x8;
+    public static const int BTNS_GROUP = 0x4;
+    public static const int BTNS_SEP = 0x1;
+    public static const int BTNS_SHOWTEXT = 0x40;
+    public static const int CBN_EDITCHANGE = 0x5;
+    public static const int CBN_KILLFOCUS = 0x4;
+    public static const int CBN_SELCHANGE = 0x1;
+    public static const int CBN_SETFOCUS = 0x3;
+    public static const int CBS_AUTOHSCROLL = 0x40;
+    public static const int CBS_DROPDOWN = 0x2;
+    public static const int CBS_DROPDOWNLIST = 0x3;
+    public static const int CBS_CHECKEDNORMAL = 5;
+    public static const int CBS_MIXEDNORMAL = 9;
+    public static const int CBS_NOINTEGRALHEIGHT = 0x400;
+    public static const int CBS_SIMPLE = 0x1;
+    public static const int CBS_UNCHECKEDNORMAL = 1;
+    public static const int CBS_CHECKEDDISABLED = 8;
+    public static const int CBS_CHECKEDHOT = 6;
+    public static const int CBS_CHECKEDPRESSED = 7;
+    public static const int CBS_MIXEDDISABLED = 0;
+    public static const int CBS_MIXEDHOT = 0;
+    public static const int CBS_MIXEDPRESSED = 0;
+    public static const int CBS_UNCHECKEDDISABLED = 4;
+    public static const int CBS_UNCHECKEDHOT = 2;
+    public static const int CBS_UNCHECKEDPRESSED = 3;
+    public static const int CB_ADDSTRING = 0x143;
+    public static const int CB_DELETESTRING = 0x144;
+    public static const int CB_ERR = 0xffffffff;
+    public static const int CB_ERRSPACE = 0xfffffffe;
+    public static const int CB_FINDSTRINGEXACT = 0x158;
+    public static const int CB_GETCOUNT = 0x146;
+    public static const int CB_GETCURSEL = 0x147;
+    public static const int CB_GETDROPPEDCONTROLRECT = 0x152;
+    public static const int CB_GETDROPPEDSTATE = 0x157;
+    public static const int CB_GETDROPPEDWIDTH = 0x015f;
+    public static const int CB_GETEDITSEL = 0x140;
+    public static const int CB_GETHORIZONTALEXTENT = 0x015d;
+    public static const int CB_GETITEMHEIGHT = 0x154;
+    public static const int CB_GETLBTEXT = 0x148;
+    public static const int CB_GETLBTEXTLEN = 0x149;
+    public static const int CB_INSERTSTRING = 0x14a;
+    public static const int CB_LIMITTEXT = 0x141;
+    public static const int CB_RESETCONTENT = 0x14b;
+    public static const int CB_SELECTSTRING = 0x14d;
+    public static const int CB_SETCURSEL = 0x14e;
+    public static const int CB_SETDROPPEDWIDTH= 0x0160;
+    public static const int CB_SETEDITSEL = 0x142;
+    public static const int CB_SETHORIZONTALEXTENT = 0x015e;
+    public static const int CB_SETITEMHEIGHT = 0x0153;
+    public static const int CB_SHOWDROPDOWN = 0x14f;
+    public static const int CBXS_NORMAL = 1;
+    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;
+    public static const int CCS_NODIVIDER = 0x40;
+    public static const int CCS_NORESIZE = 0x4;
+    public static const int CCS_VERT = 0x80;
+    public static const int CC_ANYCOLOR = 0x100;
+    public static const int CC_ENABLEHOOK = 0x10;
+    public static const int CC_FULLOPEN = 0x2;
+    public static const int CC_RGBINIT = 0x1;
+    public static const int CDDS_POSTERASE = 0x00000004;
+    public static const int CDDS_POSTPAINT = 0x00000002;
+    public static const int CDDS_PREERASE = 0x00000003;
+    public static const int CDDS_PREPAINT = 0x00000001;
+    public static const int CDDS_ITEM = 0x00010000;
+    public static const int CDDS_ITEMPOSTPAINT = CDDS_ITEM | CDDS_POSTPAINT;
+    public static const int CDDS_ITEMPREPAINT = CDDS_ITEM | CDDS_PREPAINT;
+    public static const int CDDS_SUBITEM = 0x00020000;
+    public static const int CDDS_SUBITEMPOSTPAINT = CDDS_ITEMPOSTPAINT | CDDS_SUBITEM;
+    public static const int CDDS_SUBITEMPREPAINT = CDDS_ITEMPREPAINT | CDDS_SUBITEM;
+    public static const int CDIS_SELECTED = 0x0001;
+    public static const int CDIS_GRAYED = 0x0002;
+    public static const int CDIS_DISABLED = 0x0004;
+    public static const int CDIS_CHECKED = 0x0008;
+    public static const int CDIS_FOCUS = 0x0010;
+    public static const int CDIS_DEFAULT = 0x0020;
+    public static const int CDIS_HOT = 0x0040;
+    public static const int CDIS_MARKED = 0x0080;
+    public static const int CDIS_INDETERMINATE = 0x0100;
+    public static const int CDM_FIRST = 0x0400 + 100;
+    public static const int CDM_GETSPEC = CDM_FIRST;
+    public static const int CDN_FIRST = -601;
+    public static const int CDN_SELCHANGE = CDN_FIRST - 1;
+    public static const int CDRF_DODEFAULT = 0x00000000;
+    public static const int CDRF_DOERASE = 0x00000008;
+    public static const int CDRF_NEWFONT = 0x00000002;
+    public static const int CDRF_NOTIFYITEMDRAW = 0x00000020;
+    public static const int CDRF_NOTIFYPOSTERASE = 0x00000040;
+    public static const int CDRF_NOTIFYPOSTPAINT = 0x00000010;
+    public static const int CDRF_NOTIFYSUBITEMDRAW = 0x00000020;
+    public static const int CDRF_SKIPDEFAULT = 0x04;
+    public static const int CDRF_SKIPPOSTPAINT = 0x00000100;
+    public static const int CFE_AUTOCOLOR = 0x40000000;
+    public static const int CFE_ITALIC = 0x2;
+    public static const int CFE_STRIKEOUT = 0x8;
+    public static const int CFE_UNDERLINE = 0x4;
+    public static const int CFM_BOLD = 0x1;
+    public static const int CFM_CHARSET = 0x8000000;
+    public static const int CFM_COLOR = 0x40000000;
+    public static const int CFM_FACE = 0x20000000;
+    public static const int CFM_ITALIC = 0x2;
+    public static const int CFM_SIZE = 0x80000000;
+    public static const int CFM_STRIKEOUT = 0x8;
+    public static const int CFM_UNDERLINE = 0x4;
+    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;
+    public static const int CF_TEXT = 0x1;
+    public static const int CF_UNICODETEXT = 13;
+    public static const int CF_USESTYLE = 0x80;
+    public static const int CLR_DEFAULT = 0xff000000;
+    public static const int CLR_INVALID = 0xffffffff;
+    public static const int CLR_NONE = 0xffffffff;
+    public static const int CLSCTX_INPROC_SERVER = 1;
+    public static const int COLORONCOLOR = 0x3;
+    public static const int COLOR_3DDKSHADOW = 0x15 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_3DFACE = 0xf | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_3DHIGHLIGHT = 0x14 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_3DHILIGHT = 0x14 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_3DLIGHT = 0x16 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_3DSHADOW = 0x10 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_ACTIVECAPTION = 0x2 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_BTNFACE = 0xf | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_BTNHIGHLIGHT = 0x14 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_BTNSHADOW = 0x10 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_BTNTEXT = 0x12 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_CAPTIONTEXT = 0x9 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_GRADIENTACTIVECAPTION = 0x1b | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_GRADIENTINACTIVECAPTION = 0x1c | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_GRAYTEXT = 0x11 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_HIGHLIGHT = 0xd | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_HIGHLIGHTTEXT = 0xe | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_HOTLIGHT = 26 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_INACTIVECAPTION = 0x3 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_INACTIVECAPTIONTEXT = 0x13 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_INFOBK = 0x18 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_INFOTEXT = 0x17 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_MENU = 0x4 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_MENUTEXT = 0x7 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_SCROLLBAR = 0x0 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_WINDOW = 0x5 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_WINDOWFRAME = 0x6 | SYS_COLOR_INDEX_FLAG;
+    public static const int COLOR_WINDOWTEXT = 0x8 | SYS_COLOR_INDEX_FLAG;
+    public static const int COMPLEXREGION = 0x3;
+    public static const int CP_ACP = 0x0;
+    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;
+    public static const int CS_GLOBALCLASS = 0x4000;
+    public static const int CS_HREDRAW = 0x2;
+    public static const int CS_VREDRAW = 0x1;
+    public static const int CW_USEDEFAULT = 0x80000000;
+    public static const TCHAR[] DATETIMEPICK_CLASS = "SysDateTimePick32"; //$NON-NLS-1$
+    public static const int DATE_LONGDATE = 0x00000002;
+    public static const int DATE_SHORTDATE = 0x00000001;
+    public static const int DATE_YEARMONTH = 0x00000008; //#if(WINVER >= 0x0500)
+    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;
+    public static const int DFCS_CHECKED = 0x400;
+    public static const int DFCS_FLAT = 0x4000;
+    public static const int DFCS_INACTIVE = 0x100;
+    public static const int DFCS_PUSHED = 0x200;
+    public static const int DFCS_SCROLLDOWN = 0x1;
+    public static const int DFCS_SCROLLLEFT = 0x2;
+    public static const int DFCS_SCROLLRIGHT = 0x3;
+    public static const int DFCS_SCROLLUP = 0x0;
+    public static const int DFC_BUTTON = 0x4;
+    public static const int DFC_SCROLL = 0x3;
+    public static const int DIB_RGB_COLORS = 0x0;
+    public static const int DISP_E_EXCEPTION = 0x80020009;
+    public static const int DI_NORMAL = 0x3;
+    public static const int DI_NOMIRROR = 0x10;
+    public static const int DLGC_BUTTON = 0x2000;
+    public static const int DLGC_HASSETSEL = 0x8;
+    public static const int DLGC_STATIC = 0x100;
+    public static const int DLGC_WANTALLKEYS = 0x4;
+    public static const int DLGC_WANTARROWS = 0x1;
+    public static const int DLGC_WANTCHARS = 0x80;
+    public static const int DLGC_WANTTAB = 0x2;
+    public static const int DM_SETDEFID = 0x401;
+    public static const int DSS_DISABLED = 0x20;
+    public static const int DSTINVERT = 0x550009;
+    public static const int DST_BITMAP = 0x4;
+    public static const int DST_ICON = 0x3;
+    public static const int DT_BOTTOM = 0x8;
+    public static const int DT_CALCRECT = 0x400;
+    public static const int DT_CENTER = 0x1;
+    public static const int DT_EDITCONTROL = 0x2000;
+    public static const int DT_EXPANDTABS = 0x40;
+    public static const int DT_ENDELLIPSIS = 32768;
+    public static const int DT_HIDEPREFIX = 0x100000;
+    public static const int DT_LEFT = 0x0;
+    public static const int DT_NOPREFIX = 0x800;
+    public static const int DT_RASPRINTER = 0x2;
+    public static const int DT_RIGHT = 0x2;
+    public static const int DT_SINGLELINE = 0x20;
+    public static const int DT_TOP = 0;
+    public static const int DT_VCENTER = 4;
+    public static const int DT_WORDBREAK = 0x10;
+    public static const int DTM_FIRST = 0x1000;
+    public static const int DTM_GETSYSTEMTIME = DTM_FIRST + 1;
+    public static const int DTM_SETFORMAT = IsUnicode ? DTM_FIRST + 50 : DTM_FIRST + 5;
+    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;
+    public static const int EBP_NORMALGROUPEXPAND = 7;
+    public static const int EBP_NORMALGROUPHEAD = 8;
+    public static const int EBNGC_NORMAL = 1;
+    public static const int EBNGC_HOT = 2;
+    public static const int EBNGC_PRESSED = 3;
+    public static const int EBP_HEADERBACKGROUND = 1;
+    public static const int EC_LEFTMARGIN = 0x1;
+    public static const int EC_RIGHTMARGIN = 0x2;
+    public static const int ECOOP_AND = 0x3;
+    public static const int ECOOP_OR = 0x2;
+    public static const int ECO_AUTOHSCROLL = 0x80;
+    public static const int EDGE_RAISED = (BDR_RAISEDOUTER | BDR_RAISEDINNER);
+    public static const int EDGE_SUNKEN = (BDR_SUNKENOUTER | BDR_SUNKENINNER);
+    public static const int EDGE_ETCHED = (BDR_SUNKENOUTER | BDR_RAISEDINNER);
+    public static const int EDGE_BUMP = (BDR_RAISEDOUTER | BDR_SUNKENINNER);
+    public static const int ELF_VENDOR_SIZE = 4;
+    public static const int EM_CANUNDO = 0xc6;
+    public static const int EM_CHARFROMPOS = 0xd7;
+    public static const int EM_DISPLAYBAND = 0x433;
+    public static const int EM_GETFIRSTVISIBLELINE = 0xce;
+    public static const int EM_GETLIMITTEXT = 0xd5;
+    public static const int EM_GETLINE = 0xc4;
+    public static const int EM_GETLINECOUNT = 0xba;
+    public static const int EM_GETMARGINS = 0xd4;
+    public static const int EM_GETPASSWORDCHAR = 0xd2;
+    public static const int EM_GETSCROLLPOS = 0x4dd;
+    public static const int EM_GETSEL = 0xb0;
+    public static const int EM_LIMITTEXT = 0xc5;
+    public static const int EM_LINEFROMCHAR = 0xc9;
+    public static const int EM_LINEINDEX = 0xbb;
+    public static const int EM_LINELENGTH = 0xc1;
+    public static const int EM_LINESCROLL = 0xb6;
+    public static const int EM_POSFROMCHAR = 0xd6;
+    public static const int EM_REPLACESEL = 0xc2;
+    public static const int EM_SCROLLCARET = 0xb7;
+    public static const int EM_SETBKGNDCOLOR = 0x443;
+    public static const int EM_SETLIMITTEXT = 0xc5;
+    public static const int EM_SETMARGINS = 211;
+    public static const int EM_SETOPTIONS = 0x44d;
+    public static const int EM_SETPARAFORMAT = 0x447;
+    public static const int EM_SETPASSWORDCHAR = 0xcc;
+    public static const int EM_SETCUEBANNER = 0x1500 + 1;
+    public static const int EM_SETREADONLY = 0xcf;
+    public static const int EM_SETSEL = 0xb1;
+    public static const int EM_SETTABSTOPS = 0xcb;
+    public static const int EM_UNDO = 199;
+    public static const int EMR_EXTCREATEFONTINDIRECTW = 82;
+    public static const int EMR_EXTTEXTOUTW = 84;
+    public static const int EN_ALIGN_LTR_EC = 0x0700;
+    public static const int EN_ALIGN_RTL_EC = 0x0701;
+    public static const int EN_CHANGE = 0x300;
+    public static const int EP_EDITTEXT = 1;
+    public static const int ERROR_NO_MORE_ITEMS = 0x103;
+    public static const int ESB_DISABLE_BOTH = 0x3;
+    public static const int ESB_ENABLE_BOTH = 0x0;
+    public static const int ES_AUTOHSCROLL = 0x80;
+    public static const int ES_AUTOVSCROLL = 0x40;
+    public static const int ES_CENTER = 0x1;
+    public static const int ES_MULTILINE = 0x4;
+    public static const int ES_NOHIDESEL = 0x100;
+    public static const int ES_PASSWORD = 0x20;
+    public static const int ES_READONLY = 0x800;
+    public static const int ES_RIGHT = 0x2;
+    public static const int ETO_CLIPPED = 0x4;
+    public static const int ETS_NORMAL = 1;
+    public static const int ETS_HOT = 2;
+    public static const int ETS_SELECTED = 3;
+    public static const int ETS_DISABLED = 4;
+    public static const int ETS_FOCUSED = 5;
+    public static const int ETS_READONLY = 6;
+    public static const int EVENT_OBJECT_FOCUS = 0x8005;
+    public static const int EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
+//  public static const int EVENT_OBJECT_SELECTION = 0x8006;
+    public static const int EVENT_OBJECT_SELECTIONWITHIN = 0x8009;
+    public static const int EVENT_OBJECT_VALUECHANGE = 0x800E;
+    public static const int FALT = 0x10;
+    public static const int FCONTROL = 0x8;
+    public static const int FE_FONTSMOOTHINGCLEARTYPE = 0x0002;
+    public static const int FEATURE_DISABLE_NAVIGATION_SOUNDS = 21;
+    public static const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
+    public static const int FNERR_INVALIDFILENAME = 0x3002;
+    public static const int FNERR_BUFFERTOOSMALL = 0x3003;
+    public static const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
+    public static const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+    public static const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+    public static const int FR_PRIVATE = 0x10;
+    public static const int FSHIFT = 0x4;
+    public static const int FVIRTKEY = 0x1;
+    public static const int GBS_NORMAL = 1;
+    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;
+    public static const int GLPS_OPENED = 2;
+    public static const int GM_ADVANCED = 2;
+    public static const int GMDI_USEDISABLED = 0x1;
+    public static const int GMEM_FIXED = 0x0;
+    public static const int GMEM_ZEROINIT = 0x40;
+    public static const int GN_CONTEXTMENU = 1000;
+    public static const int GPTR = 0x40;
+    public static const int GRADIENT_FILL_RECT_H = 0x0;
+    public static const int GRADIENT_FILL_RECT_V = 0x1;
+    public static const int GTL_NUMBYTES = 0x10;
+    public static const int GTL_NUMCHARS = 0x8;
+    public static const int GTL_PRECISE = 0x2;
+    public static const int GT_DEFAULT = 0x0;
+    public static const int GUI_16BITTASK = 0x20;
+    public static const int GUI_CARETBLINKING = 0x1;
+    public static const int GUI_INMENUMODE = 0x4;
+    public static const int GUI_INMOVESIZE = 0x2;
+    public static const int GUI_POPUPMENUMODE = 0x10;
+    public static const int GUI_SYSTEMMENUMODE = 0x8;
+    public static const int GWL_EXSTYLE = 0xffffffec;
+    public static const int GWL_ID = -12;
+    public static const int GWL_HWNDPARENT = -8;
+    public static const int GWL_STYLE = 0xfffffff0;
+    public static const int GWL_USERDATA = 0xffffffeb;
+    public static const int GWL_WNDPROC = 0xfffffffc;
+    public static const int GWLP_ID = -12;
+    public static const int GWLP_HWNDPARENT = -8;
+    public static const int GWLP_USERDATA = 0xffffffeb;
+    public static const int GWLP_WNDPROC = 0xfffffffc;
+    public static const int GW_CHILD = 0x5;
+    public static const int GW_HWNDFIRST = 0x0;
+    public static const int GW_HWNDLAST = 0x1;
+    public static const int GW_HWNDNEXT = 0x2;
+    public static const int GW_HWNDPREV = 0x3;
+    public static const int GW_OWNER = 0x4;
+    public static const HBITMAP HBMMENU_CALLBACK = cast(HBITMAP) 0xffffffff;
+    public static const int HCBT_CREATEWND = 3;
+    public static const int HCF_HIGHCONTRASTON = 0x1;
+    public static const int HDF_BITMAP = 0x2000;
+    public static const int HDF_BITMAP_ON_RIGHT = 0x1000;
+    public static const int HDF_CENTER = 2;
+    public static const int HDF_JUSTIFYMASK = 0x3;
+    public static const int HDF_IMAGE = 0x0800;
+    public static const int HDF_LEFT = 0;
+    public static const int HDF_RIGHT = 1;
+    public static const int HDF_SORTUP = 0x0400;
+    public static const int HDF_SORTDOWN = 0x0200;
+    public static const int HDI_BITMAP = 0x0010;
+    public static const int HDI_IMAGE = 32;
+    public static const int HDI_ORDER = 0x80;
+    public static const int HDI_TEXT = 0x2;
+    public static const int HDI_WIDTH = 0x1;
+    public static const int HDI_FORMAT = 0x4;
+    public static const int HDM_FIRST = 0x1200;
+    public static const int HDM_DELETEITEM = HDM_FIRST + 2;
+    public static const int HDM_GETBITMAPMARGIN = HDM_FIRST + 21;
+    public static const int HDM_GETITEMCOUNT = 0x1200;
+    public static const int HDM_GETITEMA = HDM_FIRST + 3;
+    public static const int HDM_GETITEMW = HDM_FIRST + 11;
+    public static const int HDM_GETITEM = IsUnicode ? HDM_GETITEMW : HDM_GETITEMA;
+    public static const int HDM_GETITEMRECT = HDM_FIRST + 7;
+    public static const int HDM_GETORDERARRAY = HDM_FIRST + 17;
+    public static const int HDM_HITTEST = HDM_FIRST + 6;
+    public static const int HDM_INSERTITEMA = HDM_FIRST + 1;
+    public static const int HDM_INSERTITEMW = HDM_FIRST + 10;
+    public static const int HDM_INSERTITEM = IsUnicode ? HDM_INSERTITEMW : HDM_INSERTITEMA;
+    public static const int HDM_LAYOUT = HDM_FIRST + 5;
+    public static const int HDM_ORDERTOINDEX = HDM_FIRST + 15;
+    public static const int HDM_SETIMAGELIST = HDM_FIRST + 8;
+    public static const int HDM_SETITEMA = HDM_FIRST + 4;
+    public static const int HDM_SETITEMW = HDM_FIRST + 12;
+    public static const int HDM_SETITEM = IsUnicode ? HDM_SETITEMW : HDM_SETITEMA;
+    public static const int HDM_SETORDERARRAY = HDM_FIRST + 18;
+    public static const int HDN_FIRST = 0xfffffed4;
+    public static const int HDN_BEGINDRAG = HDN_FIRST - 10;
+    public static const int HDN_BEGINTRACK = IsUnicode ? 0xfffffeba : 0xfffffece;
+    public static const int HDN_BEGINTRACKW = 0xfffffeba;
+    public static const int HDN_BEGINTRACKA = 0xfffffece;
+    public static const int HDN_DIVIDERDBLCLICKA = HDN_FIRST - 5;
+    public static const int HDN_DIVIDERDBLCLICKW = HDN_FIRST - 25;
+    public static const int HDN_DIVIDERDBLCLICK = IsUnicode ? HDN_DIVIDERDBLCLICKW : HDN_DIVIDERDBLCLICKA;
+    public static const int HDN_ENDDRAG = HDN_FIRST - 11;
+    public static const int HDN_ITEMCHANGED = IsUnicode ? 0xfffffebf : 0xfffffed3;
+    public static const int HDN_ITEMCHANGEDW = 0xfffffebf;
+    public static const int HDN_ITEMCHANGEDA = 0xfffffed3;
+    public static const int HDN_ITEMCHANGINGW = HDN_FIRST - 20;
+    public static const int HDN_ITEMCHANGINGA = HDN_FIRST;
+    public static const int HDN_ITEMCLICKW = HDN_FIRST - 22;
+    public static const int HDN_ITEMCLICKA = HDN_FIRST - 2;
+    public static const int HDN_ITEMDBLCLICKW = HDN_FIRST - 23;
+    public static const int HDN_ITEMDBLCLICKA = HDN_FIRST - 3;
+    public static const int HDN_ITEMDBLCLICK = IsUnicode ? HDN_ITEMDBLCLICKW : HDN_ITEMDBLCLICKA;
+    public static const int HDS_BUTTONS = 0x2;
+    public static const int HDS_DRAGDROP = 0x0040;
+    public static const int HDS_FULLDRAG = 0x80;
+    public static const int HDS_HIDDEN = 0x8;
+//  public static const int HEAP_ZERO_MEMORY = 0x8;
+    public static const int HELPINFO_MENUITEM = 0x2;
+    public static const int HHT_ONDIVIDER = 0x4;
+    public static const int HHT_ONDIVOPEN = 0x8;
+    public static const int HICF_ARROWKEYS = 0x2;
+    public static const int HINST_COMMCTRL = 0xffffffff;
+    public static const int HKEY_CLASSES_ROOT = 0x80000000;
+    public static const int HKEY_CURRENT_USER = 0x80000001;
+    public static const int HKEY_LOCAL_MACHINE = 0x80000002;
+    public static const int HORZRES = 0x8;
+    public static const int HTBORDER = 0x12;
+    public static const int HTCAPTION = 0x2;
+    public static const int HTCLIENT = 0x1;
+    public static const int HTERROR = -2;
+    public static const int HTHSCROLL = 0x6;
+    public static const int HTMENU = 0x5;
+    public static const int HTNOWHERE = 0x0;
+    public static const int HTSYSMENU = 0x3;
+    public static const int HTTRANSPARENT = 0xffffffff;
+    public static const int HTVSCROLL = 0x7;
+    public static const int HWND_BOTTOM = 0x1;
+    public static const int HWND_TOP = 0x0;
+    public static const int HWND_TOPMOST = 0xffffffff;
+    public static const int HWND_NOTOPMOST = -2;
+    public static const int ICC_COOL_CLASSES = 0x400;
+    public static const int ICC_DATE_CLASSES = 0x100;
+    public static const int ICM_NOTOPEN = 0x0;
+    public static const int ICON_BIG = 0x1;
+    public static const int ICON_SMALL = 0x0;
+    public static const int I_IMAGECALLBACK = -1;
+    public static const int I_IMAGENONE = -2;
+    public static const int IDABORT = 0x3;
+    public static const int IDANI_CAPTION = 3;
+    public static const int IDB_STD_SMALL_COLOR = 0x0;
+    public static const int IDC_APPSTARTING = 0x7f8a;
+    public static const int IDC_ARROW = 0x7f00;
+    public static const int IDC_CROSS = 0x7f03;
+    public static const TCHAR* IDC_HAND = cast(TCHAR*) 0x7f89;
+    public static const int IDC_HELP = 0x7f8b;
+    public static const int IDC_IBEAM = 0x7f01;
+    public static const int IDC_NO = 0x7f88;
+    public static const int IDC_SIZE = 0x7f80;
+    public static const int IDC_SIZEALL = 0x7f86;
+    public static const int IDC_SIZENESW = 0x7f83;
+    public static const int IDC_SIZENS = 0x7f85;
+    public static const int IDC_SIZENWSE = 0x7f82;
+    public static const int IDC_SIZEWE = 0x7f84;
+    public static const int IDC_UPARROW = 0x7f04;
+    public static const int IDC_WAIT = 0x7f02;
+    public static const int IDI_APPLICATION = 32512;
+    public static const int IDNO = 0x7;
+    public static const int IDOK = 0x1;
+    public static const int IDRETRY = 0x4;
+    public static const int IDYES = 0x6;
+    public static const int ILC_COLOR = 0x0;
+    public static const int ILC_COLOR16 = 0x10;
+    public static const int ILC_COLOR24 = 0x18;
+    public static const int ILC_COLOR32 = 0x20;
+    public static const int ILC_COLOR4 = 0x4;
+    public static const int ILC_COLOR8 = 0x8;
+    public static const int ILC_MASK = 0x1;
+    public static const int ILC_MIRROR = 0x2000;
+    public static const int ILD_NORMAL = 0x0;
+    public static const int ILD_SELECTED = 0x4;
+    public static const int IMAGE_BITMAP = 0x0;
+    public static const int IMAGE_CURSOR = 0x2;
+    public static const int IMAGE_ICON = 0x1;
+    public static const int IME_CMODE_FULLSHAPE = 0x8;
+    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;
+    public static const int INTERNET_OPTION_END_BROWSER_SESSION = 42;
+    public static const int KEY_ENUMERATE_SUB_KEYS = 0x8;
+    public static const int KEY_NOTIFY = 0x10;
+    public static const int KEY_QUERY_VALUE = 0x1;
+    public static const int KEY_READ = 0x20019;
+    public static const int KEYEVENTF_KEYUP = 0x0002;
+    public static const int L_MAX_URL_LENGTH = 2084;
+//  public static const int LANG_KOREAN = 0x12;
+    public static const int LANG_NEUTRAL = 0x0;
+    public static const int LANG_USER_DEFAULT = 1 << 10;
+    public static const int LAYOUT_RTL = 0x1;
+    public static const int LAYOUT_BITMAPORIENTATIONPRESERVED = 0x8;
+    public static const int LBN_DBLCLK = 0x2;
+    public static const int LBN_SELCHANGE = 0x1;
+    public static const int LBS_EXTENDEDSEL = 0x800;
+    public static const int LBS_MULTIPLESEL = 0x8;
+    public static const int LBS_NOINTEGRALHEIGHT = 0x100;
+    public static const int LBS_NOTIFY = 0x1;
+    public static const int LB_ADDSTRING = 0x180;
+    public static const int LB_DELETESTRING = 0x182;
+    public static const int LB_ERR = 0xffffffff;
+    public static const int LB_ERRSPACE = 0xfffffffe;
+    public static const int LB_FINDSTRINGEXACT = 0x1a2;
+    public static const int LB_GETCARETINDEX = 0x19f;
+    public static const int LB_GETCOUNT = 0x18b;
+    public static const int LB_GETCURSEL = 0x188;
+    public static const int LB_GETHORIZONTALEXTENT = 0x193;
+    public static const int LB_GETITEMHEIGHT = 0x1a1;
+    public static const int LB_GETITEMRECT = 0x198;
+    public static const int LB_GETSEL = 0x187;
+    public static const int LB_GETSELCOUNT = 0x190;
+    public static const int LB_GETSELITEMS = 0x191;
+    public static const int LB_GETTEXT = 0x189;
+    public static const int LB_GETTEXTLEN = 0x18a;
+    public static const int LB_GETTOPINDEX = 0x18e;
+    public static const int LB_INITSTORAGE = 0x1a8;
+    public static const int LB_INSERTSTRING = 0x181;
+    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;
+    public static const int LB_SETSEL = 0x185;
+    public static const int LB_SETTOPINDEX = 0x197;
+    public static const int LF_FULLFACESIZE = 64;
+    public static const int LF_FACESIZE = 32;
+    public static const int LGRPID_ARABIC = 0xd;
+    public static const int LGRPID_HEBREW = 0xc;
+    public static const int LGRPID_INSTALLED = 1;
+    public static const int LIF_ITEMINDEX = 0x1;
+    public static const int LIF_STATE = 0x2;
+    public static const int LIS_FOCUSED = 0x1;
+    public static const int LIS_ENABLED = 0x2;
+    public static const int LISS_HOT = 0x2;
+    public static const int LISS_SELECTED = 0x3;
+    public static const int LISS_SELECTEDNOTFOCUS = 0x5;
+    public static const int LM_GETIDEALHEIGHT = 0x701;
+    public static const int LM_SETITEM = 0x702;
+    public static const int LM_GETITEM = 0x703;
+    public static const int LCID_SUPPORTED = 0x2;
+    public static const int LOCALE_IDEFAULTANSICODEPAGE = 0x1004;
+    public static const int LOCALE_IDATE = 0x00000021;
+    public static const int LOCALE_ITIME = 0x00000023;
+    public static const int LOCALE_RETURN_NUMBER = 0x20000000; // #if(WINVER >= 0x0400)
+    public static const int LOCALE_S1159 = 0x00000028;
+    public static const int LOCALE_S2359 = 0x00000029;
+    public static const int LOCALE_SDECIMAL = 14;
+    public static const int LOCALE_SISO3166CTRYNAME = 0x5a;
+    public static const int LOCALE_SISO639LANGNAME = 0x59;
+    public static const int LOCALE_SLONGDATE = 0x00000020;
+    public static const int LOCALE_SSHORTDATE = 0x0000001F;
+    public static const int LOCALE_STIMEFORMAT = 0x00001003;
+    public static const int LOCALE_SYEARMONTH = 0x00001006;  // #if(WINVER >= 0x0500)
+    public static const int LOCALE_SDAYNAME1    = 0x0000002A;   // long name for Monday
+    public static const int LOCALE_SDAYNAME2    = 0x0000002B;   // long name for Tuesday
+    public static const int LOCALE_SDAYNAME3    = 0x0000002C;   // long name for Wednesday
+    public static const int LOCALE_SDAYNAME4    = 0x0000002D;   // long name for Thursday
+    public static const int LOCALE_SDAYNAME5    = 0x0000002E;   // long name for Friday
+    public static const int LOCALE_SDAYNAME6    = 0x0000002F;   // long name for Saturday
+    public static const int LOCALE_SDAYNAME7    = 0x00000030;   // long name for Sunday
+    public static const int LOCALE_SMONTHNAME1  = 0x00000038;   // long name for January
+    public static const int LOCALE_SMONTHNAME2  = 0x00000039;   // long name for February
+    public static const int LOCALE_SMONTHNAME3  = 0x0000003A;   // long name for March
+    public static const int LOCALE_SMONTHNAME4  = 0x0000003B;   // long name for April
+    public static const int LOCALE_SMONTHNAME5  = 0x0000003C;   // long name for May
+    public static const int LOCALE_SMONTHNAME6  = 0x0000003D;   // long name for June
+    public static const int LOCALE_SMONTHNAME7  = 0x0000003E;   // long name for July
+    public static const int LOCALE_SMONTHNAME8  = 0x0000003F;   // long name for August
+    public static const int LOCALE_SMONTHNAME9  = 0x00000040;   // long name for September
+    public static const int LOCALE_SMONTHNAME10 = 0x00000041;   // long name for October
+    public static const int LOCALE_SMONTHNAME11 = 0x00000042;   // long name for November
+    public static const int LOCALE_SMONTHNAME12 = 0x00000043;   // long name for December
+    public static const int LOCALE_USER_DEFAULT = 1024;
+    public static const int LOGPIXELSX = 0x58;
+    public static const int LOGPIXELSY = 0x5a;
+    public static const TCHAR* LPSTR_TEXTCALLBACK = cast(TCHAR*)0xffffffff;
+    public static const int LR_DEFAULTCOLOR = 0x0;
+    public static const int LR_SHARED = 0x8000;
+    public static const int LVCFMT_BITMAP_ON_RIGHT = 0x1000;
+    public static const int LVCFMT_CENTER = 0x2;
+    public static const int LVCFMT_IMAGE = 0x800;
+    public static const int LVCFMT_LEFT = 0x0;
+    public static const int LVCFMT_RIGHT = 0x1;
+    public static const int LVCF_FMT = 0x1;
+    public static const int LVCF_IMAGE = 0x10;
+    public static const int LVCFMT_JUSTIFYMASK = 0x3;
+    public static const int LVCF_TEXT = 0x4;
+    public static const int LVCF_WIDTH = 0x2;
+    public static const int LVHT_ONITEM = 0xe;
+    public static const int LVHT_ONITEMICON = 0x2;
+    public static const int LVHT_ONITEMLABEL = 0x4;
+    public static const int LVHT_ONITEMSTATEICON = 0x8;
+    public static const int LVIF_IMAGE = 0x2;
+    public static const int LVIF_INDENT = 0x10;
+    public static const int LVIF_STATE = 0x8;
+    public static const int LVIF_TEXT = 0x1;
+    public static const int LVIR_BOUNDS = 0x0;
+    public static const int LVIR_ICON = 0x1;
+    public static const int LVIR_LABEL = 0x2;
+    public static const int LVIR_SELECTBOUNDS = 0x3;
+    public static const int LVIS_DROPHILITED = 0x8;
+    public static const int LVIS_FOCUSED = 0x1;
+    public static const int LVIS_SELECTED = 0x2;
+    public static const int LVIS_STATEIMAGEMASK = 0xf000;
+    public static const int LVM_FIRST = 0x1000;
+    public static const int LVM_APPROXIMATEVIEWRECT = 0x1040;
+    public static const int LVM_CREATEDRAGIMAGE = LVM_FIRST + 33;
+    public static const int LVM_DELETEALLITEMS = 0x1009;
+    public static const int LVM_DELETECOLUMN = 0x101c;
+    public static const int LVM_DELETEITEM = 0x1008;
+    public static const int LVM_ENSUREVISIBLE = 0x1013;
+    public static const int LVM_GETBKCOLOR = 0x1000;
+    public static const int LVM_GETCOLUMN = IsUnicode ? 0x105f : 0x1019;
+    public static const int LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59;
+    public static const int LVM_GETCOLUMNWIDTH = 0x101d;
+    public static const int LVM_GETCOUNTPERPAGE = 0x1028;
+    public static const int LVM_GETEXTENDEDLISTVIEWSTYLE = 0x1037;
+    public static const int LVM_GETHEADER = 0x101f;
+    public static const int LVM_GETIMAGELIST = 0x1002;
+    public static const int LVM_GETITEM = IsUnicode ? 0x104b : 0x1005;
+    public static const int LVM_GETITEMW = 0x104b;
+    public static const int LVM_GETITEMA = 0x1005;
+    public static const int LVM_GETITEMCOUNT = 0x1004;
+    public static const int LVM_GETITEMRECT = 0x100e;
+    public static const int LVM_GETITEMSTATE = 0x102c;
+    public static const int LVM_GETNEXTITEM = 0x100c;
+    public static const int LVM_GETSELECTEDCOLUMN = LVM_FIRST + 174;
+    public static const int LVM_GETSELECTEDCOUNT = 0x1032;
+    public static const int LVM_GETSTRINGWIDTH = IsUnicode ? 0x1057 : 0x1011;
+    public static const int LVM_GETSUBITEMRECT = 0x1038;
+    public static const int LVM_GETTEXTCOLOR = 0x1023;
+    public static const int LVM_GETTOOLTIPS = 0x104e;
+    public static const int LVM_GETTOPINDEX = 0x1027;
+    public static const int LVM_HITTEST = 0x1012;
+    public static const int LVM_INSERTCOLUMN = IsUnicode ? 0x1061 : 0x101b;
+    public static const int LVM_INSERTITEM = IsUnicode ? 0x104d : 0x1007;
+    public static const int LVM_REDRAWITEMS = LVM_FIRST + 21;
+    public static const int LVM_SCROLL = 0x1014;
+    public static const int LVM_SETBKCOLOR = 0x1001;
+    public static const int LVM_SETCALLBACKMASK = LVM_FIRST + 11;
+    public static const int LVM_SETCOLUMN = IsUnicode ? 0x1060 : 0x101a;
+    public static const int LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58;
+    public static const int LVM_SETCOLUMNWIDTH = 0x101e;
+    public static const int LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036;
+    public static const int LVM_SETIMAGELIST = 0x1003;
+    public static const int LVM_SETITEM = IsUnicode ? 0x104c : 0x1006;
+    public static const int LVM_SETITEMCOUNT = LVM_FIRST + 47;
+    public static const int LVM_SETITEMSTATE = 0x102b;
+    public static const int LVM_SETSELECTIONMARK = LVM_FIRST + 67;
+    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;
+    public static const int LVN_BEGINRDRAG = 0xffffff91;
+    public static const int LVN_COLUMNCLICK = 0xffffff94;
+    public static const int LVN_FIRST = 0xffffff9c;
+    public static const int LVN_GETDISPINFOA = LVN_FIRST - 50;
+    public static const int LVN_GETDISPINFOW = LVN_FIRST - 77;
+    public static const int LVN_ITEMACTIVATE = 0xffffff8e;
+    public static const int LVN_ITEMCHANGED = 0xffffff9b;
+    public static const int LVN_MARQUEEBEGIN = 0xffffff64;
+    public static const int LVN_ODFINDITEMA = LVN_FIRST - 52;
+    public static const int LVN_ODFINDITEMW = LVN_FIRST - 79;
+    public static const int LVN_ODSTATECHANGED = LVN_FIRST - 15;
+    public static const int LVP_LISTITEM = 1;
+    public static const int LVSCW_AUTOSIZE = 0xffffffff;
+    public static const int LVSCW_AUTOSIZE_USEHEADER = 0xfffffffe;
+    public static const int LVSICF_NOINVALIDATEALL = 0x1;
+    public static const int LVSICF_NOSCROLL = 0x2;
+    public static const int LVSIL_SMALL = 0x1;
+    public static const int LVSIL_STATE = 0x2;
+    public static const int LVS_EX_DOUBLEBUFFER = 0x10000;
+    public static const int LVS_EX_FULLROWSELECT = 0x20;
+    public static const int LVS_EX_GRIDLINES = 0x1;
+    public static const int LVS_EX_HEADERDRAGDROP = 0x10;
+    public static const int LVS_EX_LABELTIP = 0x4000;
+    public static const int LVS_EX_ONECLICKACTIVATE = 0x40;
+    public static const int LVS_EX_SUBITEMIMAGES = 0x2;
+    public static const int LVS_EX_TRACKSELECT = 0x8;
+    public static const int LVS_EX_TRANSPARENTBKGND = 0x800000;
+    public static const int LVS_EX_TWOCLICKACTIVATE = 0x80;
+    public static const int LVS_LIST = 0x3;
+    public static const int LVS_NOCOLUMNHEADER = 0x4000;
+    public static const int LVS_NOSCROLL = 0x2000;
+    public static const int LVS_OWNERDATA = 0x1000;
+    public static const int LVS_OWNERDRAWFIXED = 0x400;
+    public static const int LVS_REPORT = 0x1;
+    public static const int LVS_SHAREIMAGELISTS = 0x40;
+    public static const int LVS_SHOWSELALWAYS = 0x8;
+    public static const int LVS_SINGLESEL = 0x4;
+    public static const int LWA_COLORKEY = 0x00000001;
+    public static const int LWA_ALPHA = 0x00000002;
+    public static const int MAX_LINKID_TEXT = 48;
+//  public static const int MAX_PATH = 260;
+    public static const int MA_NOACTIVATE = 0x3;
+//  public static const int MANIFEST_RESOURCE_ID = 2;
+    public static const int MB_ABORTRETRYIGNORE = 0x2;
+    public static const int MB_APPLMODAL = 0x0;
+    public static const int MB_ICONERROR = 0x10;
+    public static const int MB_ICONINFORMATION = 0x40;
+    public static const int MB_ICONQUESTION = 0x20;
+    public static const int MB_ICONWARNING = 0x30;
+    public static const int MB_OK = 0x0;
+    public static const int MB_OKCANCEL = 0x1;
+    public static const int MB_PRECOMPOSED = 0x1;
+    public static const int MB_RETRYCANCEL = 0x5;
+    public static const int MB_RIGHT = 0x00080000;
+    public static const int MB_RTLREADING = 0x100000;
+    public static const int MB_SYSTEMMODAL = 0x1000;
+    public static const int MB_TASKMODAL = 0x2000;
+    public static const int MB_TOPMOST = 0x00040000;
+    public static const int MB_YESNO = 0x4;
+    public static const int MB_YESNOCANCEL = 0x3;
+    public static const int MCM_FIRST = 0x1000;
+    public static const int MCM_GETCURSEL = MCM_FIRST + 1;
+    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;
+    public static const int MFS_CHECKED = 0x8;
+    public static const int MFS_DISABLED = 0x3;
+    public static const int MFS_GRAYED = 0x3;
+    public static const int MFT_RADIOCHECK = 0x200;
+    public static const int MFT_RIGHTJUSTIFY = 0x4000;
+    public static const int MFT_RIGHTORDER = 0x2000;
+    public static const int MFT_SEPARATOR = 0x800;
+    public static const int MFT_STRING = 0x0;
+    public static const int MF_BYCOMMAND = 0x0;
+    public static const int MF_BYPOSITION = 0x400;
+    public static const int MF_CHECKED = 0x8;
+    public static const int MF_DISABLED = 0x2;
+    public static const int MF_ENABLED = 0x0;
+    public static const int MF_GRAYED = 0x1;
+    public static const int MF_HILITE = 0x80;
+    public static const int MF_POPUP = 0x10;
+    public static const int MF_SEPARATOR = 0x800;
+    public static const int MF_SYSMENU = 0x2000;
+    public static const int MF_UNCHECKED = 0x0;
+    public static const int MIIM_BITMAP = 0x80;
+    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;
+    public static const int MIM_STYLE = 0x10;
+    public static const int MK_ALT = 0x20;
+    public static const int MK_CONTROL = 0x8;
+    public static const int MK_LBUTTON = 0x1;
+    public static const int MK_MBUTTON = 0x10;
+    public static const int MK_RBUTTON = 0x2;
+    public static const int MK_SHIFT = 0x4;
+    public static const int MK_XBUTTON1 = 0x20;
+    public static const int MK_XBUTTON2 = 0x40;
+    public static const int MM_TEXT = 0x1;
+    public static const int MNC_CLOSE = 0x1;
+    public static const int MNS_CHECKORBMP = 0x4000000;
+    public static const int MONITOR_DEFAULTTONEAREST = 0x2;
+    public static const int MONITORINFOF_PRIMARY = 0x1;
+    public static const TCHAR[] MONTHCAL_CLASS = "SysMonthCal32"; //$NON-NLS-1$
+    public static const int MOUSEEVENTF_ABSOLUTE = 0x8000;
+    public static const int MOUSEEVENTF_LEFTDOWN = 0x0002;
+    public static const int MOUSEEVENTF_LEFTUP = 0x0004;
+    public static const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
+    public static const int MOUSEEVENTF_MIDDLEUP = 0x0040;
+    public static const int MOUSEEVENTF_MOVE = 0x0001;
+    public static const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
+    public static const int MOUSEEVENTF_RIGHTUP = 0x0010;
+    public static const int MOUSEEVENTF_VIRTUALDESK = 0x4000;
+    public static const int MOUSEEVENTF_WHEEL = 0x0800;
+    public static const int MOUSEEVENTF_XDOWN = 0x0080;
+    public static const int MOUSEEVENTF_XUP = 0x0100;
+    public static const int MSGF_DIALOGBOX = 0;
+    public static const int MSGF_COMMCTRL_BEGINDRAG = 0x4200;
+    public static const int MSGF_COMMCTRL_SIZEHEADER = 0x4201;
+    public static const int MSGF_COMMCTRL_DRAGSELECT = 0x4202;
+    public static const int MSGF_COMMCTRL_TOOLBARCUST = 0x4203;
+    public static const int MSGF_MAINLOOP = 8;
+    public static const int MSGF_MENU = 2;
+    public static const int MSGF_MOVE = 3;
+    public static const int MSGF_MESSAGEBOX = 1;
+    public static const int MSGF_NEXTWINDOW = 6;
+    public static const int MSGF_SCROLLBAR = 5;
+    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;
+    public static const int NIF_STATE = 0x00000008;
+    public static const int NIF_TIP = 0x00000004;
+    public static const int NIIF_ERROR = 0x00000003;
+    public static const int NIIF_INFO = 0x00000001;
+    public static const int NIIF_NONE = 0x00000000;
+    public static const int NIIF_WARNING = 0x00000002;
+    public static const int NIM_ADD = 0x00000000;
+    public static const int NIM_DELETE = 0x00000002;
+    public static const int NIM_MODIFY = 0x00000001;
+    public static const int NIN_SELECT = 0x400 + 0;
+    public static const int NINF_KEY = 0x1;
+    public static const int NIN_KEYSELECT = NIN_SELECT | NINF_KEY;
+    public static const int NIN_BALLOONSHOW = 0x400 + 2;
+    public static const int NIN_BALLOONHIDE = 0x400 + 3;
+    public static const int NIN_BALLOONTIMEOUT = 0x400 + 4;
+    public static const int NIN_BALLOONUSERCLICK = 0x400 + 5;
+    public static const int NIS_HIDDEN = 0x00000001;
+    public static const int NM_FIRST = 0x0;
+    public static const int NM_CLICK = 0xfffffffe;
+    public static const int NM_CUSTOMDRAW = NM_FIRST - 12;
+    public static const int NM_DBLCLK = 0xfffffffd;
+    public static const int NM_RECOGNIZEGESTURE = NM_FIRST - 16;
+    public static const int NM_RELEASEDCAPTURE = NM_FIRST - 16;
+    public static const int NM_RETURN = 0xfffffffc;
+    public static int NOTIFYICONDATAA_V2_SIZE;
+    public static int NOTIFYICONDATAW_V2_SIZE;
+    public static int NOTIFYICONDATA_V2_SIZE;
+    public static const int NOTSRCCOPY = 0x330008;
+    public static const int NULLREGION = 0x1;
+    public static const int NULL_BRUSH = 0x5;
+    public static const int NULL_PEN = 0x8;
+    public static const int NUMRESERVED = 106;
+    public static const int OBJID_CARET = 0xFFFFFFF8;
+    public static const int OBJID_CLIENT = 0xFFFFFFFC;
+    public static const int OBJID_MENU = 0xFFFFFFFD;
+    public static const int OBJID_WINDOW = 0x00000000;
+    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;
+    public static const int OFN_ALLOWMULTISELECT = 0x200;
+    public static const int OFN_EXPLORER = 0x80000;
+    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;
+    public static const int OIC_QUES = 0x7F02;
+    public static const int OIC_WINLOGO = 0x7F05;
+    public static const int OPAQUE = 0x2;
+    public static const int PATCOPY = 0xf00021;
+    public static const int PATINVERT = 0x5a0049;
+    public static const int PBM_GETPOS = 0x408;
+    public static const int PBM_GETRANGE = 0x407;
+    public static const int PBM_GETSTATE = 0x400 + 17;
+    public static const int PBM_SETBARCOLOR = 0x409;
+    public static const int PBM_SETBKCOLOR = 0x2001;
+    public static const int PBM_SETMARQUEE = 0x400 + 10;
+    public static const int PBM_SETPOS = 0x402;
+    public static const int PBM_SETRANGE32 = 0x406;
+    public static const int PBM_SETSTATE = 0x400 + 16;
+    public static const int PBM_STEPIT = 0x405;
+    public static const int PBS_MARQUEE = 0x08;
+    public static const int PBS_SMOOTH = 0x1;
+    public static const int PBS_VERTICAL = 0x4;
+    public static const int PBS_NORMAL = 1;
+    public static const int PBS_HOT = 2;
+    public static const int PBS_PRESSED = 3;
+    public static const int PBS_DISABLED = 4;
+    public static const int PBS_DEFAULTED = 5;
+    public static const int PBST_NORMAL = 0x0001;
+    public static const int PBST_ERROR = 0x0002;
+    public static const int PBST_PAUSED = 0x0003;
+    public static const int PD_ALLPAGES = 0x0;
+    public static const int PD_COLLATE = 0x10;
+    public static const int PD_PAGENUMS = 0x2;
+    public static const int PD_PRINTTOFILE = 0x20;
+    public static const int PD_RETURNDC = 0x100;
+    public static const int PD_SELECTION = 0x1;
+    public static const int PD_USEDEVMODECOPIESANDCOLLATE = 0x40000;
+    public static const int PT_CLOSEFIGURE = 1;
+    public static const int PT_LINETO = 2;
+    public static const int PT_BEZIERTO = 4;
+    public static const int PT_MOVETO = 6;
+    public static const int PFM_TABSTOPS = 0x10;
+    public static const int PHYSICALHEIGHT = 0x6f;
+    public static const int PHYSICALOFFSETX = 0x70;
+    public static const int PHYSICALOFFSETY = 0x71;
+    public static const int PHYSICALWIDTH = 0x6e;
+    public static const int PLANES = 0xe;
+    public static const int PM_NOREMOVE = 0x0;
+    public static const int PM_NOYIELD = 0x2;
+    public static const int QS_HOTKEY = 0x0080;
+    public static const int QS_KEY = 0x0001;
+    public static const int QS_MOUSEMOVE = 0x0002;
+    public static const int QS_MOUSEBUTTON = 0x0004;
+    public static const int QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON;
+    public static const int QS_INPUT = QS_KEY | QS_MOUSE;
+    public static const int QS_POSTMESSAGE = 0x0008;
+    public static const int QS_TIMER = 0x0010;
+    public static const int QS_PAINT = 0x0020;
+    public static const int QS_SENDMESSAGE = 0x0040;
+    public static const int QS_ALLINPUT = QS_MOUSEMOVE | QS_MOUSEBUTTON | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_SENDMESSAGE;
+    public static const int PM_QS_INPUT = QS_INPUT << 16;
+    public static const int PM_QS_POSTMESSAGE = (QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16;
+    public static const int PM_QS_PAINT = QS_PAINT << 16;
+    public static const int PM_QS_SENDMESSAGE = QS_SENDMESSAGE << 16;
+    public static const int PM_REMOVE = 0x1;
+    public static const TCHAR[] PROGRESS_CLASS = "msctls_progress32"; //$NON-NLS-1$
+    public static const int PP_BAR = 1;
+    public static const int PP_BARVERT = 2;
+    public static const int PP_CHUNK = 3;
+    public static const int PP_CHUNKVERT = 4;
+    public static const int PRF_CHILDREN = 16;
+    public static const int PRF_CLIENT = 0x4;
+    public static const int PRF_ERASEBKGND = 0x8;
+    public static const int PRF_NONCLIENT = 0x2;
+    public static const int PROGRESSCHUNKSIZE = 2411;
+    public static const int PROGRESSSPACESIZE = 2412;
+    public static const int PS_DASH = 0x1;
+    public static const int PS_DASHDOT = 0x3;
+    public static const int PS_DASHDOTDOT = 0x4;
+    public static const int PS_DOT = 0x2;
+    public static const int PS_ENDCAP_FLAT = 0x200;
+    public static const int PS_ENDCAP_SQUARE = 0x100;
+    public static const int PS_ENDCAP_ROUND = 0x000;
+    public static const int PS_ENDCAP_MASK = 0xF00;
+    public static const int PS_GEOMETRIC = 0x10000;
+    public static const int PS_JOIN_BEVEL = 0x1000;
+    public static const int PS_JOIN_MASK = 0xF000;
+    public static const int PS_JOIN_MITER = 0x2000;
+    public static const int PS_JOIN_ROUND = 0x0000;
+    public static const int PS_SOLID = 0x0;
+    public static const int PS_STYLE_MASK = 0xf;
+    public static const int PS_TYPE_MASK = 0x000f0000;
+    public static const int PS_USERSTYLE = 0x7;
+    public static const int R2_COPYPEN = 0xd;
+    public static const int R2_XORPEN = 0x7;
+    public static const int RASTERCAPS = 0x26;
+    public static const int RASTER_FONTTYPE = 0x1;
+    public static const int RBBIM_CHILD = 0x10;
+    public static const int RBBIM_CHILDSIZE = 0x20;
+    public static const int RBBIM_COLORS = 0x2;
+    public static const int RBBIM_HEADERSIZE = 0x800;
+    public static const int RBBIM_ID = 0x100;
+    public static const int RBBIM_IDEALSIZE = 0x200;
+    public static const int RBBIM_SIZE = 0x40;
+    public static const int RBBIM_STYLE = 0x1;
+    public static const int RBBIM_TEXT = 0x4;
+    public static const int RBBS_BREAK = 0x1;
+    public static const int RBBS_GRIPPERALWAYS = 0x80;
+    public static const int RBBS_NOGRIPPER = 0x00000100;
+    public static const int RBBS_USECHEVRON = 0x00000200;
+    public static const int RBBS_VARIABLEHEIGHT = 0x40;
+    public static const int RBN_FIRST = 0xfffffcc1;
+    public static const int RBN_BEGINDRAG = RBN_FIRST - 4;
+    public static const int RBN_CHILDSIZE = RBN_FIRST - 8;
+    public static const int RBN_CHEVRONPUSHED = RBN_FIRST - 10;
+    public static const int RBN_HEIGHTCHANGE = 0xfffffcc1;
+    public static const int RBS_DBLCLKTOGGLE = 0x8000;
+    public static const int RBS_BANDBORDERS = 0x400;
+    public static const int RBS_VARHEIGHT = 0x200;
+    public static const int RB_DELETEBAND = 0x402;
+    public static const int RB_GETBANDBORDERS = 0x422;
+    public static const int RB_GETBANDCOUNT = 0x40c;
+    public static const int RB_GETBANDINFO = IsUnicode ? 0x41c : 0x41d;
+    public static const int RB_GETBANDMARGINS = 0x428;
+    public static const int RB_GETBARHEIGHT = 0x41b;
+    public static const int RB_GETBKCOLOR = 0x414;
+    public static const int RB_GETRECT = 0x409;
+    public static const int RB_GETTEXTCOLOR = 0x416;
+    public static const int RB_IDTOINDEX = 0x410;
+    public static const int RB_INSERTBAND = IsUnicode ? 0x40a : 0x401;
+    public static const int RB_MOVEBAND = 0x427;
+    public static const int RB_SETBANDINFO = IsUnicode ? 0x40b : 0x406;
+    public static const int RB_SETBKCOLOR = 0x413;
+    public static const int RB_SETTEXTCOLOR = 0x415;
+    public static const int RC_BITBLT = 0x1;
+    public static const int RC_PALETTE = 0x100;
+    public static const int RDW_ALLCHILDREN = 0x80;
+    public static const int RDW_ERASE = 0x4;
+    public static const int RDW_FRAME = 0x400;
+    public static const int RDW_INVALIDATE = 0x1;
+    public static const int RDW_UPDATENOW = 0x100;
+    public static const int READ_CONTROL = 0x20000;
+    public static const TCHAR[] REBARCLASSNAME = "ReBarWindow32"; //$NON-NLS-1$
+    public static const int RGN_AND = 0x1;
+    public static const int RGN_COPY = 5;
+    public static const int RGN_DIFF = 0x4;
+    public static const int RGN_ERROR = 0;
+    public static const int RGN_OR = 0x2;
+    public static const int RP_BAND = 3;
+    public static const int SBP_ARROWBTN = 0x1;
+    public static const int SBP_THUMBBTNHORZ = 2;
+    public static const int SBP_THUMBBTNVERT = 3;
+    public static const int SBP_LOWERTRACKHORZ = 4;
+    public static const int SBP_UPPERTRACKHORZ = 5;
+    public static const int SBP_LOWERTRACKVERT = 6;
+    public static const int SBP_UPPERTRACKVERT = 7;
+    public static const int SBP_GRIPPERHORZ = 8;
+    public static const int SBP_GRIPPERVERT = 9;
+    public static const int SBP_SIZEBOX = 10;
+    public static const int SBS_HORZ = 0x0;
+    public static const int SBS_VERT = 0x1;
+    public static const int SB_BOTH = 0x3;
+    public static const int SB_BOTTOM = 0x7;
+    public static const int SB_CTL = 0x2;
+    public static const int SB_ENDSCROLL = 0x8;
+    public static const int SB_HORZ = 0x0;
+    public static const int SB_LINEDOWN = 0x1;
+    public static const int SB_LINEUP = 0x0;
+    public static const int SB_PAGEDOWN = 0x3;
+    public static const int SB_PAGEUP = 0x2;
+    public static const int SB_THUMBPOSITION = 0x4;
+    public static const int SB_THUMBTRACK = 0x5;
+    public static const int SB_TOP = 0x6;
+    public static const int SB_VERT = 0x1;
+    public static const int SCF_ALL = 0x4;
+    public static const int SCF_DEFAULT = 0x0;
+    public static const int SCF_SELECTION = 0x1;
+    public static const int SC_CLOSE = 0xf060;
+    public static const int SC_HSCROLL = 0xf080;
+    public static const int SC_KEYMENU = 0xf100;
+    public static const int SC_MAXIMIZE = 0xf030;
+    public static const int SC_MINIMIZE = 0xf020;
+    public static const int SC_NEXTWINDOW = 0xF040;
+    public static const int SC_RESTORE = 0xf120;
+    public static const int SC_SIZE = 0xf000;
+    public static const int SC_TASKLIST = 0xf130;
+    public static const int SC_VSCROLL = 0xf070;
+    public static const int SCRBS_NORMAL = 1;
+    public static const int SCRBS_HOT = 2;
+    public static const int SCRBS_PRESSED = 3;
+    public static const int SCRBS_DISABLED = 4;
+    public static const int SEM_FAILCRITICALERRORS = 0x1;
+    public static const int SET_FEATURE_ON_PROCESS = 0x2;
+    public static const int SF_RTF = 0x2;
+    public static const int SHCMBF_HIDDEN = 0x2;
+    public static const int SHCMBM_OVERRIDEKEY = 0x400 + 403;
+    public static const int SHCMBM_SETSUBMENU = 0x590;
+    public static const int SHCMBM_GETSUBMENU = 0x591;
+    public static const int SHGFI_ICON = 0x000000100;
+    public static const int SHGFI_SMALLICON= 0x1;
+    public static const int SHGFI_USEFILEATTRIBUTES = 0x000000010;
+    public static const int SHMBOF_NODEFAULT = 0x1;
+    public static const int SHMBOF_NOTIFY = 0x2;
+    public static const int SHRG_RETURNCMD = 0x1;
+    public static const int SIF_ALL = 0x17;
+    public static const int SIF_DISABLENOSCROLL = 0x8;
+    public static const int SIF_PAGE = 0x2;
+    public static const int SIF_POS = 0x4;
+    public static const int SIF_RANGE = 0x1;
+    public static const int SIF_TRACKPOS = 0x10;
+    public static const int SIP_DOWN = 1;
+    public static const int SIP_UP = 0;
+    public static const int SIPF_ON = 0x1;
+    public static const int SIZE_RESTORED = 0;
+    public static const int SIZE_MINIMIZED = 1;
+    public static const int SIZE_MAXIMIZED = 2;
+    public static const int SIZEPALETTE = 104;
+    public static const int SM_CMONITORS = 80;
+    public static const int SM_CXBORDER = 0x5;
+    public static const int SM_CXCURSOR = 0xd;
+    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;
+    public static const int SM_CXVIRTUALSCREEN = 78;
+    public static const int SM_CYVIRTUALSCREEN = 79;
+    public static const int SM_CXSMICON = 49;
+    public static const int SM_CYSMICON = 50;
+    public static const int SM_CXSCREEN = 0x0;
+    public static const int SM_XVIRTUALSCREEN = 76;
+    public static const int SM_YVIRTUALSCREEN = 77;
+    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;
+    public static const int SM_CYMINTRACK = 35;
+    public static const int SM_CMOUSEBUTTONS = 43;
+    public static const int SM_CYSCREEN = 0x1;
+    public static const int SM_CYVSCROLL = 0x14;
+//  public static const int SM_DBCSENABLED = 0x2A;
+//  public static const int SM_IMMENABLED = 0x52;
+    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;
+    public static const int SRCCOPY = 0xcc0020;
+    public static const int SRCINVERT = 0x660046;
+    public static const int SRCPAINT = 0xee0086;
+    public static const int SS_BITMAP = 0xe;
+    public static const int SS_CENTER = 0x1;
+    public static const int SS_CENTERIMAGE = 0x200;
+    public static const int SS_EDITCONTROL = 0x2000;
+    public static const int SS_ICON = 0x3;
+    public static const int SS_LEFT = 0x0;
+    public static const int SS_LEFTNOWORDWRAP = 0xc;
+    public static const int SS_NOTIFY = 0x100;
+    public static const int SS_OWNERDRAW = 0xd;
+    public static const int SS_REALSIZEIMAGE = 0x800;
+    public static const int SS_RIGHT = 0x2;
+    public static const int SSA_FALLBACK = 0x00000020;
+    public static const int SSA_GLYPHS = 0x00000080;
+    public static const int SSA_METAFILE = 0x00000800;
+    public static const int SSA_LINK = 0x00001000;
+    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;
+    public static const int STD_FILEOPEN = 0x7;
+    public static const int STD_FILESAVE = 0x8;
+    public static const int STD_PASTE = 0x2;
+    public static const int STM_GETIMAGE = 0x173;
+    public static const int STM_SETIMAGE = 0x172;
+    public static const int SWP_ASYNCWINDOWPOS = 0x4000;
+    public static const int SWP_DRAWFRAME = 0x20;
+    public static const int SWP_NOACTIVATE = 0x10;
+    public static const int SWP_NOCOPYBITS = 0x100;
+    public static const int SWP_NOMOVE = 0x2;
+    public static const int SWP_NOREDRAW = 0x8;
+    public static const int SWP_NOSIZE = 0x1;
+    public static const int SWP_NOZORDER = 0x4;
+    public static const int SW_ERASE = 0x4;
+    public static const int SW_HIDE = 0x0;
+    public static const int SW_INVALIDATE = 0x2;
+    public static const int SW_MINIMIZE = 0x6;
+    public static const int SW_PARENTOPENING = 0x3;
+    public static const int SW_RESTORE = IsWinCE ? 0xd : 0x9;
+    public static const int SW_SCROLLCHILDREN = 0x1;
+    public static const int SW_SHOW = 0x5;
+    public static const int SW_SHOWMAXIMIZED = IsWinCE ? 0xb : 0x3;
+    public static const int SW_SHOWMINIMIZED = 0x2;
+    public static const int SW_SHOWMINNOACTIVE = 0x7;
+    public static const int SW_SHOWNA = 0x8;
+    public static const int SW_SHOWNOACTIVATE = 0x4;
+    public static const int SYNCHRONIZE = 0x100000;
+    public static const int SYSRGN = 0x4;
+    public static const int SYSTEM_FONT = 0xd;
+    public static const int S_OK = 0x0;
+    public static const int TABP_TABITEM = 1;
+    public static const int TABP_TABITEMLEFTEDGE = 2;
+    public static const int TABP_TABITEMRIGHTEDGE = 3;
+    public static const int TABP_TABITEMBOTHEDGE = 4;
+    public static const int TABP_TOPTABITEM = 5;
+    public static const int TABP_TOPTABITEMLEFTEDGE = 6;
+    public static const int TABP_TOPTABITEMRIGHTEDGE = 7;
+    public static const int TABP_TOPTABITEMBOTHEDGE = 8;
+    public static const int TABP_PANE = 9;
+    public static const int TABP_BODY = 10;
+    public static const int TBIF_COMMAND = 0x20;
+    public static const int TBIF_STATE = 0x4;
+    public static const int TBIF_IMAGE = 0x1;
+    public static const int TBIF_LPARAM = 0x10;
+    public static const int TBIF_SIZE = 0x40;
+    public static const int TBIF_STYLE = 0x8;
+    public static const int TBIF_TEXT = 0x2;
+    public static const int TB_GETEXTENDEDSTYLE = 0x400 + 85;
+    public static const int TBM_GETLINESIZE = 0x418;
+    public static const int TBM_GETPAGESIZE = 0x416;
+    public static const int TBM_GETPOS = 0x400;
+    public static const int TBM_GETRANGEMAX = 0x402;
+    public static const int TBM_GETRANGEMIN = 0x401;
+    public static const int TBM_GETTHUMBRECT = 0x419;
+    public static const int TBM_SETLINESIZE = 0x417;
+    public static const int TBM_SETPAGESIZE = 0x415;
+    public static const int TBM_SETPOS = 0x405;
+    public static const int TBM_SETRANGEMAX = 0x408;
+    public static const int TBM_SETRANGEMIN = 0x407;
+    public static const int TBM_SETTICFREQ = 0x414;
+    public static const int TBN_DROPDOWN = 0xfffffd3a;
+    public static const int TBN_FIRST = 0xfffffd44;
+    public static const int TBN_HOTITEMCHANGE = 0xFFFFFD37;
+    public static const int TBSTATE_CHECKED = 0x1;
+    public static const int TBSTATE_PRESSED = 0x02;
+    public static const int TBSTYLE_CUSTOMERASE = 0x2000;
+    public static const int TBSTYLE_DROPDOWN = 0x8;
+    public static const int TBSTATE_ENABLED = 0x4;
+    public static const int TBSTYLE_AUTOSIZE = 0x10;
+    public static const int TBSTYLE_EX_DOUBLEBUFFER = 0x80;
+    public static const int TBSTYLE_EX_DRAWDDARROWS = 0x1;
+    public static const int TBSTYLE_EX_HIDECLIPPEDBUTTONS = 0x10;
+    public static const int TBSTYLE_EX_MIXEDBUTTONS = 0x8;
+    public static const int TBSTYLE_FLAT = 0x800;
+    public static const int TBSTYLE_LIST = 0x1000;
+    public static const int TBSTYLE_TOOLTIPS = 0x100;
+    public static const int TBSTYLE_TRANSPARENT = 0x8000;
+    public static const int TBSTYLE_WRAPABLE = 0x200;
+    public static const int TBS_AUTOTICKS = 0x1;
+    public static const int TBS_BOTH = 0x8;
+    public static const int TBS_DOWNISLEFT = 0x0400;
+    public static const int TBS_HORZ = 0x0;
+    public static const int TBS_VERT = 0x2;
+    public static const int TB_ADDSTRING = IsUnicode ? 0x44d : 0x41c;
+    public static const int TB_AUTOSIZE = 0x421;
+    public static const int TB_BUTTONCOUNT = 0x418;
+    public static const int TB_BUTTONSTRUCTSIZE = 0x41e;
+    public static const int TB_COMMANDTOINDEX = 0x419;
+    public static const int TB_DELETEBUTTON = 0x416;
+    public static const int TB_ENDTRACK = 0x8;
+    public static const int TB_GETBUTTON = 0x417;
+    public static const int TB_GETBUTTONINFO = IsUnicode ? 0x43f : 0x441;
+    public static const int TB_GETBUTTONSIZE = 0x43a;
+    public static const int TB_GETBUTTONTEXT = IsUnicode ? 0x44b : 0x42d;
+    public static const int TB_GETDISABLEDIMAGELIST = 0x437;
+    public static const int TB_GETHOTIMAGELIST = 0x435;
+    public static const int TB_GETHOTITEM = 0x0400 + 71;
+    public static const int TB_GETIMAGELIST = 0x431;
+    public static const int TB_GETITEMRECT = 0x41d;
+    public static const int TB_GETPADDING = 0x0400 + 86;
+    public static const int TB_GETROWS = 0x428;
+    public static const int TB_GETSTATE = 0x412;
+    public static const int TB_GETTOOLTIPS = 0x423;
+    public static const int TB_INSERTBUTTON = IsUnicode ? 0x443 : 0x415;
+    public static const int TB_LOADIMAGES = 0x432;
+    public static const int TB_MAPACCELERATOR = 0x0400 + (IsUnicode ? 90 : 78);
+    public static const int TB_SETBITMAPSIZE = 0x420;
+    public static const int TB_SETBUTTONINFO = IsUnicode ? 0x440 : 0x442;
+    public static const int TB_SETBUTTONSIZE = 0x41f;
+    public static const int TB_SETDISABLEDIMAGELIST = 0x436;
+    public static const int TB_SETEXTENDEDSTYLE = 0x454;
+    public static const int TB_SETHOTIMAGELIST = 0x434;
+    public static const int TB_SETHOTITEM =  0x0400 + 72;
+    public static const int TB_SETIMAGELIST = 0x430;
+    public static const int TB_SETPARENT = 0x400 + 37;
+    public static const int TB_SETROWS = 0x427;
+    public static const int TB_SETSTATE = 0x411;
+    public static const int TB_THUMBPOSITION = 0x4;
+    public static const int TCIF_IMAGE = 0x2;
+    public static const int TCIF_TEXT = 0x1;
+    public static const int TCI_SRCCHARSET = 0x1;
+    public static const int TCI_SRCCODEPAGE = 0x2;
+    public static const int TCM_ADJUSTRECT = 0x1328;
+    public static const int TCM_DELETEITEM = 0x1308;
+    public static const int TCM_GETCURSEL = 0x130b;
+    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;
+    public static const int TCM_SETITEM = IsUnicode ? 0x133d : 0x1306;
+    public static const int TCN_SELCHANGE = 0xfffffdd9;
+    public static const int TCN_SELCHANGING = 0xfffffdd8;
+    public static const int TCS_BOTTOM = 0x0002;
+    public static const int TCS_FOCUSNEVER = 0x8000;
+    public static const int TCS_MULTILINE = 0x200;
+    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;
+    public static const int TIS_SELECTED = 3;
+    public static const int TIS_DISABLED = 4;
+    public static const int TIS_FOCUSED = 5;
+    public static const int TKP_TRACK = 1;
+    public static const int TKP_TRACKVERT = 2;
+    public static const int TKP_THUMB = 3;
+    public static const int TKP_THUMBBOTTOM = 4;
+    public static const int TKP_THUMBTOP = 5;
+    public static const int TKP_THUMBVERT = 6;
+    public static const int TKP_THUMBLEFT = 7;
+    public static const int TKP_THUMBRIGHT = 8;
+    public static const int TKP_TICS = 9;
+    public static const int TKP_TICSVERT = 10;
+    public static const int TME_HOVER = 0x1;
+    public static const int TME_LEAVE = 0x2;
+    public static const int TME_QUERY = 0x40000000;
+    public static const int TMPF_VECTOR = 0x2;
+    public static const int TMT_CONTENTMARGINS = 3602;
+    public static const TCHAR[] TOOLBARCLASSNAME = "ToolbarWindow32"; //$NON-NLS-1$
+    public static const TCHAR[] TOOLTIPS_CLASS = "tooltips_class32"; //$NON-NLS-1$
+    public static const int TP_BUTTON = 1;
+    public static const int TP_DROPDOWNBUTTON = 2;
+    public static const int TP_SPLITBUTTON = 3;
+    public static const int TP_SPLITBUTTONDROPDOWN = 4;
+    public static const int TP_SEPARATOR = 5;
+    public static const int TP_SEPARATORVERT = 6;
+    public static const int TPM_LEFTALIGN = 0x0;
+    public static const int TPM_LEFTBUTTON = 0x0;
+    public static const int TPM_RIGHTBUTTON = 0x2;
+    public static const int TPM_RIGHTALIGN = 0x8;
+    public static const TCHAR[] TRACKBAR_CLASS = "msctls_trackbar32"; //$NON-NLS-1$
+    public static const int TRANSPARENT = 0x1;
+    public static const int TREIS_DISABLED = 4;
+    public static const int TREIS_HOT = 2;
+    public static const int TREIS_NORMAL = 1;
+    public static const int TREIS_SELECTED = 3;
+    public static const int TREIS_SELECTEDNOTFOCUS = 5;
+    public static const int TS_MIN = 0;
+    public static const int TS_TRUE = 1;
+    public static const int TS_DRAW = 2;
+    public static const int TS_NORMAL = 1;
+    public static const int TS_HOT = 2;
+    public static const int TS_PRESSED = 3;
+    public static const int TS_DISABLED = 4;
+    public static const int TS_CHECKED = 5;
+    public static const int TS_HOTCHECKED = 6;
+    public static const int TTDT_AUTOMATIC = 0;
+    public static const int TTDT_RESHOW = 1;
+    public static const int TTDT_AUTOPOP = 2;
+    public static const int TTDT_INITIAL = 3;
+    public static const int TTF_ABSOLUTE = 0x80;
+    public static const int TTF_IDISHWND = 0x1;
+    public static const int TTF_SUBCLASS = 0x10;
+    public static const int TTF_RTLREADING = 0x4;
+    public static const int TTF_TRACK = 0x20;
+    public static const int TTF_TRANSPARENT = 0x100;
+    public static const int TTI_NONE = 0;
+    public static const int TTI_INFO = 1;
+    public static const int TTI_WARNING = 2;
+    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);
+    public static const int TTM_GETDELAYTIME = 0x400 + 21;
+    public static const int TTM_DELTOOL = IsUnicode ? 0x433 : 0x405;
+    public static const int TTM_GETTOOLINFO = 0x400 + (IsUnicode ? 53 : 8);
+    public static const int TTM_NEWTOOLRECT = 0x400 + (IsUnicode ? 52 : 6);
+    public static const int TTM_POP = 0x400 + 28;
+    public static const int TTM_SETDELAYTIME = 0x400 + 3;
+    public static const int TTM_SETMAXTIPWIDTH = 0x418;
+    public static const int TTM_SETTITLEA = 0x400 + 32;
+    public static const int TTM_SETTITLEW = 0x400 + 33;
+    public static const int TTM_SETTITLE = 0x400 + (IsUnicode ? 33 : 32);
+    public static const int TTM_TRACKPOSITION = 1042;
+    public static const int TTM_TRACKACTIVATE = 1041;
+    public static const int TTM_UPDATE = 0x41D;
+    public static const int TTN_FIRST = 0xfffffdf8;
+    public static const int TTN_GETDISPINFO = IsUnicode ? 0xfffffdee : 0xfffffdf8;
+    public static const int TTN_GETDISPINFOW = 0xfffffdee;
+    public static const int TTN_GETDISPINFOA = 0xfffffdf8;
+    public static const int TTN_POP = TTN_FIRST - 2;
+    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;
+    public static const int TVE_EXPAND = 0x2;
+    public static const int TVGN_CARET = 0x9;
+    public static const int TVGN_CHILD = 0x4;
+    public static const int TVGN_DROPHILITED = 0x8;
+    public static const int TVGN_FIRSTVISIBLE = 0x5;
+    public static const int TVGN_LASTVISIBLE = 0xa;
+    public static const int TVGN_NEXT = 0x1;
+    public static const int TVGN_NEXTVISIBLE = 0x6;
+    public static const int TVGN_PARENT = 0x3;
+    public static const int TVGN_PREVIOUS = 0x2;
+    public static const int TVGN_PREVIOUSVISIBLE = 0x7;
+    public static const int TVGN_ROOT = 0x0;
+    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;
+    public static const int TVIF_IMAGE = 0x2;
+    public static const int TVIF_INTEGRAL = 0x0080;
+    public static const int TVIF_PARAM = 0x4;
+    public static const int TVIF_SELECTEDIMAGE = 0x20;
+    public static const int TVIF_STATE = 0x8;
+    public static const int TVIF_TEXT = 0x1;
+    public static const int TVIS_DROPHILITED = 0x8;
+    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 /*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;
+    public static const int TVM_EXPAND = 0x1102;
+    public static const int TVM_GETBKCOLOR = 0x111f;
+    public static const int TVM_GETCOUNT = 0x1105;
+    public static const int TVM_GETEXTENDEDSTYLE = TV_FIRST + 45;
+    public static const int TVM_GETIMAGELIST = 0x1108;
+    public static const int TVM_GETITEM = IsUnicode ? 0x113e : 0x110c;
+    public static const int TVM_GETITEMHEIGHT = 0x111c;
+    public static const int TVM_GETITEMRECT = 0x1104;
+    public static const int TVM_GETITEMSTATE = TV_FIRST + 39;
+    public static const int TVM_GETNEXTITEM = 0x110a;
+    public static const int TVM_GETTEXTCOLOR = 0x1120;
+    public static const int TVM_GETTOOLTIPS = TV_FIRST + 25;
+    public static const int TVM_GETVISIBLECOUNT = TV_FIRST + 16;
+    public static const int TVM_HITTEST = 0x1111;
+    public static const int TVM_INSERTITEM = IsUnicode ? 0x1132 : 0x1100;
+    public static const int TVM_MAPACCIDTOHTREEITEM = TV_FIRST + 42;
+    public static const int TVM_MAPHTREEITEMTOACCID = TV_FIRST + 43;
+    public static const int TVM_SELECTITEM = 0x110b;
+    public static const int TVM_SETBKCOLOR = 0x111d;
+    public static const int TVM_SETEXTENDEDSTYLE = TV_FIRST + 44;
+    public static const int TVM_SETIMAGELIST = 0x1109;
+    public static const int TVM_SETINSERTMARK = 0x111a;
+    public static const int TVM_SETITEM = IsUnicode ? 0x113f : 0x110d;
+    public static const int TVM_SETITEMHEIGHT = TV_FIRST + 27;
+    public static const int TVM_SETSCROLLTIME = TV_FIRST + 33;
+    public static const int TVM_SETTEXTCOLOR = 0x111e;
+    public static const int TVM_SORTCHILDREN = TV_FIRST + 19;
+    public static const int TVM_SORTCHILDRENCB = TV_FIRST + 21;
+    public static const int TVN_BEGINDRAGW = 0xfffffe38;
+    public static const int TVN_BEGINDRAGA = 0xfffffe69;
+    public static const int TVN_BEGINRDRAGW = 0xfffffe37;
+    public static const int TVN_BEGINRDRAGA = 0xfffffe68;
+    public static const int TVN_FIRST = 0xfffffe70;
+    public static const int TVN_GETDISPINFOA = TVN_FIRST - 3;
+    public static const int TVN_GETDISPINFOW = TVN_FIRST - 52;
+    public static const int TVN_ITEMCHANGINGW = TVN_FIRST - 17;
+    public static const int TVN_ITEMCHANGINGA = TVN_FIRST - 16;
+    public static const int TVN_ITEMEXPANDEDA = TVN_FIRST -6;
+    public static const int TVN_ITEMEXPANDEDW = TVN_FIRST - 55;
+    public static const int TVN_ITEMEXPANDINGW = 0xfffffe3a;
+    public static const int TVN_ITEMEXPANDINGA = 0xfffffe6b;
+    public static const int TVN_SELCHANGEDW = 0xfffffe3d;
+    public static const int TVN_SELCHANGEDA = 0xfffffe6e;
+    public static const int TVN_SELCHANGINGW = 0xfffffe3e;
+    public static const int TVN_SELCHANGINGA = 0xfffffe6f;
+    public static const int TVP_GLYPH = 2;
+    public static const int TVP_TREEITEM = 1;
+    public static const int TVSIL_NORMAL = 0x0;
+    public static const int TVSIL_STATE = 0x2;
+    public static const int TVS_DISABLEDRAGDROP = 0x10;
+    public static const int TVS_EX_AUTOHSCROLL = 0x0020;
+    public static const int TVS_EX_DOUBLEBUFFER = 0x0004;
+    public static const int TVS_EX_DIMMEDCHECKBOXES = 0x0200;
+    public static const int TVS_EX_DRAWIMAGEASYNC = 0x0400;
+    public static const int TVS_EX_EXCLUSIONCHECKBOXES = 0x0100;
+    public static const int TVS_EX_FADEINOUTEXPANDOS = 0x0040;
+    public static const int TVS_EX_MULTISELECT = 0x0002;
+    public static const int TVS_EX_NOINDENTSTATE = 0x0008;
+    public static const int TVS_EX_PARTIALCHECKBOXES = 0x0080;
+    public static const int TVS_EX_RICHTOOLTIP = 0x0010;
+    public static const int TVS_FULLROWSELECT = 0x1000;
+    public static const int TVS_HASBUTTONS = 0x1;
+    public static const int TVS_HASLINES = 0x2;
+    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;
+    public static const int UDM_GETACCEL = 0x046C;
+    public static const int UDM_GETRANGE32 = 0x0470;
+    public static const int UDM_GETPOS = 0x468;
+    public static const int UDM_GETPOS32 = 0x0472;
+    public static const int UDM_SETACCEL = 0x046B;
+    public static const int UDM_SETRANGE32 = 0x046f;
+    public static const int UDM_SETPOS = 0x467;
+    public static const int UDM_SETPOS32 = 0x0471;
+    public static const int UDN_DELTAPOS = -722;
+    public static const int UDS_ALIGNLEFT = 0x008;
+    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$
+    public static const int USP_E_SCRIPT_NOT_IN_FONT = 0x80040200;
+    public static const int VERTRES = 0xa;
+    public static const int VK_BACK = 0x8;
+    public static const int VK_CANCEL = 0x3;
+    public static const int VK_CAPITAL = 0x14;
+    public static const int VK_CONTROL = 0x11;
+    public static const int VK_DECIMAL = 0x6E;
+    public static const int VK_DELETE = 0x2e;
+    public static const int VK_DIVIDE = 0x6f;
+    public static const int VK_DOWN = 0x28;
+    public static const int VK_END = 0x23;
+    public static const int VK_ESCAPE = 0x1b;
+    public static const int VK_F1 = 0x70;
+    public static const int VK_F10 = 0x79;
+    public static const int VK_F11 = 0x7a;
+    public static const int VK_F12 = 0x7b;
+    public static const int VK_F13 = 0x7c;
+    public static const int VK_F14 = 0x7d;
+    public static const int VK_F15 = 0x7e;
+    public static const int VK_F2 = 0x71;
+    public static const int VK_F3 = 0x72;
+    public static const int VK_F4 = 0x73;
+    public static const int VK_F5 = 0x74;
+    public static const int VK_F6 = 0x75;
+    public static const int VK_F7 = 0x76;
+    public static const int VK_F8 = 0x77;
+    public static const int VK_F9 = 0x78;
+    public static const int VK_HOME = 0x24;
+    public static const int VK_INSERT = 0x2d;
+    public static const int VK_LBUTTON = 0x1;
+    public static const int VK_LEFT = 0x25;
+    public static const int VK_MBUTTON = 0x4;
+    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_NEXT = 0x22;
+    public static const int VK_NUMLOCK = 0x90;
+    public static const int VK_NUMPAD0 = 0x60;
+    public static const int VK_NUMPAD1 = 0x61;
+    public static const int VK_NUMPAD2 = 0x62;
+    public static const int VK_NUMPAD3 = 0x63;
+    public static const int VK_NUMPAD4 = 0x64;
+    public static const int VK_NUMPAD5 = 0x65;
+    public static const int VK_NUMPAD6 = 0x66;
+    public static const int VK_NUMPAD7 = 0x67;
+    public static const int VK_NUMPAD8 = 0x68;
+    public static const int VK_NUMPAD9 = 0x69;
+    public static const int VK_PAUSE = 0x13;
+    public static const int VK_PRIOR = 0x21;
+    public static const int VK_RBUTTON = 0x2;
+    public static const int VK_RETURN = 0xd;
+    public static const int VK_RIGHT = 0x27;
+    public static const int VK_SCROLL = 0x91;
+    public static const int VK_SEPARATOR = 0x6C;
+    public static const int VK_SHIFT = 0x10;
+    public static const int VK_SNAPSHOT = 0x2C;
+    public static const int VK_SPACE = 0x20;
+    public static const int VK_SUBTRACT = 0x6D;
+    public static const int VK_TAB = 0x9;
+    public static const int VK_UP = 0x26;
+    public static const int VK_XBUTTON1 = 0x05;
+    public static const int VK_XBUTTON2 = 0x06;
+    public static const int VK_ADD = 0x6B;
+    public static const int VK_APP1 = 0xc1;
+    public static const int VK_APP2 = 0xc2;
+    public static const int VK_APP3 = 0xc3;
+    public static const int VK_APP4 = 0xc4;
+    public static const int VK_APP5 = 0xc5;
+    public static const int VK_APP6 = 0xc6;
+    public static const TCHAR[] WC_HEADER = "SysHeader32"; //$NON-NLS-1$
+    public static const TCHAR[] WC_LINK = "SysLink"; //$NON-NLS-1$
+    public static const TCHAR[] WC_LISTVIEW = "SysListView32"; //$NON-NLS-1$
+    public static const TCHAR[] WC_TABCONTROL = "SysTabControl32"; //$NON-NLS-1$
+    public static const TCHAR[] WC_TREEVIEW = "SysTreeView32"; //$NON-NLS-1$
+    public static const int WINDING = 2;
+    public static const int WH_CBT = 5;
+    public static const int WH_GETMESSAGE = 0x3;
+    public static const int WH_MSGFILTER = 0xFFFFFFFF;
+    public static const int WH_FOREGROUNDIDLE = 11;
+    public static const int WHEEL_DELTA = 120;
+    public static const int WHEEL_PAGESCROLL = 0xFFFFFFFF;
+    public static const int WHITE_BRUSH = 0;
+    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;
+    public static const int WM_CHAR = 0x102;
+    public static const int WM_CLEAR = 0x303;
+    public static const int WM_CLOSE = 0x10;
+    public static const int WM_COMMAND = 0x111;
+    public static const int WM_CONTEXTMENU = 0x7b;
+    public static const int WM_COPY = 0x301;
+    public static const int WM_CREATE = 0x0001;
+    public static const int WM_CTLCOLORBTN = 0x135;
+    public static const int WM_CTLCOLORDLG = 0x136;
+    public static const int WM_CTLCOLOREDIT = 0x133;
+    public static const int WM_CTLCOLORLISTBOX = 0x134;
+    public static const int WM_CTLCOLORMSGBOX = 0x132;
+    public static const int WM_CTLCOLORSCROLLBAR = 0x137;
+    public static const int WM_CTLCOLORSTATIC = 0x138;
+    public static const int WM_CUT = 0x300;
+    public static const int WM_DEADCHAR = 0x103;
+    public static const int WM_DESTROY = 0x2;
+    public static const int WM_DRAWITEM = 0x2b;
+    public static const int WM_ENDSESSION = 0x16;
+    public static const int WM_ENTERIDLE = 0x121;
+    public static const int WM_ERASEBKGND = 0x14;
+    public static const int WM_GETDLGCODE = 0x87;
+    public static const int WM_GETFONT = 0x31;
+//  public static const int WM_GETICON = 0x7f;
+    public static const int WM_GETOBJECT = 0x003D;
+    public static const int WM_GETMINMAXINFO = 0x0024;
+    public static const int WM_HELP = 0x53;
+    public static const int WM_HOTKEY = 0x0312;
+    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;
+    public static const int WM_KEYDOWN = 0x100;
+    public static const int WM_KEYFIRST = 0x100;
+    public static const int WM_KEYLAST = 0x108;
+    public static const int WM_KEYUP = 0x101;
+    public static const int WM_KILLFOCUS = 0x8;
+    public static const int WM_LBUTTONDBLCLK = 0x203;
+    public static const int WM_LBUTTONDOWN = 0x201;
+    public static const int WM_LBUTTONUP = 0x202;
+    public static const int WM_MBUTTONDBLCLK = 0x209;
+    public static const int WM_MBUTTONDOWN = 0x207;
+    public static const int WM_MBUTTONUP = 0x208;
+    public static const int WM_MEASUREITEM = 0x2c;
+    public static const int WM_MENUCHAR = 0x120;
+    public static const int WM_MENUSELECT = 0x11f;
+    public static const int WM_MOUSEACTIVATE = 0x21;
+    public static const int WM_MOUSEFIRST = 0x200;
+    public static const int WM_MOUSEHOVER = 0x2a1;
+    public static const int WM_MOUSELEAVE = 0x2a3;
+    public static const int WM_MOUSEMOVE = 0x200;
+    public static const int WM_MOUSEWHEEL = 0x20a;
+    public static const int WM_MOUSELAST = 0x20d;
+    public static const int WM_MOVE = 0x3;
+    public static const int WM_NCACTIVATE = 0x86;
+    public static const int WM_NCCALCSIZE = 0x83;
+    public static const int WM_NCHITTEST = 0x84;
+    public static const int WM_NCLBUTTONDOWN = 0x00A1;
+    public static const int WM_NCPAINT = 0x85;
+    public static const int WM_NOTIFY = 0x4e;
+    public static const int WM_NULL = 0x0;
+    public static const int WM_PAINT = 0xf;
+    public static const int WM_PALETTECHANGED = 0x311;
+    public static const int WM_PARENTNOTIFY = 0x0210;
+    public static const int WM_PASTE = 0x302;
+    public static const int WM_PRINT = 0x0317;
+    public static const int WM_PRINTCLIENT = 0x0318;
+    public static const int WM_QUERYENDSESSION = 0x11;
+    public static const int WM_QUERYNEWPALETTE = 0x30f;
+    public static const int WM_QUERYOPEN = 0x13;
+    public static const int WM_QUERYUISTATE = 0x129;
+    public static const int WM_RBUTTONDBLCLK = 0x206;
+    public static const int WM_RBUTTONDOWN = 0x204;
+    public static const int WM_RBUTTONUP = 0x205;
+    public static const int WM_SETCURSOR = 0x20;
+    public static const int WM_SETFOCUS = 0x7;
+    public static const int WM_SETFONT = 0x30;
+    public static const int WM_SETICON = 0x80;
+    public static const int WM_SETREDRAW = 0xb;
+    public static const int WM_SETTEXT = 12;
+    public static const int WM_SETTINGCHANGE = 0x1A;
+    public static const int WM_SHOWWINDOW = 0x18;
+    public static const int WM_SIZE = 0x5;
+    public static const int WM_SYSCHAR = 0x106;
+    public static const int WM_SYSCOLORCHANGE = 0x15;
+    public static const int WM_SYSCOMMAND = 0x112;
+    public static const int WM_SYSKEYDOWN = 0x104;
+    public static const int WM_SYSKEYUP = 0x105;
+    public static const int WM_TIMER = 0x113;
+    public static const int WM_THEMECHANGED = 0x031a;
+    public static const int WM_UNDO = 0x304;
+    public static const int WM_UPDATEUISTATE = 0x0128;
+    public static const int WM_USER = 0x400;
+    public static const int WM_VSCROLL = 0x115;
+    public static const int WM_WINDOWPOSCHANGED = 0x47;
+    public static const int WM_WINDOWPOSCHANGING = 0x46;
+    public static const int WS_BORDER = 0x800000;
+    public static const int WS_CAPTION = 0xc00000;
+    public static const int WS_CHILD = 0x40000000;
+    public static const int WS_MINIMIZE = 0x20000000; //PORTING_TODO: from org.eclipse.swt, why?
+    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;
+    public static const int WS_EX_LEFTSCROLLBAR = 0x00004000;
+    public static const int WS_EX_MDICHILD = 0x00000040;
+    public static const int WS_EX_NOINHERITLAYOUT = 0x00100000;
+    public static const int WS_EX_NOACTIVATE = 0x08000000;
+    public static const int WS_EX_RIGHT = 0x00001000;
+    public static const int WS_EX_RTLREADING = 0x00002000;
+    public static const int WS_EX_STATICEDGE = 0x20000;
+    public static const int WS_EX_TOOLWINDOW = 0x80;
+    public static const int WS_EX_TOPMOST = 0x8;
+    public static const int WS_EX_TRANSPARENT = 0x20;
+    public static const int WS_HSCROLL = 0x100000;
+    public static const int WS_MAXIMIZEBOX = IsWinCE ? 0x20000 : 0x10000;
+    public static const int WS_MINIMIZEBOX = IsWinCE ? 0x10000 : 0x20000;
+    public static const int WS_OVERLAPPED = IsWinCE ? WS_BORDER | WS_CAPTION : 0x0;
+    public static const int WS_OVERLAPPEDWINDOW = 0xcf0000;
+    public static const int WS_POPUP = 0x80000000;
+    public static const int WS_SYSMENU = 0x80000;
+    public static const int WS_TABSTOP = 0x10000;
+    public static const int WS_THICKFRAME = 0x40000;
+    public static const int WS_VISIBLE = 0x10000000;
+    public static const int WS_VSCROLL = 0x200000;
+    public static const int WM_XBUTTONDOWN = 0x020B;
+    public static const int WM_XBUTTONUP = 0x020C;
+    public static const int WM_XBUTTONDBLCLK = 0x020D;
+    public static const int XBUTTON1 = 0x1;
+    public static const int XBUTTON2 = 0x2;
+
+
+/** Ansi/Unicode wrappers */
+// Unicode/Ansi alias
+version(ANSI) {
+    alias WINAPI.AddFontResourceExA AddFontResourceEx;
+    alias WINAPI.AssocQueryStringA AssocQueryString;
+    alias WINAPI.CallWindowProcA CallWindowProc;
+    alias WINAPI.CharLowerA CharLower;
+    alias WINAPI.CharUpperA CharUpper;
+    alias WINAPI.ChooseColorA ChooseColor;
+    alias WINAPI.ChooseFontA ChooseFont;
+    alias WINAPI.CreateAcceleratorTableA CreateAcceleratorTable;
+    alias WINAPI.CreateDCA CreateDC;
+    alias WINAPI.CreateEnhMetaFileA CreateEnhMetaFile;
+    alias WINAPI.CreateEventA CreateEvent;
+    alias WINAPI.CreateFileA CreateFile;
+    alias WINAPI.CreateFontIndirectA CreateFontIndirect;
+    alias WINAPI.CreateWindowExA CreateWindowEx;
+    alias WINAPI.DefFrameProcA DefFrameProc;
+    alias WINAPI.DefMDIChildProcA DefMDIChildProc;
+    alias WINAPI.DefWindowProcA DefWindowProc;
+    alias WINAPI.DeleteFileA DeleteFile;
+    alias WINAPI.DispatchMessageA DispatchMessage;
+    alias WINAPI.DragQueryFileA DragQueryFile;
+    alias WINAPI.DrawStateA DrawState;
+    alias WINAPI.DrawTextA DrawText;
+    alias WINAPI.EnumFontFamiliesExA EnumFontFamiliesEx;
+    alias WINAPI.EnumFontFamiliesA EnumFontFamilies;
+    alias WINAPI.EnumSystemLanguageGroupsA EnumSystemLanguageGroups;
+    alias EnumSystemLocalesA EnumSystemLocales;
+    alias WINAPI.ExpandEnvironmentStringsA ExpandEnvironmentStrings;
+    alias WINAPI.ExtTextOutA ExtTextOut;
+    alias WINAPI.ExtractIconExA ExtractIconEx;
+    alias WINAPI.FindResourceA FindResource;
+    alias WINAPI.FindWindowA FindWindow;
+    alias WINAPI.FormatMessageA FormatMessage;
+    alias WINAPI.GetCharABCWidthsA GetCharABCWidths;
+    alias WINAPI.GetCharWidthA GetCharWidth;
+    alias WINAPI.GetCharacterPlacementA GetCharacterPlacement;
+    alias WINAPI.GetClassInfoA GetClassInfo;
+    alias WINAPI.GetClassNameA GetClassName;
+    alias WINAPI.GetClipboardFormatNameA GetClipboardFormatName;
+    alias WINAPI.GetDateFormatA GetDateFormat;
+    alias WINAPI.GetTimeFormatA GetTimeFormat;
+    alias WINAPI.GetKeyNameTextA GetKeyNameText;
+    alias WINAPI.GetLocaleInfoA GetLocaleInfo;
+    alias WINAPI.GetMenuItemInfoA GetMenuItemInfo;
+    alias WINAPI.GetMessageA GetMessage;
+    alias WINAPI.GetModuleFileNameA GetModuleFileName;
+    alias WINAPI.GetModuleHandleA GetModuleHandle;
+    alias WINAPI.GetMonitorInfoA GetMonitorInfo;
+    alias WINAPI.GetObjectA GetObject;
+    alias WINAPI.GetOpenFileNameA GetOpenFileName;
+    alias WINAPI.GetOutlineTextMetricsA GetOutlineTextMetrics;
+    alias WINAPI.GetProfileStringA _GetProfileString;
+    alias WINAPI.GetPropA GetProp;
+    alias WINAPI.GetSaveFileNameA GetSaveFileName;
+    alias WINAPI.GetStartupInfoA GetStartupInfo;
+    alias WINAPI.GetTextExtentPoint32A GetTextExtentPoint32;
+    alias WINAPI.GetTextMetricsA GetTextMetrics;
+    alias WINAPI.GetVersionExA GetVersionEx;
+    alias WINAPI.GetWindowLongA GetWindowLong;
+    alias WINAPI.GetWindowLongA GetWindowLongPtr; // is a macro
+    alias WINAPI.GetWindowTextA _GetWindowText;
+    alias WINAPI.GetWindowTextLengthA GetWindowTextLength;
+    alias WINAPI.GlobalAddAtomA GlobalAddAtom;
+//     alias WINAPI.ImmGetCompositionFontA ImmGetCompositionFont;
+//     alias WINAPI.ImmGetCompositionStringA ImmGetCompositionString;
+//     alias WINAPI.ImmSetCompositionFontA ImmSetCompositionFont;
+    alias WINAPI.InsertMenuA InsertMenu;
+    alias WINAPI.InsertMenuItemA InsertMenuItem;
+    alias WINAPI.LoadBitmapA LoadBitmap;
+    alias WINAPI.LoadCursorA LoadCursor;
+    alias WINAPI.LoadIconA LoadIcon;
+    alias WINAPI.LoadImageA LoadImage;
+    alias WINAPI.LoadLibraryA LoadLibrary;
+    alias WINAPI.LoadStringA LoadString;
+    alias WINAPI.MapVirtualKeyA MapVirtualKey;
+    alias WINAPI.MessageBoxA MessageBox;
+    alias WINAPI.OutputDebugStringA OutputDebugString;
+    alias WINAPI.PeekMessageA PeekMessage;
+    alias WINAPI.PostMessageA PostMessage;
+    alias WINAPI.PostThreadMessageA PostThreadMessage;
+    alias WINAPI.PrintDlgA PrintDlg;
+    alias WINAPI.RegEnumKeyExA RegEnumKeyEx;
+    alias WINAPI.RegOpenKeyExA RegOpenKeyEx;
+    alias WINAPI.RegQueryInfoKeyA RegQueryInfoKey;
+    alias WINAPI.RegQueryValueExA RegQueryValueEx;
+    alias WINAPI.RegisterClassA RegisterClass;
+    alias WINAPI.RegisterClipboardFormatA RegisterClipboardFormat;
+    alias WINAPI.RegOpenKeyExA RegOpenKeyEx;
+    alias WINAPI.RegisterWindowMessageA RegisterWindowMessage;
+    alias WINAPI.RemovePropA RemoveProp;
+    alias WINAPI.SHBrowseForFolderA SHBrowseForFolder;
+    alias WINAPI.SHGetPathFromIDListA SHGetPathFromIDList;
+    alias WINAPI.SendMessageA SendMessage;
+    alias WINAPI.SetMenuItemInfoA SetMenuItemInfo;
+    alias WINAPI.SetPropA SetProp;
+    alias WINAPI.SetWindowLongA SetWindowLong;
+    alias WINAPI.SetWindowLongA SetWindowLongPtr;
+    alias WINAPI.SetWindowTextA SetWindowText;
+    alias WINAPI.SetWindowsHookExA SetWindowsHookEx;
+    alias WINAPI.ShellExecuteExA ShellExecuteEx;
+    alias WINAPI.Shell_NotifyIconA Shell_NotifyIcon;
+    alias WINAPI.StartDocA StartDoc;
+    alias WINAPI.SystemParametersInfoA SystemParametersInfo;
+    alias WINAPI.TranslateAcceleratorA TranslateAccelerator;
+    alias WINAPI.UnregisterClassA UnregisterClass;
+    alias WINAPI.VkKeyScanA VkKeyScan;
+}else{
+    alias DWTWINAPI.AddFontResourceExW AddFontResourceEx;
+    alias DWTWINAPI.AssocQueryStringW AssocQueryString;
+    alias WINAPI.CallWindowProcW CallWindowProc;
+    alias WINAPI.CharLowerW CharLower;
+    alias WINAPI.CharUpperW CharUpper;
+    alias WINAPI.ChooseColorW ChooseColor;
+    alias WINAPI.ChooseFontW ChooseFont;
+    alias WINAPI.CreateAcceleratorTableW CreateAcceleratorTable;
+    alias WINAPI.CreateDCW CreateDC;
+    alias WINAPI.CreateEnhMetaFileW CreateEnhMetaFile;
+    alias WINAPI.CreateEventW CreateEvent;
+    alias WINAPI.CreateFileW CreateFile;
+    alias WINAPI.CreateFontIndirectW CreateFontIndirect;
+    alias WINAPI.CreateWindowExW CreateWindowEx;
+    alias WINAPI.DefFrameProcW DefFrameProc;
+    alias WINAPI.DefMDIChildProcW DefMDIChildProc;
+    alias WINAPI.DefWindowProcW DefWindowProc;
+    alias WINAPI.DeleteFileW DeleteFile;
+    alias WINAPI.DispatchMessageW DispatchMessage;
+    alias WINAPI.DragQueryFileW DragQueryFile;
+    alias WINAPI.DrawStateW DrawState;
+    alias WINAPI.DrawTextW DrawText;
+    alias WINAPI.EnumFontFamiliesExW EnumFontFamiliesEx;
+    alias WINAPI.EnumFontFamiliesW EnumFontFamilies;
+    alias EnumSystemLanguageGroupsW EnumSystemLanguageGroups;
+    alias EnumSystemLocalesW EnumSystemLocales;
+    alias WINAPI.ExpandEnvironmentStringsW ExpandEnvironmentStrings;
+    alias WINAPI.ExtTextOutW ExtTextOut;
+    alias DWTWINAPI.ExtractIconExW ExtractIconEx;
+    alias WINAPI.FindResourceW FindResource;
+    alias WINAPI.FindWindowW FindWindow;
+    alias WINAPI.FormatMessageW FormatMessage;
+    alias WINAPI.GetCharABCWidthsW GetCharABCWidths;
+    alias WINAPI.GetCharWidthW GetCharWidth;
+    alias WINAPI.GetCharacterPlacementW GetCharacterPlacement;
+    alias WINAPI.GetClassInfoW GetClassInfo;
+    alias WINAPI.GetClassNameW GetClassName;
+    alias WINAPI.GetClipboardFormatNameW GetClipboardFormatName;
+    alias WINAPI.GetDateFormatW GetDateFormat;
+    alias WINAPI.GetTimeFormatW GetTimeFormat;
+    alias WINAPI.GetKeyNameTextW GetKeyNameText;
+    alias WINAPI.GetLocaleInfoW GetLocaleInfo;
+    alias WINAPI.GetMenuItemInfoW GetMenuItemInfo;
+    alias WINAPI.GetMessageW GetMessage;
+    alias WINAPI.GetModuleFileNameW GetModuleFileName;
+    alias WINAPI.GetModuleHandleW GetModuleHandle;
+    alias DWTWINAPI.GetMonitorInfoW GetMonitorInfo;
+    alias WINAPI.GetObjectW GetObject;
+    alias WINAPI.GetOpenFileNameW GetOpenFileName;
+    alias WINAPI.GetOutlineTextMetricsW GetOutlineTextMetrics;
+    alias WINAPI.GetProfileStringW _GetProfileString;
+    alias WINAPI.GetPropW GetProp;
+    alias WINAPI.GetSaveFileNameW GetSaveFileName;
+    alias WINAPI.CreateProcessW CreateProcess;
+    alias WINAPI.GetStartupInfoW GetStartupInfo;
+    alias WINAPI.GetTextExtentPoint32W GetTextExtentPoint32;
+    alias WINAPI.GetTextMetricsW GetTextMetrics;
+    alias WINAPI.GetVersionExW GetVersionEx;
+    alias WINAPI.GetWindowLongW GetWindowLong;
+    alias WINAPI.GetWindowLongW GetWindowLongPtr; // is a macro
+    alias WINAPI.GetWindowTextW _GetWindowText;
+    alias WINAPI.GetWindowTextLengthW GetWindowTextLength;
+    alias WINAPI.GlobalAddAtomW GlobalAddAtom;
+//     alias WINAPI.ImmGetCompositionFontW ImmGetCompositionFont;
+//     alias WINAPI.ImmGetCompositionStringW ImmGetCompositionString;
+//     alias WINAPI.ImmSetCompositionFontW ImmSetCompositionFont;
+    alias WINAPI.InsertMenuW InsertMenu;
+    alias WINAPI.InsertMenuItemW InsertMenuItem;
+    alias WINAPI.LoadBitmapW LoadBitmap;
+    alias WINAPI.LoadCursorW LoadCursor;
+    alias WINAPI.LoadIconW LoadIcon;
+    alias WINAPI.LoadImageW LoadImage;
+    alias WINAPI.LoadLibraryW LoadLibrary;
+    alias WINAPI.LoadStringW LoadString;
+    alias WINAPI.MapVirtualKeyW MapVirtualKey;
+    alias WINAPI.MessageBoxW MessageBox;
+    alias WINAPI.OutputDebugStringW OutputDebugString;
+    alias WINAPI.PeekMessageW PeekMessage;
+    alias WINAPI.PostMessageW PostMessage;
+    alias WINAPI.PostThreadMessageW PostThreadMessage;
+    alias WINAPI.PrintDlgW PrintDlg;
+    alias WINAPI.RegEnumKeyExW RegEnumKeyEx;
+    alias WINAPI.RegOpenKeyExW RegOpenKeyEx;
+    alias WINAPI.RegQueryInfoKeyW RegQueryInfoKey;
+    alias WINAPI.RegQueryValueExW RegQueryValueEx;
+    alias WINAPI.RegisterClassW RegisterClass;
+    alias WINAPI.RegisterClipboardFormatW RegisterClipboardFormat;
+    alias WINAPI.RegOpenKeyExW RegOpenKeyEx;
+    alias WINAPI.RegisterWindowMessageW RegisterWindowMessage;
+    alias WINAPI.RemovePropW RemoveProp;
+    alias DWTWINAPI.SHBrowseForFolderW SHBrowseForFolder;
+    alias DWTWINAPI.SHGetPathFromIDListW SHGetPathFromIDList;
+    alias WINAPI.SendMessageW SendMessage;
+    alias WINAPI.SetMenuItemInfoW SetMenuItemInfo;
+    alias WINAPI.SetWindowLongW SetWindowLong;
+    alias WINAPI.SetWindowLongW SetWindowLongPtr;
+    alias WINAPI.SetWindowTextW SetWindowText;
+    alias WINAPI.SetWindowsHookExW SetWindowsHookEx;
+    alias WINAPI.SetPropW SetProp;
+    alias DWTWINAPI.ShellExecuteExW ShellExecuteEx;
+    alias DWTWINAPI.Shell_NotifyIconW Shell_NotifyIcon;
+    alias WINAPI.StartDocW StartDoc;
+    alias WINAPI.SystemParametersInfoW SystemParametersInfo;
+    alias WINAPI.TranslateAcceleratorW TranslateAccelerator;
+    alias WINAPI.UnregisterClassW UnregisterClass;
+    alias WINAPI.VkKeyScanW VkKeyScan;
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// UxTheme dummies until dynamic loading is in place.
+// ----------------------------------------------------------------------------
+public static extern(Windows) {
+    BOOL function (
+    ) IsAppThemed;
+
+    HRESULT function(
+        HTHEME hTheme,
+        HDC hdc,
+        int iPartId,
+        int iStateId,
+        RECT *pRect,
+        RECT *pClipRect
+    ) DrawThemeBackground;
+
+    HRESULT function(
+        HTHEME hTheme,
+        HDC hdc,
+        int iPartId,
+        int iStateId,
+        LPCRECT pDestRect,
+        UINT uEdge,
+        UINT uFlags,
+        LPRECT pContentRect
+    ) DrawThemeEdge;
+
+    HRESULT function(
+        HTHEME hTheme,
+        HDC hdc,
+        int iPartId,
+        int iStateId,
+        LPCRECT pRect,
+        HIMAGELIST himl,
+        int iImageIndex
+    ) DrawThemeIcon;
+
+    HRESULT function(
+        HWND hwnd,
+        HDC hdc,
+        RECT *prc
+    ) DrawThemeParentBackground;
+
+    HRESULT function(
+        HTHEME hTheme,
+        HDC hdc,
+        int iPartId,
+        int iStateId,
+        LPCWSTR pszText,
+        int iCharCount,
+        DWORD dwTextFlags,
+        DWORD dwTextFlags2,
+        LPCRECT pRect
+    ) DrawThemeText;
+
+    HTHEME function(
+        HWND hwnd,
+        LPCWSTR pszClassList
+    ) OpenThemeData;
+
+    HRESULT function(
+    )BufferedPaintInit;
+
+    HRESULT function(
+        HTHEME hTheme
+    ) CloseThemeData;
+
+    HRESULT function(
+    ) BufferedPaintUnInit;
+
+    HPAINTBUFFER function(
+        HDC hdcTarget,
+        RECT *prcTarget,
+        uint/+BP_BUFFERFORMAT+/ dwFormat,
+        void*/+BP_PAINTPARAMS+/ pPaintParams,
+        HDC *phdc
+    ) BeginBufferedPaint;
+
+    HRESULT function(
+        HPAINTBUFFER hBufferedPaint,
+        BOOL fUpdateTarget
+    ) EndBufferedPaint;
+
+    HRESULT function(
+        HTHEME hTheme,
+        HDC hdc,
+        int iPartId,
+        int iStateId,
+        LPCWSTR pszText,
+        int iCharCount,
+        DWORD dwTextFlags,
+        LPCRECT pBoundingRect,
+        LPRECT pExtentRect
+    ) GetThemeTextExtent;
+
+    HRESULT function(
+        HWND hwnd,
+        LPCWSTR pszSubAppName,
+        LPCWSTR pszSubIdList
+    ) SetWindowTheme;
+
+} // public static
+
+static Symbol[] Symbols_UxTheme = [
+    { "IsAppThemed", cast(void**)& IsAppThemed, 5, 1 },
+    { "DrawThemeBackground", cast(void**)& DrawThemeBackground, 5, 1 },
+    { "DrawThemeEdge", cast(void**)& DrawThemeEdge, 5, 1 },
+    { "DrawThemeIcon", cast(void**)& DrawThemeIcon, 5, 1 },
+    { "DrawThemeParentBackground", cast(void**)& DrawThemeParentBackground, 5, 1 },
+    { "DrawThemeText", cast(void**)& DrawThemeText, 5, 1 },
+    { "OpenThemeData", cast(void**)& OpenThemeData, 5, 1 },
+    { "CloseThemeData", cast(void**)& CloseThemeData, 5, 1 },
+    { "GetThemeTextExtent", cast(void**)& GetThemeTextExtent, 5, 1 },
+    { "SetWindowTheme", cast(void**)& SetWindowTheme, 5, 1 },
+    { "BufferedPaintUnInit", cast(void**)& BufferedPaintUnInit, 6, 0 },
+    { "BufferedPaintInit", cast(void**)& BufferedPaintInit, 6, 0 },
+    { "BeginBufferedPaint", cast(void**)& BeginBufferedPaint, 6, 0 },
+    { "EndBufferedPaint", cast(void**)& EndBufferedPaint, 6, 0 },
+];
+
+static void loadLib_UxTheme(){
+    if (auto lib = SharedLib.load(`uxtheme.dll`)) {
+        foreach( inout s; Symbols_UxTheme ){
+            if( OS.WIN32_VERSION >= OS.VERSION( s.major, s.minor )){
+                *s.symbol = lib.getSymbol( s.name.ptr );
+                if( *s.symbol is null ){
+                    getDwtLogger.error("UxTheme.dll: Symbol '{}' not found", s.name );
+                }
+            }
+        }
+    } else {
+        getDwtLogger.error("Could not load the library UxTheme.dll");
+    }
+}
+//----------------------------------------------------------------------
+// Coreimm.lib (WinCE)
+// this function vars exist primarily for link error elimination
+//----------------------------------------------------------------------
+public static extern(Windows) {
+
+    BOOL function(
+        HWND hwnd,
+        COLORREF *pcrKey,
+        BYTE *pbAlpha,
+        DWORD *pdwFlags
+    )GetLayeredWindowAttributes;
+
+    BOOL function(
+        HWND hwnd,
+        COLORREF crKey,
+        BYTE bAlpha,
+        DWORD dwFlags
+    )SetLayeredWindowAttributes;
+
+    BOOL function(
+        HWND hwnd,               // Window to copy
+        HDC  hdcBlt,             // HDC to print into
+        UINT nFlags              // Optional flags
+    ) PrintWindow;
+} // public static extern(Windows)
+
+
+static Symbol[] Symbols_CoreImm = [
+];
+
+// user32.dll vista
+public static extern(Windows){
+    BOOL function() SetProcessDPIAware;
+    BOOL function( HWND hWnd )IsHungAppWindow;
+}
+
+static Symbol[] Symbols_User32 = [
+    { "SetProcessDPIAware", cast(void**)& SetProcessDPIAware, 6, 0 },
+    { "GetLayeredWindowAttributes", cast(void**)& GetLayeredWindowAttributes, 5, 1 },
+    { "SetLayeredWindowAttributes", cast(void**)& SetLayeredWindowAttributes, 5, 0 },
+    { "PrintWindow", cast(void**)& PrintWindow, 5, 1 },
+    { "IsHungAppWindow", cast(void**)& IsHungAppWindow, 5, 0 },
+];
+
+// Imm32.lib
+public static extern(Windows) {
+HIMC function( HWND hWnd ) ImmGetContext;
+BOOL function( DWORD idThread ) ImmDisableTextFrameService;
+HIMC function( HWND hWnd, HIMC hIMC ) ImmAssociateContext;
+
+HIMC function() ImmCreateContext;
+int function( HIMC hIMC ) ImmDestroyContext;
+BOOL function( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence ) ImmGetConversionStatus;
+HWND function( HWND hWnd ) ImmGetDefaultIMEWnd;
+BOOL function( HIMC hIMC ) ImmGetOpenStatus;
+BOOL function( HWND hWnd, HIMC hIMC ) ImmReleaseContext;
+version(ANSI) {
+    BOOL function( HIMC hIMC, LOGFONTA* lplf ) ImmSetCompositionFont;
+    LONG function( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen ) ImmGetCompositionString;
+    BOOL function( HIMC hIMC, LPLOGFONTA lplf ) ImmGetCompositionFont;
+
+} else {
+    BOOL function( HIMC hIMC, LOGFONTW* lplf ) ImmSetCompositionFont;
+    LONG function( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen ) ImmGetCompositionString;
+    BOOL function( HIMC hIMC, LOGFONTW* lplf ) ImmGetCompositionFont;
+}
+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;
+
+    BOOL function(
+        HIMC hIMC,
+        LPCANDIDATEFORM lpCandidate
+    ) ImmSetCandidateWindow;
+
+}
+
+static Symbol[] Symbols_Imm32 = [
+    { "ImmAssociateContext", cast(void**)& ImmAssociateContext, 5, 1 },
+    { "ImmCreateContext", cast(void**)& ImmCreateContext, 5, 1 },
+    { "ImmDestroyContext", cast(void**)& ImmDestroyContext, 5, 1 },
+    { "ImmGetContext", cast(void**)& ImmGetContext, 5, 1 },
+    { "ImmGetConversionStatus", cast(void**)& ImmGetConversionStatus, 5, 1 },
+    { "ImmGetDefaultIMEWnd", cast(void**)& ImmGetDefaultIMEWnd, 5, 1 },
+    { "ImmGetOpenStatus", cast(void**)& ImmGetOpenStatus, 5, 1 },
+    { "ImmReleaseContext", cast(void**)& ImmReleaseContext, 5, 1 },
+    { "ImmSetCompositionFontW", cast(void**)& ImmSetCompositionFont, 5, 1 },
+    { "ImmGetCompositionStringW", cast(void**)& ImmGetCompositionString, 5, 1 },
+    { "ImmGetCompositionFontW", cast(void**)& ImmGetCompositionFont, 5, 1 },
+    { "ImmSetCompositionWindow", cast(void**)& ImmSetCompositionWindow, 5, 1 },
+    { "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 },
+    { "ImmSetCandidateWindow", cast(void**)& ImmSetCandidateWindow, 5, 1 },
+];
+
+version(ANSI){
+}else{
+static Symbol[] Symbols_Kernel32 = [
+    { "CreateActCtxW", cast(void**)& CreateActCtx, 5, 1 },
+    { "ActivateActCtx", cast(void**)& ActivateActCtx, 5, 1 },
+    { "GetSystemDefaultUILanguage", cast(void**)& GetSystemDefaultUILanguage, 5, 0 },
+    { "EnumSystemLanguageGroupsW", cast(void**)& EnumSystemLanguageGroupsW, 4, 0 },
+    { "EnumSystemLanguageGroupsA", cast(void**)& EnumSystemLanguageGroupsA, 4, 0 },
+    { "EnumSystemLocalesW", cast(void**)& EnumSystemLocalesW, 4, 0 },
+    { "EnumSystemLocalesA", cast(void**)& EnumSystemLocalesA, 4, 0 },
+];
+}
+
+
+//------------------------------------------------------------------------
+/** All Natives */
+alias WINAPI.AbortDoc AbortDoc;
+alias WINAPI.ActivateKeyboardLayout ActivateKeyboardLayout;
+alias WINAPI.AdjustWindowRectEx AdjustWindowRectEx;
+alias DWTWINAPI.AlphaBlend AlphaBlend;
+alias WINAPI.Arc Arc;
+alias WINAPI.BeginDeferWindowPos BeginDeferWindowPos;
+alias WINAPI.BeginPaint BeginPaint;
+alias WINAPI.BeginPath BeginPath;
+alias WINAPI.BitBlt BitBlt;
+alias WINAPI.BringWindowToTop BringWindowToTop;
+alias WINAPI.CallNextHookEx CallNextHookEx;
+alias WINAPI.CallWindowProcA CallWindowProcA;
+alias WINAPI.CallWindowProcW CallWindowProcW;
+alias WINAPI.CharLowerA CharLowerA;
+alias WINAPI.CharLowerW CharLowerW;
+alias WINAPI.CharUpperA CharUpperA;
+alias WINAPI.CharUpperW CharUpperW;
+alias WINAPI.CheckMenuItem CheckMenuItem;
+alias WINAPI.ChooseColorA ChooseColorA;
+alias WINAPI.ChooseColorW ChooseColorW;
+alias WINAPI.ChooseFontA ChooseFontA;
+alias WINAPI.ChooseFontW ChooseFontW;
+alias WINAPI.ClientToScreen ClientToScreen;
+alias WINAPI.CloseHandle CloseHandle;
+alias WINAPI.CloseClipboard CloseClipboard;
+alias WINAPI.CloseEnhMetaFile CloseEnhMetaFile;
+alias WINAPI.CloseMetaFile CloseMetaFile;
+alias WINAPI.CombineRgn CombineRgn;
+alias DWTWINAPI.CommDlgExtendedError CommDlgExtendedError;
+
+version(WinCE){
+alias WINAPI.CommandBar_AddAdornments CommandBar_AddAdornments;
+alias WINAPI.CommandBar_Create CommandBar_Create;
+alias WINAPI.CommandBar_Destroy CommandBar_Destroy;
+alias WINAPI.CommandBar_DrawMenuBar CommandBar_DrawMenuBar;
+alias WINAPI.CommandBar_Height CommandBar_Height;
+alias WINAPI.CommandBar_InsertMenubarEx CommandBar_InsertMenubarEx;
+alias WINAPI.CommandBar_Show CommandBar_Show;
+}
+
+alias WINAPI.CopyImage CopyImage;
+alias WINAPI.CreateAcceleratorTableA CreateAcceleratorTableA;
+alias WINAPI.CreateAcceleratorTableW CreateAcceleratorTableW;
+alias WINAPI.CreateBitmap CreateBitmap;
+alias WINAPI.CreateCaret CreateCaret;
+alias WINAPI.CreateCompatibleBitmap CreateCompatibleBitmap;
+alias WINAPI.CreateCompatibleDC CreateCompatibleDC;
+alias WINAPI.CreateCursor CreateCursor;
+alias WINAPI.CreateDCA CreateDCA;
+alias WINAPI.CreateDCW CreateDCW;
+alias WINAPI.CreateDIBSection CreateDIBSection;
+alias WINAPI.CreateEventA CreateEventA;
+alias WINAPI.CreateEventW CreateEventW;
+alias WINAPI.CreateFileA CreateFileA;
+alias WINAPI.CreateFileW CreateFileW;
+alias WINAPI.CreateFontIndirectA CreateFontIndirectA;
+alias WINAPI.CreateFontIndirectW CreateFontIndirectW;
+alias WINAPI.CreateIconIndirect CreateIconIndirect;
+alias WINAPI.CreateMenu CreateMenu;
+alias WINAPI.CreatePalette CreatePalette;
+alias WINAPI.CreatePatternBrush CreatePatternBrush;
+alias WINAPI.CreatePen CreatePen;
+alias WINAPI.CreatePolygonRgn CreatePolygonRgn;
+alias WINAPI.CreatePopupMenu CreatePopupMenu;
+alias WINAPI.CreateRectRgn CreateRectRgn;
+alias WINAPI.CreateSolidBrush CreateSolidBrush;
+alias WINAPI.CreateWindowExA CreateWindowExA;
+alias WINAPI.CreateWindowExW CreateWindowExW;
+alias WINAPI.DefFrameProcA DefFrameProcA;
+alias WINAPI.DefFrameProcW DefFrameProcW;
+alias WINAPI.DefMDIChildProcA DefMDIChildProcA;
+alias WINAPI.DefMDIChildProcW DefMDIChildProcW;
+alias WINAPI.DefWindowProcA DefWindowProcA;
+alias WINAPI.DefWindowProcW DefWindowProcW;
+alias WINAPI.DeferWindowPos DeferWindowPos;
+alias WINAPI.DeleteDC DeleteDC;
+alias WINAPI.DeleteEnhMetaFile DeleteEnhMetaFile;
+alias WINAPI.DeleteMenu DeleteMenu;
+alias WINAPI.DeleteObject DeleteObject;
+alias WINAPI.DestroyAcceleratorTable DestroyAcceleratorTable;
+alias WINAPI.DestroyCaret DestroyCaret;
+alias WINAPI.DestroyCursor DestroyCursor;
+alias WINAPI.DestroyIcon DestroyIcon;
+alias WINAPI.DestroyMenu DestroyMenu;
+alias WINAPI.DestroyWindow DestroyWindow;
+alias WINAPI.DispatchMessageA DispatchMessageA;
+alias WINAPI.DispatchMessageW DispatchMessageW;
+alias WINAPI.DragDetect DragDetect;
+alias WINAPI.DragFinish DragFinish;
+alias WINAPI.DragQueryFileA DragQueryFileA;
+alias WINAPI.DragQueryFileW DragQueryFileW;
+alias WINAPI.DrawEdge DrawEdge;
+alias WINAPI.DrawFocusRect DrawFocusRect;
+alias WINAPI.DrawFrameControl DrawFrameControl;
+alias WINAPI.DrawIconEx DrawIconEx;
+alias WINAPI.DrawMenuBar DrawMenuBar;
+alias WINAPI.DrawStateA DrawStateA;
+alias WINAPI.DrawStateW DrawStateW;
+alias WINAPI.DrawTextA DrawTextA;
+alias WINAPI.DrawTextW DrawTextW;
+alias WINAPI.Ellipse Ellipse;
+alias WINAPI.EnableMenuItem EnableMenuItem;
+alias WINAPI.EnableScrollBar EnableScrollBar;
+alias WINAPI.EnableWindow EnableWindow;
+alias WINAPI.EndDeferWindowPos EndDeferWindowPos;
+alias WINAPI.EndDoc EndDoc;
+alias WINAPI.EndPage EndPage;
+alias WINAPI.EndPaint EndPaint;
+alias WINAPI.EndPath EndPath;
+alias WINAPI.EnumDisplayMonitors EnumDisplayMonitors;
+alias WINAPI.EnumEnhMetaFile EnumEnhMetaFile;
+alias WINAPI.EnumFontFamiliesA EnumFontFamiliesA;
+alias WINAPI.EnumFontFamiliesExA EnumFontFamiliesExA;
+alias WINAPI.EnumFontFamiliesExW EnumFontFamiliesExW;
+alias WINAPI.EnumFontFamiliesW EnumFontFamiliesW;
+alias DWTWINAPI.EqualRect EqualRect;
+alias WINAPI.EqualRgn EqualRgn;
+alias WINAPI.ExcludeClipRect ExcludeClipRect;
+alias WINAPI.ExpandEnvironmentStringsA ExpandEnvironmentStringsA;
+alias WINAPI.ExpandEnvironmentStringsW ExpandEnvironmentStringsW;
+alias WINAPI.ExtTextOutA ExtTextOutA;
+alias WINAPI.ExtTextOutW ExtTextOutW;
+alias DWTWINAPI.ExtractIconExA ExtractIconExA;
+alias DWTWINAPI.ExtractIconExW ExtractIconExW;
+alias WINAPI.ExtCreatePen ExtCreatePen;
+alias WINAPI.ExtCreateRegion ExtCreateRegion;
+alias WINAPI.FillRect FillRect;
+alias WINAPI.FindResourceA FindResourceA;
+alias WINAPI.FindResourceW FindResourceW;
+alias WINAPI.FindWindowA FindWindowA;
+alias WINAPI.FindWindowW FindWindowW;
+alias WINAPI.FormatMessageA FormatMessageA;
+alias WINAPI.FormatMessageW FormatMessageW;
+alias WINAPI.FreeLibrary FreeLibrary;
+alias WINAPI.GdiSetBatchLimit GdiSetBatchLimit;
+alias WINAPI.GetACP GetACP;
+alias WINAPI.GetAsyncKeyState GetAsyncKeyState;
+alias WINAPI.GetActiveWindow GetActiveWindow;
+alias WINAPI.GetBkColor GetBkColor;
+alias WINAPI.GetCapture GetCapture;
+alias WINAPI.GetCaretPos GetCaretPos;
+alias WINAPI.GetCharABCWidthsA GetCharABCWidthsA;
+alias WINAPI.GetCharABCWidthsW GetCharABCWidthsW;
+alias WINAPI.GetCharWidthA GetCharWidthA;
+alias WINAPI.GetCharWidthW GetCharWidthW;
+alias WINAPI.GetCharacterPlacementA GetCharacterPlacementA;
+alias WINAPI.GetCharacterPlacementW GetCharacterPlacementW;
+alias WINAPI.GetClassInfoA GetClassInfoA;
+alias WINAPI.GetClassInfoW GetClassInfoW;
+alias WINAPI.GetClientRect GetClientRect;
+alias WINAPI.GetClipBox GetClipBox;
+alias WINAPI.GetClipRgn GetClipRgn;
+alias WINAPI.GetClipboardData GetClipboardData;
+alias WINAPI.GetClipboardFormatNameA GetClipboardFormatNameA;
+alias WINAPI.GetClipboardFormatNameW GetClipboardFormatNameW;
+alias DWTWINAPI.GetComboBoxInfo GetComboBoxInfo;
+alias WINAPI.GetCurrentObject GetCurrentObject;
+alias WINAPI.GetCurrentProcessId GetCurrentProcessId;
+alias WINAPI.GetCurrentThreadId GetCurrentThreadId;
+alias WINAPI.GetCursor GetCursor;
+alias WINAPI.GetCursorPos GetCursorPos;
+alias WINAPI.GetDC GetDC;
+alias WINAPI.GetDCEx GetDCEx;
+alias WINAPI.GetDIBColorTable GetDIBColorTable;
+alias WINAPI.GetDIBits GetDIBits;
+alias WINAPI.GetDesktopWindow GetDesktopWindow;
+alias WINAPI.GetDeviceCaps GetDeviceCaps;
+alias WINAPI.GetDialogBaseUnits GetDialogBaseUnits;
+alias WINAPI.GetDlgItem GetDlgItem;
+alias WINAPI.GetDoubleClickTime GetDoubleClickTime;
+alias WINAPI.GetFocus GetFocus;
+alias WINAPI.GetFontLanguageInfo GetFontLanguageInfo;
+alias DWTWINAPI.GetGUIThreadInfo GetGUIThreadInfo;
+alias WINAPI.GetIconInfo GetIconInfo;
+alias WINAPI.GetKeyNameTextA GetKeyNameTextA;
+alias WINAPI.GetKeyNameTextW GetKeyNameTextW;
+alias WINAPI.GetKeyState GetKeyState;
+alias WINAPI.GetKeyboardLayout GetKeyboardLayout;
+alias WINAPI.GetKeyboardLayoutList GetKeyboardLayoutList;
+alias WINAPI.GetKeyboardState GetKeyboardState;
+alias WINAPI.GetLastActivePopup GetLastActivePopup;
+alias WINAPI.GetLastError GetLastError;
+alias DWTWINAPI.GetLayout GetLayout;
+alias WINAPI.GetLocaleInfoA GetLocaleInfoA;
+alias WINAPI.GetLocaleInfoW GetLocaleInfoW;
+alias WINAPI.GetMenu GetMenu;
+alias DWTWINAPI.GetMenuBarInfo GetMenuBarInfo;
+alias WINAPI.GetMenuDefaultItem GetMenuDefaultItem;
+alias DWTWINAPI.GetMenuInfo GetMenuInfo;
+alias WINAPI.GetMenuItemCount GetMenuItemCount;
+alias WINAPI.GetMenuItemInfoA GetMenuItemInfoA;
+alias WINAPI.GetMenuItemInfoW GetMenuItemInfoW;
+alias WINAPI.GetMenuItemRect GetMenuItemRect;
+alias WINAPI.GetMessageA GetMessageA;
+alias WINAPI.GetMessagePos GetMessagePos;
+alias WINAPI.GetMessageTime GetMessageTime;
+alias WINAPI.GetMetaRgn GetMetaRgn;
+alias WINAPI.GetMessageW GetMessageW;
+alias WINAPI.GetModuleFileNameA GetModuleFileNameA;
+alias WINAPI.GetModuleFileNameW GetModuleFileNameW;
+alias WINAPI.GetModuleHandleA GetModuleHandleA;
+alias WINAPI.GetModuleHandleW GetModuleHandleW;
+alias WINAPI.GetMonitorInfoA GetMonitorInfoA;
+alias DWTWINAPI.GetMonitorInfoW GetMonitorInfoW;
+alias WINAPI.GetNearestPaletteIndex GetNearestPaletteIndex;
+alias WINAPI.GetPath GetPath;
+alias WINAPI.GetObjectA GetObjectA;
+alias WINAPI.GetObjectW GetObjectW;
+alias WINAPI.GetOpenFileNameA GetOpenFileNameA;
+alias WINAPI.GetOpenFileNameW GetOpenFileNameW;
+alias WINAPI.GetPaletteEntries GetPaletteEntries;
+alias WINAPI.GetParent GetParent;
+alias WINAPI.GetPixel GetPixel;
+alias WINAPI.GetPolyFillMode GetPolyFillMode;
+alias WINAPI.GetProcAddress GetProcAddress;
+alias WINAPI.GetProcessHeap GetProcessHeap;
+alias WINAPI.GetProfileStringA GetProfileStringA;
+alias WINAPI.GetProfileStringW GetProfileStringW;
+alias WINAPI.GetROP2 GetROP2;
+alias DWTWINAPI.GetRandomRgn GetRandomRgn;
+alias WINAPI.GetRegionData GetRegionData;
+alias WINAPI.GetRgnBox GetRgnBox;
+alias WINAPI.GetSaveFileNameA GetSaveFileNameA;
+alias WINAPI.GetSaveFileNameW GetSaveFileNameW;
+alias WINAPI.GetScrollInfo GetScrollInfo;
+alias WINAPI.GetStockObject GetStockObject;
+alias WINAPI.GetSysColor GetSysColor;
+alias WINAPI.GetSysColorBrush GetSysColorBrush;
+//alias DWTWINAPI.GetSystemDefaultUILanguage GetSystemDefaultUILanguage;
+alias WINAPI.GetSystemMenu GetSystemMenu;
+alias WINAPI.GetSystemMetrics GetSystemMetrics;
+alias WINAPI.GetSystemPaletteEntries GetSystemPaletteEntries;
+alias WINAPI.GetTextCharset GetTextCharset;
+alias WINAPI.GetTextColor GetTextColor;
+alias WINAPI.GetTextExtentPoint32A GetTextExtentPoint32A;
+alias WINAPI.GetTextExtentPoint32W GetTextExtentPoint32W;
+alias WINAPI.GetTextMetricsA GetTextMetricsA;
+alias WINAPI.GetTextMetricsW GetTextMetricsW;
+alias WINAPI.GetTickCount GetTickCount;
+alias WINAPI.GetUpdateRect GetUpdateRect;
+alias WINAPI.GetUpdateRgn GetUpdateRgn;
+alias WINAPI.GetVersion GetVersion;
+alias WINAPI.GetVersionExA GetVersionExA;
+alias WINAPI.GetVersionExW GetVersionExW;
+alias WINAPI.GetWindow GetWindow;
+alias WINAPI.GetWindowDC GetWindowDC;
+alias WINAPI.GetWindowOrgEx GetWindowOrgEx;
+alias WINAPI.GetWindowLongA GetWindowLongA;
+alias WINAPI.GetWindowLongW GetWindowLongW;
+alias WINAPI.GetWindowPlacement GetWindowPlacement;
+alias WINAPI.GetWindowRect GetWindowRect;
+alias WINAPI.GetWindowRgn GetWindowRgn;
+alias WINAPI.GetWindowTextA GetWindowTextA;
+alias WINAPI.GetWindowTextLengthA GetWindowTextLengthA;
+alias WINAPI.GetWindowTextLengthW GetWindowTextLengthW;
+alias WINAPI.GetWindowTextW GetWindowTextW;
+alias WINAPI.GetWindowThreadProcessId GetWindowThreadProcessId;
+alias WINAPI.GlobalAlloc GlobalAlloc;
+alias WINAPI.GlobalFree GlobalFree;
+alias WINAPI.GlobalLock GlobalLock;
+alias WINAPI.GlobalSize GlobalSize;
+alias WINAPI.GlobalUnlock GlobalUnlock;
+alias DWTWINAPI.GradientFill GradientFill;
+alias WINAPI.HeapAlloc HeapAlloc;
+alias WINAPI.HeapFree HeapFree;
+alias WINAPI.HideCaret HideCaret;
+alias DWTWINAPI.IIDFromString IIDFromString;
+alias WINAPI.ImageList_Add ImageList_Add;
+alias WINAPI.ImageList_AddMasked ImageList_AddMasked;
+alias WINAPI.ImageList_BeginDrag ImageList_BeginDrag;
+alias WINAPI.ImageList_Create ImageList_Create;
+alias WINAPI.ImageList_Destroy ImageList_Destroy;
+alias WINAPI.ImageList_DragEnter ImageList_DragEnter;
+alias WINAPI.ImageList_DragLeave ImageList_DragLeave;
+alias WINAPI.ImageList_DragMove ImageList_DragMove;
+alias WINAPI.ImageList_DragShowNolock ImageList_DragShowNolock;
+alias WINAPI.ImageList_Draw ImageList_Draw;
+alias WINAPI.ImageList_EndDrag ImageList_EndDrag;
+alias WINAPI.ImageList_GetIcon ImageList_GetIcon;
+alias WINAPI.ImageList_GetIconSize ImageList_GetIconSize;
+alias WINAPI.ImageList_GetImageCount ImageList_GetImageCount;
+alias WINAPI.ImageList_Remove ImageList_Remove;
+alias WINAPI.ImageList_Replace ImageList_Replace;
+alias WINAPI.ImageList_ReplaceIcon ImageList_ReplaceIcon;
+alias WINAPI.ImageList_SetIconSize ImageList_SetIconSize;
+// alias WINAPI.ImmAssociateContext ImmAssociateContext;
+// alias WINAPI.ImmCreateContext ImmCreateContext;
+// alias WINAPI.ImmDestroyContext ImmDestroyContext;
+// alias WINAPI.ImmGetCompositionFontA ImmGetCompositionFontA;
+// alias WINAPI.ImmGetCompositionFontW ImmGetCompositionFontW;
+// alias WINAPI.ImmGetCompositionStringA ImmGetCompositionStringA;
+// alias WINAPI.ImmGetCompositionStringW ImmGetCompositionStringW;
+// alias WINAPI.ImmGetContext ImmGetContext;
+// alias WINAPI.ImmGetConversionStatus ImmGetConversionStatus;
+// alias WINAPI.ImmGetDefaultIMEWnd ImmGetDefaultIMEWnd;
+// alias WINAPI.ImmGetOpenStatus ImmGetOpenStatus;
+// alias WINAPI.ImmReleaseContext ImmReleaseContext;
+// alias WINAPI.ImmSetCompositionFontA ImmSetCompositionFontA;
+// alias WINAPI.ImmSetCompositionFontW ImmSetCompositionFontW;
+// alias WINAPI.ImmSetOpenStatus ImmSetOpenStatus;
+alias WINAPI.InitCommonControls InitCommonControls;
+alias DWTWINAPI.InitCommonControlsEx InitCommonControlsEx;
+alias WINAPI.InsertMenuA InsertMenuA;
+alias WINAPI.InsertMenuItemA InsertMenuItemA;
+alias WINAPI.InsertMenuItemW InsertMenuItemW;
+alias WINAPI.InsertMenuW InsertMenuW;
+alias WINAPI.InterlockedDecrement InterlockedDecrement;
+alias WINAPI.InterlockedIncrement InterlockedIncrement;
+alias WINAPI.IntersectClipRect IntersectClipRect;
+alias WINAPI.IntersectRect IntersectRect;
+alias WINAPI.InvalidateRect InvalidateRect;
+alias WINAPI.InvalidateRgn InvalidateRgn;
+alias WINAPI.IsDBCSLeadByte IsDBCSLeadByte;
+//alias DWTWINAPI.IsHungAppWindow IsHungAppWindow;
+alias WINAPI.IsIconic IsIconic;
+alias WINAPI.IsWindow IsWindow;
+alias WINAPI.IsWindowEnabled IsWindowEnabled;
+alias WINAPI.IsWindowVisible IsWindowVisible;
+alias WINAPI.IsZoomed IsZoomed;
+alias WINAPI.KillTimer KillTimer;
+alias WINAPI.LineTo LineTo;
+alias WINAPI.LoadBitmapA LoadBitmapA;
+alias WINAPI.LoadBitmapW LoadBitmapW;
+alias WINAPI.LoadCursorA LoadCursorA;
+alias WINAPI.LoadCursorW LoadCursorW;
+alias WINAPI.LoadIconA LoadIconA;
+alias WINAPI.LoadIconW LoadIconW;
+alias WINAPI.LoadImageA LoadImageA;
+alias WINAPI.LoadImageW LoadImageW;
+alias WINAPI.LoadLibraryA LoadLibraryA;
+alias WINAPI.LoadLibraryW LoadLibraryW;
+alias WINAPI.LoadResource LoadResource;
+alias WINAPI.LoadStringA LoadStringA;
+alias WINAPI.LoadStringW LoadStringW;
+alias WINAPI.LocalFree LocalFree;
+alias WINAPI.LockResource LockResource;
+alias WINAPI.MapVirtualKeyA MapVirtualKeyA;
+alias WINAPI.MapVirtualKeyW MapVirtualKeyW;
+alias WINAPI.MapWindowPoints MapWindowPoints;
+alias WINAPI.MessageBeep MessageBeep;
+alias WINAPI.MessageBoxA MessageBoxA;
+alias WINAPI.MessageBoxW MessageBoxW;
+alias DWTWINAPI.MonitorFromWindow MonitorFromWindow;
+alias WINAPI.MoveToEx MoveToEx;
+alias DWTWINAPI.MsgWaitForMultipleObjectsEx MsgWaitForMultipleObjectsEx;
+alias WINAPI.MultiByteToWideChar MultiByteToWideChar;
+alias DWTWINAPI.NotifyWinEvent NotifyWinEvent;
+alias WINAPI.OffsetRect OffsetRect;
+alias WINAPI.OffsetRgn OffsetRgn;
+//alias WINAPI.OleInitialize OleInitialize;
+//alias WINAPI.OleUninitialize OleUninitialize;
+alias WINAPI.OpenClipboard OpenClipboard;
+alias WINAPI.OutputDebugStringA OutputDebugStringA;
+alias WINAPI.OutputDebugStringW OutputDebugStringW;
+alias WINAPI.PatBlt PatBlt;
+alias WINAPI.PeekMessageA PeekMessageA;
+alias WINAPI.PeekMessageW PeekMessageW;
+alias WINAPI.Pie Pie;
+alias WINAPI.Polygon Polygon;
+alias WINAPI.Polyline Polyline;
+alias WINAPI.PostMessageA PostMessageA;
+alias WINAPI.PostMessageW PostMessageW;
+alias WINAPI.PostThreadMessageA PostThreadMessageA;
+alias WINAPI.PostThreadMessageW PostThreadMessageW;
+alias WINAPI.PrintDlgA PrintDlgA;
+alias WINAPI.PrintDlgW PrintDlgW;
+alias WINAPI.PtInRect PtInRect;
+alias WINAPI.PtInRegion PtInRegion;
+alias WINAPI.RealizePalette RealizePalette;
+alias WINAPI.Rectangle Rectangle;
+alias WINAPI.RectInRegion RectInRegion;
+// <Shawn> Renamed : may conflict with org.eclipse.swt.graphics.rectangle.Rectangle
+alias WINAPI.Rectangle _Rectangle;
+alias WINAPI.RedrawWindow RedrawWindow;
+alias WINAPI.RegCloseKey RegCloseKey;
+alias WINAPI.RegEnumKeyExA RegEnumKeyExA;
+alias WINAPI.RegEnumKeyExW RegEnumKeyExW;
+alias WINAPI.RegOpenKeyExA RegOpenKeyExA;
+alias WINAPI.RegOpenKeyExW RegOpenKeyExW;
+alias WINAPI.RegQueryInfoKeyA RegQueryInfoKeyA;
+alias WINAPI.RegQueryInfoKeyW RegQueryInfoKeyW;
+alias WINAPI.RegQueryValueExA RegQueryValueExA;
+alias WINAPI.RegQueryValueExW RegQueryValueExW;
+alias WINAPI.RegisterClassA RegisterClassA;
+alias WINAPI.RegisterClassW RegisterClassW;
+alias WINAPI.RegisterClipboardFormatA RegisterClipboardFormatA;
+alias WINAPI.RegisterClipboardFormatW RegisterClipboardFormatW;
+alias WINAPI.RegisterWindowMessageA RegisterWindowMessageA;
+alias WINAPI.RegisterWindowMessageW RegisterWindowMessageW;
+alias WINAPI.ReleaseCapture ReleaseCapture;
+alias WINAPI.ReleaseDC ReleaseDC;
+alias WINAPI.RemoveMenu RemoveMenu;
+alias WINAPI.RestoreDC RestoreDC;
+alias WINAPI.RoundRect RoundRect;
+alias DWTWINAPI.RtlMoveMemory MoveMemory;
+alias DWTWINAPI.SHBrowseForFolderA SHBrowseForFolderA;
+alias DWTWINAPI.SHBrowseForFolderW SHBrowseForFolderW;
+version(WinCE){
+    alias WINAPI.SHCreateMenuBar SHCreateMenuBar;
+}
+alias DWTWINAPI.SHGetMalloc SHGetMalloc;
+alias DWTWINAPI.SHGetPathFromIDListA SHGetPathFromIDListA;
+alias DWTWINAPI.SHGetPathFromIDListW SHGetPathFromIDListW;
+version(WinCE)
+{
+    alias WINAPI.SHHandleWMSettingChange SHHandleWMSettingChange;
+    alias WINAPI.SHRecognizeGesture SHRecognizeGesture;
+    alias WINAPI.SHSendBackToFocusWindow SHSendBackToFocusWindow;
+    alias WINAPI.SHSetAppKeyWndAssoc SHSetAppKeyWndAssoc;
+    alias WINAPI.SHSipPreference SHSipPreference;
+}
+alias WINAPI.SaveDC SaveDC;
+alias WINAPI.ScreenToClient ScreenToClient;
+alias DWTWINAPI.ScriptApplyDigitSubstitution ScriptApplyDigitSubstitution;
+alias DWTWINAPI.ScriptBreak ScriptBreak;
+alias DWTWINAPI.ScriptCPtoX ScriptCPtoX;
+alias DWTWINAPI.ScriptCacheGetHeight ScriptCacheGetHeight;
+alias DWTWINAPI.ScriptFreeCache ScriptFreeCache;
+alias DWTWINAPI.ScriptGetFontProperties ScriptGetFontProperties;
+alias DWTWINAPI.ScriptGetLogicalWidths ScriptGetLogicalWidths;
+alias DWTWINAPI.ScriptGetProperties ScriptGetProperties;
+alias DWTWINAPI.ScriptItemize ScriptItemize;
+alias DWTWINAPI.ScriptJustify ScriptJustify;
+alias DWTWINAPI.ScriptLayout ScriptLayout;
+alias DWTWINAPI.ScriptPlace ScriptPlace;
+alias DWTWINAPI.ScriptRecordDigitSubstitution ScriptRecordDigitSubstitution;
+alias DWTWINAPI.ScriptGetCMap ScriptGetCMap;
+alias DWTWINAPI.ScriptShape ScriptShape;
+alias DWTWINAPI.ScriptStringAnalyse ScriptStringAnalyse;
+alias DWTWINAPI.ScriptStringOut ScriptStringOut;
+alias DWTWINAPI.ScriptStringFree ScriptStringFree;
+alias DWTWINAPI.ScriptTextOut ScriptTextOut;
+alias DWTWINAPI.ScriptXtoCP ScriptXtoCP;
+alias WINAPI.ScrollWindowEx ScrollWindowEx;
+alias WINAPI.SelectClipRgn SelectClipRgn;
+alias WINAPI.SelectObject SelectObject;
+alias WINAPI.SelectPalette SelectPalette;
+alias DWTWINAPI.SendInput SendInput;
+alias WINAPI.SendMessageA SendMessageA;
+alias WINAPI.SendMessageW SendMessageW;
+alias WINAPI.SetActiveWindow SetActiveWindow;
+alias WINAPI.SetBkColor SetBkColor;
+alias WINAPI.SetBkMode SetBkMode;
+alias WINAPI.SetBrushOrgEx SetBrushOrgEx;
+alias WINAPI.SetCapture SetCapture;
+alias WINAPI.SetCaretPos SetCaretPos;
+alias WINAPI.SetClipboardData SetClipboardData;
+alias WINAPI.SetCursor SetCursor;
+alias WINAPI.SetCursorPos SetCursorPos;
+alias WINAPI.SetDIBColorTable SetDIBColorTable;
+alias WINAPI.SetErrorMode SetErrorMode;
+alias WINAPI.SetEvent SetEvent;
+alias WINAPI.SetFocus SetFocus;
+alias WINAPI.SetForegroundWindow SetForegroundWindow;
+alias WINAPI.SetGraphicsMode SetGraphicsMode;
+alias WINAPI.SetLastError SetLastError;
+alias DWTWINAPI.SetLayout SetLayout;
+alias WINAPI.SetMenu SetMenu;
+alias WINAPI.SetMenuDefaultItem SetMenuDefaultItem;
+alias DWTWINAPI.SetMenuInfo SetMenuInfo;
+alias WINAPI.SetMenuItemInfoA SetMenuItemInfoA;
+alias WINAPI.SetMenuItemInfoW SetMenuItemInfoW;
+alias WINAPI.SetMetaRgn SetMetaRgn;
+alias WINAPI.SetPaletteEntries SetPaletteEntries;
+alias WINAPI.SetParent SetParent;
+alias WINAPI.SetPixel SetPixel;
+alias WINAPI.SetPolyFillMode SetPolyFillMode;
+alias WINAPI.SetROP2 SetROP2;
+alias WINAPI.SetRect SetRect;
+alias WINAPI.SetRectRgn SetRectRgn;
+alias WINAPI.SetScrollInfo SetScrollInfo;
+alias WINAPI.SetStretchBltMode SetStretchBltMode;
+alias WINAPI.SetTextAlign SetTextAlign;
+alias WINAPI.SetTextColor SetTextColor;
+alias WINAPI.SetTimer SetTimer;
+alias WINAPI.SetWindowLongA SetWindowLongA;
+alias WINAPI.SetWindowLongW SetWindowLongW;
+alias WINAPI.SetWindowOrgEx SetWindowOrgEx;
+alias WINAPI.SetWindowPlacement SetWindowPlacement;
+alias WINAPI.SetWindowPos SetWindowPos;
+alias WINAPI.SetWindowRgn SetWindowRgn;
+alias WINAPI.SetWorldTransform SetWorldTransform;
+alias WINAPI.SetWindowTextA SetWindowTextA;
+alias WINAPI.SetWindowTextW SetWindowTextW;
+alias WINAPI.SetWindowsHookExA SetWindowsHookExA;
+alias WINAPI.SetWindowsHookExW SetWindowsHookExW;
+alias DWTWINAPI.ShellExecuteExA ShellExecuteExA;
+alias DWTWINAPI.ShellExecuteExW ShellExecuteExW;
+alias DWTWINAPI.Shell_NotifyIconA Shell_NotifyIconA;
+alias DWTWINAPI.Shell_NotifyIconW Shell_NotifyIconW;
+alias WINAPI.SHGetFileInfo SHGetFileInfo;
+alias WINAPI.ShowCaret ShowCaret;
+alias WINAPI.ShowOwnedPopups ShowOwnedPopups;
+alias WINAPI.ShowScrollBar ShowScrollBar;
+alias WINAPI.ShowWindow ShowWindow;
+version(WinCE){
+alias WINAPI.SipGetInfo SipGetInfo;
+}
+alias WINAPI.SizeofResource SizeofResource;
+alias WINAPI.Sleep Sleep;
+alias WINAPI.StartDocA StartDocA;
+alias WINAPI.StartDocW StartDocW;
+alias WINAPI.StartPage StartPage;
+alias WINAPI.StretchBlt StretchBlt;
+alias WINAPI.SystemParametersInfoA SystemParametersInfoA;
+alias WINAPI.SystemParametersInfoW SystemParametersInfoW;
+alias WINAPI.ToAscii ToAscii;
+alias WINAPI.ToUnicode ToUnicode;
+alias DWTWINAPI.TrackMouseEvent TrackMouseEvent;
+alias WINAPI.TrackPopupMenu TrackPopupMenu;
+alias WINAPI.TranslateAcceleratorA TranslateAcceleratorA;
+alias WINAPI.TranslateAcceleratorW TranslateAcceleratorW;
+alias WINAPI.TranslateCharsetInfo TranslateCharsetInfo;
+alias WINAPI.TranslateMDISysAccel TranslateMDISysAccel;
+alias WINAPI.TranslateMessage TranslateMessage;
+alias DWTWINAPI.TransparentBlt TransparentBlt;
+version(WinCE){
+    alias WINAPI.TransparentImage TransparentImage;
+}
+alias WINAPI.UnhookWindowsHookEx UnhookWindowsHookEx;
+alias WINAPI.UnregisterClassA UnregisterClassA;
+alias WINAPI.UnregisterClassW UnregisterClassW;
+alias WINAPI.UpdateWindow UpdateWindow;
+alias WINAPI.ValidateRect ValidateRect;
+alias WINAPI.VkKeyScanA VkKeyScanA;
+alias WINAPI.VkKeyScanW VkKeyScanW;
+alias WINAPI.WaitForMultipleObjects WaitForMultipleObjects;
+alias WINAPI.WaitForSingleObject WaitForSingleObject;
+alias WINAPI.WaitMessage WaitMessage;
+alias WINAPI.WideCharToMultiByte WideCharToMultiByte;
+alias WINAPI.WindowFromDC WindowFromDC;
+alias WINAPI.WindowFromPoint WindowFromPoint;
+alias DWTWINAPI.wcslen wcslen;
+
+public static int VERSION (int major, int minor) {  return major << 16 | minor;}
+
+//static int DrawText(int hDC, String lpString, RECT* lpRect, int uFormat){
+//  return WINAPI.DrawText(hDC, Convert.StringToTCHARz(lpString), lpString.length, lpRect, uFormat);
+//}
+//
+//static int DrawText(int hDC, TCHAR* lpString, int length, RECT* lpRect, int uFormat){
+//  return WINAPI.DrawText(hDC, lpString, length, lpRect, uFormat);
+//}
+
+static int GetProfileString(char[] lpAppName, char[] lpKeyName, char[] lpDefault, out char[] lpReturnedString, int nSize ){
+    TCHAR[] buffer = new TCHAR[nSize];
+    int result = _GetProfileString(.StrToTCHARz(lpAppName), .StrToTCHARz(lpKeyName), .StrToTCHARz(lpDefault), buffer.ptr, nSize);
+    lpReturnedString = .TCHARzToStr(buffer.ptr);
+    return result;
+}
+
+static char[] GetWindowText(HWND hwnd){
+    assert(hwnd);
+    int len = GetWindowTextLength(hwnd);
+    if(len > 0){
+        TCHAR[] buffer = new TCHAR[len + 1];
+        len = _GetWindowText(hwnd, buffer.ptr, buffer.length);
+        return .TCHARzToStr(buffer.ptr, len);
+    }
+    return "";
+}
+
+// Note: nMaxCount including the NULL character
+static int GetWindowText(HWND hWnd, TCHAR* lpString, int nMaxCount)
+{
+    return _GetWindowText(hWnd, lpString, nMaxCount);
+}
+
+// <Shawn Liu> added this method, copied from ATL : atlwin.h
+static int CenterWindow(HWND m_hWnd, HWND hWndCenter = null)
+{
+    assert(m_hWnd);
+
+    // determine owner window to center against
+    uint dwStyle = OS.GetWindowLong(m_hWnd, OS.GWL_STYLE);
+    if(hWndCenter is null)
+    {
+        if(dwStyle & OS.WS_CHILD)
+            hWndCenter = OS.GetParent(m_hWnd);
+        else
+            hWndCenter = OS.GetWindow(m_hWnd, OS.GW_OWNER);
+    }
+
+    // get coordinates of the window relative to its parent
+    RECT rcDlg;
+    OS.GetWindowRect(m_hWnd, &rcDlg);
+    RECT rcArea;
+    RECT rcCenter;
+    HWND hWndParent;
+    if(!(dwStyle & OS.WS_CHILD))
+    {
+        // don't center against invisible or minimized WINAPI
+        if(hWndCenter !is null)
+        {
+            uint dwStyleCenter = OS.GetWindowLong(hWndCenter, OS.GWL_STYLE);
+            if(!(dwStyleCenter & OS.WS_VISIBLE) || (dwStyleCenter & OS.WS_MINIMIZE))
+                hWndCenter = null;
+        }
+
+        // center within screen coordinates
+        OS.SystemParametersInfo(OS.SPI_GETWORKAREA, 0, &rcArea, 0);
+        if(hWndCenter is null)
+            rcCenter = rcArea;
+        else
+            OS.GetWindowRect(hWndCenter, &rcCenter);
+    }
+    else
+    {
+        // center within parent client coordinates
+        hWndParent = OS.GetParent(m_hWnd);
+        assert(OS.IsWindow(hWndParent));
+
+        OS.GetClientRect(hWndParent, &rcArea);
+        assert(OS.IsWindow(hWndCenter));
+        OS.GetClientRect(hWndCenter, &rcCenter);
+        OS.MapWindowPoints(hWndCenter, hWndParent, cast(POINT*)&rcCenter, 2);
+    }
+
+    int DlgWidth = rcDlg.right - rcDlg.left;
+    int DlgHeight = rcDlg.bottom - rcDlg.top;
+
+    // find dialog's upper left based on rcCenter
+    int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
+    int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
+
+    // if the dialog is outside the screen, move it inside
+    if(xLeft < rcArea.left)
+        xLeft = rcArea.left;
+    else if(xLeft + DlgWidth > rcArea.right)
+        xLeft = rcArea.right - DlgWidth;
+
+    if(yTop < rcArea.top)
+        yTop = rcArea.top;
+    else if(yTop + DlgHeight > rcArea.bottom)
+        yTop = rcArea.bottom - DlgHeight;
+
+    // map screen coordinates to child coordinates
+    return OS.SetWindowPos(m_hWnd, null, xLeft, yTop, -1, -1,
+        OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE);
+}
+
+
+alias DWTWINAPI.OleInitialize OleInitialize;
+alias DWTWINAPI.OleUninitialize OleUninitialize;
+alias DWTWINAPI.CoCreateInstance CoCreateInstance;
+
+/**
+ * <Shawn Liu>
+ * VtbCall partially kept, use VtbCall instead of automation can promote performace
+ * and VtbCall doesn't need prototype of interface declaration
+ */
+
+public static int VtblCall(int fnNumber, void* ppVtbl) {
+    Function1 fn = cast(Function1)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0){
+    Function2 fn = cast(Function2)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1){
+    Function3 fn = cast(Function3)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2){
+    Function4 fn = cast(Function4)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1, arg2);
+}
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3){
+    Function5 fn = cast(Function5)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1, arg2, arg3);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4){
+    Function6 fn = cast(Function6)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5){
+    Function7 fn = cast(Function7)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6){
+    Function8 fn = cast(Function8)(*cast(int **)ppVtbl)[fnNumber];
+    return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+}
+
+public static int VtblCall(int fnNumber, void* ppVtbl, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7){
+    Function9 fn = cast(Function9)(*cast(int **)ppVtbl)[fnNumber];
+    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 MAKELONG( int low, int high){
+    return (low & 0xFFFF) | (high << 16);
+}
+public static int /*long*/ MAKEWPARAM(int l, int h){
+    return MAKELONG( l, h );
+}
+public static int /*long*/ MAKELPARAM(int l, int h){
+    return MAKELONG( l, h );
+}
+public static int /*long*/ MAKELRESULT(int l, int h){
+    return MAKELONG( l, h );
+}
+public static int GET_WHEEL_DELTA_WPARAM(int /*long*/ wParam){
+    return  cast(short) HIWORD(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);
+}
+
+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( PCHAR ptr ){
+    return tango.stdc.string.strlen( cast(char*)ptr );
+}
+
+static void POINTSTOPOINT( inout POINT pt, int pts) {
+    pt.x = cast(SHORT) LOWORD(pts);
+    pt.y = cast(SHORT) HIWORD(pts);
+}
+
+alias DWTWINAPI.GetScrollBarInfo GetScrollBarInfo;
+} // END of OS
+//-----------------------------------------------------------------------------
+import tango.sys.win32.CodePage : CodePage;
+private import tango.text.convert.Utf;
+private import tango.stdc.stringz;
+
+// convert UTF-8 to MBCS
+alias StrToMBCS StrToMBCSs;
+public CHAR[] StrToMBCS(char[] sc, uint codepage = 0) {
+    CHAR[] ret = cast(CHAR[]) sc;
+    try{
+        foreach (char c; sc){
+            if (c >= 0x80)
+            {
+                CHAR[] result;
+                int i;
+                wchar[] ws = .toString16(sc);
+                result.length = OS.WideCharToMultiByte(codepage, 0, ws.ptr, ws.length, null, 0, null, null);
+                i = OS.WideCharToMultiByte(codepage, 0, ws.ptr, ws.length, result.ptr, result.length, null, null);
+                assert(i == result.length);
+                return result;
+            }
+        }
+    }catch(Exception e){
+        // do nothing
+        ret = null;
+    }
+    return ret;
+}
+
+// convert UTF-8 to MBCSz
+public char* StrToMBCSz(char[] sc) {
+    char* ret = null;
+    try{
+        if( CodePage.isAscii( sc )){
+            return .toStringz( sc );
+        }
+        char[] dst;
+        dst.length = sc.length;
+        return toStringz( tango.sys.win32.CodePage.CodePage.into( sc, dst ));
+    }catch(Exception e){
+        // do nothing
+        ret = "";
+    }
+
+    return ret;
+}
+
+public wchar[] StrToWCHARs(uint codepage , char[] sc, bool terminated = false ) {
+    return StrToWCHARs( sc, terminated );
+}
+public wchar[] StrToWCHARs(char[] sc, bool terminated = false ) {
+    wchar[] ret;
+    try{
+        ret = toString16(sc);
+    }catch(Exception e){
+        // do nothing
+        ret = "";
+    }
+    if( terminated ){
+        ret ~= \0;
+    }
+    return ret;
+}
+
+public wchar* StrToWCHARz( uint codepage, char[] sc, uint* length = null ) {
+    return StrToWCHARz( sc, length );
+}
+
+public wchar* StrToWCHARz(char[] sc, uint* length = null ) {
+    return StrToWCHARs(sc, true ).ptr;
+}
+
+public char[] MBCSsToStr(CHAR[] string, uint codepage = 0){
+    return MBCSzToStr( string.ptr, string.length, codepage);
+}
+
+public char[] MBCSzToStr(PCHAR pString, int _length = -1, uint codepage = 0) {
+    // null terminated string pointer
+    if(_length == -1){
+        _length = 0;
+        while(*(pString + _length))
+            ++_length;
+    }
+    // convert MBCS to UTF-8
+    if(_length == 0)
+        return null;
+
+    wchar[] wcs = _mbcszToWs(pString, _length, codepage);
+    char[] result;
+    try{
+        result = .toString(wcs);
+    }catch(Exception e){
+    }
+    return result;
+}
+
+public char[] WCHARsToStr(wchar[] string){
+    return WCHARzToStr(string.ptr, string.length);
+}
+
+public char[] WCHARzToStr(wchar* pString, int _length = -1)
+{
+    if( pString is null ){
+        return null;
+    }
+    // null terminated string pointer
+    if(_length == -1){
+        _length = 0;
+        while(*(pString + _length))
+            ++_length;
+    }
+    if(_length == 0)
+        return null;
+    // convert wchar* to UTF-8
+    wchar[] wcs = pString[0.._length];
+
+    char[] result;
+    try{
+        result = .toString(wcs);
+    }catch(Exception e){
+        // do nothing
+    }
+    return result;
+}
+
+/**
+ * <Shawn> difference between WCHARzToStr(pwstr, -1) :
+ * BSTRToStr() internally call WCHARzToStr(pwstr, length) with length set,
+ * instead to determine the null ended, this mean BSTRToStr() can get string
+ * which has embedded null characters.
+ */
+
+version(OLE_COM)
+{
+// BSTR is aliased to wchar*
+// Note : Free the "bstr" memory if freeTheString is true, default false
+static char[] BSTRToStr(/*BSTR*/ inout wchar* bstr, bool freeTheString = false){
+    if(bstr is null) return null;
+    int size = (SysStringByteLen(bstr) + 1)/wchar.sizeof;
+    char[] result = WCHARzToStr(bstr, size);
+    if(freeTheString) {
+        // free the string and set ptr to null
+        SysFreeString(bstr);
+        bstr = null;
+    }
+    return result;
+}
+} // end of OLE_COM
+
+
+public static wchar[] _mbcszToWs(PCHAR pMBCS, int len, uint codepage = 0)
+{
+    wchar[] wbuf;
+    // Convert MBCS to unicode
+    wbuf.length = OS.MultiByteToWideChar(codepage, 0, pMBCS, len, null, 0);
+    int n = OS.MultiByteToWideChar(codepage, 0, pMBCS, len, wbuf.ptr, wbuf.length);
+    assert(n == wbuf.length);
+    return wbuf;
+}
+
+// static methods
+public int _tcslen(TCHAR* pString){
+    int _length = 0;
+    while(*(pString + _length))
+        ++_length;
+
+    return _length;
+}
+
+/**
+ * There is a bug in Phobos std.string.toupper() to lower() with
+ std.string.toupper() and std.string.tolower() give a wrong result when deal with a mixture of upper/lower English and Chinese characters. e.g.
+char[] a = "AbCd中文eFgH";
+char[] b = std.string.toupper(a);
+char[] c = std.string.tolower(a);
+The length of a is 11, but the length of b,c is 18 now.
+ *
+ */
+public char[] tolower(char[] string) {
+    TCHAR* ps = StrToTCHARz(string);
+    TCHAR* ps2 = OS.CharLower(ps);
+    return TCHARzToStr(ps2);
+}
+public char[] toupper(char[] string) {
+    TCHAR* ps = StrToTCHARz(string);
+    TCHAR* ps2 = OS.CharUpper(ps);
+    return TCHARzToStr(ps2);
+}
+
+version(ANSI){
+    alias StrToMBCS         StrToTCHARs;
+    alias StrToMBCSz        StrToTCHARz;
+    alias MBCSzToStr        TCHARzToStr;
+    alias MBCSsToStr        TCHARsToStr;
+}else{
+    // Unicode
+    alias StrToWCHARs       StrToTCHARs;
+    alias StrToWCHARz       StrToTCHARz;
+    alias WCHARzToStr       TCHARzToStr;
+    alias WCHARsToStr       TCHARsToStr;
+    alias _tcslen           TCHARzLen;
+}
+
+
+//alias Converter.StrToTCHARs     StrToTCHARs;
+//alias Converter.StrToTCHARz     StrToTCHARz;
+//alias Converter.TCHARzToStr     TCHARzToStr;
+//alias Converter.TCHARsToStr     TCHARsToStr;
+
+
+TCHAR[] NewTCHARs( uint codepage, uint len ){
+    auto res = new TCHAR[ len ];
+    res[] = '\0';
+    return res;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/WINAPI.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,3832 @@
+/**
+ * This module declared window APIs required by SWT but not in std.c.windows.windows,
+ * The one in the std.c.windows.windows module are aliased
+ */
+
+
+module org.eclipse.swt.internal.win32.WINAPI;
+
+public import org.eclipse.swt.internal.win32.WINTYPES;
+//import tango_sys_win32.Types;
+//import STDWIN = tango_sys_win32.UserGdi;
+
+version(TANGOSVN){
+    import tango.sys.win32.Types;
+}
+else{ // !TANGOSVN
+
+extern(Windows)
+{
+
+//     BOOL GetWindowInfo(HWND, PWINDOWINFO);
+//     BOOL EnumDisplayMonitors(HDC, RECT*, MONITORENUMPROC, LPARAM);
+//     BOOL GetMonitorInfoA(HMONITOR, LPMONITORINFO);
+//     WINBOOL GetBinaryTypeA(LPCSTR, LPDWORD);
+//     DWORD GetShortPathNameA(LPCSTR, LPSTR, DWORD);
+//     LPSTR GetEnvironmentStringsA();
+//     WINBOOL FreeEnvironmentStringsA(LPSTR);
+//     DWORD FormatMessageA(DWORD, LPCVOID, DWORD, DWORD, LPSTR, DWORD, VA_LIST*);
+//     HANDLE CreateMailslotA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     int lstrcmpA(LPCSTR, LPCSTR);
+//     int lstrcmpiA(LPCSTR, LPCSTR);
+//     LPSTR lstrcpynA(LPSTR, LPCSTR, int);
+//     LPSTR lstrcpyA(LPSTR, LPCSTR);
+//     LPSTR lstrcatA(LPSTR, LPCSTR);
+//     int lstrlenA(LPCSTR);
+//     HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES, WINBOOL, LPCSTR);
+//     HANDLE OpenMutexA(DWORD, WINBOOL, LPCSTR);
+//     HANDLE CreateEventA(LPSECURITY_ATTRIBUTES, WINBOOL, WINBOOL, LPCSTR);
+//     HANDLE OpenEventA(DWORD, WINBOOL, LPCSTR);
+//     HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES, LONG, LONG, LPCSTR);
+//     HANDLE OpenSemaphoreA(DWORD, WINBOOL, LPCSTR);
+//     HANDLE CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR);
+//     HANDLE OpenFileMappingA(DWORD, WINBOOL, LPCSTR);
+//     DWORD GetLogicalDriveStringsA(DWORD, LPSTR);
+    HINST LoadLibraryA(LPCSTR);
+//     HINST LoadLibraryExA(LPCSTR, HANDLE, DWORD);
+//     DWORD GetModuleFileNameA(HINST, LPSTR, DWORD);
+    HMODULE GetModuleHandleA(LPCSTR);
+//     void FatalAppExitA(UINT);
+//     LPSTR GetCommandLineA();
+//     DWORD GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD);
+//     WINBOOL SetEnvironmentVariableA(LPCSTR, LPCSTR);
+//     DWORD ExpandEnvironmentStringsA(LPCSTR, LPSTR, DWORD);
+//     void OutputDebugStringA(LPCSTR);
+//     HRSRC FindResourceA(HINST, LPCSTR, LPCSTR);
+//     HRSRC FindResourceExA(HINST, LPCSTR, LPCSTR, ushort);
+//     WINBOOL EnumResourceTypesA(HINST, ENUMRESTYPEPROC, LONG);
+//     WINBOOL EnumResourceNamesA(HINST, LPCSTR, ENUMRESNAMEPROC, LONG);
+//     WINBOOL EnumResourceLanguagesA(HINST, LPCSTR, LPCSTR, ENUMRESLANGPROC, LONG);
+//     HANDLE BeginUpdateResourceA(LPCSTR, WINBOOL);
+//     WINBOOL UpdateResourceA(HANDLE, LPCSTR, LPCSTR, ushort, LPVOID, DWORD);
+//     WINBOOL EndUpdateResourceA(HANDLE, WINBOOL);
+//     ATOM GlobalAddAtomA(LPCSTR);
+//     ATOM GlobalFindAtomA(LPCSTR);
+//     UINT GlobalGetAtomNameA(ATOM, LPSTR, int);
+//     ATOM AddAtomA(LPCSTR);
+//     ATOM FindAtomA(LPCSTR);
+//     UINT GetAtomNameA(ATOM, LPSTR, int);
+//     UINT GetProfileIntA(LPCSTR, LPCSTR, INT);
+//     DWORD GetProfileStringA(LPCSTR, LPCSTR, LPCSTR, LPSTR, DWORD);
+//     WINBOOL WriteProfileStringA(LPCSTR, LPCSTR, LPCSTR);
+//     DWORD GetProfileSectionA(LPCSTR, LPSTR, DWORD);
+//     WINBOOL WriteProfileSectionA(LPCSTR, LPCSTR);
+//     UINT GetPrivateProfileIntA(LPCSTR, LPCSTR, INT, LPCSTR);
+//     DWORD GetPrivateProfileStringA(LPCSTR, LPCSTR, LPCSTR, LPSTR, DWORD, LPCSTR);
+//     WINBOOL WritePrivateProfileStringA(LPCSTR, LPCSTR, LPCSTR, LPCSTR);
+//     DWORD GetPrivateProfileSectionA(LPCSTR, LPSTR, DWORD, LPCSTR);
+//     WINBOOL WritePrivateProfileSectionA(LPCSTR, LPCSTR, LPCSTR);
+//     UINT GetDriveTypeA(LPCSTR);
+//     UINT GetSystemDirectoryA(LPSTR, UINT);
+//     DWORD GetTempPathA(DWORD, LPSTR);
+//     UINT GetTempFileNameA(LPCSTR, LPCSTR, UINT, LPSTR);
+//     UINT GetWindowsDirectoryA(LPSTR, UINT);
+//     WINBOOL SetCurrentDirectoryA(LPCSTR);
+//     DWORD GetCurrentDirectoryA(DWORD, LPSTR);
+//     WINBOOL GetDiskFreeSpaceA(LPCSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL CreateDirectoryA(LPCSTR, LPSECURITY_ATTRIBUTES);
+//     WINBOOL CreateDirectoryExA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES);
+//     WINBOOL RemoveDirectoryA(LPCSTR);
+//     DWORD GetFullPathNameA(LPCSTR, DWORD, LPSTR, LPSTR*);
+//     WINBOOL DefineDosDeviceA(DWORD, LPCSTR, LPCSTR);
+//     DWORD QueryDosDeviceA(LPCSTR, LPSTR, DWORD);
+    HANDLE CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+//     WINBOOL SetFileAttributesA(LPCSTR, DWORD);
+//     DWORD GetFileAttributesA(LPCSTR);
+//     BOOL GetFileAttributesExA(LPCSTR, DWORD, WIN32_FILE_ATTRIBUTE_DATA*);
+//     DWORD GetCompressedFileSizeA(LPCSTR, LPDWORD);
+//     WINBOOL DeleteFileA(LPCSTR);
+//     DWORD SearchPathA(LPCSTR, LPCSTR, LPCSTR, DWORD, LPSTR, LPSTR);
+//     WINBOOL CopyFileA(LPCSTR, LPCSTR, WINBOOL);
+//     WINBOOL MoveFileA(LPCSTR, LPCSTR);
+//     WINBOOL MoveFileExA(LPCSTR, LPCSTR, DWORD);
+//     HANDLE CreateNamedPipeA(LPCSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     WINBOOL GetNamedPipeHandleStateA(HANDLE, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD);
+//     WINBOOL CallNamedPipeA(LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, DWORD);
+//     WINBOOL WaitNamedPipeA(LPCSTR, DWORD);
+//     WINBOOL SetVolumeLabelA(LPCSTR, LPCSTR);
+//     WINBOOL GetVolumeInformationA(LPCSTR, LPSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPSTR, DWORD);
+//     WINBOOL ClearEventLogA(HANDLE, LPCSTR);
+//     WINBOOL BackupEventLogA(HANDLE, LPCSTR);
+//     HANDLE OpenEventLogA(LPCSTR, LPCSTR);
+//     HANDLE RegisterEventSourceA(LPCSTR, LPCSTR);
+//     HANDLE OpenBackupEventLogA(LPCSTR, LPCSTR);
+//     WINBOOL ReadEventLogA(HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD);
+//     WINBOOL ReportEventA(HANDLE, ushort, ushort, DWORD, PSID, ushort, DWORD, LPCSTR*, LPVOID);
+//     WINBOOL AccessCheckAndAuditAlarmA(LPCSTR, LPVOID, LPSTR, LPSTR, PSECURITY_DESCRIPTOR, DWORD, PGENERIC_MAPPING, WINBOOL, LPDWORD, LPBOOL, LPBOOL);
+//     WINBOOL ObjectOpenAuditAlarmA(LPCSTR, LPVOID, LPSTR, LPSTR, PSECURITY_DESCRIPTOR, HANDLE, DWORD, DWORD, PPRIVILEGE_SET, WINBOOL, WINBOOL, LPBOOL);
+//     WINBOOL ObjectPrivilegeAuditAlarmA(LPCSTR, LPVOID, HANDLE, DWORD, PPRIVILEGE_SET, WINBOOL);
+//     WINBOOL ObjectCloseAuditAlarmA(LPCSTR, LPVOID, WINBOOL);
+//     WINBOOL PrivilegedServiceAuditAlarmA(LPCSTR, LPCSTR, HANDLE, PPRIVILEGE_SET, WINBOOL);
+//     WINBOOL SetFileSecurityA(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     WINBOOL GetFileSecurityA(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+//     HANDLE FindFirstChangeNotificationA(LPCSTR, WINBOOL, DWORD);
+//     WINBOOL IsBadStringPtrA(LPCSTR, UINT);
+//     WINBOOL LookupAccountSidA(LPCSTR, PSID, LPSTR, LPDWORD, LPSTR, LPDWORD, PSID_NAME_USE);
+//     WINBOOL LookupAccountNameA(LPCSTR, LPCSTR, PSID, LPDWORD, LPSTR, LPDWORD, PSID_NAME_USE);
+//     WINBOOL LookupPrivilegeValueA(LPCSTR, LPCSTR, PLUID);
+//     WINBOOL LookupPrivilegeNameA(LPCSTR, PLUID, LPSTR, LPDWORD);
+//     WINBOOL LookupPrivilegeDisplayNameA(LPCSTR, LPCSTR, LPSTR, LPDWORD, LPDWORD);
+//     WINBOOL BuildCommDCBA(LPCSTR, LPDCB);
+//     WINBOOL BuildCommDCBAndTimeoutsA(LPCSTR, LPDCB, LPCOMMTIMEOUTS);
+//     WINBOOL CommConfigDialogA(LPCSTR, HWND, LPCOMMCONFIG);
+//     WINBOOL GetDefaultCommConfigA(LPCSTR, LPCOMMCONFIG, LPDWORD);
+//     WINBOOL SetDefaultCommConfigA(LPCSTR, LPCOMMCONFIG, DWORD);
+//     WINBOOL GetComputerNameA(LPSTR, LPDWORD);
+//     WINBOOL SetComputerNameA(LPCSTR);
+//     WINBOOL GetUserNameA(LPSTR, LPDWORD);
+//     int wvsprintfA(LPSTR, LPCSTR, VA_LIST*);
+//     HKL LoadKeyboardLayoutA(LPCSTR, UINT);
+//     WINBOOL GetKeyboardLayoutNameA(LPSTR);
+//     HDESK CreateDesktopA(LPSTR, LPSTR, LPDEVMODE, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     HDESK OpenDesktopA(LPSTR, DWORD, WINBOOL, DWORD);
+//     WINBOOL EnumDesktopsA(HWINSTA, DESKTOPENUMPROC, LPARAM);
+//     HWINSTA CreateWindowStationA(LPSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     HWINSTA OpenWindowStationA(LPSTR, WINBOOL, DWORD);
+//     WINBOOL EnumWindowStationsA(ENUMWINDOWSTATIONPROC, LPARAM);
+//     WINBOOL GetUserObjectInformationA(HANDLE, int, PVOID, DWORD, LPDWORD);
+//     WINBOOL SetUserObjectInformationA(HANDLE, int, PVOID, DWORD);
+//     UINT RegisterWindowMessageA(LPCSTR);
+    WINBOOL GetMessageA(LPMSG, HWND, UINT, UINT);
+//     LONG DispatchMessageA(LPMSG);
+    WINBOOL PeekMessageA(LPMSG, HWND, UINT, UINT, UINT);
+//     LRESULT SendMessageA(HWND, UINT, WPARAM, LPARAM);
+//     LRESULT SendMessageTimeoutA(HWND, UINT, WPARAM, LPARAM, UINT, UINT, LPDWORD);
+//     WINBOOL SendNotifyMessageA(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL SendMessageCallbackA(HWND, UINT, WPARAM, LPARAM, SENDASYNCPROC, DWORD);
+//     WINBOOL PostMessageA(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL PostThreadMessageA(DWORD, UINT, WPARAM, LPARAM);
+    LRESULT DefWindowProcA(HWND, UINT, WPARAM, LPARAM);
+//     LRESULT CallWindowProcA(WNDPROC, HWND, UINT, WPARAM, LPARAM);
+//     ATOM RegisterClassA(LPWNDCLASSA);
+//     WINBOOL UnregisterClassA(LPCSTR, HINST);
+//     WINBOOL GetClassInfoA(HINST, LPCSTR, LPWNDCLASS);
+//     ATOM RegisterClassExA(LPWNDCLASSEX);
+//     WINBOOL GetClassInfoExA(HINST, LPCSTR, LPWNDCLASSEX);
+    HWND CreateWindowExA(DWORD, LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINST, LPVOID);
+//     HWND CreateDialogParamA(HINST, LPCSTR, HWND, DLGPROC, LPARAM);
+//     HWND CreateDialogIndirectParamA(HINST, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
+//     int DialogBoxParamA(HINST, LPCSTR, HWND, DLGPROC, LPARAM);
+//     int DialogBoxIndirectParamA(HINST, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
+//     WINBOOL SetDlgItemTextA(HWND, int, LPCSTR);
+//     UINT GetDlgItemTextA(HWND, int, LPSTR, int);
+//     LONG SendDlgItemMessageA(HWND, int, UINT, WPARAM, LPARAM);
+//     LRESULT DefDlgProcA(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL CallMsgFilterA(LPMSG, int);
+//     UINT RegisterClipboardFormatA(LPCSTR);
+//     int GetClipboardFormatNameA(UINT, LPSTR, int);
+//     WINBOOL CharToOemA(LPCSTR, LPSTR);
+//     WINBOOL OemToCharA(LPCSTR, LPSTR);
+//     WINBOOL CharToOemBuffA(LPCSTR, LPSTR, DWORD);
+//     WINBOOL OemToCharBuffA(LPCSTR, LPSTR, DWORD);
+//     LPSTR CharUpperA(LPSTR);
+//     DWORD CharUpperBuffA(LPSTR, DWORD);
+//     LPSTR CharLowerA(LPSTR);
+//     DWORD CharLowerBuffA(LPSTR, DWORD);
+//     LPSTR CharNextA(LPCSTR);
+//     LPSTR CharPrevA(LPCSTR, LPCSTR);
+//     WINBOOL IsCharAlphaA(char);
+//     WINBOOL IsCharAlphaNumericA(char);
+//     WINBOOL IsCharUpperA(char);
+//     WINBOOL IsCharLowerA(char);
+//     int GetKeyNameTextA(LONG, LPSTR, int);
+//     SHORT VkKeyScanA(char);
+//     SHORT VkKeyScanExA(char, HKL);
+//     UINT MapVirtualKeyA(UINT, UINT);
+//     UINT MapVirtualKeyExA(UINT, UINT, HKL);
+//     HACCEL LoadAcceleratorsA(HINST, LPCSTR);
+//     HACCEL CreateAcceleratorTableA(LPACCEL, int);
+//     int CopyAcceleratorTableA(HACCEL, LPACCEL, int);
+//     int TranslateAcceleratorA(HWND, HACCEL, LPMSG);
+//     HMENU LoadMenuA(HINST, LPCSTR);
+//     HMENU LoadMenuIndirectA(LPMENUTEMPLATE);
+//     WINBOOL ChangeMenuA(HMENU, UINT, LPCSTR, UINT, UINT);
+//     int GetMenuStringA(HMENU, UINT, LPSTR, int, UINT);
+//     WINBOOL InsertMenuA(HMENU, UINT, UINT, UINT, LPCSTR);
+//     WINBOOL AppendMenuA(HMENU, UINT, UINT, LPCSTR);
+//     WINBOOL ModifyMenuA(HMENU, UINT, UINT, UINT, LPCSTR);
+//     WINBOOL InsertMenuItemA(HMENU, UINT, WINBOOL, LPCMENUITEMINFO);
+//     WINBOOL GetMenuItemInfoA(HMENU, UINT, WINBOOL, LPMENUITEMINFO);
+//     WINBOOL SetMenuItemInfoA(HMENU, UINT, WINBOOL, LPCMENUITEMINFO);
+//     int DrawTextA(HDC, LPCSTR, int, LPRECT, UINT);
+//     int DrawTextExA(HDC, LPSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS);
+//     WINBOOL GrayStringA(HDC, HBRUSH, GRAYSTRINGPROC, LPARAM, int, int, int, int, int);
+//     WINBOOL DrawStateA(HDC, HBRUSH, DRAWSTATEPROC, LPARAM, WPARAM, int, int, int, int, UINT);
+//     LONG TabbedTextOutA(HDC, int, int, LPCSTR, int, int, LPINT, int);
+//     DWORD GetTabbedTextExtentA(HDC, LPCSTR, int, int, LPINT);
+//     WINBOOL SetPropA(HWND, LPCSTR, HANDLE);
+//     HANDLE GetPropA(HWND, LPCSTR);
+//     HANDLE RemovePropA(HWND, LPCSTR);
+//     int EnumPropsExA(HWND, PROPENUMPROCEX, LPARAM);
+//     int EnumPropsA(HWND, PROPENUMPROC);
+//     WINBOOL SetWindowTextA(HWND, LPCSTR);
+//     int GetWindowTextA(HWND, LPSTR, int);
+//     int GetWindowTextLengthA(HWND);
+    int MessageBoxA(HWND, LPCSTR, LPCSTR, UINT);
+//     int MessageBoxExA(HWND, LPCSTR, LPCSTR, UINT, ushort);
+//     int MessageBoxIndirectA(LPMSGBOXPARAMS);
+//     LONG GetWindowLongA(HWND, int);
+//     LONG SetWindowLongA(HWND, int, LONG);
+//     DWORD GetClassLongA(HWND, int);
+//     DWORD SetClassLongA(HWND, int, LONG);
+//     HWND FindWindowA(LPCSTR, LPCSTR);
+//     HWND FindWindowExA(HWND, HWND, LPCSTR, LPCSTR);
+//     int GetClassNameA(HWND, LPSTR, int);
+//     HHOOK SetWindowsHookExA(int, HOOKPROC, HINST, DWORD);
+//     HBITMAP LoadBitmapA(HINST, LPCSTR);
+    HCURSOR LoadCursorA(HINST, LPCSTR);
+//     HCURSOR LoadCursorFromFileA(LPCSTR);
+    HICON LoadIconA(HINST, LPCSTR);
+//     HANDLE LoadImageA(HINST, LPCSTR, UINT, int, int, UINT);
+//     int LoadStringA(HINST, UINT, LPSTR, int);
+//     WINBOOL IsDialogMessageA(HWND, LPMSG);
+//     int DlgDirListA(HWND, LPSTR, int, int, UINT);
+//     WINBOOL DlgDirSelectExA(HWND, LPSTR, int, int);
+//     int DlgDirListComboBoxA(HWND, LPSTR, int, int, UINT);
+//     WINBOOL DlgDirSelectComboBoxExA(HWND, LPSTR, int, int);
+//     LRESULT DefFrameProcA(HWND, HWND, UINT, WPARAM, LPARAM);
+//     LRESULT DefMDIChildProcA(HWND, UINT, WPARAM, LPARAM);
+//     HWND CreateMDIWindowA(LPSTR, LPSTR, DWORD, int, int, int, int, HWND, HINST, LPARAM);
+//     WINBOOL WinHelpA(HWND, LPCSTR, UINT, DWORD);
+//     LONG ChangeDisplaySettingsA(LPDEVMODE, DWORD);
+//     WINBOOL EnumDisplaySettingsA(LPCSTR, DWORD, LPDEVMODE);
+//     WINBOOL SystemParametersInfoA(UINT, UINT, PVOID, UINT);
+//     int AddFontResourceA(LPCSTR);
+//     HMETAFILE CopyMetaFileA(HMETAFILE, LPCSTR);
+//     HFONT CreateFontIndirectA(LPLOGFONT);
+//     HDC CreateICA(LPCSTR, LPCSTR, LPCSTR, LPDEVMODE);
+//     HDC CreateMetaFileA(LPCSTR);
+//     WINBOOL CreateScalableFontResourceA(DWORD, LPCSTR, LPCSTR, LPCSTR);
+//     int EnumFontFamiliesExA(HDC, LPLOGFONT, FONTENUMEXPROC, LPARAM, DWORD);
+//     int EnumFontFamiliesA(HDC, LPCSTR, FONTENUMPROC, LPARAM);
+//     int EnumFontsA(HDC, LPCSTR, ENUMFONTSPROC, LPARAM);
+//     WINBOOL GetCharWidthA(HDC, UINT, UINT, LPINT);
+//     WINBOOL GetCharWidth32A(HDC, UINT, UINT, LPINT);
+//     WINBOOL GetCharWidthFloatA(HDC, UINT, UINT, PFLOAT);
+//     WINBOOL GetCharABCWidthsA(HDC, UINT, UINT, LPABC);
+//     WINBOOL GetCharABCWidthsFloatA(HDC, UINT, UINT, LPABCFLOAT);
+//     DWORD GetGlyphOutlineA(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, PMAT2);
+//     HMETAFILE GetMetaFileA(LPCSTR);
+     UINT GetOutlineTextMetricsA(HDC, UINT, LPOUTLINETEXTMETRIC);
+//     WINBOOL GetTextExtentPointA(HDC, LPCSTR, int, LPSIZE);
+//     WINBOOL GetTextExtentPoint32A(HDC, LPCSTR, int, LPSIZE);
+//     WINBOOL GetTextExtentExPointA(HDC, LPCSTR, int, int, LPINT, LPINT, LPSIZE);
+//     DWORD GetCharacterPlacementA(HDC, LPCSTR, int, int, LPGCP_RESULTS, DWORD);
+//     HDC ResetDCA(HDC, LPDEVMODE);
+//     WINBOOL RemoveFontResourceA(LPCSTR);
+//     HENHMETAFILE CopyEnhMetaFileA(HENHMETAFILE, LPCSTR);
+    HDC CreateEnhMetaFileA(HDC, LPCSTR, LPRECT, LPCSTR);
+//     HENHMETAFILE GetEnhMetaFileA(LPCSTR);
+//     UINT GetEnhMetaFileDescriptionA(HENHMETAFILE, UINT, LPSTR);
+    WINBOOL GetTextMetricsA(HDC, LPTEXTMETRIC);
+//     int StartDocA(HDC, PDOCINFO);
+    int GetObjectA(HGDIOBJ, int, LPVOID);
+//     WINBOOL TextOutA(HDC, int, int, LPCSTR, int);
+//     WINBOOL ExtTextOutA(HDC, int, int, UINT, LPRECT, LPCSTR, UINT, LPINT);
+//     WINBOOL PolyTextOutA(HDC, PPOLYTEXT, int);
+//     int GetTextFaceA(HDC, int, LPSTR);
+//     DWORD GetKerningPairsA(HDC, DWORD, LPKERNINGPAIR);
+//     HCOLORSPACE CreateColorSpaceA(LPLOGCOLORSPACE);
+//     WINBOOL GetLogColorSpaceA(HCOLORSPACE, LPLOGCOLORSPACE, DWORD);
+//     WINBOOL GetICMProfileA(HDC, DWORD, LPSTR);
+//     WINBOOL SetICMProfileA(HDC, LPSTR);
+//     WINBOOL UpdateICMRegKeyA(DWORD, DWORD, LPSTR, UINT);
+//     int EnumICMProfilesA(HDC, ICMENUMPROC, LPARAM);
+//     int PropertySheetA(LPCPROPSHEETHEADER);
+//     HIMAGELIST ImageList_LoadImageA(HINST, LPCSTR, int, int, COLORREF, UINT, UINT);
+//     HWND CreateStatusWindowA(LONG, LPCSTR, HWND, UINT);
+//     void DrawStatusTextA(HDC, LPRECT, LPCSTR);
+//     WINBOOL GetOpenFileNameA(LPOPENFILENAME);
+//     WINBOOL GetSaveFileNameA(LPOPENFILENAME);
+//     int GetFileTitleA(LPCSTR, LPSTR, ushort);
+//     WINBOOL ChooseColorA(LPCHOOSECOLOR);
+//     HWND FindTextA(LPFINDREPLACE);
+//     HWND ReplaceTextA(LPFINDREPLACE);
+//     WINBOOL ChooseFontA(LPCHOOSEFONT);
+    WINBOOL PrintDlgA(LPPRINTDLG);
+//     WINBOOL PageSetupDlgA(LPPAGESETUPDLG);
+//     WINBOOL CreateProcessA(LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, WINBOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
+//     void GetStartupInfoA(LPSTARTUPINFO);
+//     HANDLE FindFirstFileA(LPCSTR, LPWIN32_FIND_DATA);
+//     WINBOOL FindNextFileA(HANDLE, LPWIN32_FIND_DATA);
+//     WINBOOL GetVersionExA(LPOSVERSIONINFO);
+//     HDC CreateDCA(LPCSTR, LPCSTR, LPCSTR, PDEVMODE);
+//     DWORD VerInstallFileA(DWORD, LPSTR, LPSTR, LPSTR, LPSTR, LPSTR, LPSTR, PUINT);
+//     DWORD GetFileVersionInfoSizeA(LPSTR, LPDWORD);
+//     WINBOOL GetFileVersionInfoA(LPSTR, DWORD, DWORD, LPVOID);
+//     DWORD VerLanguageNameA(DWORD, LPSTR, DWORD);
+//     WINBOOL VerQueryValueA(LPVOID, LPSTR, LPVOID, PUINT);
+//     DWORD VerFindFileA(DWORD, LPSTR, LPSTR, LPSTR, LPSTR, PUINT, LPSTR, PUINT);
+//     LONG RegConnectRegistryA(LPSTR, HKEY, PHKEY);
+//     LONG RegCreateKeyA(HKEY, LPCSTR, PHKEY);
+//     LONG RegCreateKeyExA(HKEY, LPCSTR, DWORD, LPSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
+//     LONG RegDeleteKeyA(HKEY, LPCSTR);
+//     LONG RegDeleteValueA(HKEY, LPCSTR);
+//     LONG RegEnumKeyA(HKEY, DWORD, LPSTR, DWORD);
+//     LONG RegEnumKeyExA(HKEY, DWORD, LPSTR, LPDWORD, LPDWORD, LPSTR, LPDWORD, PFILETIME);
+//     LONG RegEnumValueA(HKEY, DWORD, LPSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
+//     LONG RegLoadKeyA(HKEY, LPCSTR, LPCSTR);
+//     LONG RegOpenKeyA(HKEY, LPCSTR, PHKEY);
+//     LONG RegOpenKeyExA(HKEY, LPCSTR, DWORD, REGSAM, PHKEY);
+//     LONG RegQueryInfoKeyA(HKEY, LPSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, PFILETIME);
+//     LONG RegQueryValueA(HKEY, LPCSTR, LPSTR, PLONG);
+//     LONG RegQueryMultipleValuesA(HKEY, PVALENT, DWORD, LPSTR, LPDWORD);
+//     LONG RegQueryValueExA(HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
+//     LONG RegReplaceKeyA(HKEY, LPCSTR, LPCSTR, LPCSTR);
+//     LONG RegRestoreKeyA(HKEY, LPCSTR, DWORD);
+//     LONG RegSaveKeyA(HKEY, LPCSTR, LPSECURITY_ATTRIBUTES);
+//     LONG RegSetValueA(HKEY, LPCSTR, DWORD, LPCSTR, DWORD);
+//     LONG RegSetValueExA(HKEY, LPCSTR, DWORD, DWORD, LPBYTE, DWORD);
+//     LONG RegUnLoadKeyA(HKEY, LPCSTR);
+//     WINBOOL InitiateSystemShutdownA(LPSTR, LPSTR, DWORD, WINBOOL, WINBOOL);
+//     WINBOOL AbortSystemShutdownA(LPSTR);
+//     int CompareStringA(LCID, DWORD, LPCSTR, int, LPCSTR, int);
+//     int LCMapStringA(LCID, DWORD, LPCSTR, int, LPSTR, int);
+//     int GetLocaleInfoA(LCID, LCTYPE, LPSTR, int);
+//     WINBOOL SetLocaleInfoA(LCID, LCTYPE, LPCSTR);
+     int GetTimeFormatA(LCID, DWORD, LPSYSTEMTIME, LPCSTR, LPSTR, int);
+     int GetDateFormatA(LCID, DWORD, LPSYSTEMTIME, LPCSTR, LPSTR, int);
+//     int GetNumberFormatA(LCID, DWORD, LPCSTR, PNUMBERFMT, LPSTR, int);
+//     int GetCurrencyFormatA(LCID, DWORD, LPCSTR, PCURRENCYFMT, LPSTR, int);
+//     WINBOOL EnumCalendarInfoA(CALINFO_ENUMPROC, LCID, CALID, CALTYPE);
+//     WINBOOL EnumTimeFormatsA(TIMEFMT_ENUMPROC, LCID, DWORD);
+//     WINBOOL EnumDateFormatsA(DATEFMT_ENUMPROC, LCID, DWORD);
+//     WINBOOL GetStringTypeExA(LCID, DWORD, LPCSTR, int, LPWORD);
+//     WINBOOL GetStringTypeA(LCID, DWORD, LPCSTR, int, LPWORD);
+//     int FoldStringA(DWORD, LPCSTR, int, LPSTR, int);
+//     WINBOOL EnumSystemLocalesA(LOCALE_ENUMPROC, DWORD);
+//     WINBOOL EnumSystemCodePagesA(CODEPAGE_ENUMPROC, DWORD);
+//     WINBOOL PeekConsoleInputA(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL ReadConsoleInputA(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL WriteConsoleInputA(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL ReadConsoleOutputA(HANDLE, PCHAR_INFO, COORD, COORD, PSMALL_RECT);
+//     WINBOOL WriteConsoleOutputA(HANDLE, PCHAR_INFO, COORD, COORD, PSMALL_RECT);
+//     WINBOOL ReadConsoleOutputCharacterA(HANDLE, LPSTR, DWORD, COORD, LPDWORD);
+//     WINBOOL WriteConsoleOutputCharacterA(HANDLE, LPCSTR, DWORD, COORD, LPDWORD);
+//     WINBOOL FillConsoleOutputCharacterA(HANDLE, char, DWORD, COORD, LPDWORD);
+//     WINBOOL ScrollConsoleScreenBufferA(HANDLE, PSMALL_RECT, PSMALL_RECT, COORD, PCHAR_INFO);
+//     DWORD GetConsoleTitleA(LPSTR, DWORD);
+//     WINBOOL SetConsoleTitleA(LPCSTR);
+//     WINBOOL ReadConsoleA(HANDLE, LPVOID, DWORD, LPDWORD, LPVOID);
+//     WINBOOL WriteConsoleA(HANDLE, POINTER, DWORD, LPDWORD, LPVOID);
+//     DWORD WNetAddConnectionA(LPCSTR, LPCSTR, LPCSTR);
+//     DWORD WNetAddConnection2A(LPNETRESOURCE, LPCSTR, LPCSTR, DWORD);
+//     DWORD WNetAddConnection3A(HWND, LPNETRESOURCE, LPCSTR, LPCSTR, DWORD);
+//     DWORD WNetCancelConnectionA(LPCSTR, WINBOOL);
+//     DWORD WNetCancelConnection2A(LPCSTR, DWORD, WINBOOL);
+//     DWORD WNetGetConnectionA(LPCSTR, LPSTR, LPDWORD);
+//     DWORD WNetUseConnectionA(HWND, LPNETRESOURCE, LPCSTR, LPCSTR, DWORD, LPSTR, LPDWORD, LPDWORD);
+//     DWORD WNetSetConnectionA(LPCSTR, DWORD, LPVOID);
+//     DWORD WNetConnectionDialog1A(LPCONNECTDLGSTRUCT);
+//     DWORD WNetDisconnectDialog1A(LPDISCDLGSTRUCT);
+//     DWORD WNetOpenEnumA(DWORD, DWORD, DWORD, LPNETRESOURCE, LPHANDLE);
+//     DWORD WNetEnumResourceA(HANDLE, LPDWORD, LPVOID, LPDWORD);
+//     DWORD WNetGetUniversalNameA(LPCSTR, DWORD, LPVOID, LPDWORD);
+//     DWORD WNetGetUserA(LPCSTR, LPSTR, LPDWORD);
+//     DWORD WNetGetProviderNameA(DWORD, LPSTR, LPDWORD);
+//     DWORD WNetGetNetworkInformationA(LPCSTR, LPNETINFOSTRUCT);
+//     DWORD WNetGetLastErrorA(LPDWORD, LPSTR, DWORD, LPSTR, DWORD);
+//     DWORD MultinetGetConnectionPerformanceA(LPNETRESOURCE, LPNETCONNECTINFOSTRUCT);
+//     WINBOOL ChangeServiceConfigA(SC_HANDLE, DWORD, DWORD, DWORD, LPCSTR, LPCSTR, LPDWORD, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
+//     SC_HANDLE CreateServiceA(SC_HANDLE, LPCSTR, LPCSTR, DWORD, DWORD, DWORD, DWORD, LPCSTR, LPCSTR, LPDWORD, LPCSTR, LPCSTR, LPCSTR);
+//     WINBOOL EnumDependentServicesA(SC_HANDLE, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD);
+//     WINBOOL EnumServicesStatusA(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL GetServiceKeyNameA(SC_HANDLE, LPCSTR, LPSTR, LPDWORD);
+//     WINBOOL GetServiceDisplayNameA(SC_HANDLE, LPCSTR, LPSTR, LPDWORD);
+//     SC_HANDLE OpenSCManagerA(LPCSTR, LPCSTR, DWORD);
+//     SC_HANDLE OpenServiceA(SC_HANDLE, LPCSTR, DWORD);
+//     WINBOOL QueryServiceConfigA(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD);
+//     WINBOOL QueryServiceLockStatusA(SC_HANDLE, LPQUERY_SERVICE_LOCK_STATUS, DWORD, LPDWORD);
+//     SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerA(LPCSTR, LPHANDLER_FUNCTION);
+//     WINBOOL StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRY);
+//     WINBOOL StartServiceA(SC_HANDLE, DWORD, LPCSTR);
+//     uint DragQueryFileA(HDROP, uint, PCHAR, uint);
+//     HICON ExtractAssociatedIconA(HINST, PCHAR, LPWORD);
+//     HICON ExtractIconA(HINST, PCHAR, uint);
+//     HINST FindExecutableA(PCHAR, PCHAR, PCHAR);
+//     int ShellAboutA(HWND, PCHAR, PCHAR, HICON);
+//     HINST ShellExecuteA(HWND, PCHAR, PCHAR, PCHAR, PCHAR, int);
+//     HSZ DdeCreateStringHandleA(DWORD, PCHAR, int);
+//     UINT DdeInitializeA(LPDWORD, PFNCALLBACK, DWORD, DWORD);
+//     DWORD DdeQueryStringA(DWORD, HSZ, PCHAR, DWORD, int);
+//     WINBOOL LogonUserA(LPSTR, LPSTR, LPSTR, DWORD, DWORD, PHANDLE);
+//     WINBOOL CreateProcessAsUserA(HANDLE, LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, WINBOOL, DWORD, LPVOID, LPCTSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
+//     WINBOOL GetBinaryTypeW(LPCWSTR, LPDWORD);
+//     DWORD GetShortPathNameW(LPCWSTR, LPWSTR, DWORD);
+//     LPWSTR GetEnvironmentStringsW();
+//     WINBOOL FreeEnvironmentStringsW(LPWSTR);
+//     DWORD FormatMessageW(DWORD, LPCVOID, DWORD, DWORD, LPWSTR, DWORD, VA_LIST*);
+//     HANDLE CreateMailslotW(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     int lstrcmpW(LPCWSTR, LPCWSTR);
+//     int lstrcmpiW(LPCWSTR, LPCWSTR);
+//     LPWSTR lstrcpynW(LPWSTR, LPCWSTR, int);
+//     LPWSTR lstrcpyW(LPWSTR, LPCWSTR);
+//     LPWSTR lstrcatW(LPWSTR, LPCWSTR);
+//     int lstrlenW(LPCWSTR);
+//     HANDLE CreateMutexW(LPSECURITY_ATTRIBUTES, WINBOOL, LPCWSTR);
+//     HANDLE OpenMutexW(DWORD, WINBOOL, LPCWSTR);
+//     HANDLE CreateEventW(LPSECURITY_ATTRIBUTES, WINBOOL, WINBOOL, LPCWSTR);
+//     HANDLE OpenEventW(DWORD, WINBOOL, LPCWSTR);
+//     HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES, LONG, LONG, LPCWSTR);
+//     HANDLE OpenSemaphoreW(DWORD, WINBOOL, LPCWSTR);
+//     HANDLE CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCWSTR);
+//     HANDLE OpenFileMappingW(DWORD, WINBOOL, LPCWSTR);
+//     DWORD GetLogicalDriveStringsW(DWORD, LPWSTR);
+//     HINST LoadLibraryW(LPCWSTR);
+//     HINST LoadLibraryExW(LPCWSTR, HANDLE, DWORD);
+//     DWORD GetModuleFileNameW(HINST, LPWSTR, DWORD);
+//     HMODULE GetModuleHandleW(LPCWSTR);
+//     void FatalAppExitW(UINT);
+//     LPWSTR GetCommandLineW();
+//     DWORD GetEnvironmentVariableW(LPCWSTR, LPWSTR, DWORD);
+//     WINBOOL SetEnvironmentVariableW(LPCWSTR, LPCWSTR);
+//     DWORD ExpandEnvironmentStringsW(LPCWSTR, LPWSTR, DWORD);
+//     void OutputDebugStringW(LPCWSTR);
+//     HRSRC FindResourceW(HINST, LPCWSTR, LPCWSTR);
+//     HRSRC FindResourceExW(HINST, LPCWSTR, LPCWSTR, ushort);
+//     WINBOOL EnumResourceTypesW(HINST, ENUMRESTYPEPROC, LONG);
+//     WINBOOL EnumResourceNamesW(HINST, LPCWSTR, ENUMRESNAMEPROC, LONG);
+//     WINBOOL EnumResourceLanguagesW(HINST, LPCWSTR, LPCWSTR, ENUMRESLANGPROC, LONG);
+//     HANDLE BeginUpdateResourceW(LPCWSTR, WINBOOL);
+//     WINBOOL UpdateResourceW(HANDLE, LPCWSTR, LPCWSTR, ushort, LPVOID, DWORD);
+//     WINBOOL EndUpdateResourceW(HANDLE, WINBOOL);
+    ATOM GlobalAddAtomW(LPCWSTR);
+//     ATOM GlobalFindAtomW(LPCWSTR);
+//     UINT GlobalGetAtomNameW(ATOM, LPWSTR, int);
+//     ATOM AddAtomW(LPCWSTR);
+//     ATOM FindAtomW(LPCWSTR);
+//     UINT GetAtomNameW(ATOM, LPWSTR, int);
+//     UINT GetProfileIntW(LPCWSTR, LPCWSTR, INT);
+//     DWORD GetProfileStringW(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, DWORD);
+//     WINBOOL WriteProfileStringW(LPCWSTR, LPCWSTR, LPCWSTR);
+//     DWORD GetProfileSectionW(LPCWSTR, LPWSTR, DWORD);
+//     WINBOOL WriteProfileSectionW(LPCWSTR, LPCWSTR);
+//     UINT GetPrivateProfileIntW(LPCWSTR, LPCWSTR, INT, LPCWSTR);
+//     DWORD GetPrivateProfileStringW(LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
+//     WINBOOL WritePrivateProfileStringW(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
+//     DWORD GetPrivateProfileSectionW(LPCWSTR, LPWSTR, DWORD, LPCWSTR);
+//     WINBOOL WritePrivateProfileSectionW(LPCWSTR, LPCWSTR, LPCWSTR);
+//     UINT GetDriveTypeW(LPCWSTR);
+//     UINT GetSystemDirectoryW(LPWSTR, UINT);
+//     DWORD GetTempPathW(DWORD, LPWSTR);
+//     UINT GetTempFileNameW(LPCWSTR, LPCWSTR, UINT, LPWSTR);
+//     UINT GetWindowsDirectoryW(LPWSTR, UINT);
+//     WINBOOL SetCurrentDirectoryW(LPCWSTR);
+//     DWORD GetCurrentDirectoryW(DWORD, LPWSTR);
+//     WINBOOL GetDiskFreeSpaceW(LPCWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL CreateDirectoryW(LPCWSTR, LPSECURITY_ATTRIBUTES);
+//     WINBOOL CreateDirectoryExW(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
+//     WINBOOL RemoveDirectoryW(LPCWSTR);
+//     DWORD GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR*);
+//     WINBOOL DefineDosDeviceW(DWORD, LPCWSTR, LPCWSTR);
+//     DWORD QueryDosDeviceW(LPCWSTR, LPWSTR, DWORD);
+    HANDLE CreateFileW(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+//     WINBOOL SetFileAttributesW(LPCWSTR, DWORD);
+//     DWORD GetFileAttributesW(LPCWSTR);
+//     BOOL GetFileAttributesExW(LPCWSTR, DWORD, WIN32_FILE_ATTRIBUTE_DATA*);
+//     DWORD GetCompressedFileSizeW(LPCWSTR, LPDWORD);
+    WINBOOL DeleteFileW(LPCWSTR);
+//     DWORD SearchPathW(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPWSTR);
+//     WINBOOL CopyFileW(LPCWSTR, LPCWSTR, WINBOOL);
+//     WINBOOL MoveFileW(LPCWSTR, LPCWSTR);
+//     WINBOOL MoveFileExW(LPCWSTR, LPCWSTR, DWORD);
+//     HANDLE CreateNamedPipeW(LPCWSTR, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     WINBOOL GetNamedPipeHandleStateW(HANDLE, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR, DWORD);
+//     WINBOOL CallNamedPipeW(LPCWSTR, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, DWORD);
+//     WINBOOL WaitNamedPipeW(LPCWSTR, DWORD);
+//     WINBOOL SetVolumeLabelW(LPCWSTR, LPCWSTR);
+//     WINBOOL GetVolumeInformationW(LPCWSTR, LPWSTR, DWORD, LPDWORD, LPDWORD, LPDWORD, LPWSTR, DWORD);
+//     WINBOOL ClearEventLogW(HANDLE, LPCWSTR);
+//     WINBOOL BackupEventLogW(HANDLE, LPCWSTR);
+//     HANDLE OpenEventLogW(LPCWSTR, LPCWSTR);
+//     HANDLE RegisterEventSourceW(LPCWSTR, LPCWSTR);
+//     HANDLE OpenBackupEventLogW(LPCWSTR, LPCWSTR);
+//     WINBOOL ReadEventLogW(HANDLE, DWORD, DWORD, LPVOID, DWORD, LPDWORD, LPDWORD);
+//     WINBOOL ReportEventW(HANDLE, ushort, ushort, DWORD, PSID, ushort, DWORD, LPCWSTR*, LPVOID);
+//     WINBOOL AccessCheckAndAuditAlarmW(LPCWSTR, LPVOID, LPWSTR, LPWSTR, PSECURITY_DESCRIPTOR, DWORD, PGENERIC_MAPPING, WINBOOL, LPDWORD, LPBOOL, LPBOOL);
+//     WINBOOL ObjectOpenAuditAlarmW(LPCWSTR, LPVOID, LPWSTR, LPWSTR, PSECURITY_DESCRIPTOR, HANDLE, DWORD, DWORD, PPRIVILEGE_SET, WINBOOL, WINBOOL, LPBOOL);
+//     WINBOOL ObjectPrivilegeAuditAlarmW(LPCWSTR, LPVOID, HANDLE, DWORD, PPRIVILEGE_SET, WINBOOL);
+//     WINBOOL ObjectCloseAuditAlarmW(LPCWSTR, LPVOID, WINBOOL);
+//     WINBOOL PrivilegedServiceAuditAlarmW(LPCWSTR, LPCWSTR, HANDLE, PPRIVILEGE_SET, WINBOOL);
+//     WINBOOL SetFileSecurityW(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     WINBOOL GetFileSecurityW(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+//     HANDLE FindFirstChangeNotificationW(LPCWSTR, WINBOOL, DWORD);
+//     WINBOOL IsBadStringPtrW(LPCWSTR, UINT);
+//     WINBOOL LookupAccountSidW(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
+//     WINBOOL LookupAccountNameW(LPCWSTR, LPCWSTR, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
+//     WINBOOL LookupPrivilegeValueW(LPCWSTR, LPCWSTR, PLUID);
+//     WINBOOL LookupPrivilegeNameW(LPCWSTR, PLUID, LPWSTR, LPDWORD);
+//     WINBOOL LookupPrivilegeDisplayNameW(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD, LPDWORD);
+//     WINBOOL BuildCommDCBW(LPCWSTR, LPDCB);
+//     WINBOOL BuildCommDCBAndTimeoutsW(LPCWSTR, LPDCB, LPCOMMTIMEOUTS);
+//     WINBOOL CommConfigDialogW(LPCWSTR, HWND, LPCOMMCONFIG);
+//     WINBOOL GetDefaultCommConfigW(LPCWSTR, LPCOMMCONFIG, LPDWORD);
+//     WINBOOL SetDefaultCommConfigW(LPCWSTR, LPCOMMCONFIG, DWORD);
+//     WINBOOL GetComputerNameW(LPWSTR, LPDWORD);
+//     WINBOOL SetComputerNameW(LPCWSTR);
+//     WINBOOL GetUserNameW(LPWSTR, LPDWORD);
+//     int wvsprintfW(LPWSTR, LPCWSTR, VA_LIST*);
+//     HKL LoadKeyboardLayoutW(LPCWSTR, UINT);
+//     WINBOOL GetKeyboardLayoutNameW(LPWSTR);
+//     HDESK CreateDesktopW(LPWSTR, LPWSTR, LPDEVMODE, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     HDESK OpenDesktopW(LPWSTR, DWORD, WINBOOL, DWORD);
+//     WINBOOL EnumDesktopsW(HWINSTA, DESKTOPENUMPROC, LPARAM);
+//     HWINSTA CreateWindowStationW(LPWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES);
+//     HWINSTA OpenWindowStationW(LPWSTR, WINBOOL, DWORD);
+//     WINBOOL EnumWindowStationsW(ENUMWINDOWSTATIONPROC, LPARAM);
+//     WINBOOL GetUserObjectInformationW(HANDLE, int, PVOID, DWORD, LPDWORD);
+//     WINBOOL SetUserObjectInformationW(HANDLE, int, PVOID, DWORD);
+//     UINT RegisterWindowMessageW(LPCWSTR);
+//     WINBOOL GetMessageW(LPMSG, HWND, UINT, UINT);
+//     LONG DispatchMessageW(LPMSG);
+//     WINBOOL PeekMessageW(LPMSG, HWND, UINT, UINT, UINT);
+//     LRESULT SendMessageW(HWND, UINT, WPARAM, LPARAM);
+//     LRESULT SendMessageTimeoutW(HWND, UINT, WPARAM, LPARAM, UINT, UINT, LPDWORD);
+//     WINBOOL SendNotifyMessageW(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL SendMessageCallbackW(HWND, UINT, WPARAM, LPARAM, SENDASYNCPROC, DWORD);
+//     WINBOOL PostMessageW(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL PostThreadMessageW(DWORD, UINT, WPARAM, LPARAM);
+//     LRESULT DefWindowProcW(HWND, UINT, WPARAM, LPARAM);
+//     LRESULT CallWindowProcW(WNDPROC, HWND, UINT, WPARAM, LPARAM);
+//     ATOM RegisterClassW(LPWNDCLASSW);
+//     WINBOOL UnregisterClassW(LPCWSTR, HINST);
+//     WINBOOL GetClassInfoW(HINST, LPCWSTR, LPWNDCLASS);
+//     ATOM RegisterClassExW(LPWNDCLASSEX);
+//     WINBOOL GetClassInfoExW(HINST, LPCWSTR, LPWNDCLASSEX);
+//     HWND CreateWindowExW(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINST, LPVOID);
+//     HWND CreateDialogParamW(HINST, LPCWSTR, HWND, DLGPROC, LPARAM);
+//     HWND CreateDialogIndirectParamW(HINST, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
+//     int DialogBoxParamW(HINST, LPCWSTR, HWND, DLGPROC, LPARAM);
+//     int DialogBoxIndirectParamW(HINST, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
+//     WINBOOL SetDlgItemTextW(HWND, int, LPCWSTR);
+//     UINT GetDlgItemTextW(HWND, int, LPWSTR, int);
+//     LONG SendDlgItemMessageW(HWND, int, UINT, WPARAM, LPARAM);
+//     LRESULT DefDlgProcW(HWND, UINT, WPARAM, LPARAM);
+//     WINBOOL CallMsgFilterW(LPMSG, int);
+//     UINT RegisterClipboardFormatW(LPCWSTR);
+//     int GetClipboardFormatNameW(UINT, LPWSTR, int);
+//     WINBOOL CharToOemW(LPCWSTR, LPSTR);
+//     WINBOOL OemToCharW(LPCSTR, LPWSTR);
+//     WINBOOL CharToOemBuffW(LPCWSTR, LPSTR, DWORD);
+//     WINBOOL OemToCharBuffW(LPCSTR, LPWSTR, DWORD);
+//     LPWSTR CharUpperW(LPWSTR);
+//     DWORD CharUpperBuffW(LPWSTR, DWORD);
+//     LPWSTR CharLowerW(LPWSTR);
+//     DWORD CharLowerBuffW(LPWSTR, DWORD);
+//     LPWSTR CharNextW(LPCWSTR);
+//     LPWSTR CharPrevW(LPCWSTR, LPCWSTR);
+//     WINBOOL IsCharAlphaW(WCHAR);
+//     WINBOOL IsCharAlphaNumericW(WCHAR);
+//     WINBOOL IsCharUpperW(WCHAR);
+//     WINBOOL IsCharLowerW(WCHAR);
+//     int GetKeyNameTextW(LONG, LPWSTR, int);
+//     SHORT VkKeyScanW(WCHAR);
+//     SHORT VkKeyScanExW(WCHAR, HKL);
+//     UINT MapVirtualKeyW(UINT, UINT);
+//     UINT MapVirtualKeyExW(UINT, UINT, HKL);
+//     HACCEL LoadAcceleratorsW(HINST, LPCWSTR);
+//     HACCEL CreateAcceleratorTableW(LPACCEL, int);
+//     int CopyAcceleratorTableW(HACCEL, LPACCEL, int);
+//     int TranslateAcceleratorW(HWND, HACCEL, LPMSG);
+//     HMENU LoadMenuW(HINST, LPCWSTR);
+//     HMENU LoadMenuIndirectW(LPMENUTEMPLATE);
+//     WINBOOL ChangeMenuW(HMENU, UINT, LPCWSTR, UINT, UINT);
+//     int GetMenuStringW(HMENU, UINT, LPWSTR, int, UINT);
+//     WINBOOL InsertMenuW(HMENU, UINT, UINT, UINT, LPCWSTR);
+//     WINBOOL AppendMenuW(HMENU, UINT, UINT, LPCWSTR);
+//     WINBOOL ModifyMenuW(HMENU, UINT, UINT, UINT, LPCWSTR);
+//     WINBOOL InsertMenuItemW(HMENU, UINT, WINBOOL, LPCMENUITEMINFO);
+//     WINBOOL GetMenuItemInfoW(HMENU, UINT, WINBOOL, LPMENUITEMINFO);
+//     WINBOOL SetMenuItemInfoW(HMENU, UINT, WINBOOL, LPCMENUITEMINFO);
+//     int DrawTextW(HDC, LPCWSTR, int, LPRECT, UINT);
+//     int DrawTextExW(HDC, LPWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS);
+//     WINBOOL GrayStringW(HDC, HBRUSH, GRAYSTRINGPROC, LPARAM, int, int, int, int, int);
+//     WINBOOL DrawStateW(HDC, HBRUSH, DRAWSTATEPROC, LPARAM, WPARAM, int, int, int, int, UINT);
+//     LONG TabbedTextOutW(HDC, int, int, LPCWSTR, int, int, LPINT, int);
+//     DWORD GetTabbedTextExtentW(HDC, LPCWSTR, int, int, LPINT);
+    WINBOOL SetPropW(HWND, LPCWSTR, HANDLE);
+    HANDLE GetPropW(HWND, LPCWSTR);
+    HANDLE RemovePropW(HWND, LPCWSTR);
+//     int EnumPropsExW(HWND, PROPENUMPROCEX, LPARAM);
+//     int EnumPropsW(HWND, PROPENUMPROC);
+//     WINBOOL SetWindowTextW(HWND, LPCWSTR);
+//     int GetWindowTextW(HWND, LPWSTR, int);
+//     int GetWindowTextLengthW(HWND);
+//     int MessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT);
+//     int MessageBoxExW(HWND, LPCWSTR, LPCWSTR, UINT, ushort);
+//     int MessageBoxIndirectW(LPMSGBOXPARAMS);
+//     LONG GetWindowLongW(HWND, int);
+//     LONG SetWindowLongW(HWND, int, LONG);
+//     DWORD GetClassLongW(HWND, int);
+//     DWORD SetClassLongW(HWND, int, LONG);
+//     HWND FindWindowW(LPCWSTR, LPCWSTR);
+//     HWND FindWindowExW(HWND, HWND, LPCWSTR, LPCWSTR);
+    int GetClassNameW(HWND, LPWSTR, int);
+//     HHOOK SetWindowsHookExW(int, HOOKPROC, HINST, DWORD);
+//     HBITMAP LoadBitmapW(HINST, LPCWSTR);
+    HCURSOR LoadCursorW(HINST, LPCWSTR);
+//     HCURSOR LoadCursorFromFileW(LPCWSTR);
+    HICON LoadIconW(HINST, LPCWSTR);
+//     HANDLE LoadImageW(HINST, LPCWSTR, UINT, int, int, UINT);
+//     int LoadStringW(HINST, UINT, LPWSTR, int);
+//     WINBOOL IsDialogMessageW(HWND, LPMSG);
+//     int DlgDirListW(HWND, LPWSTR, int, int, UINT);
+//     WINBOOL DlgDirSelectExW(HWND, LPWSTR, int, int);
+//     int DlgDirListComboBoxW(HWND, LPWSTR, int, int, UINT);
+//     WINBOOL DlgDirSelectComboBoxExW(HWND, LPWSTR, int, int);
+//     LRESULT DefFrameProcW(HWND, HWND, UINT, WPARAM, LPARAM);
+//     LRESULT DefMDIChildProcW(HWND, UINT, WPARAM, LPARAM);
+//     HWND CreateMDIWindowW(LPWSTR, LPWSTR, DWORD, int, int, int, int, HWND, HINST, LPARAM);
+//     WINBOOL WinHelpW(HWND, LPCWSTR, UINT, DWORD);
+//     LONG ChangeDisplaySettingsW(LPDEVMODE, DWORD);
+//     WINBOOL EnumDisplaySettingsW(LPCWSTR, DWORD, LPDEVMODE);
+//     WINBOOL SystemParametersInfoW(UINT, UINT, PVOID, UINT);
+//     int AddFontResourceW(LPCWSTR);
+//     HMETAFILE CopyMetaFileW(HMETAFILE, LPCWSTR);
+//     HFONT CreateFontIndirectW(PLOGFONT);
+//     HFONT CreateFontW(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCWSTR);
+//     HDC CreateICW(LPCWSTR, LPCWSTR, LPCWSTR, LPDEVMODE);
+//     HDC CreateMetaFileW(LPCWSTR);
+//     WINBOOL CreateScalableFontResourceW(DWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+//     int EnumFontFamiliesExW(HDC, LPLOGFONT, FONTENUMEXPROC, LPARAM, DWORD);
+//     int EnumFontFamiliesW(HDC, LPCWSTR, FONTENUMPROC, LPARAM);
+//     int EnumFontsW(HDC, LPCWSTR, ENUMFONTSPROC, LPARAM);
+//     WINBOOL GetCharWidthW(HDC, UINT, UINT, LPINT);
+//     WINBOOL GetCharWidth32W(HDC, UINT, UINT, LPINT);
+//     WINBOOL GetCharWidthFloatW(HDC, UINT, UINT, PFLOAT);
+//     WINBOOL GetCharABCWidthsW(HDC, UINT, UINT, LPABC);
+//     WINBOOL GetCharABCWidthsFloatW(HDC, UINT, UINT, LPABCFLOAT);
+//     DWORD GetGlyphOutlineW(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, PMAT2);
+//     HMETAFILE GetMetaFileW(LPCWSTR);
+     UINT GetOutlineTextMetricsW(HDC, UINT, LPOUTLINETEXTMETRIC);
+//     WINBOOL GetTextExtentPointW(HDC, LPCWSTR, int, LPSIZE);
+//     WINBOOL GetTextExtentPoint32W(HDC, LPCWSTR, int, LPSIZE);
+//     WINBOOL GetTextExtentExPointW(HDC, LPCWSTR, int, int, LPINT, LPINT, LPSIZE);
+//     DWORD GetCharacterPlacementW(HDC, LPCWSTR, int, int, LPGCP_RESULTS, DWORD);
+//     HDC ResetDCW(HDC, LPDEVMODE);
+//     WINBOOL RemoveFontResourceW(LPCWSTR);
+//     HENHMETAFILE CopyEnhMetaFileW(HENHMETAFILE, LPCWSTR);
+    HDC CreateEnhMetaFileW(HDC, LPCWSTR, LPRECT, LPCWSTR);
+//     HENHMETAFILE GetEnhMetaFileW(LPCWSTR);
+//     UINT GetEnhMetaFileDescriptionW(HENHMETAFILE, UINT, LPWSTR);
+//     WINBOOL GetTextMetricsW(HDC, LPTEXTMETRIC);
+//     int StartDocW(HDC, PDOCINFO);
+    int GetObjectW(HGDIOBJ, int, LPVOID);
+//     WINBOOL TextOutW(HDC, int, int, LPCWSTR, int);
+//     WINBOOL ExtTextOutW(HDC, int, int, UINT, LPRECT, LPCWSTR, UINT, LPINT);
+//     WINBOOL PolyTextOutW(HDC, PPOLYTEXT, int);
+//     int GetTextFaceW(HDC, int, LPWSTR);
+//     DWORD GetKerningPairsW(HDC, DWORD, LPKERNINGPAIR);
+//     WINBOOL GetLogColorSpaceW(HCOLORSPACE, LPLOGCOLORSPACE, DWORD);
+//     HCOLORSPACE CreateColorSpaceW(LPLOGCOLORSPACE);
+//     WINBOOL GetICMProfileW(HDC, DWORD, LPWSTR);
+//     WINBOOL SetICMProfileW(HDC, LPWSTR);
+//     WINBOOL UpdateICMRegKeyW(DWORD, DWORD, LPWSTR, UINT);
+//     int EnumICMProfilesW(HDC, ICMENUMPROC, LPARAM);
+//     HPROPSHEETPAGE CreatePropertySheetPageW(LPCPROPSHEETPAGE);
+//     int PropertySheetW(LPCPROPSHEETHEADER);
+//     HIMAGELIST ImageList_LoadImageW(HINST, LPCWSTR, int, int, COLORREF, UINT, UINT);
+//     HWND CreateStatusWindowW(LONG, LPCWSTR, HWND, UINT);
+//     void DrawStatusTextW(HDC, LPRECT, LPCWSTR);
+//     WINBOOL GetOpenFileNameW(LPOPENFILENAME);
+//     WINBOOL GetSaveFileNameW(LPOPENFILENAME);
+//     int GetFileTitleW(LPCWSTR, LPWSTR, ushort);
+//     WINBOOL ChooseColorW(LPCHOOSECOLOR);
+//     HWND ReplaceTextW(LPFINDREPLACE);
+//     WINBOOL ChooseFontW(LPCHOOSEFONT);
+//     HWND FindTextW(LPFINDREPLACE);
+    WINBOOL PrintDlgW(LPPRINTDLG);
+//     WINBOOL PageSetupDlgW(LPPAGESETUPDLG);
+    WINBOOL CreateProcessW(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, WINBOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
+    void GetStartupInfoW(LPSTARTUPINFO);
+//     HANDLE FindFirstFileW(LPCWSTR, LPWIN32_FIND_DATAW);
+//     WINBOOL FindNextFileW(HANDLE, LPWIN32_FIND_DATAW);
+//     WINBOOL GetVersionExW(LPOSVERSIONINFO);
+//     HDC CreateDCW(LPCWSTR, LPCWSTR, LPCWSTR, PDEVMODE);
+//     HFONT CreateFontA(int, int, int, int, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, LPCSTR);
+//     DWORD VerInstallFileW(DWORD, LPWSTR, LPWSTR, LPWSTR, LPWSTR, LPWSTR, LPWSTR, PUINT);
+//     DWORD GetFileVersionInfoSizeW(LPWSTR, LPDWORD);
+//     WINBOOL GetFileVersionInfoW(LPWSTR, DWORD, DWORD, LPVOID);
+//     DWORD VerLanguageNameW(DWORD, LPWSTR, DWORD);
+//     WINBOOL VerQueryValueW(LPVOID, LPWSTR, LPVOID, PUINT);
+//     DWORD VerFindFileW(DWORD, LPWSTR, LPWSTR, LPWSTR, LPWSTR, PUINT, LPWSTR, PUINT);
+//     LONG RegSetValueExW(HKEY, LPCWSTR, DWORD, DWORD, LPBYTE, DWORD);
+//     LONG RegUnLoadKeyW(HKEY, LPCWSTR);
+//     WINBOOL InitiateSystemShutdownW(LPWSTR, LPWSTR, DWORD, WINBOOL, WINBOOL);
+//     WINBOOL AbortSystemShutdownW(LPWSTR);
+//     LONG RegRestoreKeyW(HKEY, LPCWSTR, DWORD);
+//     LONG RegSaveKeyW(HKEY, LPCWSTR, LPSECURITY_ATTRIBUTES);
+//     LONG RegSetValueW(HKEY, LPCWSTR, DWORD, LPCWSTR, DWORD);
+//     LONG RegQueryValueW(HKEY, LPCWSTR, LPWSTR, PLONG);
+//     LONG RegQueryMultipleValuesW(HKEY, PVALENT, DWORD, LPWSTR, LPDWORD);
+//     LONG RegQueryValueExW(HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
+//     LONG RegReplaceKeyW(HKEY, LPCWSTR, LPCWSTR, LPCWSTR);
+//     LONG RegConnectRegistryW(LPWSTR, HKEY, PHKEY);
+//     LONG RegCreateKeyW(HKEY, LPCWSTR, PHKEY);
+//     LONG RegCreateKeyExW(HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
+//     LONG RegDeleteKeyW(HKEY, LPCWSTR);
+//     LONG RegDeleteValueW(HKEY, LPCWSTR);
+//     LONG RegEnumKeyW(HKEY, DWORD, LPWSTR, DWORD);
+//     LONG RegEnumKeyExW(HKEY, DWORD, LPWSTR, LPDWORD, LPDWORD, LPWSTR, LPDWORD, PFILETIME);
+//     LONG RegEnumValueW(HKEY, DWORD, LPWSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
+//     LONG RegLoadKeyW(HKEY, LPCWSTR, LPCWSTR);
+//     LONG RegOpenKeyW(HKEY, LPCWSTR, PHKEY);
+//     LONG RegOpenKeyExW(HKEY, LPCWSTR, DWORD, REGSAM, PHKEY);
+//     LONG RegQueryInfoKeyW(HKEY, LPWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, PFILETIME);
+//     int CompareStringW(LCID, DWORD, LPCWSTR, int, LPCWSTR, int);
+//     int LCMapStringW(LCID, DWORD, LPCWSTR, int, LPWSTR, int);
+//     int GetLocaleInfoW(LCID, LCTYPE, LPWSTR, int);
+//     WINBOOL SetLocaleInfoW(LCID, LCTYPE, LPCWSTR);
+     int GetTimeFormatW(LCID, DWORD, LPSYSTEMTIME, LPCWSTR, LPWSTR, int);
+     int GetDateFormatW(LCID, DWORD, LPSYSTEMTIME, LPCWSTR, LPWSTR, int);
+//     int GetNumberFormatW(LCID, DWORD, LPCWSTR, PNUMBERFMT, LPWSTR, int);
+//     int GetCurrencyFormatW(LCID, DWORD, LPCWSTR, PCURRENCYFMT, LPWSTR, int);
+//     WINBOOL EnumCalendarInfoW(CALINFO_ENUMPROC, LCID, CALID, CALTYPE);
+//     WINBOOL EnumTimeFormatsW(TIMEFMT_ENUMPROC, LCID, DWORD);
+//     WINBOOL EnumDateFormatsW(DATEFMT_ENUMPROC, LCID, DWORD);
+//     WINBOOL GetStringTypeExW(LCID, DWORD, LPCWSTR, int, LPWORD);
+//     WINBOOL GetStringTypeW(DWORD, LPCWSTR, int, LPWORD);
+//     int FoldStringW(DWORD, LPCWSTR, int, LPWSTR, int);
+//     WINBOOL EnumSystemLocalesW(LOCALE_ENUMPROC, DWORD);
+//     WINBOOL EnumSystemCodePagesW(CODEPAGE_ENUMPROC, DWORD);
+//     WINBOOL PeekConsoleInputW(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL ReadConsoleInputW(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL WriteConsoleInputW(HANDLE, PINPUTRECORD, DWORD, LPDWORD);
+//     WINBOOL ReadConsoleOutputW(HANDLE, PCHAR_INFO, COORD, COORD, PSMALL_RECT);
+//     WINBOOL WriteConsoleOutputW(HANDLE, PCHAR_INFO, COORD, COORD, PSMALL_RECT);
+//     WINBOOL ReadConsoleOutputCharacterW(HANDLE, LPWSTR, DWORD, COORD, LPDWORD);
+//     WINBOOL WriteConsoleOutputCharacterW(HANDLE, LPCWSTR, DWORD, COORD, LPDWORD);
+//     WINBOOL FillConsoleOutputCharacterW(HANDLE, WCHAR, DWORD, COORD, LPDWORD);
+//     WINBOOL ScrollConsoleScreenBufferW(HANDLE, PSMALL_RECT, PSMALL_RECT, COORD, PCHAR_INFO);
+//     DWORD GetConsoleTitleW(LPWSTR, DWORD);
+//     WINBOOL SetConsoleTitleW(LPCWSTR);
+//     WINBOOL ReadConsoleW(HANDLE, LPVOID, DWORD, LPDWORD, LPVOID);
+//     WINBOOL WriteConsoleW(HANDLE, POINTER, DWORD, LPDWORD, LPVOID);
+//     DWORD WNetAddConnectionW(LPCWSTR, LPCWSTR, LPCWSTR);
+//     DWORD WNetAddConnection2W(LPNETRESOURCE, LPCWSTR, LPCWSTR, DWORD);
+//     DWORD WNetAddConnection3W(HWND, LPNETRESOURCE, LPCWSTR, LPCWSTR, DWORD);
+//     DWORD WNetCancelConnectionW(LPCWSTR, WINBOOL);
+//     DWORD WNetCancelConnection2W(LPCWSTR, DWORD, WINBOOL);
+//     DWORD WNetGetConnectionW(LPCWSTR, LPWSTR, LPDWORD);
+//     DWORD WNetUseConnectionW(HWND, LPNETRESOURCE, LPCWSTR, LPCWSTR, DWORD, LPWSTR, LPDWORD, LPDWORD);
+//     DWORD WNetSetConnectionW(LPCWSTR, DWORD, LPVOID);
+//     DWORD WNetConnectionDialog1W(LPCONNECTDLGSTRUCT);
+//     DWORD WNetDisconnectDialog1W(LPDISCDLGSTRUCT);
+//     DWORD WNetOpenEnumW(DWORD, DWORD, DWORD, LPNETRESOURCE, LPHANDLE);
+//     DWORD WNetEnumResourceW(HANDLE, LPDWORD, LPVOID, LPDWORD);
+//     DWORD WNetGetUniversalNameW(LPCWSTR, DWORD, LPVOID, LPDWORD);
+//     DWORD WNetGetUserW(LPCWSTR, LPWSTR, LPDWORD);
+//     DWORD WNetGetProviderNameW(DWORD, LPWSTR, LPDWORD);
+//     DWORD WNetGetNetworkInformationW(LPCWSTR, LPNETINFOSTRUCT);
+//     DWORD WNetGetLastErrorW(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
+//     DWORD MultinetGetConnectionPerformanceW(LPNETRESOURCE, LPNETCONNECTINFOSTRUCT);
+//     WINBOOL ChangeServiceConfigW(SC_HANDLE, DWORD, DWORD, DWORD, LPCWSTR, LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
+//     SC_HANDLE CreateServiceW(SC_HANDLE, LPCWSTR, LPCWSTR, DWORD, DWORD, DWORD, DWORD, LPCWSTR, LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR);
+//     WINBOOL EnumDependentServicesW(SC_HANDLE, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD);
+//     WINBOOL EnumServicesStatusW(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUS, DWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL GetServiceKeyNameW(SC_HANDLE, LPCWSTR, LPWSTR, LPDWORD);
+//     WINBOOL GetServiceDisplayNameW(SC_HANDLE, LPCWSTR, LPWSTR, LPDWORD);
+//     SC_HANDLE OpenSCManagerW(LPCWSTR, LPCWSTR, DWORD);
+//     SC_HANDLE OpenServiceW(SC_HANDLE, LPCWSTR, DWORD);
+//     WINBOOL QueryServiceConfigW(SC_HANDLE, LPQUERY_SERVICE_CONFIG, DWORD, LPDWORD);
+//     WINBOOL QueryServiceLockStatusW(SC_HANDLE, LPQUERY_SERVICE_LOCK_STATUS, DWORD, LPDWORD);
+//     SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerW(LPCWSTR, LPHANDLER_FUNCTION);
+//     WINBOOL StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRY);
+//     WINBOOL StartServiceW(SC_HANDLE, DWORD, LPCWSTR);
+//     uint DragQueryFileW(HDROP, uint, LPCWSTR, uint);
+//     HICON ExtractAssociatedIconW(HINST, LPCWSTR, LPWORD);
+//     HICON ExtractIconW(HINST, LPCWSTR, uint);
+//     HINST FindExecutableW(LPCWSTR, LPCWSTR, LPCWSTR);
+//     int ShellAboutW(HWND, LPCWSTR, LPCWSTR, HICON);
+//     HINST ShellExecuteW(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, int);
+//     HSZ DdeCreateStringHandleW(DWORD, LPCWSTR, int);
+//     UINT DdeInitializeW(LPDWORD, PFNCALLBACK, DWORD, DWORD);
+//     DWORD DdeQueryStringW(DWORD, HSZ, LPCWSTR, DWORD, int);
+//     WINBOOL LogonUserW(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD, PHANDLE);
+//     WINBOOL CreateProcessAsUserW(HANDLE, LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, WINBOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
+//     WINBOOL AccessCheck(PSECURITY_DESCRIPTOR, HANDLE, DWORD, PGENERIC_MAPPING, PPRIVILEGE_SET, LPDWORD, LPDWORD, LPBOOL);
+//     LONG InterlockedIncrement(LPLONG);
+//     LONG InterlockedDecrement(LPLONG);
+//     LONG InterlockedExchange(LPLONG, LONG);
+//     WINBOOL FreeResource(HGLOBAL);
+//     LPVOID LockResource(HGLOBAL);
+    WINBOOL FreeLibrary(HINST);
+//     void FreeLibraryAndExitThread(HMODULE, DWORD);
+//     WINBOOL DisableThreadLibraryCalls(HMODULE);
+    FARPROC GetProcAddress(HINST, LPCSTR);
+//     DWORD GetVersion();
+//     HGLOBAL GlobalAlloc(UINT, DWORD);
+//     HGLOBAL GlobalReAlloc(HGLOBAL, DWORD, UINT);
+//     DWORD GlobalSize(HGLOBAL);
+//     UINT GlobalFlags(HGLOBAL);
+//     LPVOID GlobalLock(HGLOBAL);
+//     HGLOBAL GlobalHandle(LPCVOID);
+//     WINBOOL GlobalUnlock(HGLOBAL);
+//     HGLOBAL GlobalFree(HGLOBAL);
+//     UINT GlobalCompact(DWORD);
+//     void GlobalFix(HGLOBAL);
+//     void GlobalUnfix(HGLOBAL);
+//     LPVOID GlobalWire(HGLOBAL);
+//     WINBOOL GlobalUnWire(HGLOBAL);
+//     void GlobalMemoryStatus(LPMEMORYSTATUS);
+//     HLOCAL LocalAlloc(UINT, UINT);
+//     HLOCAL LocalReAlloc(HLOCAL, UINT, UINT);
+//     LPVOID LocalLock(HLOCAL);
+//     HLOCAL LocalHandle(LPCVOID);
+//     WINBOOL LocalUnlock(HLOCAL);
+//     UINT LocalSize(HLOCAL);
+//     UINT LocalFlags(HLOCAL);
+//     HLOCAL LocalFree(HLOCAL);
+//     UINT LocalShrink(HLOCAL, UINT);
+//     UINT LocalCompact(UINT);
+//     WINBOOL FlushInstructionCache(HANDLE, LPCVOID, DWORD);
+//     LPVOID VirtualAlloc(LPVOID, DWORD, DWORD, DWORD);
+//     WINBOOL VirtualFree(LPVOID, DWORD, DWORD);
+//     WINBOOL VirtualProtect(LPVOID, DWORD, DWORD, PDWORD);
+//     DWORD VirtualQuery(LPCVOID, PMEMORY_BASIC_INFORMATION, DWORD);
+//     WINBOOL VirtualProtectEx(HANDLE, LPVOID, DWORD, DWORD, PDWORD);
+//     DWORD VirtualQueryEx(HANDLE, LPCVOID, PMEMORY_BASIC_INFORMATION, DWORD);
+//     HANDLE HeapCreate(DWORD, DWORD, DWORD);
+//     WINBOOL HeapDestroy(HANDLE);
+//     LPVOID HeapAlloc(HANDLE, DWORD, DWORD);
+//     LPVOID HeapReAlloc(HANDLE, DWORD, LPVOID, DWORD);
+//     WINBOOL HeapFree(HANDLE, DWORD, LPVOID);
+//     DWORD HeapSize(HANDLE, DWORD, LPCVOID);
+//     WINBOOL HeapValidate(HANDLE, DWORD, LPCVOID);
+//     UINT HeapCompact(HANDLE, DWORD);
+//     HANDLE GetProcessHeap();
+//     DWORD GetProcessHeaps(DWORD, PHANDLE);
+//     WINBOOL HeapLock(HANDLE);
+//     WINBOOL HeapUnlock(HANDLE);
+//     WINBOOL HeapWalk(HANDLE, LPPROCESS_HEAP_ENTRY);
+//     WINBOOL GetProcessAffinityMask(HANDLE, LPDWORD, LPDWORD);
+//     WINBOOL GetProcessTimes(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
+//     WINBOOL GetProcessWorkingSetSize(HANDLE, LPDWORD, LPDWORD);
+//     WINBOOL SetProcessWorkingSetSize(HANDLE, DWORD, DWORD);
+//     HANDLE OpenProcess(DWORD, WINBOOL, DWORD);
+//     HANDLE GetCurrentProcess();
+//     DWORD GetCurrentProcessId();
+//     void ExitProcess(UINT);
+//     WINBOOL TerminateProcess(HANDLE, UINT);
+//     WINBOOL GetExitCodeProcess(HANDLE, LPDWORD);
+//     void FatalExit(int);
+//     void RaiseException(DWORD, DWORD, DWORD);
+//     LONG UnhandledExceptionFilter(EMPTYRECORD*);
+//     HANDLE CreateRemoteThread(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
+//     HANDLE GetCurrentThread();
+//     DWORD GetCurrentThreadId();
+//     DWORD SetThreadAffinityMask(HANDLE, DWORD);
+//     WINBOOL SetThreadPriority(HANDLE, int);
+//     int GetThreadPriority(HANDLE);
+//     WINBOOL GetThreadTimes(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
+//     void ExitThread(DWORD);
+//     WINBOOL TerminateThread(HANDLE, DWORD);
+//     WINBOOL GetExitCodeThread(HANDLE, LPDWORD);
+//     WINBOOL GetThreadSelectorEntry(HANDLE, DWORD, LPLDT_ENTRY);
+//     DWORD GetLastError();
+//     void SetLastError(DWORD);
+//     HANDLE CreateIoCompletionPort(HANDLE, HANDLE, DWORD, DWORD);
+//     UINT SetErrorMode(UINT);
+//     WINBOOL ReadProcessMemory(HANDLE, LPCVOID, LPVOID, DWORD, LPDWORD);
+//     WINBOOL WriteProcessMemory(HANDLE, LPVOID, LPVOID, DWORD, LPDWORD);
+//     WINBOOL GetThreadContext(HANDLE, LPCONTEXT);
+//     DWORD SuspendThread(HANDLE);
+//     DWORD ResumeThread(HANDLE);
+//     void DebugBreak();
+//     WINBOOL WaitForDebugEvent(LPDEBUG_EVENT, DWORD);
+//     WINBOOL ContinueDebugEvent(DWORD, DWORD, DWORD);
+//     WINBOOL DebugActiveProcess(DWORD);
+//     void InitializeCriticalSection(LPCRITICAL_SECTION);
+//     void EnterCriticalSection(LPCRITICAL_SECTION);
+//     WINBOOL TryEnterCriticalSection(LPCRITICAL_SECTION);
+//     void LeaveCriticalSection(LPCRITICAL_SECTION);
+//     void DeleteCriticalSection(LPCRITICAL_SECTION);
+//     WINBOOL SetEvent(HANDLE);
+//     WINBOOL ResetEvent(HANDLE);
+//     WINBOOL PulseEvent(HANDLE);
+//     WINBOOL ReleaseSemaphore(HANDLE, LONG, LPLONG);
+//     WINBOOL ReleaseMutex(HANDLE);
+    DWORD WaitForSingleObject(HANDLE, DWORD);
+    DWORD WaitForMultipleObjects(DWORD, HANDLE*, WINBOOL, DWORD);
+//     void Sleep(DWORD);
+//     HGLOBAL LoadResource(HINST, HRSRC);
+//     DWORD SizeofResource(HINST, HRSRC);
+//     ATOM GlobalDeleteAtom(ATOM);
+//     WINBOOL InitAtomTable(DWORD);
+//     ATOM DeleteAtom(ATOM);
+//     UINT SetHandleCount(UINT);
+//     DWORD GetLogicalDrives();
+//     WINBOOL LockFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
+//     WINBOOL UnlockFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
+//     WINBOOL LockFileEx(HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED);
+//     WINBOOL UnlockFileEx(HANDLE, DWORD, DWORD, DWORD, LPOVERLAPPED);
+//     WINBOOL GetFileInformationByHandle(HANDLE, LPBY_HANDLE_FILE_INFORMATION);
+//     DWORD GetFileType(HANDLE);
+//     DWORD GetFileSize(HANDLE, LPDWORD);
+//     HANDLE GetStdHandle(DWORD);
+//     WINBOOL SetStdHandle(DWORD, HANDLE);
+//     WINBOOL FlushFileBuffers(HANDLE);
+//     WINBOOL DeviceIoControl(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
+//     WINBOOL SetEndOfFile(HANDLE);
+//     DWORD SetFilePointer(HANDLE, LONG, PLONG, DWORD);
+//     WINBOOL FindClose(HANDLE);
+//     WINBOOL GetFileTime(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME);
+//     WINBOOL SetFileTime(HANDLE, FILETIME*, FILETIME*, FILETIME*);
+    WINBOOL CloseHandle(HANDLE);
+//     WINBOOL DuplicateHandle(HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, WINBOOL, DWORD);
+//     WINBOOL GetHandleInformation(HANDLE, LPDWORD);
+//     WINBOOL SetHandleInformation(HANDLE, DWORD, DWORD);
+//     DWORD LoadModule(LPCSTR, LPVOID);
+//     UINT WinExec(LPCSTR, UINT);
+//     WINBOOL ClearCommBreak(HANDLE);
+//     WINBOOL ClearCommError(HANDLE, LPDWORD, LPCOMSTAT);
+//     WINBOOL SetupComm(HANDLE, DWORD, DWORD);
+//     WINBOOL EscapeCommFunction(HANDLE, DWORD);
+//     WINBOOL GetCommConfig(HANDLE, LPCOMMCONFIG, LPDWORD);
+//     WINBOOL GetCommProperties(HANDLE, LPCOMMPROP);
+//     WINBOOL GetCommModemStatus(HANDLE, PDWORD);
+//     WINBOOL GetCommState(HANDLE, PDCB);
+//     WINBOOL GetCommTimeouts(HANDLE, PCOMMTIMEOUTS);
+//     WINBOOL PurgeComm(HANDLE, DWORD);
+//     WINBOOL SetCommBreak(HANDLE);
+//     WINBOOL SetCommConfig(HANDLE, LPCOMMCONFIG, DWORD);
+//     WINBOOL SetCommMask(HANDLE, DWORD);
+//     WINBOOL SetCommState(HANDLE, TDCB*);
+//     WINBOOL SetCommTimeouts(HANDLE, TCOMMTIMEOUTS*);
+//     WINBOOL TransmitCommChar(HANDLE, char);
+//     WINBOOL WaitCommEvent(HANDLE, LPDWORD, LPOVERLAPPED);
+//     DWORD SetTapePosition(HANDLE, DWORD, DWORD, DWORD, DWORD, WINBOOL);
+//     DWORD GetTapePosition(HANDLE, DWORD, LPDWORD, LPDWORD, LPDWORD);
+//     DWORD PrepareTape(HANDLE, DWORD, WINBOOL);
+//     DWORD EraseTape(HANDLE, DWORD, WINBOOL);
+//     DWORD CreateTapePartition(HANDLE, DWORD, DWORD, DWORD);
+//     DWORD WriteTapemark(HANDLE, DWORD, DWORD, WINBOOL);
+//     DWORD GetTapeStatus(HANDLE);
+//     DWORD GetTapeParameters(HANDLE, DWORD, LPDWORD, LPVOID);
+//     DWORD SetTapeParameters(HANDLE, DWORD, LPVOID);
+//     WINBOOL Beep(DWORD, DWORD);
+//     int MulDiv(int, int, int);
+//     void GetSystemTime(LPSYSTEMTIME);
+//         void GetSystemTimeAsFileTime(FILETIME*);
+//     WINBOOL SetSystemTime(SYSTEMTIME*);
+//     void GetLocalTime(LPSYSTEMTIME);
+//     WINBOOL SetLocalTime(SYSTEMTIME*);
+//     void GetSystemInfo(LPSYSTEM_INFO);
+//     WINBOOL SystemTimeToTzSpecificLocalTime(LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
+//     DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION);
+//     WINBOOL SetTimeZoneInformation(TIME_ZONE_INFORMATION*);
+//     WINBOOL SystemTimeToFileTime(SYSTEMTIME*, LPFILETIME);
+//     WINBOOL FileTimeToLocalFileTime(FILETIME*, LPFILETIME);
+//     WINBOOL LocalFileTimeToFileTime(FILETIME*, LPFILETIME);
+//     WINBOOL FileTimeToSystemTime(FILETIME*, LPSYSTEMTIME);
+//     LONG CompareFileTime(FILETIME*, FILETIME*);
+//     WINBOOL FileTimeToDosDateTime(FILETIME*, LPWORD, LPWORD);
+//     WINBOOL DosDateTimeToFileTime(ushort, ushort, LPFILETIME);
+//     DWORD GetTickCount();
+//     WINBOOL SetSystemTimeAdjustment(DWORD, WINBOOL);
+//     WINBOOL GetSystemTimeAdjustment(PDWORD, PDWORD, PWINBOOL);
+//     WINBOOL CreatePipe(PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
+//     WINBOOL ConnectNamedPipe(HANDLE, LPOVERLAPPED);
+//     WINBOOL DisconnectNamedPipe(HANDLE);
+//     WINBOOL SetNamedPipeHandleState(HANDLE, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL GetNamedPipeInfo(HANDLE, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL PeekNamedPipe(HANDLE, LPVOID, DWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL TransactNamedPipe(HANDLE, LPVOID, DWORD, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
+//     WINBOOL GetMailslotInfo(HANDLE, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
+//     WINBOOL SetMailslotInfo(HANDLE, DWORD);
+//     LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD);
+//     WINBOOL FlushViewOfFile(LPCVOID, DWORD);
+//     WINBOOL UnmapViewOfFile(LPVOID);
+//     HFILE OpenFile(LPCSTR, LPOFSTRUCT, UINT);
+//     HFILE _lopen(LPCSTR, int);
+//     HFILE _lcreat(LPCSTR, int);
+//     UINT _lread(HFILE, LPVOID, UINT);
+//     UINT _lwrite(HFILE, LPCSTR, UINT);
+//     int _hread(HFILE, LPVOID, int);
+//     int _hwrite(HFILE, LPCSTR, int);
+//     HFILE _lclose(HFILE);
+//     LONG _llseek(HFILE, LONG, int);
+//     WINBOOL IsTextUnicode(LPVOID, int, LPINT);
+//     DWORD TlsAlloc();
+//     LPVOID TlsGetValue(DWORD);
+//     WINBOOL TlsSetValue(DWORD, LPVOID);
+//     WINBOOL TlsFree(DWORD);
+//     DWORD SleepEx(DWORD, WINBOOL);
+//     DWORD WaitForSingleObjectEx(HANDLE, DWORD, WINBOOL);
+//     DWORD WaitForMultipleObjectsEx(DWORD, HANDLE*, WINBOOL, DWORD, WINBOOL);
+//     WINBOOL ReadFileEx(HANDLE, LPVOID, DWORD, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE);
+//     WINBOOL WriteFileEx(HANDLE, LPCVOID, DWORD, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE);
+//     WINBOOL BackupRead(HANDLE, LPBYTE, DWORD, LPDWORD, WINBOOL, WINBOOL, LPVOID*);
+//     WINBOOL BackupSeek(HANDLE, DWORD, DWORD, LPDWORD, LPDWORD, LPVOID*);
+//     WINBOOL BackupWrite(HANDLE, LPBYTE, DWORD, LPDWORD, WINBOOL, WINBOOL, LPVOID*);
+//     WINBOOL SetProcessShutdownParameters(DWORD, DWORD);
+//     WINBOOL GetProcessShutdownParameters(LPDWORD, LPDWORD);
+//     void SetFileApisToOEM();
+//     void SetFileApisToANSI();
+//     WINBOOL AreFileApisANSI();
+//     WINBOOL CloseEventLog(HANDLE);
+//     WINBOOL DeregisterEventSource(HANDLE);
+//     WINBOOL NotifyChangeEventLog(HANDLE, HANDLE);
+//     WINBOOL GetNumberOfEventLogRecords(HANDLE, PDWORD);
+//     WINBOOL GetOldestEventLogRecord(HANDLE, PDWORD);
+//     WINBOOL DuplicateToken(HANDLE, SECURITY_IMPERSONATION_LEVEL, PHANDLE);
+//     WINBOOL GetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+//     WINBOOL ImpersonateNamedPipeClient(HANDLE);
+//     WINBOOL ImpersonateLoggedOnUser(HANDLE);
+//     WINBOOL ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL);
+//     WINBOOL RevertToSelf();
+//     WINBOOL SetThreadToken(PHANDLE, HANDLE);
+//     WINBOOL OpenProcessToken(HANDLE, DWORD, PHANDLE);
+//     WINBOOL OpenThreadToken(HANDLE, DWORD, WINBOOL, PHANDLE);
+//     WINBOOL GetTokenInformation(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD);
+//     WINBOOL SetTokenInformation(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD);
+//     WINBOOL AdjustTokenPrivileges(HANDLE, WINBOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
+//     WINBOOL AdjustTokenGroups(HANDLE, WINBOOL, PTOKEN_GROUPS, DWORD, PTOKEN_GROUPS, PDWORD);
+//     WINBOOL PrivilegeCheck(HANDLE, PPRIVILEGE_SET, LPBOOL);
+//     WINBOOL IsValidSid(PSID);
+//     WINBOOL EqualSid(PSID, PSID);
+//     WINBOOL EqualPrefixSid(PSID, PSID);
+//     DWORD GetSidLengthRequired(UCHAR);
+//     WINBOOL AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY, ubyte, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
+//     PVOID FreeSid(PSID);
+//     WINBOOL InitializeSid(PSID, PSID_IDENTIFIER_AUTHORITY, ubyte);
+//     PSID_IDENTIFIER_AUTHORITY GetSidIdentifierAuthority(PSID);
+//     PDWORD GetSidSubAuthority(PSID, DWORD);
+//     PUCHAR GetSidSubAuthorityCount(PSID);
+//     DWORD GetLengthSid(PSID);
+//     WINBOOL CopySid(DWORD, PSID, PSID);
+//     WINBOOL AreAllAccessesGranted(DWORD, DWORD);
+//     WINBOOL AreAnyAccessesGranted(DWORD, DWORD);
+//     void MapGenericMask(PDWORD);
+//     WINBOOL IsValidAcl(PACL);
+//     WINBOOL InitializeAcl(PACL, DWORD, DWORD);
+//     WINBOOL GetAclInformation(PACL, LPVOID, DWORD, ACL_INFORMATION_CLASS);
+//     WINBOOL SetAclInformation(PACL, LPVOID, DWORD, ACL_INFORMATION_CLASS);
+//     WINBOOL AddAce(PACL, DWORD, DWORD, LPVOID, DWORD);
+//     WINBOOL DeleteAce(PACL, DWORD);
+//     WINBOOL GetAce(PACL, DWORD, LPVOID*);
+//     WINBOOL AddAccessAllowedAce(PACL, DWORD, DWORD, PSID);
+//     WINBOOL AddAccessDeniedAce(PACL, DWORD, DWORD, PSID);
+//     WINBOOL AddAuditAccessAce(PACL, DWORD, DWORD, PSID, WINBOOL, WINBOOL);
+//     WINBOOL FindFirstFreeAce(PACL, LPVOID*);
+//     WINBOOL InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR, DWORD);
+//     WINBOOL IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
+//     DWORD GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR);
+//     WINBOOL GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR_CONTROL, LPDWORD);
+//     WINBOOL SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, WINBOOL, PACL, WINBOOL);
+//     WINBOOL GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR, LPBOOL, PACL*, LPBOOL);
+//     WINBOOL SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, WINBOOL, PACL, WINBOOL);
+//     WINBOOL GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR, LPBOOL, PACL*, LPBOOL);
+//     WINBOOL SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID, WINBOOL);
+//     WINBOOL GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR, PSID*, LPBOOL);
+//     WINBOOL SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID, WINBOOL);
+//     WINBOOL GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR, PSID*, LPBOOL);
+//     WINBOOL CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR*, WINBOOL, HANDLE, PGENERIC_MAPPING);
+//     WINBOOL SetPrivateObjectSecurity(SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR*, PGENERIC_MAPPING, HANDLE);
+//     WINBOOL GetPrivateObjectSecurity(PSECURITY_DESCRIPTOR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, PDWORD);
+//     WINBOOL DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR);
+//     WINBOOL MakeSelfRelativeSD(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD);
+//     WINBOOL MakeAbsoluteSD(PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD, PACL, LPDWORD, PACL, LPDWORD, PSID, LPDWORD, PSID, LPDWORD);
+//     WINBOOL SetKernelObjectSecurity(HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     WINBOOL FindNextChangeNotification(HANDLE);
+//     WINBOOL FindCloseChangeNotification(HANDLE);
+//     WINBOOL VirtualLock(LPVOID, DWORD);
+//     WINBOOL VirtualUnlock(LPVOID, DWORD);
+//     LPVOID MapViewOfFileEx(HANDLE, DWORD, DWORD, DWORD, DWORD, LPVOID);
+//     WINBOOL SetPriorityClass(HANDLE, DWORD);
+//     DWORD GetPriorityClass(HANDLE);
+//     WINBOOL IsBadReadPtr(POINTER, UINT);
+//     WINBOOL IsBadWritePtr(LPVOID, UINT);
+//     WINBOOL IsBadHugeReadPtr(POINTER, UINT);
+//     WINBOOL IsBadHugeWritePtr(LPVOID, UINT);
+//     WINBOOL IsBadCodePtr(FARPROC);
+//     WINBOOL AllocateLocallyUniqueId(PLUID);
+//     WINBOOL QueryPerformanceCounter(PLARGE_INTEGER);
+//     WINBOOL QueryPerformanceFrequency(PLARGE_INTEGER);
+//     WINBOOL ActivateKeyboardLayout(HKL, UINT);
+//     WINBOOL UnloadKeyboardLayout(HKL);
+//     int GetKeyboardLayoutList(int, HKL*);
+//     HKL GetKeyboardLayout(DWORD);
+//     HDESK OpenInputDesktop(DWORD, WINBOOL, DWORD);
+//     WINBOOL EnumDesktopWindows(HDESK, ENUMWINDOWSPROC, LPARAM);
+//     WINBOOL SwitchDesktop(HDESK);
+//     WINBOOL SetThreadDesktop(HDESK);
+//     WINBOOL CloseDesktop(HDESK);
+//     HDESK GetThreadDesktop(DWORD);
+//     WINBOOL CloseWindowStation(HWINSTA);
+//     WINBOOL SetProcessWindowStation(HWINSTA);
+//     HWINSTA GetProcessWindowStation();
+//     WINBOOL SetUserObjectSecurity(HANDLE, PSECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     WINBOOL GetUserObjectSecurity(HANDLE, PSECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+//     WINBOOL TranslateMessage(LPMSG);
+//     WINBOOL SetMessageQueue(int);
+//     WINBOOL RegisterHotKey(HWND, int, UINT, UINT);
+//     WINBOOL UnregisterHotKey(HWND, int);
+//     WINBOOL ExitWindowsEx(UINT, DWORD);
+//     WINBOOL SwapMouseButton(WINBOOL);
+//     DWORD GetMessagePos();
+//     LONG GetMessageTime();
+//     LONG GetMessageExtraInfo();
+//     LPARAM SetMessageExtraInfo(LPARAM);
+//     int BroadcastSystemMessage(DWORD, LPDWORD, UINT, WPARAM, LPARAM);
+//     WINBOOL AttachThreadInput(DWORD, DWORD, WINBOOL);
+//     WINBOOL ReplyMessage(LRESULT);
+//     WINBOOL WaitMessage();
+//     DWORD WaitForInputIdle(HANDLE, DWORD);
+//     void PostQuitMessage(int);
+//     WINBOOL InSendMessage();
+//     UINT GetDoubleClickTime();
+//     WINBOOL SetDoubleClickTime(UINT);
+//     WINBOOL IsWindow(HWND);
+//     WINBOOL IsMenu(HMENU);
+//     WINBOOL IsChild(HWND, HWND);
+//     WINBOOL DestroyWindow(HWND);
+    WINBOOL ShowWindow(HWND, int);
+//     WINBOOL ShowWindowAsync(HWND, int);
+//     WINBOOL FlashWindow(HWND, WINBOOL);
+//     WINBOOL ShowOwnedPopups(HWND, WINBOOL);
+//     WINBOOL OpenIcon(HWND);
+//     WINBOOL CloseWindow(HWND);
+//     WINBOOL MoveWindow(HWND, int, int, int, int, WINBOOL);
+//     WINBOOL SetWindowPos(HWND, HWND, int, int, int, int, UINT);
+//     WINBOOL GetWindowPlacement(HWND, WINDOWPLACEMENT*);
+//     WINBOOL SetWindowPlacement(HWND, WINDOWPLACEMENT*);
+//     HDWP BeginDeferWindowPos(int);
+//     HDWP DeferWindowPos(HDWP, HWND, HWND, int, int, int, int, UINT);
+//     WINBOOL EndDeferWindowPos(HDWP);
+//     WINBOOL IsWindowVisible(HWND);
+//     WINBOOL IsIconic(HWND);
+//     WINBOOL AnyPopup();
+//     WINBOOL BringWindowToTop(HWND);
+//     WINBOOL IsZoomed(HWND);
+//     WINBOOL EndDialog(HWND, int);
+    HWND GetDlgItem(HWND, int);
+//     WINBOOL SetDlgItemInt(HWND, int, UINT, WINBOOL);
+//     UINT GetDlgItemInt(HWND, int, WINBOOL*, WINBOOL);
+//     WINBOOL CheckDlgButton(HWND, int, UINT);
+//     WINBOOL CheckRadioButton(HWND, int, int, int);
+//     UINT IsDlgButtonChecked(HWND, int);
+//     HWND GetNextDlgGroupItem(HWND, HWND, WINBOOL);
+//     HWND GetNextDlgTabItem(HWND, HWND, WINBOOL);
+//     int GetDlgCtrlID(HWND);
+//     int GetDialogBaseUnits();
+//     WINBOOL OpenClipboard(HWND);
+//     WINBOOL CloseClipboard();
+//     HWND GetClipboardOwner();
+//     HWND SetClipboardViewer(HWND);
+//     HWND GetClipboardViewer();
+//     WINBOOL ChangeClipboardChain(HWND, HWND);
+//     HANDLE SetClipboardData(UINT, HANDLE);
+//     HANDLE GetClipboardData(UINT);
+//     int CountClipboardFormats();
+//     UINT EnumClipboardFormats(UINT);
+//     WINBOOL EmptyClipboard();
+//     WINBOOL IsClipboardFormatAvailable(UINT);
+//     int GetPriorityClipboardFormat(UINT*, int);
+//     HWND GetOpenClipboardWindow();
+//     LPSTR CharNextExA(ushort, LPCSTR, DWORD);
+//     LPSTR CharPrevExA(ushort, LPCSTR, LPCSTR, DWORD);
+    HWND SetFocus(HWND);
+//     HWND GetActiveWindow();
+    HWND GetFocus();
+//     UINT GetKBCodePage();
+//     SHORT GetKeyState(int);
+    SHORT GetAsyncKeyState(int);
+//     WINBOOL GetKeyboardState(PBYTE);
+//     WINBOOL SetKeyboardState(LPBYTE);
+//     int GetKeyboardType(int);
+//     int ToAscii(UINT, UINT, PBYTE, LPWORD, UINT);
+//     int ToAsciiEx(UINT, UINT, PBYTE, LPWORD, UINT, HKL);
+//     int ToUnicode(UINT, UINT, PBYTE, LPWSTR, int, UINT);
+//     DWORD OemKeyScan(ushort);
+//     void keybd_event(ubyte, ubyte, DWORD);
+//     void mouse_event(DWORD, DWORD, DWORD, DWORD);
+//     WINBOOL GetInputState();
+//     DWORD GetQueueStatus(UINT);
+//     HWND GetCapture();
+//     HWND SetCapture(HWND);
+//     WINBOOL ReleaseCapture();
+//     DWORD MsgWaitForMultipleObjects(DWORD, LPHANDLE, WINBOOL, DWORD, DWORD);
+//     UINT SetTimer(HWND, UINT, UINT, TIMERPROC);
+//     WINBOOL KillTimer(HWND, UINT);
+//     WINBOOL IsWindowUnicode(HWND);
+//     WINBOOL EnableWindow(HWND, WINBOOL);
+//     WINBOOL IsWindowEnabled(HWND);
+//     WINBOOL DestroyAcceleratorTable(HACCEL);
+//     int GetSystemMetrics(int);
+//     HMENU GetMenu(HWND);
+//     WINBOOL SetMenu(HWND, HMENU);
+//     WINBOOL HiliteMenuItem(HWND, HMENU, UINT, UINT);
+//     UINT GetMenuState(HMENU, UINT, UINT);
+//     WINBOOL DrawMenuBar(HWND);
+//     HMENU GetSystemMenu(HWND, WINBOOL);
+//     HMENU CreateMenu();
+//     HMENU CreatePopupMenu();
+//     WINBOOL DestroyMenu(HMENU);
+//     DWORD CheckMenuItem(HMENU, UINT, UINT);
+//     WINBOOL EnableMenuItem(HMENU, UINT, UINT);
+//     HMENU GetSubMenu(HMENU, int);
+//     UINT GetMenuItemID(HMENU, int);
+//     int GetMenuItemCount(HMENU);
+//     WINBOOL RemoveMenu(HMENU, UINT, UINT);
+//     WINBOOL DeleteMenu(HMENU, UINT, UINT);
+//     WINBOOL SetMenuItemBitmaps(HMENU, UINT, UINT, HBITMAP, HBITMAP);
+//     LONG GetMenuCheckMarkDimensions();
+    WINBOOL TrackPopupMenu(HMENU, UINT, int, int, int, HWND, RECT*);
+//     UINT GetMenuDefaultItem(HMENU, UINT, UINT);
+//     WINBOOL SetMenuDefaultItem(HMENU, UINT, UINT);
+//     WINBOOL GetMenuItemRect(HWND, HMENU, UINT, LPRECT);
+//     int MenuItemFromPoint(HWND, HMENU, POINT);
+//     DWORD DragObject(HWND, HWND, UINT, DWORD, HCURSOR);
+//     WINBOOL DragDetect(HWND, POINT);
+//     WINBOOL DrawIcon(HDC, int, int, HICON);
+    WINBOOL UpdateWindow(HWND);
+    HWND SetActiveWindow(HWND);
+//     HWND GetForegroundWindow();
+//     WINBOOL PaintDesktop(HDC);
+    WINBOOL SetForegroundWindow(HWND);
+    HWND WindowFromDC(HDC);
+    HDC GetDC(HWND);
+    HDC GetDCEx(HWND, HRGN, DWORD);
+    HDC GetWindowDC(HWND);
+    int ReleaseDC(HWND, HDC);
+    HDC BeginPaint(HWND, LPPAINTSTRUCT);
+    WINBOOL EndPaint(HWND, LPPAINTSTRUCT);
+    WINBOOL GetUpdateRect(HWND, LPRECT, WINBOOL);
+    int GetUpdateRgn(HWND, HRGN, WINBOOL);
+    int SetWindowRgn(HWND, HRGN, WINBOOL);
+    int GetWindowRgn(HWND, HRGN);
+//     int ExcludeUpdateRgn(HDC, HWND);
+    WINBOOL InvalidateRect(HWND, RECT*, WINBOOL);
+    WINBOOL ValidateRect(HWND, RECT*);
+    WINBOOL InvalidateRgn(HWND, HRGN, WINBOOL);
+//     WINBOOL ValidateRgn(HWND, HRGN);
+    WINBOOL RedrawWindow(HWND, RECT*, HRGN, UINT);
+//     WINBOOL LockWindowUpdate(HWND);
+//     WINBOOL ScrollWindow(HWND, int, int, RECT*, RECT*);
+//     WINBOOL ScrollDC(HDC, int, int, RECT*, RECT*, HRGN, LPRECT);
+    int ScrollWindowEx(HWND, int, int, RECT*, RECT*, HRGN, LPRECT, UINT);
+//     int SetScrollPos(HWND, int, int, WINBOOL);
+//     int GetScrollPos(HWND, int);
+//     WINBOOL SetScrollRange(HWND, int, int, int, WINBOOL);
+//     WINBOOL GetScrollRange(HWND, int, LPINT, LPINT);
+    WINBOOL ShowScrollBar(HWND, int, WINBOOL);
+    WINBOOL EnableScrollBar(HWND, UINT, UINT);
+    WINBOOL GetClientRect(HWND, LPRECT);
+    WINBOOL GetWindowRect(HWND, LPRECT);
+//     WINBOOL AdjustWindowRect(LPRECT, DWORD, WINBOOL);
+//     WINBOOL AdjustWindowRectEx(LPRECT, DWORD, WINBOOL, DWORD);
+//     WINBOOL SetWindowContextHelpId(HWND, DWORD);
+//     DWORD GetWindowContextHelpId(HWND);
+//     WINBOOL SetMenuContextHelpId(HMENU, DWORD);
+//     DWORD GetMenuContextHelpId(HMENU);
+//     WINBOOL MessageBeep(UINT);
+//     int ShowCursor(WINBOOL);
+    WINBOOL SetCursorPos(int, int);
+    HCURSOR SetCursor(HCURSOR);
+//     WINBOOL GetCursorPos(LPPOINT);
+//     WINBOOL ClipCursor(RECT*);
+//     WINBOOL GetClipCursor(LPRECT);
+//     HCURSOR GetCursor();
+    WINBOOL CreateCaret(HWND, HBITMAP, int, int);
+//     UINT GetCaretBlinkTime();
+//     WINBOOL SetCaretBlinkTime(UINT);
+//     WINBOOL DestroyCaret();
+    WINBOOL HideCaret(HWND);
+    WINBOOL ShowCaret(HWND);
+//     WINBOOL SetCaretPos(int, int);
+//     WINBOOL GetCaretPos(LPPOINT);
+    WINBOOL ClientToScreen(HWND, LPPOINT);
+    WINBOOL ScreenToClient(HWND, LPPOINT);
+    int MapWindowPoints(HWND, HWND, LPPOINT, UINT);
+    HWND WindowFromPoint(POINT);
+//     HWND ChildWindowFromPoint(HWND, POINT);
+//     DWORD GetSysColor(int);
+//     HBRUSH GetSysColorBrush(int);
+//     WINBOOL SetSysColors(int, WINT*, COLORREF*);
+//     WINBOOL DrawFocusRect(HDC, RECT*);
+    int FillRect(HDC, RECT*, HBRUSH);
+//     int FrameRect(HDC, RECT*, HBRUSH);
+//     WINBOOL InvertRect(HDC, RECT*);
+//     WINBOOL SetRect(LPRECT, int, int, int, int);
+//     WINBOOL SetRectEmpty(LPRECT);
+//     WINBOOL CopyRect(LPRECT, RECT*);
+//     WINBOOL InflateRect(LPRECT, int, int);
+//     WINBOOL IntersectRect(LPRECT, RECT*, RECT*);
+//     WINBOOL UnionRect(LPRECT, RECT*, RECT*);
+//     WINBOOL SubtractRect(LPRECT, RECT*, RECT*);
+    WINBOOL OffsetRect(LPRECT, int, int);
+//     WINBOOL IsRectEmpty(RECT*);
+//     WINBOOL EqualRect(RECT*, RECT*);
+//     WINBOOL PtInRect(RECT*, POINT);
+//     ushort GetWindowWord(HWND, int);
+//     ushort SetWindowWord(HWND, int, ushort);
+//     ushort GetClassWord(HWND, int);
+//     ushort SetClassWord(HWND, int, ushort);
+//     HWND GetDesktopWindow();
+//     HWND GetParent(HWND);
+//     HWND SetParent(HWND, HWND);
+//     WINBOOL EnumChildWindows(HWND, ENUMWINDOWSPROC, LPARAM);
+//     WINBOOL EnumWindows(ENUMWINDOWSPROC, LPARAM);
+//     WINBOOL EnumThreadWindows(DWORD, ENUMWINDOWSPROC, LPARAM);
+//     HWND GetTopWindow(HWND);
+//     DWORD GetWindowThreadProcessId(HWND, LPDWORD);
+//     HWND GetLastActivePopup(HWND);
+//     HWND GetWindow(HWND, UINT);
+//     WINBOOL UnhookWindowsHook(int, HOOKPROC);
+//     WINBOOL UnhookWindowsHookEx(HHOOK);
+//     LRESULT CallNextHookEx(HHOOK, int, WPARAM, LPARAM);
+//     WINBOOL CheckMenuRadioItem(HMENU, UINT, UINT, UINT, UINT);
+//     HCURSOR CreateCursor(HINST, int, int, int, int, POINTER, POINTER);
+//     WINBOOL DestroyCursor(HCURSOR);
+//     WINBOOL SetSystemCursor(HCURSOR, DWORD);
+//     HICON CreateIcon(HINST, int, int, ubyte, ubyte, ubyte*, ubyte*);
+//     WINBOOL DestroyIcon(HICON);
+//     int LookupIconIdFromDirectory(PBYTE, WINBOOL);
+//     int LookupIconIdFromDirectoryEx(PBYTE, WINBOOL, int, int, UINT);
+//     HICON CreateIconFromResource(PBYTE, DWORD, WINBOOL, DWORD);
+//     HICON CreateIconFromResourceEx(PBYTE, DWORD, WINBOOL, DWORD, int, int, UINT);
+//     HICON CopyImage(HANDLE, UINT, int, int, UINT);
+//     HICON CreateIconIndirect(PICONINFO);
+//     HICON CopyIcon(HICON);
+//     WINBOOL GetIconInfo(HICON, PICONINFO);
+//     WINBOOL MapDialogRect(HWND, LPRECT);
+//     int SetScrollInfo(HWND, int, LPCSCROLLINFO, WINBOOL);
+//     WINBOOL GetScrollInfo(HWND, int, LPSCROLLINFO);
+//     WINBOOL TranslateMDISysAccel(HWND, LPMSG);
+//     UINT ArrangeIconicWindows(HWND);
+//     ushort TileWindows(HWND, UINT, RECT*, UINT, HWND*);
+//     ushort CascadeWindows(HWND, UINT, RECT*, UINT, HWND*);
+//     void SetLastErrorEx(DWORD);
+//     void SetDebugErrorLevel(DWORD);
+//     WINBOOL DrawEdge(HDC, LPRECT, UINT, UINT);
+//     WINBOOL DrawFrameControl(HDC, LPRECT, UINT, UINT);
+//     WINBOOL DrawCaption(HWND, HDC, RECT*, UINT);
+//     WINBOOL DrawAnimatedRects(HWND, int, RECT*, RECT*);
+//     WINBOOL TrackPopupMenuEx(HMENU, UINT, int, int, HWND, LPTPMPARAMS);
+//     HWND ChildWindowFromPointEx(HWND, POINT, UINT);
+//     WINBOOL DrawIconEx(HDC, int, int, HICON, int, int, UINT, HBRUSH, UINT);
+//     WINBOOL AnimatePalette(HPALETTE, UINT, UINT, PALETTEENTRY*);
+//     WINBOOL Arc(HDC, int, int, int, int, int, int, int, int);
+//     WINBOOL BitBlt(HDC, int, int, int, int, HDC, int, int, DWORD);
+//     WINBOOL CancelDC(HDC);
+//     WINBOOL Chord(HDC, int, int, int, int, int, int, int, int);
+    HMETAFILE CloseMetaFile(HDC);
+//     int CombineRgn(HRGN, HRGN, HRGN, int);
+//     HBITMAP CreateBitmap(int, int, UINT, UINT, POINTER);
+//     HBITMAP CreateBitmapIndirect(BITMAP*);
+//     HBRUSH CreateBrushIndirect(LOGBRUSH*);
+//     HBITMAP CreateCompatibleBitmap(HDC, int, int);
+//     HBITMAP CreateDiscardableBitmap(HDC, int, int);
+    HDC CreateCompatibleDC(HDC);
+//     HBITMAP CreateDIBitmap(HDC, BITMAPINFOHEADER*, DWORD, POINTER, BITMAPINFO*, UINT);
+//     HBRUSH CreateDIBPatternBrush(HGLOBAL, UINT);
+//     HBRUSH CreateDIBPatternBrushPt(POINTER, UINT);
+//     HRGN CreateEllipticRgn(int, int, int, int);
+//     HRGN CreateEllipticRgnIndirect(RECT*);
+//     HBRUSH CreateHatchBrush(int, COLORREF);
+//     HPALETTE CreatePalette(LOGPALETTE*);
+    HPEN CreatePen(int, int, COLORREF);
+//     HPEN CreatePenIndirect(LOGPEN*);
+//     HRGN CreatePolyPolygonRgn(POINT*, WINT*, int, int);
+//     HBRUSH CreatePatternBrush(HBITMAP);
+    HRGN CreateRectRgn(int, int, int, int);
+//     HRGN CreateRectRgnIndirect(RECT*);
+//     HRGN CreateRoundRectRgn(int, int, int, int, int, int);
+//     HBRUSH CreateSolidBrush(COLORREF);
+    WINBOOL DeleteDC(HDC);
+//     WINBOOL DeleteMetaFile(HMETAFILE);
+    WINBOOL DeleteObject(HGDIOBJ);
+//     int DrawEscape(HDC, int, int, LPCSTR);
+//     WINBOOL Ellipse(HDC, int, int, int, int);
+//     int EnumObjects(HDC, int, ENUMOBJECTSPROC, LPARAM);
+//     WINBOOL EqualRgn(HRGN, HRGN);
+//     int Escape(HDC, int, int, LPCSTR, LPVOID);
+//     int ExtEscape(HDC, int, int, LPCSTR, int, LPSTR);
+    int ExcludeClipRect(HDC, int, int, int, int);
+    HRGN ExtCreateRegion(XFORM*, DWORD, RGNDATA*);
+//     WINBOOL ExtFloodFill(HDC, int, int, COLORREF, UINT);
+//     WINBOOL FillRgn(HDC, HRGN, HBRUSH);
+//     WINBOOL FloodFill(HDC, int, int, COLORREF);
+//     WINBOOL FrameRgn(HDC, HRGN, HBRUSH, int, int);
+//     int GetROP2(HDC);
+//     WINBOOL GetAspectRatioFilterEx(HDC, LPSIZE);
+//     COLORREF GetBkColor(HDC);
+//     int GetBkMode(HDC);
+//     LONG GetBitmapBits(HBITMAP, LONG, LPVOID);
+//     WINBOOL GetBitmapDimensionEx(HBITMAP, LPSIZE);
+//     UINT GetBoundsRect(HDC, LPRECT, UINT);
+//     WINBOOL GetBrushOrgEx(HDC, LPPOINT);
+    int GetClipBox(HDC, LPRECT);
+    int GetClipRgn(HDC, HRGN);
+    int GetMetaRgn(HDC, HRGN);
+    HGDIOBJ GetCurrentObject(HDC, UINT);
+//     WINBOOL GetCurrentPositionEx(HDC, LPPOINT);
+    int GetDeviceCaps(HDC, int);
+//     int GetDIBits(HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT);
+//     DWORD GetFontData(HDC, DWORD, DWORD, LPVOID, DWORD);
+//     int GetGraphicsMode(HDC);
+//     int GetMapMode(HDC);
+//     UINT GetMetaFileBitsEx(HMETAFILE, UINT, LPVOID);
+//     COLORREF GetNearestColor(HDC, COLORREF);
+//     UINT GetNearestPaletteIndex(HPALETTE, COLORREF);
+//     DWORD GetObjectType(HGDIOBJ);
+//     UINT GetPaletteEntries(HPALETTE, UINT, UINT, LPPALETTEENTRY);
+//     COLORREF GetPixel(HDC, int, int);
+//     int GetPixelFormat(HDC);
+    int GetPolyFillMode(HDC);
+//     WINBOOL GetRasterizerCaps(LPRASTERIZER_STATUS, UINT);
+//     DWORD GetRegionData(HRGN, DWORD, LPRGNDATA);
+//     int GetRgnBox(HRGN, LPRECT);
+    HGDIOBJ GetStockObject(int);
+//     int GetStretchBltMode(HDC);
+//     UINT GetSystemPaletteEntries(HDC, UINT, UINT, LPPALETTEENTRY);
+//     UINT GetSystemPaletteUse(HDC);
+//     int GetTextCharacterExtra(HDC);
+//     UINT GetTextAlign(HDC);
+//     COLORREF GetTextColor(HDC);
+//     int GetTextCharset(HDC);
+//     int GetTextCharsetInfo(HDC, LPFONTSIGNATURE, DWORD);
+//     WINBOOL TranslateCharsetInfo(DWORD*, LPCHARSETINFO, DWORD);
+//     DWORD GetFontLanguageInfo(HDC);
+//     WINBOOL GetViewportExtEx(HDC, LPSIZE);
+//     WINBOOL GetViewportOrgEx(HDC, LPPOINT);
+//     WINBOOL GetWindowExtEx(HDC, LPSIZE);
+    WINBOOL GetWindowOrgEx(HDC, LPPOINT);
+//     int IntersectClipRect(HDC, int, int, int, int);
+//     WINBOOL InvertRgn(HDC, HRGN);
+//     WINBOOL LineDDA(int, int, int, int, LINEDDAPROC, LPARAM);
+    WINBOOL LineTo(HDC, int, int);
+//     WINBOOL MaskBlt(HDC, int, int, int, int, HDC, int, int, HBITMAP, int, int, DWORD);
+//     WINBOOL PlgBlt(HDC, POINT*, HDC, int, int, int, int, HBITMAP, int, int);
+//     int OffsetClipRgn(HDC, int, int);
+//     int OffsetRgn(HRGN, int, int);
+//     WINBOOL PatBlt(HDC, int, int, int, int, DWORD);
+//     WINBOOL Pie(HDC, int, int, int, int, int, int, int, int);
+//     WINBOOL PlayMetaFile(HDC, HMETAFILE);
+//     WINBOOL PaintRgn(HDC, HRGN);
+//     WINBOOL PolyPolygon(HDC, POINT*, WINT*, int);
+//     WINBOOL PtInRegion(HRGN, int, int);
+//     WINBOOL PtVisible(HDC, int, int);
+//     WINBOOL RectInRegion(HRGN, RECT*);
+//     WINBOOL RectVisible(HDC, RECT*);
+//     WINBOOL Rectangle(HDC, int, int, int, int);
+//     WINBOOL RestoreDC(HDC, int);
+//     UINT RealizePalette(HDC);
+    WINBOOL RoundRect(HDC, int, int, int, int, int, int);
+//     WINBOOL ResizePalette(HPALETTE, UINT);
+    int SaveDC(HDC);
+    int SelectClipRgn(HDC, HRGN);
+//     int ExtSelectClipRgn(HDC, HRGN, int);
+    int SetMetaRgn(HDC);
+    HGDIOBJ SelectObject(HDC, HGDIOBJ);
+    HPALETTE SelectPalette(HDC, HPALETTE, WINBOOL);
+    COLORREF SetBkColor(HDC, COLORREF);
+    int SetBkMode(HDC, int);
+//     LONG SetBitmapBits(HBITMAP, DWORD, POINTER);
+//     UINT SetBoundsRect(HDC, RECT*, UINT);
+//     int SetDIBits(HDC, HBITMAP, UINT, UINT, POINTER, PBITMAPINFO, UINT);
+//     int SetDIBitsToDevice(HDC, int, int, DWORD, DWORD, int, int, UINT, UINT, POINTER, BITMAPINFO*, UINT);
+//     DWORD SetMapperFlags(HDC, DWORD);
+    int SetGraphicsMode(HDC, int);
+//     int SetMapMode(HDC, int);
+//     HMETAFILE SetMetaFileBitsEx(UINT, ubyte*);
+//     UINT SetPaletteEntries(HPALETTE, UINT, UINT, PALETTEENTRY*);
+    COLORREF SetPixel(HDC, int, int, COLORREF);
+//     WINBOOL SetPixelV(HDC, int, int, COLORREF);
+    int SetPolyFillMode(HDC, int);
+    WINBOOL StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD);
+    WINBOOL SetRectRgn(HRGN, int, int, int, int);
+//     int StretchDIBits(HDC, int, int, int, int, int, int, int, int, POINTER, BITMAPINFO*, UINT, DWORD);
+    int SetROP2(HDC, int);
+    int SetStretchBltMode(HDC, int);
+//     UINT SetSystemPaletteUse(HDC, UINT);
+//     int SetTextCharacterExtra(HDC, int);
+    COLORREF SetTextColor(HDC, COLORREF);
+    UINT SetTextAlign(HDC, UINT);
+//     WINBOOL SetTextJustification(HDC, int, int);
+//     WINBOOL UpdateColors(HDC);
+//     WINBOOL PlayMetaFileRecord(HDC, LPHANDLETABLE, LPMETARECORD, UINT);
+//     WINBOOL EnumMetaFile(HDC, HMETAFILE, ENUMMETAFILEPROC, LPARAM);
+    HENHMETAFILE CloseEnhMetaFile(HDC);
+    WINBOOL DeleteEnhMetaFile(HENHMETAFILE);
+    WINBOOL EnumEnhMetaFile(HDC, HENHMETAFILE, ENHMETAFILEPROC, LPVOID, RECT*);
+//     UINT GetEnhMetaFileHeader(HENHMETAFILE, UINT, LPENHMETAHEADER);
+//     UINT GetEnhMetaFilePaletteEntries(HENHMETAFILE, UINT, LPPALETTEENTRY);
+//     UINT GetWinMetaFileBits(HENHMETAFILE, UINT, LPBYTE, WINT, HDC);
+//     WINBOOL PlayEnhMetaFile(HDC, HENHMETAFILE, RECT*);
+//     WINBOOL PlayEnhMetaFileRecord(HDC, LPHANDLETABLE, ENHMETARECORD*, UINT);
+//     HENHMETAFILE SetEnhMetaFileBits(UINT, ubyte*);
+//     HENHMETAFILE SetWinMetaFileBits(UINT, ubyte*, HDC, METAFILEPICT*);
+//     WINBOOL GdiComment(HDC, UINT, ubyte*);
+//     WINBOOL AngleArc(HDC, int, int, DWORD, FLOAT, FLOAT);
+//     WINBOOL PolyPolyline(HDC, POINT*, DWORD*, DWORD);
+//     WINBOOL GetWorldTransform(HDC, LPXFORM);
+    WINBOOL SetWorldTransform(HDC, XFORM*);
+//     WINBOOL ModifyWorldTransform(HDC, XFORM*, DWORD);
+//     WINBOOL CombineTransform(LPXFORM, XFORM*, XFORM*);
+//     HBITMAP CreateDIBSection(HDC, BITMAPINFO*, UINT, POINTER*, HANDLE, DWORD);
+//     UINT GetDIBColorTable(HDC, UINT, UINT, RGBQUAD*);
+//     UINT SetDIBColorTable(HDC, UINT, UINT, RGBQUAD*);
+//     WINBOOL SetColorAdjustment(HDC, COLORADJUSTMENT*);
+//     WINBOOL GetColorAdjustment(HDC, LPCOLORADJUSTMENT);
+//     HPALETTE CreateHalftonePalette(HDC);
+//     int EndDoc(HDC);
+//     int StartPage(HDC);
+//     int EndPage(HDC);
+//     int AbortDoc(HDC);
+//     int SetAbortProc(HDC, TABORTPROC);
+//     WINBOOL ArcTo(HDC, int, int, int, int, int, int, int, int);
+    WINBOOL BeginPath(HDC);
+//     WINBOOL CloseFigure(HDC);
+    WINBOOL EndPath(HDC);
+//     WINBOOL FillPath(HDC);
+//     WINBOOL FlattenPath(HDC);
+    int GetPath(HDC, LPPOINT, LPBYTE, int);
+//     HRGN PathToRegion(HDC);
+//     WINBOOL PolyDraw(HDC, POINT*, ubyte*, int);
+//     WINBOOL SelectClipPath(HDC, int);
+//     int SetArcDirection(HDC, int);
+//     WINBOOL SetMiterLimit(HDC, FLOAT, PFLOAT);
+//     WINBOOL StrokeAndFillPath(HDC);
+//     WINBOOL StrokePath(HDC);
+//     WINBOOL WidenPath(HDC);
+    HPEN ExtCreatePen(DWORD, DWORD, LOGBRUSH*, DWORD, DWORD*);
+//     WINBOOL GetMiterLimit(HDC, PFLOAT);
+//     int GetArcDirection(HDC);
+    WINBOOL MoveToEx(HDC, int, int, LPPOINT);
+//     HRGN CreatePolygonRgn(POINT*, int, int);
+//     WINBOOL DPtoLP(HDC, LPPOINT, int);
+//     WINBOOL LPtoDP(HDC, LPPOINT, int);
+//     WINBOOL Polygon(HDC, POINT*, int);
+//     WINBOOL Polyline(HDC, POINT*, int);
+//     WINBOOL PolyBezier(HDC, POINT*, DWORD);
+//     WINBOOL PolyBezierTo(HDC, POINT*, DWORD);
+//     WINBOOL PolylineTo(HDC, POINT*, DWORD);
+//     WINBOOL SetViewportExtEx(HDC, int, int, LPSIZE);
+//     WINBOOL SetViewportOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL SetWindowExtEx(HDC, int, int, LPSIZE);
+    WINBOOL SetWindowOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL OffsetViewportOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL OffsetWindowOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL ScaleViewportExtEx(HDC, int, int, int, int, LPSIZE);
+//     WINBOOL ScaleWindowExtEx(HDC, int, int, int, int, LPSIZE);
+//     WINBOOL SetBitmapDimensionEx(HBITMAP, int, int, LPSIZE);
+    WINBOOL SetBrushOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL GetDCOrgEx(HDC, LPPOINT);
+//     WINBOOL FixBrushOrgEx(HDC, int, int, LPPOINT);
+//     WINBOOL UnrealizeObject(HGDIOBJ);
+//     WINBOOL GdiFlush();
+//     DWORD GdiSetBatchLimit(DWORD);
+//     DWORD GdiGetBatchLimit();
+//     int SetICMMode(HDC, int);
+//     WINBOOL CheckColorsInGamut(HDC, LPVOID, LPVOID, DWORD);
+//     HANDLE GetColorSpace(HDC);
+//     WINBOOL SetColorSpace(HDC, HCOLORSPACE);
+//     WINBOOL DeleteColorSpace(HCOLORSPACE);
+//     WINBOOL GetDeviceGammaRamp(HDC, LPVOID);
+//     WINBOOL SetDeviceGammaRamp(HDC, LPVOID);
+//     WINBOOL ColorMatchToTarget(HDC, HDC, DWORD);
+//     HPROPSHEETPAGE CreatePropertySheetPageA(LPCPROPSHEETPAGE);
+//     WINBOOL DestroyPropertySheetPage(HPROPSHEETPAGE);
+//     void InitCommonControls();
+//     HIMAGELIST ImageList_Create(int, int, UINT, int, int);
+//     WINBOOL ImageList_Destroy(HIMAGELIST);
+//     int ImageList_GetImageCount(HIMAGELIST);
+//     int ImageList_Add(HIMAGELIST, HBITMAP, HBITMAP);
+//     int ImageList_ReplaceIcon(HIMAGELIST, int, HICON);
+//     COLORREF ImageList_SetBkColor(HIMAGELIST, COLORREF);
+//     COLORREF ImageList_GetBkColor(HIMAGELIST);
+//     WINBOOL ImageList_SetOverlayImage(HIMAGELIST, int, int);
+    WINBOOL ImageList_Draw(HIMAGELIST, int, HDC, int, int, UINT);
+//     WINBOOL ImageList_Replace(HIMAGELIST, int, HBITMAP, HBITMAP);
+//     int ImageList_AddMasked(HIMAGELIST, HBITMAP, COLORREF);
+//     WINBOOL ImageList_DrawEx(HIMAGELIST, int, HDC, int, int, int, int, COLORREF, COLORREF, UINT);
+//     WINBOOL ImageList_Remove(HIMAGELIST, int);
+//     HICON ImageList_GetIcon(HIMAGELIST, int, UINT);
+    WINBOOL ImageList_BeginDrag(HIMAGELIST, int, int, int);
+    void ImageList_EndDrag();
+    WINBOOL ImageList_DragEnter(HWND, int, int);
+    WINBOOL ImageList_DragLeave(HWND);
+    WINBOOL ImageList_DragMove(int, int);
+//     WINBOOL ImageList_SetDragCursorImage(HIMAGELIST, int, int, int);
+    WINBOOL ImageList_DragShowNolock(WINBOOL);
+//     HIMAGELIST ImageList_GetDragImage(POINT*, POINT*);
+//     WINBOOL ImageList_GetIconSize(HIMAGELIST, int*, int*);
+//     WINBOOL ImageList_SetIconSize(HIMAGELIST, int, int);
+//     WINBOOL ImageList_GetImageInfo(HIMAGELIST, int, IMAGEINFO*);
+//     HIMAGELIST ImageList_Merge(HIMAGELIST, int, HIMAGELIST, int, int, int);
+//     HWND CreateToolbarEx(HWND, DWORD, UINT, int, HINST, UINT, LPCTBBUTTON, int, int, int, int, int, UINT);
+//     HBITMAP CreateMappedBitmap(HINST, int, UINT, LPCOLORMAP, int);
+//     void MenuHelp(UINT, WPARAM, LPARAM, HMENU, HINST, HWND);
+//     WINBOOL ShowHideMenuCtl(HWND, UINT, LPINT);
+//     void GetEffectiveClientRect(HWND, LPRECT);
+//     WINBOOL MakeDragList(HWND);
+//     void DrawInsert(HWND, HWND);
+//     int LBItemFromPt(HWND, POINT, WINBOOL);
+//     HWND CreateUpDownControl(DWORD, int, int, int, int, HWND, int, HINST, HWND, int, int, int);
+//     LONG RegCloseKey(HKEY);
+//     LONG RegSetKeySecurity(HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     LONG RegFlushKey(HKEY);
+//     LONG RegGetKeySecurity(HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, LPDWORD);
+//     LONG RegNotifyChangeKeyValue(HKEY, WINBOOL, DWORD, HANDLE, WINBOOL);
+//     WINBOOL IsValidCodePage(UINT);
+//     UINT GetACP();
+//     UINT GetOEMCP();
+//     WINBOOL GetCPInfo(UINT, LPCPINFO);
+//     WINBOOL IsDBCSLeadByte(ubyte);
+//     WINBOOL IsDBCSLeadByteEx(UINT, ubyte);
+    int MultiByteToWideChar(UINT, DWORD, LPCSTR, int, LPWSTR, int);
+    int WideCharToMultiByte(UINT, DWORD, LPCWSTR, int, LPSTR, int, LPCSTR, LPBOOL);
+//     WINBOOL IsValidLocale(LCID, DWORD);
+//     LCID ConvertDefaultLocale(LCID);
+//     LCID GetThreadLocale();
+//     WINBOOL SetThreadLocale(LCID);
+//     LANGID GetSystemDefaultLangID();
+//     LANGID GetUserDefaultLangID();
+//     LCID GetSystemDefaultLCID();
+//     LCID GetUserDefaultLCID();
+//     WINBOOL ReadConsoleOutputAttribute(HANDLE, LPWORD, DWORD, COORD, LPDWORD);
+//     WINBOOL WriteConsoleOutputAttribute(HANDLE, ushort*, DWORD, COORD, LPDWORD);
+//     WINBOOL FillConsoleOutputAttribute(HANDLE, ushort, DWORD, COORD, LPDWORD);
+//     WINBOOL GetConsoleMode(HANDLE, LPDWORD);
+//     WINBOOL GetNumberOfConsoleInputEvents(HANDLE, PDWORD);
+//     WINBOOL GetConsoleScreenBufferInfo(HANDLE, PCONSOLE_SCREEN_BUFFER_INFO);
+//     COORD GetLargestConsoleWindowSize(HANDLE);
+//     WINBOOL GetConsoleCursorInfo(HANDLE, PCONSOLE_CURSOR_INFO);
+//     WINBOOL GetNumberOfConsoleMouseButtons(LPDWORD);
+//     WINBOOL SetConsoleMode(HANDLE, DWORD);
+//     WINBOOL SetConsoleActiveScreenBuffer(HANDLE);
+//     WINBOOL FlushConsoleInputBuffer(HANDLE);
+//     WINBOOL SetConsoleScreenBufferSize(HANDLE, COORD);
+//     WINBOOL SetConsoleCursorPosition(HANDLE, COORD);
+//     WINBOOL SetConsoleCursorInfo(HANDLE, PCONSOLE_CURSOR_INFO);
+//     WINBOOL SetConsoleWindowInfo(HANDLE, WINBOOL, SMALL_RECT*);
+//     WINBOOL SetConsoleTextAttribute(HANDLE, ushort);
+//     WINBOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE, WINBOOL);
+//     WINBOOL GenerateConsoleCtrlEvent(DWORD, DWORD);
+//     WINBOOL AllocConsole();
+//     WINBOOL FreeConsole();
+//     HANDLE CreateConsoleScreenBuffer(DWORD, DWORD, SECURITY_ATTRIBUTES*, DWORD, LPVOID);
+//     UINT GetConsoleCP();
+//     WINBOOL SetConsoleCP(UINT);
+//     UINT GetConsoleOutputCP();
+//     WINBOOL SetConsoleOutputCP(UINT);
+//     DWORD WNetConnectionDialog(HWND, DWORD);
+//     DWORD WNetDisconnectDialog(HWND, DWORD);
+//     DWORD WNetCloseEnum(HANDLE);
+//     WINBOOL CloseServiceHandle(SC_HANDLE);
+//     WINBOOL ControlService(SC_HANDLE, DWORD, LPSERVICE_STATUS);
+//     WINBOOL DeleteService(SC_HANDLE);
+//     SC_LOCK LockServiceDatabase(SC_HANDLE);
+//     WINBOOL NotifyBootConfigStatus(WINBOOL);
+//     WINBOOL QueryServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
+//     WINBOOL QueryServiceStatus(SC_HANDLE, LPSERVICE_STATUS);
+//     WINBOOL SetServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+//     WINBOOL SetServiceStatus(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS);
+//     WINBOOL UnlockServiceDatabase(SC_LOCK);
+//     int ChoosePixelFormat(HDC, PIXELFORMATDESCRIPTOR*);
+//     int DescribePixelFormat(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+//     WINBOOL SetPixelFormat(HDC, int, PPIXELFORMATDESCRIPTOR);
+//     WINBOOL SwapBuffers(HDC);
+//     WINBOOL DragQueryPoint(HDROP, LPPOINT);
+//     void DragFinish(HDROP);
+//     void DragAcceptFiles(HWND, BOOL);
+//     HICON DuplicateIcon(HINST, HICON);
+//     BOOL DdeAbandonTransaction(DWORD, HCONV, DWORD);
+//     PBYTE DdeAccessData(HDDEDATA, PDWORD);
+//     HDDEDATA DdeAddData(HDDEDATA, PBYTE, DWORD, DWORD);
+//     HDDEDATA DdeClientTransaction(PBYTE, DWORD, HCONV, HSZ, UINT, UINT, DWORD, PDWORD);
+//     int DdeCmpStringHandles(HSZ, HSZ);
+//     HCONV DdeConnect(DWORD, HSZ, HSZ, CONVCONTEXT*);
+//     HCONVLIST DdeConnectList(DWORD, HSZ, HSZ, HCONVLIST, PCONVCONTEXT);
+//     HDDEDATA DdeCreateDataHandle(DWORD, LPBYTE, DWORD, DWORD, HSZ, UINT, UINT);
+//     WINBOOL DdeDisconnect(HCONV);
+//     BOOL DdeDisconnectList(HCONVLIST);
+//     BOOL DdeEnableCallback(DWORD, HCONV, UINT);
+//     WINBOOL DdeFreeDataHandle(HDDEDATA);
+//     WINBOOL DdeFreeStringHandle(DWORD, HSZ);
+//     DWORD DdeGetData(HDDEDATA, ubyte*, DWORD, DWORD);
+//     UINT DdeGetLastError(DWORD);
+//     BOOL DdeImpersonateClient(HCONV);
+//     BOOL DdeKeepStringHandle(DWORD, HSZ);
+//     HDDEDATA DdeNameService(DWORD, HSZ, HSZ, UINT);
+//     WINBOOL DdePostAdvise(DWORD, HSZ, HSZ);
+//     UINT DdeQueryConvInfo(HCONV, DWORD, PCONVINFO);
+//     HCONV DdeQueryNextServer(HCONVLIST, HCONV);
+//     HCONV DdeReconnect(HCONV);
+//     BOOL DdeSetUserHandle(HCONV, DWORD, DWORD);
+//     BOOL DdeUnaccessData(HDDEDATA);
+//     WINBOOL DdeUninitialize(DWORD);
+//     void SHAddToRecentDocs(UINT);
+//     LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO);
+//     void SHChangeNotify(LONG, UINT, LPCVOID);
+//     int SHFileOperation(LPSHFILEOPSTRUCT);
+//     void SHFreeNameMappings(HANDLE);
+    DWORD SHGetFileInfo(LPCTSTR, DWORD, SHFILEINFO*, UINT, UINT);
+//     WINBOOL SHGetPathFromIDList(LPCITEMIDLIST, LPTSTR);
+//     HRESULT SHGetSpecialFolderLocation(HWND, int, LPITEMIDLIST*);
+//     THANDLE CreateThread(POINTER, DWORD, TFNTHREADSTARTROUTINE, POINTER, DWORD, DWORD*);
+//     BOOL DdeSetQualityOfService(HWND, TSECURITYQUALITYOFSERVICE*, PSECURITYQUALITYOFSERVICE);
+//     BOOL GetCommMask(THANDLE, DWORD*);
+//     BOOL GetDiskFreeSpaceExA(LPCSTR, void*, void*, PLARGEINTEGER);
+//     BOOL GetDiskFreeSpaceExW(LPWSTR, void*, void*, PLARGEINTEGER);
+//     DWORD GetKerningPairs(HDC, DWORD, void*);
+//     BOOL GetOverlappedResult(THANDLE, TOVERLAPPED*, DWORD*, BOOL);
+//     BOOL GetQueuedCompletionStatus(THANDLE, DWORD*, DWORD*, POVERLAPPED*, DWORD);
+//     BOOL GetSystemPowerStatus(TSYSTEMPOWERSTATUS*);
+//     BOOL ReadFile(THANDLE, void*, DWORD, DWORD*, POVERLAPPED);
+//     BOOL SetThreadContext(THANDLE, TCONTEXT*);
+//     BOOL wglDescribeLayerPlane(HDC, int, int, uint, TLAYERPLANEDESCRIPTOR*);
+//     int wglGetLayerPaletteEntries(HDC, int, int, int, void*);
+//     int wglSetLayerPaletteEntries(HDC, int, int, int, void*);
+//     DWORD WNetGetResourceParentA(PNETRESOURCEA, POINTER, DWORD*);
+//     BOOL WriteFile(THANDLE, void*, DWORD, DWORD*, POVERLAPPED);
+//
+//         BOOL CancelWaitableTimer(HANDLE hTimer);
+//         HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpTimerName);
+//         HANDLE OpenWaitableTimerW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpTimerName);
+//         HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCSTR lpTimerName);
+//         HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCWSTR lpTimerName);
+//         BOOL SetWaitableTimer(HANDLE hTimer, LARGE_INTEGER* pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume);
+}
+
+} // !TANGOSVN
+////////////////////////////////////////////////////////////////////////////////////////
+// org.eclipse.swt
+////////////////////////////////////////////////////////////////////////////////////////
+
+alias HANDLE HPAINTBUFFER;
+
+extern (Windows){
+HRESULT AssocQueryStringA(ASSOCF flags, int str, LPCSTR pszAssoc, LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut);
+HRESULT AssocQueryStringW(ASSOCF flags, int str, LPCWSTR pszAssoc, LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut);
+int AddFontResourceExA(char* lpszFilename, int fl, void* pdv);
+int AddFontResourceExW(wchar* lpszFilename, int fl, void* pdv);
+
+BOOL AlphaBlend(
+  HDC hdcDest,                 // handle to destination DC
+  int nXOriginDest,            // x-coord of upper-left corner
+  int nYOriginDest,            // y-coord of upper-left corner
+  int nWidthDest,              // destination width
+  int nHeightDest,             // destination height
+  HDC hdcSrc,                  // handle to source DC
+  int nXOriginSrc,             // x-coord of upper-left corner
+  int nYOriginSrc,             // y-coord of upper-left corner
+  int nWidthSrc,               // source width
+  int nHeightSrc,              // source height
+  BLENDFUNCTION blendFunction  // alpha-blending function
+);
+BOOL TransparentBlt(
+  HDC hdcDest,        // handle to destination DC
+  int nXOriginDest,   // x-coord of destination upper-left corner
+  int nYOriginDest,   // y-coord of destination upper-left corner
+  int nWidthDest,     // width of destination rectangle
+  int hHeightDest,    // height of destination rectangle
+  HDC hdcSrc,         // handle to source DC
+  int nXOriginSrc,    // x-coord of source upper-left corner
+  int nYOriginSrc,    // y-coord of source upper-left corner
+  int nWidthSrc,      // width of source rectangle
+  int nHeightSrc,     // height of source rectangle
+  UINT crTransparent  // color to make transparent
+);
+int IIDFromString (wchar* lpsz, byte* lpiid);
+HRESULT ScriptJustify(
+  SCRIPT_VISATTR* psva,
+  int* piAdvance,
+  int cGlyphs,
+  int iDx,
+  int iMinKashida,
+  int* piJustify
+);
+
+HRESULT ScriptRecordDigitSubstitution(
+  LCID Locale,
+  SCRIPT_DIGITSUBSTITUTE* psds
+);
+HRESULT ScriptApplyDigitSubstitution(
+  SCRIPT_DIGITSUBSTITUTE* psds,
+  SCRIPT_CONTROL* psc,
+  SCRIPT_STATE* pss
+);
+
+// UxTheme.dll
+BOOL IsAppThemed();
+
+HRESULT DrawThemeBackground(
+    HTHEME hTheme,
+    HDC hdc,
+    int iPartId,
+    int iStateId,
+    RECT *pRect,
+    RECT *pClipRect
+);
+HRESULT DrawThemeEdge(
+    HTHEME hTheme,
+    HDC hdc,
+    int iPartId,
+    int iStateId,
+    LPCRECT pDestRect,
+    UINT uEdge,
+    UINT uFlags,
+    LPRECT pContentRect
+);
+HRESULT DrawThemeIcon(
+    HTHEME hTheme,
+    HDC hdc,
+    int iPartId,
+    int iStateId,
+    LPCRECT pRect,
+    HIMAGELIST himl,
+    int iImageIndex
+);
+HRESULT DrawThemeParentBackground(
+    HWND hwnd,
+    HDC hdc,
+    RECT *prc
+);
+HRESULT DrawThemeText(
+    HTHEME hTheme,
+    HDC hdc,
+    int iPartId,
+    int iStateId,
+    LPCWSTR pszText,
+    int iCharCount,
+    DWORD dwTextFlags,
+    DWORD dwTextFlags2,
+    LPCRECT pRect
+);
+
+HTHEME OpenThemeData(
+    HWND hwnd,
+    LPCWSTR pszClassList
+);
+HRESULT BufferedPaintInit();
+HRESULT CloseThemeData(
+    HTHEME hTheme
+);
+HRESULT BufferedPaintUnInit();
+//BOOL IsHungAppWindow(
+//    HWND hWnd
+//);
+HPAINTBUFFER BeginBufferedPaint(
+    HDC hdcTarget,
+    RECT *prcTarget,
+    uint/+BP_BUFFERFORMAT+/ dwFormat,
+    void*/+BP_PAINTPARAMS+/ pPaintParams,
+    HDC *phdc
+);
+HRESULT EndBufferedPaint(
+    HPAINTBUFFER hBufferedPaint,
+    BOOL fUpdateTarget
+);
+
+
+HRESULT GetThemeTextExtent(
+    HTHEME hTheme,
+    HDC hdc,
+    int iPartId,
+    int iStateId,
+    LPCWSTR pszText,
+    int iCharCount,
+    DWORD dwTextFlags,
+    LPCRECT pBoundingRect,
+    LPRECT pExtentRect
+);
+HRESULT SetWindowTheme(
+    HWND hwnd,
+    LPCWSTR pszSubAppName,
+    LPCWSTR pszSubIdList
+);
+
+//Kernel32.lib
+//LANGID GetSystemDefaultUILanguage();
+
+// Macro from winnt.h/windows.h
+WORD PRIMARYLANGID(
+  WORD lgid
+);
+
+//Gdi32.lib
+int IntersectClipRect(
+  HDC hdc,         // handle to DC
+  int nLeftRect,   // x-coord of upper-left corner
+  int nTopRect,    // y-coord of upper-left corner
+  int nRightRect,  // x-coord of lower-right corner
+  int nBottomRect  // y-coord of lower-right corner
+);
+
+LRESULT CoCreateInstance(
+    byte* rclsid, void* pUnkOuter, int dwClsContext, byte* riid, void* ppv
+);
+/+
+// kernel32 winxp/vista
+version(ANSI){
+HANDLE CreateActCtxA(
+  ACTCTXA* pActCtx
+);
+}
+else{
+HANDLE CreateActCtxW(
+  ACTCTXW* pActCtx
+);
+}
+BOOL ActivateActCtx(
+  HACTCTX hActCtx,
+  uint* lpCookie
+);
++/
+}
+//--------------------------------------------------------------------------------------
+
+// Windows API
+extern (Windows){
+int AbortDoc(HDC hdc);
+HKL ActivateKeyboardLayout(
+    HKL hkl,     // handle to keyboard layout
+    UINT Flags   // keyboard layout flags
+);
+BOOL AdjustWindowRectEx(
+    LPRECT lpRect,    // pointer to client-rectangle structure
+    DWORD dwStyle,    // window styles
+    BOOL bMenu,       // menu-present flag
+    DWORD dwExStyle   // extended style
+);
+BOOL Arc(
+    HDC hdc,         // handle to device context
+    int nLeftRect,   // x-coord of bounding rectangle's upper-left corner
+    int nTopRect,    // y-coord of bounding rectangle's upper-left corner
+    int nRightRect,  // x-coord of bounding rectangle's lower-right corner
+    int nBottomRect, // y-coord of bounding rectangle's lower-right corner
+    int nXStartArc,  // first radial ending point
+    int nYStartArc,  // first radial ending point
+    int nXEndArc,    // second radial ending point
+    int nYEndArc     // second radial ending point
+);
+HDWP BeginDeferWindowPos(
+    int nNumWindows
+);
+//alias STDWIN.BeginPaint BeginPaint;
+BOOL BitBlt(
+    HDC hdcDest, // handle to destination device context
+    int nXDest,  // x-coordinate of destination rectangle's upper-left corner
+    int nYDest,  // y-coordinate of destination rectangle's upper-left corner
+    int nWidth,  // width of destination rectangle
+    int nHeight, // height of destination rectangle
+    HDC hdcSrc,  // handle to source device context
+    int nXSrc,   // x-coordinate of source rectangle's upper-left corner
+    int nYSrc,   // y-coordinate of source rectangle's upper-left corner
+    DWORD dwRop  // raster operation code
+);
+    BOOL BringWindowToTop(
+    HWND hWnd   // handle to window
+);
+LRESULT CallNextHookEx(
+    HHOOK hhk,      // handle to current hook
+    int nCode,      // hook code passed to hook procedure
+    WPARAM wParam,  // value passed to hook procedure
+    LPARAM lParam   // value passed to hook procedure
+);
+LRESULT CallWindowProcA(
+    WNDPROC lpPrevWndFunc,  // pointer to previous procedure
+    HWND hWnd,              // handle to window
+    UINT Msg,               // message
+    WPARAM wParam,          // first message parameter
+    LPARAM lParam           // second message parameter
+);
+LRESULT CallWindowProcW(
+    WNDPROC lpPrevWndFunc,  // pointer to previous procedure
+    HWND hWnd,              // handle to window
+    UINT Msg,               // message
+    WPARAM wParam,          // first message parameter
+    LPARAM lParam           // second message parameter
+);
+LPSTR CharLowerA(
+    LPSTR lpsz   // single character or pointer to string
+);
+LPWSTR CharLowerW(
+    LPWSTR lpsz   // single character or pointer to string
+);
+LPSTR CharUpperA(
+    LPSTR lpsz   // single character or pointer to string
+);
+LPWSTR CharUpperW(
+    LPWSTR lpsz   // single character or pointer to string
+);
+DWORD CheckMenuItem(
+    HMENU hmenu,        // handle to menu
+    UINT uIDCheckItem,  // menu item to check or uncheck
+    UINT uCheck         // menu item flags
+);
+BOOL ChooseColorA(
+    LPCHOOSECOLORA lpcc   // pointer to structure with initialization data
+);
+BOOL ChooseColorW(
+    LPCHOOSECOLORW lpcc   // pointer to structure with initialization data
+);
+BOOL ChooseFontA(
+    LPCHOOSEFONTA lpcf   // pointer to structure with initialization data
+);
+BOOL ChooseFontW(
+    LPCHOOSEFONTW lpcf   // pointer to structure with initialization data
+);
+//alias STDWIN.ClientToScreen ClientToScreen;
+BOOL CloseClipboard();
+int CombineRgn(
+    HRGN hrgnDest,      // handle to destination region
+    HRGN hrgnSrc1,      // handle to source region
+    HRGN hrgnSrc2,      // handle to source region
+    int fnCombineMode   // region combining mode
+);
+//alias STDWIN.CloseHandle CloseHandle;
+DWORD CommDlgExtendedError();
+
+version(WinCE){
+BOOL CommandBar_AddAdornments(HWND hwndCB, DWORD dwFlags, DWORD dwReserved);
+HWND CommandBar_Create(HINSTANCE hInst, HWND hwndParent, int idCmdBar);
+void CommandBar_Destroy(HWND hwndCB);
+BOOL CommandBar_DrawMenuBar(HWND hwndCB, int iButton);
+int CommandBar_Height(HWND hwndCB);
+int CommandBar_InsertMenubarEx(HWND hwndCB, HINSTANCE hInst, int pszMenu, int iButton);
+int CommandBar_Show(HWND hwndCB, int fShow);
+}
+
+HANDLE CopyImage(
+    HANDLE hImage,  // handle to the image to copy
+    UINT uType,     // type of image to copy
+    int cxDesired,  // desired width of new image
+    int cyDesired,  // desired height of new image
+    UINT fuFlags    // copy flags
+);
+HACCEL CreateAcceleratorTableA(
+    LPACCEL lpaccl,  // pointer to structure array with accelerator data
+    int cEntries     // number of structures in the array
+);
+HACCEL CreateAcceleratorTableW(
+    LPACCEL lpaccl,  // pointer to structure array with accelerator data
+    int cEntries     // number of structures in the array
+);
+HBITMAP CreateBitmap(
+    int nWidth,         // bitmap width, in pixels
+    int nHeight,        // bitmap height, in pixels
+    UINT cPlanes,       // number of color planes used by device
+    UINT cBitsPerPel,   // number of bits required to identify a color
+    VOID *lpvBits // pointer to array containing color data
+);
+//alias STDWIN.CreateCaret CreateCaret;
+HBITMAP CreateCompatibleBitmap(
+    HDC hdc,        // handle to device context
+    int nWidth,     // width of bitmap, in pixels
+    int nHeight     // height of bitmap, in pixels
+);
+//alias STDWIN.CreateCompatibleDC CreateCompatibleDC;
+HCURSOR CreateCursor(
+    HINSTANCE hInst,         // handle to application instance
+    int xHotSpot,            // horizontal position of hot spot
+    int yHotSpot,            // vertical position of hot spot
+    int nWidth,              // cursor width
+    int nHeight,             // cursor height
+    VOID *pvANDPlane,  // pointer to AND bitmask array
+    VOID *pvXORPlane   // pointer to XOR bitmask array
+);
+HDC CreateDCA(
+    LPCSTR lpszDriver,  // pointer to string specifying driver name
+    LPCSTR lpszDevice,  // pointer to string specifying device name
+    LPCSTR lpszOutput,  // do not use; set to NULL
+    DEVMODE *lpInitData
+                   // pointer to optional printer data
+);
+HDC CreateDCW(
+    LPCWSTR lpszDriver,  // pointer to string specifying driver name
+    LPCWSTR lpszDevice,  // pointer to string specifying device name
+    LPCWSTR lpszOutput,  // do not use; set to NULL
+    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
+);
+HANDLE CreateEventA(
+  LPSECURITY_ATTRIBUTES lpEventAttributes,
+                      // pointer to security attributes
+  BOOL bManualReset,  // flag for manual-reset event
+  BOOL bInitialState, // flag for initial state
+  LPCSTR lpName      // pointer to event-object name
+);
+HANDLE CreateEventW(
+  LPSECURITY_ATTRIBUTES lpEventAttributes,
+                      // pointer to security attributes
+  BOOL bManualReset,  // flag for manual-reset event
+  BOOL bInitialState, // flag for initial state
+  LPCWSTR lpName      // pointer to event-object name
+);
+
+//alias STDWIN.CreateFileA CreateFileA;
+//alias STDWIN.CreateFileW CreateFileW;
+HFONT CreateFontIndirectA(LOGFONTA* lplf );
+HFONT CreateFontIndirectW(LOGFONTW* lplf );
+HICON CreateIconIndirect(
+    PICONINFO piconinfo   // pointer to icon information structure
+);
+HMENU CreateMenu();
+HPALETTE CreatePalette(
+    LOGPALETTE *lplgpl   // pointer to logical color palette
+);
+HBRUSH CreatePatternBrush(
+    HBITMAP hbmp   // handle to bitmap
+);
+//alias STDWIN.CreatePen CreatePen;
+HRGN CreatePolygonRgn(
+    POINT *lppt,  // pointer to array of points
+    int cPoints,        // number of points in array
+    int fnPolyFillMode  // polygon-filling mode
+);
+HMENU CreatePopupMenu();
+//alias STDWIN.CreateRectRgn CreateRectRgn;
+HBRUSH CreateSolidBrush(
+    COLORREF crColor   // brush color value
+);
+
+//alias STDWIN.CreateWindowExA CreateWindowExA;
+HWND CreateWindowExW(
+    DWORD dwExStyle,      // extended window style
+    LPCWSTR lpClassName,  // pointer to registered class name
+    LPCWSTR lpWindowName, // pointer to window name
+    DWORD dwStyle,        // window style
+    int x,                // horizontal position of window
+    int y,                // vertical position of window
+    int nWidth,           // window width
+    int nHeight,          // window height
+    HWND hWndParent,      // handle to parent or owner window
+    HMENU hMenu,          // handle to menu, or child-window identifier
+    HINSTANCE hInstance,  // handle to application instance
+    LPVOID lpParam        // pointer to window-creation data
+);
+
+LRESULT DefFrameProcA(
+    HWND hWnd,           // handle to MDI frame window
+    HWND hWndMDIClient,  // handle to MDI client window
+    UINT uMsg,           // message
+    WPARAM wParam,       // first message parameter
+    LPARAM lParam        // second message parameter
+);
+LRESULT DefFrameProcW(
+    HWND hWnd,           // handle to MDI frame window
+    HWND hWndMDIClient,  // handle to MDI client window
+    UINT uMsg,           // message
+    WPARAM wParam,       // first message parameter
+    LPARAM lParam        // second message parameter
+);
+LRESULT DefMDIChildProcA(
+    HWND hWnd,      // handle to MDI child window
+    UINT uMsg,      // message
+    WPARAM wParam,  // first message parameter
+    LPARAM lParam   // second message parameter
+);
+LRESULT DefMDIChildProcW(
+    HWND hWnd,      // handle to MDI child window
+    UINT uMsg,      // message
+    WPARAM wParam,  // first message parameter
+    LPARAM lParam   // second message parameter
+);
+//alias STDWIN.DefWindowProcA DefWindowProcA;
+LRESULT DefWindowProcW(
+    HWND hWnd,      // handle to window
+    UINT Msg,       // message identifier
+    WPARAM wParam,  // first message parameter
+    LPARAM lParam   // second message parameter
+);
+
+HDWP DeferWindowPos(
+    HDWP hWinPosInfo,      // handle to internal structure
+    HWND hWnd,             // handle to window to position
+    HWND hWndInsertAfter,  // placement-order handle
+    int x,                 // horizontal position
+    int y,                 // vertical position
+    int cx,                // width
+    int cy,                // height
+    UINT uFlags            // window-positioning flags
+);
+
+//alias STDWIN.DeleteDC DeleteDC;
+//alias STDWIN.DeleteFileA DeleteFileA;
+BOOL DeleteMenu(
+    HMENU hMenu,     // handle to menu
+    UINT uPosition,  // menu item identifier or position
+    UINT uFlags      // menu item flag
+);
+//alias STDWIN.DeleteObject DeleteObject;
+BOOL DestroyAcceleratorTable(
+    HACCEL hAccel   // handle to accelerator table
+);
+int DestroyCaret();
+BOOL DestroyCursor(
+    HCURSOR hCursor   // handle to cursor to destroy
+);
+BOOL DestroyIcon(
+    HICON hIcon   // handle to icon to destroy
+);
+BOOL DestroyMenu(
+    HMENU hMenu  // handle to menu to destroy
+);
+BOOL DestroyWindow(
+    HWND hWnd   // handle to window to destroy
+);
+LONG DispatchMessageA(
+    MSG *lpmsg   // pointer to structure with message
+);
+LONG DispatchMessageW(
+    MSG *lpmsg   // pointer to structure with message
+);
+BOOL DragDetect(
+    HWND hwnd,
+    POINT pt
+);
+void DragFinish(
+    HDROP hDrop
+);
+UINT DragQueryFileA(
+    HDROP hDrop,
+    UINT iFile,
+    LPSTR lpszFile,
+    UINT cch
+);
+UINT DragQueryFileW(
+    HDROP hDrop,
+    UINT iFile,
+    LPWSTR lpszFile,
+    UINT cch
+);
+BOOL DrawEdge(
+    HDC hdc,       // handle to device context
+    LPRECT qrc,    // pointer to rectangle coordinates
+    UINT edge,     // type of inner and outer edge to draw
+    UINT grfFlags  // type of border
+);
+BOOL DrawFocusRect(
+    HDC hDC,          // handle to device context
+    RECT *lprc  // pointer to structure for rectangle
+);
+BOOL DrawFrameControl(
+    HDC hdc,     // handle to device context
+    LPRECT lprc, // pointer to bounding rectangle
+    UINT uType,  // frame-control type
+    UINT uState  // frame-control state
+);
+BOOL DrawIconEx(
+    HDC hdc,                    // handle to device context
+    int xLeft,                  // x-coordinate of upper left corner
+    int yTop,                   // y-coordinate of upper left corner
+    HICON hIcon,                // handle to icon to draw
+    int cxWidth,                // width of the icon
+    int cyWidth,                // height of the icon
+    UINT istepIfAniCur,         // index of frame in animated cursor
+    HBRUSH hbrFlickerFreeDraw,  // handle to background brush
+    UINT diFlags                // icon-drawing flags
+);
+BOOL DrawMenuBar(
+    HWND hWnd  // handle to window with menu bar to redraw
+);
+BOOL DrawStateA(
+    HDC hdc,                     // handle to device context
+    HBRUSH hbr,                  // handle to brush
+    DRAWSTATEPROC lpOutputFunc,  // pointer to callback function
+    LPARAM lData,                // image information
+    WPARAM wData,                // more image information
+    int x,                       // horizontal location of image
+    int y,                       // vertical location of image
+    int cx,                      // width of image
+    int cy,                      // height of image
+    UINT fuFlags                 // image type and state
+);
+BOOL DrawStateW(
+    HDC hdc,                     // handle to device context
+    HBRUSH hbr,                  // handle to brush
+    DRAWSTATEPROC lpOutputFunc,  // pointer to callback function
+    LPARAM lData,                // image information
+    WPARAM wData,                // more image information
+    int x,                       // horizontal location of image
+    int y,                       // vertical location of image
+    int cx,                      // width of image
+    int cy,                      // height of image
+    UINT fuFlags                 // image type and state
+);
+int DrawTextA(
+    HDC hDC,          // handle to device context
+    LPCSTR lpString, // pointer to string to draw
+    int nCount,       // string length, in characters
+    LPRECT lpRect,    // pointer to struct with formatting dimensions
+    UINT uFormat      // text-drawing flags
+);
+int DrawTextW(
+    HDC hDC,          // handle to device context
+    LPCWSTR lpString, // pointer to string to draw
+    int nCount,       // string length, in characters
+    LPRECT lpRect,    // pointer to struct with formatting dimensions
+    UINT uFormat      // text-drawing flags
+);
+
+BOOL Ellipse(
+    HDC hdc,        // handle to device context
+    int nLeftRect,  // x-coord of bounding rectangle's upper-left corner
+    int nTopRect,   // y-coord of bounding rectangle's upper-left corner
+    int nRightRect, // x-coord of bounding rectangle's lower-right corner
+    int nBottomRect // y-coord of bounding rectangle's lower-right corner
+);
+BOOL EnableMenuItem(
+    HMENU hMenu,         // handle to menu
+    UINT uIDEnableItem,  // menu item to enable, disable, or gray
+    UINT uEnable         // menu item flags
+);
+BOOL EnableWindow(
+    HWND hWnd,
+    BOOL bEnable
+);
+BOOL EndDeferWindowPos(
+    HDWP hWinPosInfo   // handle to internal structure
+);
+int EndDoc(HDC hDC);
+int EndPage(HDC hDC);
+BOOL EnumDisplayMonitors(
+    HDC hdc,                   // handle to display DC
+    LPCRECT lprcClip,          // clipping rectangle
+    MONITORENUMPROC lpfnEnum,  // callback function
+    LPARAM dwData              // data for callback function
+);
+int EnumFontFamiliesExA(
+    HDC hdc,              // handle to device context
+    LPLOGFONTA lpLogfont,  // pointer to logical font information
+    FONTENUMEXPROC lpEnumFontFamExProc,
+                    // pointer to callback function
+    LPARAM lParam,        // application-supplied data
+    DWORD dwFlags         // reserved; must be zero
+);
+int EnumFontFamiliesExW(
+    HDC hdc,              // handle to device context
+    LPLOGFONTW lpLogfont,  // pointer to logical font information
+    FONTENUMEXPROC lpEnumFontFamExProc,
+                    // pointer to callback function
+    LPARAM lParam,        // application-supplied data
+    DWORD dwFlags         // reserved; must be zero
+);
+
+int EnumFontFamiliesA(
+    HDC hdc,             // handle to device control
+    LPCSTR lpszFamily,  // pointer to family-name string
+    FONTENUMPROC lpEnumFontFamProc,
+                   // pointer to callback function
+    LPARAM lParam        // pointer to application-supplied data
+);
+int EnumFontFamiliesW(
+    HDC hdc,             // handle to device control
+    LPCWSTR lpszFamily,  // pointer to family-name string
+    FONTENUMPROC lpEnumFontFamProc,
+                   // pointer to callback function
+    LPARAM lParam        // pointer to application-supplied data
+);
+BOOL EqualRect(
+    RECT *lprc1,  // pointer to structure with first rectangle
+    RECT *lprc2   // pointer to structure with second rectangle
+);
+BOOL EqualRgn(
+    HRGN hSrcRgn1,  // handle to first region
+    HRGN hSrcRgn2   // handle to second region
+);
+DWORD ExpandEnvironmentStringsA(
+    LPCSTR lpSrc, // pointer to string with environment variables
+    LPSTR lpDst,  // pointer to string with expanded environment
+             // variables
+    DWORD nSize    // maximum characters in expanded string
+);
+DWORD ExpandEnvironmentStringsW(
+    LPCWSTR lpSrc, // pointer to string with environment variables
+    LPWSTR lpDst,  // pointer to string with expanded environment
+             // variables
+    DWORD nSize    // maximum characters in expanded string
+);
+BOOL ExtTextOutA(
+    HDC hdc,          // handle to device context
+    int X,            // x-coordinate of reference point
+    int Y,            // y-coordinate of reference point
+    UINT fuOptions,   // text-output options
+    RECT *lprc, // optional clipping and/or opaquing rectangle
+    LPCSTR lpString, // points to string
+    UINT cbCount,     // number of characters in string
+    INT *lpDx   // pointer to array of intercharacter spacing
+                // values
+);
+BOOL ExtTextOutW(
+    HDC hdc,          // handle to device context
+    int X,            // x-coordinate of reference point
+    int Y,            // y-coordinate of reference point
+    UINT fuOptions,   // text-output options
+    RECT *lprc, // optional clipping and/or opaquing rectangle
+    LPCWSTR lpString, // points to string
+    UINT cbCount,     // number of characters in string
+    INT *lpDx   // pointer to array of intercharacter spacing
+                // values
+);
+UINT ExtractIconExA(
+    LPCSTR lpszFile,
+    int nIconIndex,
+    HICON *phiconLarge,
+    HICON *phiconSmall,
+    UINT nIcons
+);
+UINT ExtractIconExW(
+    LPCWSTR lpszFile,
+    int nIconIndex,
+    HICON *phiconLarge,
+    HICON *phiconSmall,
+    UINT nIcons
+);
+HRSRC FindResourceA(
+    HMODULE hModule, // module handle
+    LPCSTR lpName,  // pointer to resource name
+    LPCSTR lpType   // pointer to resource type
+);
+HRSRC FindResourceW(
+    HMODULE hModule, // module handle
+    LPCWSTR lpName,  // pointer to resource name
+    LPCWSTR lpType   // pointer to resource type
+);
+HWND FindWindowA(
+    LPCSTR lpClassName,  // pointer to class name
+    LPCSTR lpWindowName  // pointer to window name
+);
+HWND FindWindowW(
+    LPCWSTR lpClassName,  // pointer to class name
+    LPCWSTR lpWindowName  // pointer to window name
+);
+DWORD FormatMessageA(
+    DWORD dwFlags,      // source and processing options
+    LPCVOID lpSource,   // pointer to  message source
+    DWORD dwMessageId,  // requested message identifier
+    DWORD dwLanguageId, // language identifier for requested message
+    LPSTR lpBuffer,    // pointer to message buffer
+    DWORD nSize,        // maximum size of message buffer
+    //  va_list *Arguments  // pointer to array of message inserts
+    void* Arguments
+);
+DWORD FormatMessageW(
+    DWORD dwFlags,      // source and processing options
+    LPCVOID lpSource,   // pointer to  message source
+    DWORD dwMessageId,  // requested message identifier
+    DWORD dwLanguageId, // language identifier for requested message
+    LPWSTR lpBuffer,    // pointer to message buffer
+    DWORD nSize,        // maximum size of message buffer
+    //  va_list *Arguments  // pointer to array of message inserts
+    void* Arguments
+);
+DWORD GdiSetBatchLimit(
+    DWORD dwLimit   // batch limit
+);
+UINT GetACP();
+HWND GetActiveWindow();
+COLORREF GetBkColor(
+    HDC hdc   // handle of device context
+);
+HWND GetCapture();
+BOOL GetCaretPos(
+    LPPOINT lpPoint   // address of structure to receive coordinates
+);
+BOOL GetCharABCWidthsA(
+    HDC hdc,         // handle to device context
+    UINT uFirstChar, // first character in range to query
+    UINT uLastChar,  // last character in range to query
+    LPABC lpabc      // pointer to character-width structure
+);
+BOOL GetCharABCWidthsW(
+    HDC hdc,         // handle to device context
+    UINT uFirstChar, // first character in range to query
+    UINT uLastChar,  // last character in range to query
+    LPABC lpabc      // pointer to character-width structure
+);
+
+BOOL GetCharWidthA(
+    HDC hdc,         // handle to device context
+    UINT iFirstChar, // first character in range to query
+    UINT iLastChar,  // last character in range to query
+    LPINT lpBuffer   // pointer to buffer for widths
+);
+BOOL GetCharWidthW(
+    HDC hdc,         // handle to device context
+    UINT iFirstChar, // first character in range to query
+    UINT iLastChar,  // last character in range to query
+    LPINT lpBuffer   // pointer to buffer for widths
+);
+DWORD GetCharacterPlacementA(
+    HDC hdc,           // handle to device context
+    LPCSTR lpString,  // pointer to string
+    int nCount,        // number of characters in string
+    int nMaxExtent,    // maximum extent for displayed string
+    LPGCP_RESULTS lpResults,
+                     // pointer to buffer for placement result
+    DWORD dwFlags      // placement flags
+);
+DWORD GetCharacterPlacementW(
+    HDC hdc,           // handle to device context
+    LPCWSTR lpString,  // pointer to string
+    int nCount,        // number of characters in string
+    int nMaxExtent,    // maximum extent for displayed string
+    LPGCP_RESULTS lpResults,
+                     // pointer to buffer for placement result
+    DWORD dwFlags      // placement flags
+);
+BOOL GetClassInfoA(
+    HINSTANCE hInstance,    // handle of application instance
+    LPCSTR lpClassName,    // address of class name string
+    LPWNDCLASSA lpWndClass   // address of structure for class data
+);
+BOOL GetClassInfoW(
+    HINSTANCE hInstance,    // handle of application instance
+    LPCWSTR lpClassName,    // address of class name string
+    LPWNDCLASSW lpWndClass   // address of structure for class data
+);
+//alias STDWIN.GetClientRect GetClientRect;
+//alias STDWIN.GetClipBox GetClipBox;
+//alias STDWIN.GetClipRgn GetClipRgn;
+HANDLE GetClipboardData(
+    UINT uFormat   // clipboard format
+);
+int GetClipboardFormatNameA(
+    UINT format,            // clipboard format to retrieve
+    LPSTR lpszFormatName,  // address of buffer for name
+    int cchMaxCount         // length of name string in characters
+);
+int GetClipboardFormatNameW(
+    UINT format,            // clipboard format to retrieve
+    LPWSTR lpszFormatName,  // address of buffer for name
+    int cchMaxCount         // length of name string in characters
+);
+BOOL GetComboBoxInfo(
+    HWND hwndCombo,
+    PCOMBOBOXINFO pcbi
+);
+//alias STDWIN.GetCurrentObject GetCurrentObject;
+DWORD GetCurrentProcessId();
+DWORD GetCurrentThreadId();
+HCURSOR GetCursor();
+BOOL GetCursorPos(
+    LPPOINT lpPoint   // address of structure for cursor position
+);
+//alias STDWIN.GetDC GetDC;
+UINT GetDIBColorTable(
+    HDC hdc,          // handle to device context whose DIB is of
+                // interest
+    UINT uStartIndex, // color table index of first entry to retrieve
+    UINT cEntries,    // number of color table entries to retrieve
+    RGBQUAD *pColors  // pointer to buffer that receives color table
+                // entries
+);
+int GetDIBits(
+    HDC hdc,           // handle to device context
+    HBITMAP hbmp,      // handle to bitmap
+    UINT uStartScan,   // first scan line to set in destination bitmap
+    UINT cScanLines,   // number of scan lines to copy
+    LPVOID lpvBits,    // address of array for bitmap bits
+    LPBITMAPINFO lpbi, // address of structure with bitmap data
+    UINT uUsage        // RGB or palette index
+);
+HWND GetDesktopWindow();
+int GetDialogBaseUnits();
+int GetDoubleClickTime();
+DWORD GetFontLanguageInfo(
+    HDC hdc  // handle to a device context
+);
+BOOL GetGUIThreadInfo(
+    DWORD idThread,
+    LPGUITHREADINFO lpgui
+);
+BOOL GetIconInfo(
+    HICON hIcon,          // icon handle
+    PICONINFO piconinfo   // address of icon structure
+);
+int GetKeyNameTextA(
+    LONG lParam,      // second parameter of keyboard message
+    LPSTR lpString,  // pointer to buffer for key name
+    int nSize         // maximum length of key-name string length
+);
+int GetKeyNameTextW(
+    LONG lParam,      // second parameter of keyboard message
+    LPWSTR lpString,  // pointer to buffer for key name
+    int nSize         // maximum length of key-name string length
+);
+HKL GetKeyboardLayout(
+    DWORD dwLayout  // thread identifier
+);
+SHORT GetKeyState(
+    int nVirtKey   // virtual-key code
+);
+UINT GetKeyboardLayoutList(
+    int nBuff,       // size of buffer in array element
+    HKL *lpList  // buffer for keyboard layout handles
+);
+BOOL GetKeyboardState(
+    PBYTE lpKeyState   // pointer to array to receive status data
+);
+HWND GetLastActivePopup(HWND hWnd);
+DWORD GetLastError();
+DWORD GetLayout(
+    HDC hdc      // handle to DC
+);
+int GetLocaleInfoA(
+    LCID Locale,      // locale identifier
+    LCTYPE LCType,    // type of information
+    LPSTR lpLCData,  // address of buffer for information
+    int cchData       // size of buffer
+);
+int GetLocaleInfoW(
+    LCID Locale,      // locale identifier
+    LCTYPE LCType,    // type of information
+    LPWSTR lpLCData,  // address of buffer for information
+    int cchData       // size of buffer
+);
+HMENU GetMenu(
+    HWND hWnd  // handle to window
+);
+BOOL GetMenuBarInfo(
+    HWND hwnd,
+    LONG idObject,
+    LONG idItem,
+    PMENUBARINFO pmbi
+);
+UINT GetMenuDefaultItem(
+    HMENU hMenu,
+    UINT fByPos,
+    UINT gmdiFlags
+);
+BOOL GetMenuInfo(
+    HMENU hmenu,
+    LPCMENUINFO lpcmi
+);
+int GetMenuItemCount(HMENU hMenu);
+BOOL GetMenuItemInfoA(
+    HMENU hMenu,
+    UINT uItem,
+    BOOL fByPosition,
+    LPMENUITEMINFO lpmii
+);
+BOOL GetMenuItemInfoW(
+    HMENU hMenu,
+    UINT uItem,
+    BOOL fByPosition,
+    LPMENUITEMINFO lpmii
+);
+BOOL GetMenuItemRect(
+    HWND hWnd,
+    HMENU hMenu,
+    UINT uItem,
+    LPRECT lprcItem
+);
+BOOL GetMessageW(
+    LPMSG lpMsg,         // address of structure with message
+    HWND hWnd,           // handle of window
+    UINT wMsgFilterMin,  // first message
+    UINT wMsgFilterMax   // last message
+);
+DWORD GetMessagePos();
+LONG GetMessageTime();
+DWORD GetModuleFileNameA(
+    HMODULE hModule,    // handle to module to find filename for
+    LPSTR lpFilename,  // pointer to buffer to receive module path
+    DWORD nSize         // size of buffer, in characters
+);
+DWORD GetModuleFileNameW(
+    HMODULE hModule,    // handle to module to find filename for
+    LPWSTR lpFilename,  // pointer to buffer to receive module path
+    DWORD nSize         // size of buffer, in characters
+);
+HMODULE GetModuleHandleW(
+  LPCWSTR lpModuleName
+);
+BOOL GetMonitorInfoA(
+    HMONITOR hMonitor,  // handle to display monitor
+    LPMONITORINFO lpmi  // pointer to display monitor information
+);
+BOOL GetMonitorInfoW(
+    HMONITOR hMonitor,  // handle to display monitor
+    LPMONITORINFO lpmi  // pointer to display monitor information
+);
+UINT GetNearestPaletteIndex(
+    HPALETTE hpal,     // handle of logical color palette
+    COLORREF crColor   // color to be matched
+);
+BOOL GetOpenFileNameA(
+    OPENFILENAMEA* lpofn   // address of structure with initialization data
+);
+BOOL GetOpenFileNameW(
+    OPENFILENAMEW* lpofn   // address of structure with initialization data
+);
+UINT GetPaletteEntries(
+  HPALETTE hpal,        // handle to logical palette
+  UINT iStartIndex,     // first entry to retrieve
+  UINT nEntries,        // number of entries to retrieve
+  LPPALETTEENTRY lppe   // array that receives entries
+);
+HWND GetParent(
+    HWND hWnd   // handle to child window
+);
+
+COLORREF GetPixel(
+    HDC hdc,   // handle to device context
+    int XPos,  // x-coordinate of pixel
+    int nYPos  // y-coordinate of pixel
+);
+HANDLE GetProcessHeap();
+DWORD GetProfileStringA(
+    LPCSTR lpAppName,        // address of section name
+    LPCSTR lpKeyName,        // address of key name
+    LPCSTR lpDefault,        // address of default string
+    LPSTR lpReturnedString,  // address of destination buffer
+    DWORD nSize               // size of destination buffer
+);
+DWORD GetProfileStringW(
+    LPCWSTR lpAppName,        // address of section name
+    LPCWSTR lpKeyName,        // address of key name
+    LPCWSTR lpDefault,        // address of default string
+    LPWSTR lpReturnedString,  // address of destination buffer
+    DWORD nSize               // size of destination buffer
+);
+int GetROP2(
+    HDC hdc   // handle of device context
+);
+int GetRandomRgn(
+    HDC  hdc,    // handle to DC
+    HRGN hrgn,   // handle to region
+    INT  iNum    // must be SYSRGN
+);
+DWORD GetRegionData(
+    HRGN hRgn,            // handle to region
+    DWORD dwCount,        // size of buffer containing region data
+    LPRGNDATA lpRgnData   // pointer to region data
+);
+int GetRgnBox(
+    HRGN hrgn,   // handle to a region
+    LPRECT lprc  // pointer that receives bounding rectangle
+);
+BOOL GetSaveFileNameA(
+    OPENFILENAMEA* lpofn   // address of structure with initialization data
+);
+BOOL GetSaveFileNameW(
+    OPENFILENAME* lpofn   // address of structure with initialization data
+);
+BOOL GetScrollInfo(
+    HWND hwnd,         // handle to window with scroll bar
+    int fnBar,         // scroll bar flag
+    LPSCROLLINFO lpsi  // pointer to structure for scroll parameters
+);
+//alias STDWIN.GetStockObject GetStockObject;
+DWORD GetSysColor(
+    int nIndex   // display element
+);
+HBRUSH GetSysColorBrush(
+    int nIndex  // system color index
+);
+HMENU GetSystemMenu(
+    HWND hWnd,    // handle to window to own window menu
+    BOOL bRevert  // reset flag
+);
+int GetSystemMetrics(
+    int nIndex   // system metric or configuration setting to retrieve
+);
+UINT GetSystemPaletteEntries(
+    HDC hdc,              // handle of device context
+    UINT iStartIndex,     // index of first entry to be retrieved
+    UINT nEntries,        // number of entries to be retrieved
+    LPPALETTEENTRY lppe   // array receiving system-palette entries
+);
+int GetTextCharset(
+    HDC hdc  // handle to DC
+);
+COLORREF GetTextColor(
+    HDC hdc   // handle to device context
+);
+BOOL GetTextExtentPoint32A(
+    HDC hdc,           // handle to device context
+    LPCSTR lpString,  // pointer to text string
+    int cbString,      // number of characters in string
+    LPSIZE lpSize      // pointer to structure for string size
+);
+BOOL GetTextExtentPoint32W(
+    HDC hdc,           // handle to device context
+    LPCWSTR lpString,  // pointer to text string
+    int cbString,      // number of characters in string
+    LPSIZE lpSize      // pointer to structure for string size
+);
+BOOL GetTextMetricsW(
+    HDC hdc,            // handle to device context
+    TEXTMETRICW* lptm   // pointer to text metrics structure
+);
+DWORD GetTickCount();
+//alias STDWIN.GetUpdateRect GetUpdateRect;
+//alias STDWIN.GetUpdateRgn GetUpdateRgn;
+DWORD GetVersion();
+BOOL GetVersionExA(
+    LPOSVERSIONINFOA lpVersionInformation   // pointer to version information structure
+);
+BOOL GetVersionExW(
+    LPOSVERSIONINFOW lpVersionInformation   // pointer to version information structure
+);
+HWND GetWindow(
+    HWND hWnd,  // handle to original window
+    UINT uCmd   // relationship flag
+);
+LONG GetWindowLongA(HWND hWnd, int nIndex);
+LONG GetWindowLongW(HWND hWnd, int nIndex);
+
+BOOL GetWindowPlacement(
+    HWND hWnd,
+    WINDOWPLACEMENT *lpwndpl
+);
+int GetWindowTextA(
+  HWND hWnd,        // handle to window or control with text
+  LPSTR lpString,  // address of buffer for text
+  int nMaxCount     // maximum number of characters to copy
+);
+int GetWindowTextW(
+  HWND hWnd,        // handle to window or control with text
+  LPWSTR lpString,  // address of buffer for text
+  int nMaxCount     // maximum number of characters to copy
+);
+int GetWindowTextLengthA(HWND hWnd);
+int GetWindowTextLengthW(HWND hWnd);
+DWORD GetWindowThreadProcessId(
+  HWND hWnd,             // handle to window
+  LPDWORD lpdwProcessId  // address of variable for process identifier
+);
+HGLOBAL GlobalAlloc(UINT uFlags, SIZE_T dwBytes);
+HGLOBAL GlobalFree(HGLOBAL hMem);
+LPVOID GlobalLock(HGLOBAL hMem);
+SIZE_T GlobalSize(HGLOBAL hMem);
+BOOL GlobalUnlock(HGLOBAL hMem);
+BOOL GradientFill(
+    HDC hdc,
+    PTRIVERTEX pVertex,
+    DWORD dwNumVertex,
+    PVOID pMesh,
+    DWORD dwNumMesh,
+    DWORD dwMode
+);
+LPVOID HeapAlloc(
+    HANDLE hHeap,  // handle to the private heap block
+    DWORD dwFlags, // heap allocation control flags
+    DWORD dwBytes  // number of bytes to allocate
+);
+BOOL HeapFree(
+    HANDLE hHeap,  // handle to the heap
+    DWORD dwFlags, // heap freeing flags
+    LPVOID lpMem   // pointer to the memory to free
+);
+//alias STDWIN.HideCaret HideCaret;
+int ImageList_Add(
+    HIMAGELIST himl,
+    HBITMAP hbmImage,
+    HBITMAP hbmMask
+);
+int ImageList_AddMasked(
+    HIMAGELIST himl,
+    HBITMAP hbmImage,
+    COLORREF crMask
+     );
+HIMAGELIST ImageList_Create(
+    int cx,
+    int cy,
+    UINT flags,
+    int cInitial,
+    int cGrow
+);
+BOOL ImageList_Destroy(
+    HIMAGELIST himl
+);
+HICON ImageList_GetIcon(
+    HIMAGELIST himl,
+    int i,
+    UINT flags
+);
+BOOL ImageList_GetIconSize(
+    HIMAGELIST himl,
+    int *cx,
+    int *cy
+);
+int ImageList_GetImageCount(
+    HIMAGELIST himl
+);
+BOOL ImageList_Remove(
+    HIMAGELIST himl,
+    int i
+);
+BOOL ImageList_Replace(
+    HIMAGELIST himl,
+    int i,
+    HBITMAP hbmImage,
+    HBITMAP hbmMask
+);
+int ImageList_ReplaceIcon(
+    HIMAGELIST himl,
+    int i,
+    HICON hicon
+);
+BOOL ImageList_SetIconSize(
+    HIMAGELIST himl,
+    int cx,
+    int cy
+);
+HIMC ImmAssociateContext(
+    HWND hWnd,
+    HIMC hIMC
+);
+HIMC ImmCreateContext();
+int ImmDestroyContext(HIMC hIMC );
+BOOL ImmGetCompositionFontA(
+    HIMC hIMC,
+    LPLOGFONTA lplf
+);
+BOOL ImmGetCompositionFontW(
+    HIMC hIMC,
+    LOGFONTW* lplf
+);
+LONG ImmGetCompositionStringA(
+    HIMC hIMC,
+    DWORD dwIndex,
+    LPVOID lpBuf,
+    DWORD dwBufLen
+);
+LONG ImmGetCompositionStringW(
+    HIMC hIMC,
+    DWORD dwIndex,
+    LPVOID lpBuf,
+    DWORD dwBufLen
+);
+HIMC ImmGetContext(
+    HWND hWnd
+);
+BOOL ImmGetConversionStatus(
+    HIMC hIMC,
+    LPDWORD lpfdwConversion,
+    LPDWORD lpfdwSentence
+);
+HWND ImmGetDefaultIMEWnd(HWND hWnd );
+BOOL ImmGetOpenStatus(
+    HIMC hIMC
+);
+BOOL ImmReleaseContext(
+    HWND hWnd,
+    HIMC hIMC
+);
+BOOL ImmSetCompositionFontA(
+    HIMC hIMC,
+    LOGFONTA* lplf
+);
+BOOL ImmSetCompositionFontW(
+    HIMC hIMC,
+    LOGFONTW* lplf
+);
+BOOL ImmSetCompositionWindow(
+    HIMC hIMC,
+    LPCOMPOSITIONFORM lpCompForm
+);
+BOOL ImmSetConversionStatus(
+    HIMC hIMC,
+    DWORD fdwConversion,
+    DWORD fdwSentence
+);
+BOOL ImmSetOpenStatus(
+    HIMC hIMC,
+    BOOL fOpen
+);
+void InitCommonControls();
+BOOL InitCommonControlsEx(
+    LPINITCOMMONCONTROLSEX lpInitCtrls
+);
+BOOL InsertMenuA(
+  HMENU hMenu,      // handle to menu
+  UINT uPosition,   // menu item that new menu item precedes
+  UINT uFlags,      // menu item flags
+  UINT uIDNewItem,  // menu item identifier or handle to drop-down
+                    // menu or submenu
+  LPCSTR lpNewItem // menu item content
+);
+BOOL InsertMenuW(
+  HMENU hMenu,      // handle to menu
+  UINT uPosition,   // menu item that new menu item precedes
+  UINT uFlags,      // menu item flags
+  UINT uIDNewItem,  // menu item identifier or handle to drop-down
+                    // menu or submenu
+  LPCWSTR lpNewItem // menu item content
+);
+
+BOOL InsertMenuItemA(
+  HMENU hMenu,
+  UINT uItem,
+  BOOL fByPosition,
+  MENUITEMINFOA* lpmii
+);
+BOOL InsertMenuItemW(
+  HMENU hMenu,
+  UINT uItem,
+  BOOL fByPosition,
+  MENUITEMINFOW* lpmii
+);
+BOOL IntersectRect(
+    LPRECT lprcDst,        // pointer to structure for intersection
+    RECT *lprcSrc1,  // pointer to structure with first rectangle
+    RECT *lprcSrc2   // pointer to structure with second rectangle
+);
+LONG InterlockedIncrement(
+    LPLONG lpAddend   // pointer to the variable to increment
+);
+LONG InterlockedDecrement(
+    LPLONG lpAddend   // address of the variable to decrement
+);
+BOOL IsDBCSLeadByte(
+    BYTE TestChar   // character to test
+);
+BOOL IsIconic(
+    HWND hWnd   // handle to window
+);
+BOOL IsWindow(
+    HWND hWnd   // handle to window
+);
+BOOL IsWindowEnabled(HWND hWnd);
+BOOL IsWindowVisible(HWND hWnd);
+BOOL IsZoomed(HWND hWnd);
+BOOL KillTimer(
+    HWND hWnd,      // handle of window that installed timer
+    UINT uIDEvent   // timer identifier
+);
+//alias STDWIN.LineTo LineTo;
+HBITMAP LoadBitmapA(
+    HINSTANCE hInstance,  // handle to application instance
+    LPCSTR lpBitmapName  // name of bitmap resource
+);
+HBITMAP LoadBitmapW(
+    HINSTANCE hInstance,  // handle to application instance
+    LPCWSTR lpBitmapName  // name of bitmap resource
+);
+HANDLE LoadImageA(
+    HINSTANCE hinst,   // handle of the instance containing the image
+    LPCSTR lpszName,  // name or identifier of image
+    UINT uType,        // type of image
+    int cxDesired,     // desired width
+    int cyDesired,     // desired height
+    UINT fuLoad        // load flags
+);
+HANDLE LoadImageW(
+    HINSTANCE hinst,   // handle of the instance containing the image
+    LPCWSTR lpszName,  // name or identifier of image
+    UINT uType,        // type of image
+    int cxDesired,     // desired width
+    int cyDesired,     // desired height
+    UINT fuLoad        // load flags
+);
+HINSTANCE LoadLibraryW(wchar* lpLibFileName );
+HGLOBAL LoadResource(
+    HMODULE hModule, // resource-module handle
+    HRSRC hResInfo   // resource handle
+);
+int LoadStringA(
+    HINSTANCE hInstance,
+    UINT uID,
+    LPSTR lpBuffer,
+    int nBufferMax
+);
+int LoadStringW(
+    HINSTANCE hInstance,
+    UINT uID,
+    LPWSTR lpBuffer,
+    int nBufferMax
+);
+HLOCAL LocalFree(
+    HLOCAL hMem   // handle to local memory object
+);
+LPVOID LockResource(
+    HGLOBAL hResData   // handle to resource to lock
+);
+UINT MapVirtualKeyA(
+    UINT uCode,     // virtual-key code or scan code
+    UINT uMapType   // translation to perform
+);
+UINT MapVirtualKeyW(
+    UINT uCode,     // virtual-key code or scan code
+    UINT uMapType   // translation to perform
+);
+BOOL MessageBeep(
+    UINT uType   // sound type
+);
+int MessageBoxW(
+    HWND hWnd,          // handle of owner window
+    LPCWSTR lpText,     // address of text in message box
+    LPCWSTR lpCaption,  // address of title of message box
+    UINT uType          // style of message box
+);
+HMONITOR MonitorFromWindow(
+    HWND hwnd,       // handle to a window
+    DWORD dwFlags    // flags if no monitor intersects the window
+);
+DWORD MsgWaitForMultipleObjectsEx(
+    DWORD nCount,          // number of handles in handle array
+    LPHANDLE pHandles,     // pointer to an object-handle array
+    DWORD dwMilliseconds,  // time-out interval in milliseconds
+    DWORD dwWakeMask,      // type of input events to wait for
+    DWORD dwFlags          // wait flags
+);
+void NotifyWinEvent(
+    DWORD event,
+    HWND hwnd,
+    LONG idObject,
+    LONG idChild
+);
+int OffsetRgn(
+    HRGN hrgn,     // handle to region
+    int nXOffset,  // offset along x-axis
+    int nYOffset   // offset along y-axis
+);
+WINOLEAPI OleInitialize(
+    LPVOID pvReserved  //Reserved; must be NULL.
+);
+void OleUninitialize();
+BOOL OpenClipboard(
+    HWND hWndNewOwner
+);
+void OutputDebugStringA(
+    LPCSTR lpOutputString
+);
+void OutputDebugStringW(
+    LPCWSTR lpOutputString
+);
+BOOL PatBlt(
+    HDC hdc,     // handle to device context
+    int nXLeft,  // x-coord. of upper-left corner of rect. to be filled
+    int nYLeft,  // y-coord. of upper-left corner of rect. to be filled
+    int nWidth,  // width of rectangle to be filled
+    int nHeight, // height of rectangle to be filled
+    DWORD dwRop  // raster operation code
+);
+BOOL PeekMessageW(
+    LPMSG lpMsg,         // pointer to structure for message
+    HWND hWnd,           // handle to window
+    UINT wMsgFilterMin,  // first message
+    UINT wMsgFilterMax,  // last message
+    UINT wRemoveMsg      // removal flags
+);
+BOOL Pie(
+    HDC hdc,         // handle to device context
+    int nLeftRect,   // x-coord of bounding rectangle's upper-left corner
+    int nTopRect,    // y-coord of bounding rectangle's upper-left corner
+    int nRightRect,  // x-coord of bounding rectangle's lower-right corner
+    int nBottomRect, // y-coord of bounding rectangle's lower-right corner
+    int nXRadial1,   // x-coord of first radial's endpoint
+    int nYRadial1,   // y-coord of first radial's endpoint
+    int nXRadial2,   // x-coord of second radial's endpoint
+    int nYRadial2    // y-coord of second radial's endpoint
+);
+BOOL Polygon(
+    HDC hdc,                // handle to device context
+    POINT *lpPoints,  // pointer to polygon's vertices
+    int nCount              // count of polygon's vertices
+);
+BOOL Polyline(
+    HDC hdc,            // handle to device context
+    POINT *lppt,  // pointer to array containing endpoints
+    int cPoints         // number of points in the array
+);
+BOOL PostMessageA(
+    HWND hWnd,
+    UINT Msg,
+    WPARAM wParam,
+    LPARAM lParam
+);
+BOOL PostMessageW(
+    HWND hWnd,
+    UINT Msg,
+    WPARAM wParam,
+    LPARAM lParam
+);
+BOOL PostThreadMessageA(
+    DWORD idThread,
+    UINT Msg,
+    WPARAM wParam,
+    LPARAM lParam
+);
+BOOL PostThreadMessageW(
+    DWORD idThread,
+    UINT Msg,
+    WPARAM wParam,
+    LPARAM lParam
+);
+BOOL PtInRect(
+    RECT *lprc,  // rectangle
+    POINT pt           // point
+);
+BOOL PtInRegion(
+    HRGN hrgn,  // handle to region
+    int X,      // x-coordinate of point
+    int Y       // y-coordinate of point
+);
+UINT RealizePalette(
+    HDC hdc   // handle of device context
+);
+BOOL RectInRegion(
+    HRGN hrgn,         // handle to region
+    RECT *lprc   // pointer to rectangle
+);
+BOOL Rectangle(
+    HDC hdc,         // handle to device context
+    int nLeftRect,   // x-coord of bounding rectangle's upper-left corner
+    int nTopRect,    // y-coord of bounding rectangle's upper-left corner
+    int nRightRect,  // x-coord of bounding rectangle's lower-right corner
+    int nBottomRect  // y-coord of bounding rectangle's lower-right corner
+);
+//alias STDWIN.RedrawWindow RedrawWindow;
+LONG RegCloseKey(
+  HKEY hKey
+);
+LONG RegEnumKeyExA(
+  HKEY hKey,
+  DWORD dwIndex,
+  LPSTR lpName,
+  LPDWORD lpcName,
+  LPDWORD lpReserved,
+  LPSTR lpClass,
+  LPDWORD lpcClass,
+  PFILETIME lpftLastWriteTime
+);
+LONG RegEnumKeyExW(
+  HKEY hKey,
+  DWORD dwIndex,
+  LPWSTR lpName,
+  LPDWORD lpcName,
+  LPDWORD lpReserved,
+  LPWSTR lpClass,
+  LPDWORD lpcClass,
+  PFILETIME lpftLastWriteTime
+);
+LONG RegOpenKeyExA(
+  HKEY hKey,
+  LPSTR lpSubKey,
+  DWORD ulOptions,
+  REGSAM samDesired,
+  PHKEY phkResult
+);
+LONG RegOpenKeyExW(
+  HKEY hKey,
+  LPWSTR lpSubKey,
+  DWORD ulOptions,
+  REGSAM samDesired,
+  PHKEY phkResult
+);
+
+LONG RegQueryInfoKeyA(
+  HKEY hKey,
+  LPSTR lpClass,
+  LPDWORD lpcClass,
+  LPDWORD lpReserved,
+  LPDWORD lpcSubKeys,
+  LPDWORD lpcMaxSubKeyLen,
+  LPDWORD lpcMaxClassLen,
+  LPDWORD lpcValues,
+  LPDWORD lpcMaxValueNameLen,
+  LPDWORD lpcMaxValueLen,
+  LPDWORD lpcbSecurityDescriptor,
+  PFILETIME lpftLastWriteTime
+);
+LONG RegQueryInfoKeyW(
+  HKEY hKey,
+  LPWSTR lpClass,
+  LPDWORD lpcClass,
+  LPDWORD lpReserved,
+  LPDWORD lpcSubKeys,
+  LPDWORD lpcMaxSubKeyLen,
+  LPDWORD lpcMaxClassLen,
+  LPDWORD lpcValues,
+  LPDWORD lpcMaxValueNameLen,
+  LPDWORD lpcMaxValueLen,
+  LPDWORD lpcbSecurityDescriptor,
+  PFILETIME lpftLastWriteTime
+);
+
+LONG RegQueryValueExA(
+  HKEY hKey,
+  LPCSTR lpValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE lpData,
+  LPDWORD lpcbData
+);
+LONG RegQueryValueExW(
+  HKEY hKey,
+  LPCWSTR lpValueName,
+  LPDWORD lpReserved,
+  LPDWORD lpType,
+  LPBYTE lpData,
+  LPDWORD lpcbData
+);
+
+ATOM RegisterClassA(
+    WNDCLASSA *lpWndClass
+);
+ATOM RegisterClassW(
+    WNDCLASSW *lpWndClass
+);
+UINT RegisterClipboardFormatA(
+    LPCSTR lpszFormat
+);
+UINT RegisterClipboardFormatW(
+    LPCWSTR lpszFormat
+);
+UINT RegisterWindowMessageA(
+    LPCSTR lpString
+);
+UINT RegisterWindowMessageW(
+    LPCWSTR lpString
+);
+BOOL ReleaseCapture();
+BOOL RemoveMenu(
+    HMENU hMenu,
+    UINT uPosition,
+    UINT uFlags
+);
+BOOL RestoreDC(
+    HDC hdc,       // handle to DC
+    int nSavedDC   // restore state
+);
+//alias STDWIN.RoundRect RoundRect;
+
+// basic
+void RtlMoveMemory(void* Destination, void* Source, DWORD Length);
+// extends
+void RtlMoveMemory(int Destination, void* Source, DWORD Length);
+void RtlMoveMemory(void* Destination, int Source, DWORD Length);
+void RtlMoveMemory(int Destination, int Source, DWORD Length);
+
+LPITEMIDLIST SHBrowseForFolderA(
+    BROWSEINFOA* lpbi
+);
+LPITEMIDLIST SHBrowseForFolderW(
+    BROWSEINFOW* lpbi
+);
+version(WinCE){
+    int SHCreateMenuBar(SHMENUBARINFO* pmb);
+}
+HRESULT SHGetMalloc(
+//  LPMALLOC *ppMalloc
+    LPVOID   *ppMalloc
+);
+BOOL SHGetPathFromIDListA(
+    LPCITEMIDLIST pidl,
+    LPSTR pszPath
+);
+BOOL SHGetPathFromIDListW(
+    LPCITEMIDLIST pidl,
+    LPWSTR pszPath
+);
+version(WinCE)
+{
+    int SHHandleWMSettingChange(HWND hwnd, int wParam, int lParam, void*  psai);
+    int SHRecognizeGesture(void* shrg);
+    void SHSendBackToFocusWindow(int uMsg, int wp, int lp);
+    int SHSetAppKeyWndAssoc(byte bVk, HWND hwnd);
+    int SHSipPreference(HWND hwnd, int st);
+}
+
+// USP methods (Unicode Complex Script processor)
+HRESULT ScriptBreak(
+  WCHAR *pwcChars,
+  int cChars,
+  SCRIPT_ANALYSIS *psa,
+  SCRIPT_LOGATTR *psla
+);
+HRESULT ScriptCPtoX(
+  int iCP,
+  BOOL fTrailing,
+  int cChars,
+  int cGlyphs,
+  WORD *pwLogClust,
+  SCRIPT_VISATTR *psva,
+  int *piAdvance,
+  SCRIPT_ANALYSIS *psa,
+  int *piX
+);
+HRESULT ScriptCacheGetHeight(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  long *tmHeight
+);
+HRESULT ScriptFreeCache(
+  SCRIPT_CACHE *psc
+);
+HRESULT ScriptGetFontProperties(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  SCRIPT_FONTPROPERTIES *sfp
+);
+HRESULT ScriptGetLogicalWidths(
+  SCRIPT_ANALYSIS *psa,
+  int cChars,
+  int cGlyphs,
+  int *piGlyphWidth,
+  WORD *pwLogClust,
+  SCRIPT_VISATTR *psva,
+  int *piDx
+);
+HRESULT ScriptGetProperties(
+  SCRIPT_PROPERTIES ***ppSp,
+  int *piNumScripts
+);
+HRESULT ScriptGetCMap(
+  HDC hdc,
+  SCRIPT_CACHE* psc,
+  WCHAR* pwcInChars,
+  int cChars,
+  DWORD dwFlags,
+  WORD* pwOutGlyphs
+);
+HRESULT ScriptStringAnalyse(
+  HDC hdc,
+  void* pString,
+  int cString,
+  int cGlyphs,
+  int iCharset,
+  DWORD dwFlags,
+  int iReqWidth,
+  SCRIPT_CONTROL* psControl,
+  SCRIPT_STATE* psState,
+  int* piDx,
+  SCRIPT_TABDEF* pTabdef,
+  BYTE* pbInClass,
+  SCRIPT_STRING_ANALYSIS* pssa
+);
+HRESULT ScriptStringOut(
+  SCRIPT_STRING_ANALYSIS ssa, 
+  int iX, 
+  int iY, 
+  UINT uOptions, 
+  RECT* prc, 
+  int iMinSel, 
+  int iMaxSel, 
+  BOOL fDisabled 
+);
+HRESULT ScriptStringFree(
+  SCRIPT_STRING_ANALYSIS* pssa  
+);
+
+HRESULT ScriptItemize(
+  WCHAR *pwcInChars,
+  int cInChars,
+  int cMaxItems,
+  SCRIPT_CONTROL *psControl,
+  SCRIPT_STATE *psState,
+  SCRIPT_ITEM *pItems,
+  int *pcItems
+);
+HRESULT ScriptLayout(
+  int cRuns,
+  BYTE *pbLevel,
+  int *piVisualToLogical,
+  int *piLogicalToVisual
+);
+HRESULT ScriptPlace(
+  HDC hdc,
+  SCRIPT_CACHE *psc,
+  WORD *pwGlyphs,
+  int cGlyphs,
+  SCRIPT_VISATTR *psva,
+  SCRIPT_ANALYSIS *psa,
+  int *piAdvance,
+  GOFFSET *pGoffset,
+  ABC *pABC
+);
+HRESULT ScriptShape(
+  HDC hdc,              // in
+  SCRIPT_CACHE *psc,    // in/out
+  WCHAR *pwcChars,      //
+  int cChars,
+  int cMaxGlyphs,
+  SCRIPT_ANALYSIS *psa,
+  WORD *pwOutGlyphs,
+  WORD *pwLogClust,
+  SCRIPT_VISATTR *psva,
+  int *pcGlyphs
+);
+HRESULT ScriptTextOut(
+  HDC hdc,              // const
+  SCRIPT_CACHE *psc,
+  int x,
+  int y,
+  UINT fuOptions,
+  RECT *lprc,           // const
+  SCRIPT_ANALYSIS *psa, // const
+  WCHAR *pwcReserved,   // const
+  int iReserved,
+  WORD *pwGlyphs,       //
+  int cGlyphs,
+  int *piAdvance,       // const
+  int *piJustify,       // const
+  GOFFSET *pGoffset     // const
+);
+HRESULT ScriptXtoCP(
+  int iX,
+  int cChars,
+  int cGlyphs,
+  WORD *pwLogClust,         //
+  SCRIPT_VISATTR *psva,     //
+  int *piAdvance,           //
+  SCRIPT_ANALYSIS *psa,     //
+  int *piCP,
+  int *piTrailing
+);
+UINT SendInput(
+    UINT nInputs,
+    LPINPUT pInputs,
+    int cbSize
+);
+// the basic
+int SendMessageA(HWND hWnd, int msg, int wParam, int lParam );
+int SendMessageW(HWND hWnd, int msg, int wParam, int lParam );
+
+int SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, void* lParam );
+int SendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, void* lParam );
+int SendMessageA(HWND hWnd, UINT Msg, void* wParam, LPARAM lParam );
+int SendMessageW(HWND hWnd, UINT Msg, void* wParam, LPARAM lParam );
+int SendMessageA(HWND hWnd, UINT Msg, void* wParam, void* lParam );
+int SendMessageW(HWND hWnd, UINT Msg, void* wParam, void* lParam );
+
+HWND SetCapture(
+    HWND hWnd
+);
+BOOL SetCaretPos(
+    int X,
+    int Y
+);
+HANDLE SetClipboardData(
+    UINT uFormat,
+    HANDLE hMem
+);
+UINT SetDIBColorTable(
+    HDC hdc,                // handle to device context whose DIB is of interest
+    UINT uStartIndex,       // color table index of first entry to set
+    UINT cEntries,          // number of color table entries to set
+    RGBQUAD *pColors  // pointer to array of color table entries
+);
+UINT SetErrorMode(
+    UINT uMode
+);
+BOOL SetEvent(
+  HANDLE hEvent   // handle to event object
+);
+void SetLastError(
+    DWORD dwErrCode
+);
+DWORD SetLayout(
+    HDC hdc,             // handle to DC
+    DWORD dwLayout       // layout options
+);
+BOOL SetMenu(
+    HWND hWnd,
+    HMENU hMenu
+);
+BOOL SetMenuDefaultItem(
+    HMENU hMenu,
+    UINT uItem,
+    UINT fByPos
+);
+BOOL SetMenuInfo(
+    HMENU hmenu,
+    LPCMENUINFO lpcmi
+);
+BOOL SetMenuItemInfoA(
+    HMENU hMenu,
+    UINT uItem,
+    BOOL fByPosition,
+    LPMENUITEMINFOA lpmii
+);
+BOOL SetMenuItemInfoW(
+    HMENU hMenu,
+    UINT uItem,
+    BOOL fByPosition,
+    LPMENUITEMINFOW lpmii
+);
+UINT SetPaletteEntries(
+    HPALETTE hpal,             // handle to logical palette
+    UINT iStart,               // index of first entry to set
+    UINT cEntries,             // number of entries to set
+    PALETTEENTRY *lppe              // array of palette entries
+);
+HWND SetParent(
+    HWND hWndChild,
+    HWND hWndNewParent
+);
+// alias STDWIN.SetPixel SetPixel;
+// alias STDWIN.SetROP2 SetROP2;
+BOOL SetRect(
+    LPRECT lprc, // rectangle
+    int xLeft,   // left side
+    int yTop,    // top side
+    int xRight,  // right side
+    int yBottom  // bottom side
+);
+// alias STDWIN.SetRectRgn SetRectRgn;
+int SetScrollInfo(
+    HWND hwnd,
+    int fnBar,
+    LPCSCROLLINFO lpsi,
+    BOOL fRedraw
+);
+UINT_PTR SetTimer(
+    HWND hWnd,
+    UINT_PTR nIDEvent,
+    UINT uElapse,
+    TIMERPROC lpTimerFunc
+);
+LONG SetWindowLongA(
+    HWND hWnd,
+    int nIndex,
+    LONG dwNewLong
+);
+LONG SetWindowLongW(
+    HWND hWnd,
+    int nIndex,
+    LONG dwNewLong
+);
+
+BOOL SetWindowPlacement(
+    HWND hWnd,
+    WINDOWPLACEMENT *lpwndpl
+);
+BOOL SetWindowPos(
+    HWND hWnd,             // handle to window
+    HWND hWndInsertAfter,  // placement-order handle
+    int X,                 // horizontal position
+    int Y,                 // vertical position
+    int cx,                // width
+    int cy,                // height
+    UINT uFlags            // window-positioning flags
+);
+BOOL SetWindowTextA(
+    HWND hWnd,
+    LPCSTR lpString
+);
+BOOL SetWindowTextW(
+    HWND hWnd,
+    LPCWSTR lpString
+);
+HHOOK SetWindowsHookExA(
+    int idHook,        // type of hook to install
+    HOOKPROC lpfn,     // address of hook procedure
+    HINSTANCE hMod,    // handle to application instance
+    DWORD dwThreadId   // identity of thread to install hook for
+);
+HHOOK SetWindowsHookExW(
+    int idHook,        // type of hook to install
+    HOOKPROC lpfn,     // address of hook procedure
+    HINSTANCE hMod,    // handle to application instance
+    DWORD dwThreadId   // identity of thread to install hook for
+);
+BOOL ShellExecuteExA(
+    LPSHELLEXECUTEINFOA lpExecInfo
+);
+BOOL ShellExecuteExW(
+    LPSHELLEXECUTEINFOW lpExecInfo
+);
+BOOL Shell_NotifyIconA(
+    DWORD dwMessage,
+    PNOTIFYICONDATAA lpdata
+);
+BOOL Shell_NotifyIconW(
+    DWORD dwMessage,
+    PNOTIFYICONDATAW lpdata
+);
+BOOL ShowOwnedPopups(
+    HWND hWnd,
+    BOOL fShow
+);
+version(WinCE)
+{
+BOOL SipGetInfo(
+    SIPINFO *pSipInfo
+);
+}
+DWORD SizeofResource(
+    HMODULE hModule, // resource-module handle
+    HRSRC hResInfo   // resource handle
+);
+void Sleep(
+    DWORD dwMilliseconds
+);
+int StartDocA(
+    HDC hdc,              // handle to DC
+    DOCINFOA* lpdi          // contains file names
+);
+int StartDocW(
+    HDC hdc,              // handle to DC
+    DOCINFOW* lpdi          // contains file names
+);
+int StartPage(
+    HDC hDC   // handle to DC
+);
+// alias STDWIN.StretchBlt StretchBlt;
+BOOL SystemParametersInfoA(
+    UINT uiAction,
+    UINT uiParam,
+    PVOID pvParam,
+    UINT fWinIni
+);
+BOOL SystemParametersInfoW(
+    UINT uiAction,
+    UINT uiParam,
+    PVOID pvParam,
+    UINT fWinIni
+);
+int ToAscii(
+    UINT uVirtKey,
+    UINT uScanCode,
+    PBYTE lpKeyState,
+    LPWORD lpChar,
+    UINT uFlags
+);
+int ToUnicode(
+    UINT wVirtKey,
+    UINT wScanCode,
+    PBYTE lpKeyState,
+    LPWSTR pwszBuff,
+    int cchBuff,
+    UINT wFlags
+);
+BOOL TrackMouseEvent(
+    LPTRACKMOUSEEVENT lpEventTrack  // pointer to a TRACKMOUSEEVENT structure
+);
+int TranslateAcceleratorA(
+    HWND hWnd,         // handle to destination window
+    HACCEL hAccTable,  // handle to accelerator table
+    LPMSG lpMsg        // address of structure with message
+);
+int TranslateAcceleratorW(
+    HWND hWnd,         // handle to destination window
+    HACCEL hAccTable,  // handle to accelerator table
+    LPMSG lpMsg        // address of structure with message
+);
+UINT TranslateCharsetInfo(
+    DWORD *lpSrc,
+    LPCHARSETINFO lpCs,
+    DWORD dwFlags
+);
+BOOL TranslateMDISysAccel(
+    HWND hWndClient,
+    LPMSG lpMsg
+);
+BOOL TranslateMessage(
+    MSG *lpMsg   // address of structure with message
+);
+version(WinCE)
+{
+BOOL TransparentImage(
+HDC hdcDest,
+LONG DstX,
+LONG DstY,
+LONG DstCx,
+LONG DstCy,
+HANDLE hSrc,
+LONG SrcX,
+LONG SrcY,
+LONG SrcCx,
+LONG SrcCy,
+COLORREF TransparentColor
+);
+}
+BOOL UnhookWindowsHookEx(
+    HHOOK hhk   // handle to hook procedure to remove
+);
+BOOL UnregisterClassA(
+    LPCSTR lpClassName,  // address of class name string
+    HINSTANCE hInstance   // handle of application instance
+);
+BOOL UnregisterClassW(
+    LPCWSTR lpClassName,  // address of class name string
+    HINSTANCE hInstance   // handle of application instance
+);
+SHORT VkKeyScanA(char ch);
+SHORT VkKeyScanW(wchar ch);
+BOOL WaitMessage();
+
+BOOL GetScrollBarInfo(
+    HWND hwnd,
+    LONG idObject,
+    PSCROLLBARINFO psbi
+);
+
+}
+
+extern (C)
+{
+    int wcslen(wchar* string);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/internal/win32/WINTYPES.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,15928 @@
+/*
+ * This module declared types required by SWT but not in std.c.windows.windows
+ */
+
+module org.eclipse.swt.internal.win32.WINTYPES;
+
+
+/*
+    adopted form tango
+    Author:     Trevor Parscal
+*/
+version(TANGOSVN){
+    public import tango.sys.win32.Types;
+}
+else{ // !TANGOSVN
+/+ Aliases, Types, and Constants +/
+const void* NULL = null;
+alias int SCODE;
+alias void VOID;
+alias void* POINTER;
+alias ushort ATOM;
+alias int WINBOOL;
+alias WINBOOL BOOL;
+alias uint CALTYPE;
+alias uint CALID;
+alias char CCHAR;
+alias char* PCHAR;
+alias uint COLORREF;
+alias uint TCOLORREF;
+alias char CHAR;
+alias ubyte BYTE;
+alias short INT16;
+alias ushort UINT16;
+alias short SHORT;
+alias int INT;
+alias int WINT;
+alias int LONG;
+alias ushort WORD;
+alias uint DWORD;
+alias int INT_PTR;
+alias uint UINT_PTR;
+alias int LONG_PTR;
+alias uint ULONG_PTR;
+alias DWORD DWORD_PTR;
+alias uint PROPID;
+const BOOL FALSE = 0;
+const BOOL TRUE = -1;
+alias char* PANSICHAR;
+alias wchar* PWIDECHAR;
+alias int* PINTEGER;
+alias long LONGLONG;
+alias LONGLONG* PLONGLONG;
+alias ulong DWORDLONG;
+alias DWORDLONG* PDWORDLONG;
+alias float FLOAT;
+alias void* HANDLE;
+alias HANDLE HACCEL;
+alias HANDLE HBITMAP;
+alias HANDLE HBRUSH;
+alias HANDLE HCOLORSPACE;
+alias HANDLE HCONV;
+alias HANDLE HCONVLIST;
+alias HANDLE HCURSOR;
+alias HANDLE HDBC;
+alias HANDLE HDC;
+alias HANDLE HDDEDATA;
+alias HANDLE HDESK;
+alias HANDLE HDROP;
+alias HANDLE HDWP;
+alias HANDLE HENHMETAFILE;
+alias HANDLE HENV;
+alias HANDLE HFILE;
+alias HANDLE HFONT;
+alias HANDLE HGDIOBJ;
+alias HANDLE HGLOBAL;
+alias HANDLE HGLRC;
+alias HANDLE HHOOK;
+alias HANDLE HICON;
+alias HANDLE HIMAGELIST;
+alias HANDLE HINST;
+alias HINST HINSTANCE;
+alias HANDLE HKEY;
+alias HANDLE HKL;
+alias HANDLE HLOCAL;
+alias HANDLE HMENU;
+alias HANDLE HMETAFILE;
+alias HANDLE HMODULE;
+alias HANDLE HPALETTE;
+alias HANDLE HPEN;
+alias HANDLE HRASCONN;
+alias int HRESULT;
+alias HANDLE HRGN;
+alias HANDLE HRSRC;
+alias HANDLE HSTMT;
+alias HANDLE HSZ;
+alias HANDLE HWINSTA;
+alias HANDLE HWND;
+alias ushort LANGID;
+alias DWORD LCID;
+alias DWORD LCTYPE;
+alias int LPARAM;
+alias ushort* LP;
+alias WINBOOL* LPBOOL;
+alias ubyte* LPBYTE;
+alias PCHAR LPCCH;
+alias PCHAR LPCH;
+alias COLORREF* LPCOLORREF;
+alias PCHAR LPCSTR;
+alias TCHAR* LPCTSTR;
+alias wchar* LPCWCH;
+alias wchar* LPCWSTR;
+alias DWORD* LPDWORD;
+alias HANDLE* LPHANDLE;
+alias int* LPINT;
+alias int* LPLONG;
+alias PCHAR LPSTR;
+alias PCHAR LPTCH;
+alias TCHAR* LPTSTR;
+alias int LRESULT;
+alias POINTER LPVOID;
+alias POINTER LPCVOID;
+alias wchar* LPWCH;
+alias wchar* LPWORD;
+alias wchar* LPWSTR;
+alias wchar* NWPSTR;
+alias WINBOOL* PWINBOOL;
+alias ubyte BOOLEAN;
+alias ubyte* PBOOLEAN;
+alias ubyte* PBYTE;
+alias PCHAR PCCH;
+alias PCHAR PCH;
+alias PCHAR PCSTR;
+alias wchar* PCWCH;
+alias wchar* PCWSTR;
+alias DWORD* PDWORD;
+alias float* PFLOAT;
+alias HANDLE* PHANDLE;
+alias HKEY* PHKEY;
+alias int* PINT;
+alias int* PLONG;
+alias int* PSHORT;
+alias PCHAR PSTR;
+alias PCHAR PSZ;
+alias ubyte* PTBYTE;
+alias PCHAR PTCH;
+alias PCHAR PTCHAR;
+alias PCHAR PTSTR;
+alias ubyte* PUCHAR;
+alias wchar* PWCH;
+alias wchar* PWCHAR;
+alias ushort* PWORD;
+alias uint* PUINT;
+alias uint* PULONG;
+alias ushort* PUSHORT;
+alias POINTER PVOID;
+// NOTE: This is defined in sqltypes.  Probably shouldn't be here.  Commenting for now.
+//alias int RETCODE;
+alias HANDLE SC_HANDLE;
+alias LPVOID SC_LOCK;
+alias SC_HANDLE* LPSC_HANDLE;
+alias DWORD SERVICE_STATUS_HANDLE;
+alias ubyte TBYTE;
+
+version(Win32SansUnicode){
+    // Strictly speaking this should be ubyte since char is UTF-8, but that
+    // fills code with so many casts that it's just not sensible.
+    // (See also DMD Issue 2193.)
+    alias  char TCHAR;
+}else{
+    alias wchar TCHAR;
+}
+
+alias ubyte BCHAR;
+alias ubyte UCHAR;
+alias wchar WCHAR;
+alias uint UINT;
+alias uint ULONG;
+alias ushort USHORT;
+alias uint WPARAM;
+alias int ACL_INFORMATION_CLASS;
+
+alias GUID IID;
+alias IID* REFIID;
+
+// Cast a string literal to a ubyte*=PCHAR
+template _PCHAR( char[] a ){
+    const PCHAR _PCHAR = cast(PCHAR)a.ptr;
+}
+
+enum { AclRevisionInformation = 1, AclSizeInformation,  };
+alias ACL_INFORMATION_CLASS _ACL_INFORMATION_CLASS;
+alias int MEDIA_TYPE;
+enum { Unknown, F5_1Pt2_512, F3_1Pt44_512, F3_2Pt88_512, F3_20Pt8_512, F3_720_512, F5_360_512, F5_320_512, F5_320_1024, F5_180_512, F5_160_512, RemovableMedia, FixedMedia,  };
+alias MEDIA_TYPE _MEDIA_TYPE;
+const int RASCS_DONE = (0x2000);
+const int RASCS_PAUSED = (0x1000);
+alias int RASCONNSTATE;
+enum { RASCS_OpenPort = 0, RASCS_PortOpened, RASCS_ConnectDevice, RASCS_DeviceConnected, RASCS_AllDevicesConnected, RASCS_Authenticate, RASCS_AuthNotify, RASCS_AuthRetry, RASCS_AuthCallback, RASCS_AuthChangePassword, RASCS_AuthProject, RASCS_AuthLinkSpeed, RASCS_AuthAck, RASCS_ReAuthenticate, RASCS_Authenticated, RASCS_PrepareForCallback, RASCS_WaitForModemReset, RASCS_WaitForCallback, RASCS_Projected, RASCS_StartAuthentication, RASCS_CallbackComplete, RASCS_LogonNetwork, RASCS_Interactive = RASCS_PAUSED, RASCS_RetryAuthentication, RASCS_CallbackSetByCaller, RASCS_PasswordExpired, RASCS_Connected = RASCS_DONE, RASCS_Disconnected,  };
+alias RASCONNSTATE _RASCONNSTATE;
+alias int RASPROJECTION;
+enum { RASP_Amb = 0x10000, RASP_PppNbf = 0x803F, RASP_PppIpx = 0x802B, RASP_PppIp = 0x8021,  };
+alias RASPROJECTION _RASPROJECTION;
+alias int SECURITY_IMPERSONATION_LEVEL;
+enum { SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation,  };
+alias SECURITY_IMPERSONATION_LEVEL _SECURITY_IMPERSONATION_LEVEL;
+alias int SID_NAME_USE;
+enum { SidTypeUser = 1, SidTypeGroup, SidTypeDomain, SidTypeAlias, SidTypeWellKnownGroup, SidTypeDeletedAccount, SidTypeInvalid, SidTypeUnknown,  };
+alias SID_NAME_USE* PSID_NAME_USE;
+alias SID_NAME_USE _SID_NAME_USE;
+alias int TOKEN_INFORMATION_CLASS;
+enum { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics,  };
+alias TOKEN_INFORMATION_CLASS _TOKEN_INFORMATION_CLASS;
+alias int TOKEN_TYPE;
+enum { TokenPrimary = 1, TokenImpersonation,  };
+alias TOKEN_TYPE TAGTOKEN_TYPE;
+
+extern(Windows){
+alias int (*BFFCALLBACK)(HWND, UINT, LPARAM, LPARAM);
+alias UINT (*LPCCHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias UINT (*LPCFHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias POINTER PTHREAD_START_ROUTINE;
+alias PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
+alias DWORD (*EDITSTREAMCALLBACK)(DWORD, LPBYTE, LONG, LONG);
+alias UINT (*LPFRHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias UINT (*LPOFNHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias UINT (*LPPRINTHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias UINT (*LPSETUPHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+alias LRESULT (*DLGPROC)(HWND, UINT, WPARAM, LPARAM);
+alias int (*PFNPROPSHEETCALLBACK)(HWND, UINT, LPARAM);
+alias void (*LPSERVICE_MAIN_FUNCTION)(DWORD, LPTSTR);
+alias int (*PFNTVCOMPARE)(LPARAM, LPARAM, LPARAM);
+alias LRESULT (*WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+alias POINTER FARPROC;
+alias FARPROC PROC;
+alias WINBOOL (*ENUMRESTYPEPROC)(HANDLE, LPTSTR, LONG);
+alias WINBOOL (*ENUMRESNAMEPROC)(HANDLE, LPCTSTR, LPTSTR, LONG);
+alias WINBOOL (*ENUMRESLANGPROC)(HANDLE, LPCTSTR, LPCTSTR, ushort, LONG);
+alias FARPROC DESKTOPENUMPROC;
+alias WINBOOL (*ENUMWINDOWSPROC)(HWND, LPARAM);
+alias WINBOOL (*ENUMWINDOWSTATIONPROC)(LPTSTR, LPARAM);
+alias void (*SENDASYNCPROC)(HWND, UINT, DWORD);
+alias void (*TIMERPROC)(HWND, UINT, UINT, DWORD);
+alias BOOL(*MONITORENUMPROC)(HMONITOR, HDC, RECT*, LPARAM);
+alias FARPROC GRAYSTRINGPROC;
+alias WINBOOL (*DRAWSTATEPROC)(HDC, LPARAM, WPARAM, int, int);
+alias WINBOOL (*PROPENUMPROCEX)(HWND, LPCTSTR, HANDLE, DWORD);
+alias WINBOOL (*PROPENUMPROC)(HWND, LPCTSTR, HANDLE);
+alias LRESULT (*HOOKPROC)(int, WPARAM, LPARAM);
+alias void (*ENUMOBJECTSPROC)(LPVOID);
+alias void (*LINEDDAPROC)(int, int);
+alias WINBOOL (*TABORTPROC)(HDC, int);
+alias UINT (*LPPAGEPAINTHOOK)(HWND, UINT, WPARAM, LPARAM);
+alias UINT (*LPPAGESETUPHOOK)(HWND, UINT, WPARAM, LPARAM);
+alias int (*ICMENUMPROC)(LPTSTR, LPARAM);
+alias LONG (*EDITWORDBREAKPROCEX)(PCHAR, LONG, ubyte, INT);
+alias int (*PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM);
+alias WINBOOL (*LOCALE_ENUMPROC)(LPTSTR);
+alias WINBOOL (*CODEPAGE_ENUMPROC)(LPTSTR);
+alias WINBOOL (*DATEFMT_ENUMPROC)(LPTSTR);
+alias WINBOOL (*TIMEFMT_ENUMPROC)(LPTSTR);
+alias WINBOOL (*CALINFO_ENUMPROC)(LPTSTR);
+alias WINBOOL (*PHANDLER_ROUTINE)(DWORD);
+alias WINBOOL (*LPHANDLER_FUNCTION)(DWORD);
+alias void (*PTIMERAPCROUTINE)(LPVOID, DWORD, DWORD);
+alias UINT (*PFNGETPROFILEPATH)(LPCTSTR, LPSTR, UINT);
+alias UINT (*PFNRECONCILEPROFILE)(LPCTSTR, LPCTSTR, DWORD);
+alias WINBOOL (*PFNPROCESSPOLICIES)(HWND, LPCTSTR, LPCTSTR, LPCTSTR, DWORD);
+}
+
+const {
+    LPCTSTR SE_CREATE_TOKEN_NAME = ("SeCreateTokenPrivilege");
+    LPCTSTR SE_ASSIGNPRIMARYTOKEN_NAME = ("SeAssignPrimaryTokenPrivilege");
+    LPCTSTR SE_LOCK_MEMORY_NAME = ("SeLockMemoryPrivilege");
+    LPCTSTR SE_INCREASE_QUOTA_NAME = ("SeIncreaseQuotaPrivilege");
+    LPCTSTR SE_UNSOLICITED_INPUT_NAME = ("SeUnsolicitedInputPrivilege");
+    LPCTSTR SE_MACHINE_ACCOUNT_NAME = ("SeMachineAccountPrivilege");
+    LPCTSTR SE_TCB_NAME = ("SeTcbPrivilege");
+    LPCTSTR SE_SECURITY_NAME = ("SeSecurityPrivilege");
+    LPCTSTR SE_TAKE_OWNERSHIP_NAME = ("SeTakeOwnershipPrivilege");
+    LPCTSTR SE_LOAD_DRIVER_NAME = ("SeLoadDriverPrivilege");
+    LPCTSTR SE_SYSTEM_PROFILE_NAME = ("SeSystemProfilePrivilege");
+    LPCTSTR SE_SYSTEMTIME_NAME = ("SeSystemtimePrivilege");
+    LPCTSTR SE_PROF_SINGLE_PROCESS_NAME = ("SeProfileSingleProcessPrivilege");
+    LPCTSTR SE_INC_BASE_PRIORITY_NAME = ("SeIncreaseBasePriorityPrivilege");
+    LPCTSTR SE_CREATE_PAGEFILE_NAME = ("SeCreatePagefilePrivilege");
+    LPCTSTR SE_CREATE_PERMANENT_NAME = ("SeCreatePermanentPrivilege");
+    LPCTSTR SE_BACKUP_NAME = ("SeBackupPrivilege");
+    LPCTSTR SE_RESTORE_NAME = ("SeRestorePrivilege");
+    LPCTSTR SE_SHUTDOWN_NAME = ("SeShutdownPrivilege");
+    LPCTSTR SE_DEBUG_NAME = ("SeDebugPrivilege");
+    LPCTSTR SE_AUDIT_NAME = ("SeAuditPrivilege");
+    LPCTSTR SE_SYSTEM_ENVIRONMENT_NAME = ("SeSystemEnvironmentPrivilege");
+    LPCTSTR SE_CHANGE_NOTIFY_NAME = ("SeChangeNotifyPrivilege");
+    LPCTSTR SE_REMOTE_SHUTDOWN_NAME = ("SeRemoteShutdownPrivilege");
+
+    LPCSTR  SERVICES_ACTIVE_DATABASEA = _PCHAR!("ServicesActive");
+    LPCWSTR SERVICES_ACTIVE_DATABASEW = ("ServicesActive");
+    LPCSTR  SERVICES_FAILED_DATABASEA = _PCHAR!("ServicesFailed");
+    LPCWSTR SERVICES_FAILED_DATABASEW = ("ServicesFailed");
+    LPCSTR  SC_GROUP_IDENTIFIERA = _PCHAR!("+");
+    LPCWSTR SC_GROUP_IDENTIFIERW = ("+");
+    version(Win32SansUnicode){
+        alias SERVICES_ACTIVE_DATABASEA SERVICES_ACTIVE_DATABASE;
+        alias SERVICES_FAILED_DATABASEA SERVICES_FAILED_DATABASE;
+        alias SC_GROUP_IDENTIFIERA SC_GROUP_IDENTIFIER;
+    }
+    else{
+        alias SERVICES_ACTIVE_DATABASEW SERVICES_ACTIVE_DATABASE;
+        alias SERVICES_FAILED_DATABASEW SERVICES_FAILED_DATABASE;
+        alias SC_GROUP_IDENTIFIERW SC_GROUP_IDENTIFIER;
+    }
+}
+
+extern(Windows){
+alias HDDEDATA (*PFNCALLBACK)(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD);
+}
+alias PFNCALLBACK CALLB;
+alias WINBOOL SECURITY___FILE___TRACKING_MODE;
+alias FARPROC WNDENUMPROC;
+alias FARPROC ENHMFENUMPROC;
+alias DWORD CCSTYLE;
+alias CCSTYLE* PCCSTYLE;
+alias CCSTYLE* LPCCSTYLE;
+alias DWORD CCSTYLEFLAGA;
+alias CCSTYLEFLAGA* PCCSTYLEFLAGA;
+alias CCSTYLEFLAGA* LPCCSTYLEFLAGA;
+
+const HANDLE INVALID_HANDLE_VALUE = cast(HANDLE) -1;
+
+
+enum : DWORD {
+    SM_CXVIRTUALSCREEN = (76),
+    SM_CYVIRTUALSCREEN = (77),
+    MONITORINFOF_PRIMARY = (1),
+    LZERROR_UNKNOWNALG = -((8)),
+    LZERROR_BADVALUE = -((7)),
+    LZERROR_GLOBLOCK = -((6)),
+    LZERROR_GLOBALLOC = -((5)),
+    LZERROR_WRITE = -((4)),
+    LZERROR_READ = -((3)),
+    LZERROR_BADOUTHANDLE = -((2)),
+    LZERROR_BADINHANDLE = -((1)),
+    NO_ERROR = (0),
+    ERROR_SUCCESS = (0),
+    ERROR_INVALID_FUNCTION = (1),
+    ERROR_FILE_NOT_FOUND = (2),
+    ERROR_PATH_NOT_FOUND = (3),
+    ERROR_TOO_MANY_OPEN_FILES = (4),
+    ERROR_ACCESS_DENIED = (5),
+    ERROR_INVALID_HANDLE = (6),
+    ERROR_ARENA_TRASHED = (7),
+    ERROR_NOT_ENOUGH_MEMORY = (8),
+    ERROR_INVALID_BLOCK = (9),
+    ERROR_BAD_ENVIRONMENT = (10),
+    ERROR_BAD_FORMAT = (11),
+    ERROR_INVALID_ACCESS = (12),
+    ERROR_INVALID_DATA = (13),
+    ERROR_OUTOFMEMORY = (14),
+    ERROR_INVALID_DRIVE = (15),
+    ERROR_CURRENT_DIRECTORY = (16),
+    ERROR_NOT_SAME_DEVICE = (17),
+    ERROR_NO_MORE_FILES = (18),
+    ERROR_WRITE_PROTECT = (19),
+    ERROR_BAD_UNIT = (20),
+    ERROR_NOT_READY = (21),
+    ERROR_BAD_COMMAND = (22),
+    ERROR_CRC = (23),
+    ERROR_BAD_LENGTH = (24),
+    ERROR_SEEK = (25),
+    ERROR_NOT_DOS_DISK = (26),
+    ERROR_SECTOR_NOT_FOUND = (27),
+    ERROR_OUT_OF_PAPER = (28),
+    ERROR_WRITE_FAULT = (29),
+    ERROR_READ_FAULT = (30),
+    ERROR_GEN_FAILURE = (31),
+    ERROR_SHARING_VIOLATION = (32),
+    ERROR_LOCK_VIOLATION = (33),
+    ERROR_WRONG_DISK = (34),
+    ERROR_SHARING_BUFFER_EXCEEDED = (36),
+    ERROR_HANDLE_EOF = (38),
+    ERROR_HANDLE_DISK_FULL = (39),
+    ERROR_NOT_SUPPORTED = (50),
+    ERROR_REM_NOT_LIST = (51),
+    ERROR_DUP_NAME = (52),
+    ERROR_BAD_NETPATH = (53),
+    ERROR_NETWORK_BUSY = (54),
+    ERROR_DEV_NOT_EXIST = (55),
+    ERROR_TOO_MANY_CMDS = (56),
+    ERROR_ADAP_HDW_ERR = (57),
+    ERROR_BAD_NET_RESP = (58),
+    ERROR_UNEXP_NET_ERR = (59),
+    ERROR_BAD_REM_ADAP = (60),
+    ERROR_PRINTQ_FULL = (61),
+    ERROR_NO_SPOOL_SPACE = (62),
+    ERROR_PRINT_CANCELLED = (63),
+    ERROR_NETNAME_DELETED = (64),
+    ERROR_NETWORK_ACCESS_DENIED = (65),
+    ERROR_BAD_DEV_TYPE = (66),
+    ERROR_BAD_NET_NAME = (67),
+    ERROR_TOO_MANY_NAMES = (68),
+    ERROR_TOO_MANY_SESS = (69),
+    ERROR_SHARING_PAUSED = (70),
+    ERROR_REQ_NOT_ACCEP = (71),
+    ERROR_REDIR_PAUSED = (72),
+    ERROR_FILE_EXISTS = (80),
+    ERROR_CANNOT_MAKE = (82),
+    ERROR_FAIL_I24 = (83),
+    ERROR_OUT_OF_STRUCTURES = (84),
+    ERROR_ALREADY_ASSIGNED = (85),
+    ERROR_INVALID_PASSWORD = (86),
+    ERROR_INVALID_PARAMETER = (87),
+    ERROR_NET_WRITE_FAULT = (88),
+    ERROR_NO_PROC_SLOTS = (89),
+    ERROR_TOO_MANY_SEMAPHORES = (100),
+    ERROR_EXCL_SEM_ALREADY_OWNED = (101),
+    ERROR_SEM_IS_SET = (102),
+    ERROR_TOO_MANY_SEM_REQUESTS = (103),
+    ERROR_INVALID_AT_INTERRUPT_TIME = (104),
+    ERROR_SEM_OWNER_DIED = (105),
+    ERROR_SEM_USER_LIMIT = (106),
+    ERROR_DISK_CHANGE = (107),
+    ERROR_DRIVE_LOCKED = (108),
+    ERROR_BROKEN_PIPE = (109),
+    ERROR_OPEN_FAILED = (110),
+    ERROR_BUFFER_OVERFLOW = (111),
+    ERROR_DISK_FULL = (112),
+    ERROR_NO_MORE_SEARCH_HANDLES = (113),
+    ERROR_INVALID_TARGET_HANDLE = (114),
+    ERROR_INVALID_CATEGORY = (117),
+    ERROR_INVALID_VERIFY_SWITCH = (118),
+    ERROR_BAD_DRIVER_LEVEL = (119),
+    ERROR_CALL_NOT_IMPLEMENTED = (120),
+    ERROR_SEM_TIMEOUT = (121),
+    ERROR_INSUFFICIENT_BUFFER = (122),
+    ERROR_INVALID_NAME = (123),
+    ERROR_INVALID_LEVEL = (124),
+    ERROR_NO_VOLUME_LABEL = (125),
+    ERROR_MOD_NOT_FOUND = (126),
+    ERROR_PROC_NOT_FOUND = (127),
+    ERROR_WAIT_NO_CHILDREN = (128),
+    ERROR_CHILD_NOT_COMPLETE = (129),
+    ERROR_DIRECT_ACCESS_HANDLE = (130),
+    ERROR_NEGATIVE_SEEK = (131),
+    ERROR_SEEK_ON_DEVICE = (132),
+    ERROR_IS_JOIN_TARGET = (133),
+    ERROR_IS_JOINED = (134),
+    ERROR_IS_SUBSTED = (135),
+    ERROR_NOT_JOINED = (136),
+    ERROR_NOT_SUBSTED = (137),
+    ERROR_JOIN_TO_JOIN = (138),
+    ERROR_SUBST_TO_SUBST = (139),
+    ERROR_JOIN_TO_SUBST = (140),
+    ERROR_SUBST_TO_JOIN = (141),
+    ERROR_BUSY_DRIVE = (142),
+    ERROR_SAME_DRIVE = (143),
+    ERROR_DIR_NOT_ROOT = (144),
+    ERROR_DIR_NOT_EMPTY = (145),
+    ERROR_IS_SUBST_PATH = (146),
+    ERROR_IS_JOIN_PATH = (147),
+    ERROR_PATH_BUSY = (148),
+    ERROR_IS_SUBST_TARGET = (149),
+    ERROR_SYSTEM_TRACE = (150),
+    ERROR_INVALID_EVENT_COUNT = (151),
+    ERROR_TOO_MANY_MUXWAITERS = (152),
+    ERROR_INVALID_LIST_FORMAT = (153),
+    ERROR_LABEL_TOO_LONG = (154),
+    ERROR_TOO_MANY_TCBS = (155),
+    ERROR_SIGNAL_REFUSED = (156),
+    ERROR_DISCARDED = (157),
+    ERROR_NOT_LOCKED = (158),
+    ERROR_BAD_THREADID_ADDR = (159),
+    ERROR_BAD_ARGUMENTS = (160),
+    ERROR_BAD_PATHNAME = (161),
+    ERROR_SIGNAL_PENDING = (162),
+    ERROR_MAX_THRDS_REACHED = (164),
+    ERROR_LOCK_FAILED = (167),
+    ERROR_BUSY = (170),
+    ERROR_CANCEL_VIOLATION = (173),
+    ERROR_ATOMIC_LOCKS_NOT_SUPPORTED = (174),
+    ERROR_INVALID_SEGMENT_NUMBER = (180),
+    ERROR_INVALID_ORDINAL = (182),
+    ERROR_ALREADY_EXISTS = (183),
+    ERROR_INVALID_FLAG_NUMBER = (186),
+    ERROR_SEM_NOT_FOUND = (187),
+    ERROR_INVALID_STARTING_CODESEG = (188),
+    ERROR_INVALID_STACKSEG = (189),
+    ERROR_INVALID_MODULETYPE = (190),
+    ERROR_INVALID_EXE_SIGNATURE = (191),
+    ERROR_EXE_MARKED_INVALID = (192),
+    ERROR_BAD_EXE_FORMAT = (193),
+    ERROR_ITERATED_DATA_EXCEEDS_64k = (194),
+    ERROR_INVALID_MINALLOCSIZE = (195),
+    ERROR_DYNLINK_FROM_INVALID_RING = (196),
+    ERROR_IOPL_NOT_ENABLED = (197),
+    ERROR_INVALID_SEGDPL = (198),
+    ERROR_AUTODATASEG_EXCEEDS_64k = (199),
+    ERROR_RING2SEG_MUST_BE_MOVABLE = (200),
+    ERROR_RELOC_CHAIN_XEEDS_SEGLIM = (201),
+    ERROR_INFLOOP_IN_RELOC_CHAIN = (202),
+    ERROR_ENVVAR_NOT_FOUND = (203),
+    ERROR_NO_SIGNAL_SENT = (205),
+    ERROR_FILENAME_EXCED_RANGE = (206),
+    ERROR_RING2_STACK_IN_USE = (207),
+    ERROR_META_EXPANSION_TOO_LONG = (208),
+    ERROR_INVALID_SIGNAL_NUMBER = (209),
+    ERROR_THREAD_1_INACTIVE = (210),
+    ERROR_LOCKED = (212),
+    ERROR_TOO_MANY_MODULES = (214),
+    ERROR_NESTING_NOT_ALLOWED = (215),
+    ERROR_BAD_PIPE = (230),
+    ERROR_PIPE_BUSY = (231),
+    ERROR_NO_DATA = (232),
+    ERROR_PIPE_NOT_CONNECTED = (233),
+    ERROR_MORE_DATA = (234),
+    ERROR_VC_DISCONNECTED = (240),
+    ERROR_INVALID_EA_NAME = (254),
+    ERROR_EA_LIST_INCONSISTENT = (255),
+    ERROR_NO_MORE_ITEMS = (259),
+    ERROR_CANNOT_COPY = (266),
+    ERROR_DIRECTORY = (267),
+    ERROR_EAS_DIDNT_FIT = (275),
+    ERROR_EA_FILE_CORRUPT = (276),
+    ERROR_EA_TABLE_FULL = (277),
+    ERROR_INVALID_EA_HANDLE = (278),
+    ERROR_EAS_NOT_SUPPORTED = (282),
+    ERROR_NOT_OWNER = (288),
+    ERROR_TOO_MANY_POSTS = (298),
+    ERROR_PARTIAL_COPY = (299),
+    ERROR_MR_MID_NOT_FOUND = (317),
+    ERROR_INVALID_ADDRESS = (487),
+    ERROR_ARITHMETIC_OVERFLOW = (534),
+    ERROR_PIPE_CONNECTED = (535),
+    ERROR_PIPE_LISTENING = (536),
+    ERROR_EA_ACCESS_DENIED = (994),
+    ERROR_OPERATION_ABORTED = (995),
+    ERROR_IO_INCOMPLETE = (996),
+    ERROR_IO_PENDING = (997),
+    ERROR_NOACCESS = (998),
+    ERROR_SWAPERROR = (999),
+    ERROR_STACK_OVERFLOW = (1001),
+    ERROR_INVALID_MESSAGE = (1002),
+    ERROR_CAN_NOT_COMPLETE = (1003),
+    ERROR_INVALID_FLAGS = (1004),
+    ERROR_UNRECOGNIZED_VOLUME = (1005),
+    ERROR_FILE_INVALID = (1006),
+    ERROR_FULLSCREEN_MODE = (1007),
+    ERROR_NO_TOKEN = (1008),
+    ERROR_BADDB = (1009),
+    ERROR_BADKEY = (1010),
+    ERROR_CANTOPEN = (1011),
+    ERROR_CANTREAD = (1012),
+    ERROR_CANTWRITE = (1013),
+    ERROR_REGISTRY_RECOVERED = (1014),
+    ERROR_REGISTRY_CORRUPT = (1015),
+    ERROR_REGISTRY_IO_FAILED = (1016),
+    ERROR_NOT_REGISTRY_FILE = (1017),
+    ERROR_KEY_DELETED = (1018),
+    ERROR_NO_LOG_SPACE = (1019),
+    ERROR_KEY_HAS_CHILDREN = (1020),
+    ERROR_CHILD_MUST_BE_VOLATILE = (1021),
+    ERROR_NOTIFY_ENUM_DIR = (1022),
+    ERROR_DEPENDENT_SERVICES_RUNNING = (1051),
+    ERROR_INVALID_SERVICE_CONTROL = (1052),
+    ERROR_SERVICE_REQUEST_TIMEOUT = (1053),
+    ERROR_SERVICE_NO_THREAD = (1054),
+    ERROR_SERVICE_DATABASE_LOCKED = (1055),
+    ERROR_SERVICE_ALREADY_RUNNING = (1056),
+    ERROR_INVALID_SERVICE_ACCOUNT = (1057),
+    ERROR_SERVICE_DISABLED = (1058),
+    ERROR_CIRCULAR_DEPENDENCY = (1059),
+    ERROR_SERVICE_DOES_NOT_EXIST = (1060),
+    ERROR_SERVICE_CANNOT_ACCEPT_CTRL = (1061),
+    ERROR_SERVICE_NOT_ACTIVE = (1062),
+    ERROR_FAILED_SERVICE_CONTROLLER_CONNECT = (1063),
+    ERROR_EXCEPTION_IN_SERVICE = (1064),
+    ERROR_DATABASE_DOES_NOT_EXIST = (1065),
+    ERROR_SERVICE_SPECIFIC_ERROR = (1066),
+    ERROR_PROCESS_ABORTED = (1067),
+    ERROR_SERVICE_DEPENDENCY_FAIL = (1068),
+    ERROR_SERVICE_LOGON_FAILED = (1069),
+    ERROR_SERVICE_START_HANG = (1070),
+    ERROR_INVALID_SERVICE_LOCK = (1071),
+    ERROR_SERVICE_MARKED_FOR_DELETE = (1072),
+    ERROR_SERVICE_EXISTS = (1073),
+    ERROR_ALREADY_RUNNING_LKG = (1074),
+    ERROR_SERVICE_DEPENDENCY_DELETED = (1075),
+    ERROR_BOOT_ALREADY_ACCEPTED = (1076),
+    ERROR_SERVICE_NEVER_STARTED = (1077),
+    ERROR_DUPLICATE_SERVICE_NAME = (1078),
+    ERROR_END_OF_MEDIA = (1100),
+    ERROR_FILEMARK_DETECTED = (1101),
+    ERROR_BEGINNING_OF_MEDIA = (1102),
+    ERROR_SETMARK_DETECTED = (1103),
+    ERROR_NO_DATA_DETECTED = (1104),
+    ERROR_PARTITION_FAILURE = (1105),
+    ERROR_INVALID_BLOCK_LENGTH = (1106),
+    ERROR_DEVICE_NOT_PARTITIONED = (1107),
+    ERROR_UNABLE_TO_LOCK_MEDIA = (1108),
+    ERROR_UNABLE_TO_UNLOAD_MEDIA = (1109),
+    ERROR_MEDIA_CHANGED = (1110),
+    ERROR_BUS_RESET = (1111),
+    ERROR_NO_MEDIA_IN_DRIVE = (1112),
+    ERROR_NO_UNICODE_TRANSLATION = (1113),
+    ERROR_DLL_INIT_FAILED = (1114),
+    ERROR_SHUTDOWN_IN_PROGRESS = (1115),
+    ERROR_NO_SHUTDOWN_IN_PROGRESS = (1116),
+    ERROR_IO_DEVICE = (1117),
+    ERROR_SERIAL_NO_DEVICE = (1118),
+    ERROR_IRQ_BUSY = (1119),
+    ERROR_MORE_WRITES = (1120),
+    ERROR_COUNTER_TIMEOUT = (1121),
+    ERROR_FLOPPY_ID_MARK_NOT_FOUND = (1122),
+    ERROR_FLOPPY_WRONG_CYLINDER = (1123),
+    ERROR_FLOPPY_UNKNOWN_ERROR = (1124),
+    ERROR_FLOPPY_BAD_REGISTERS = (1125),
+    ERROR_DISK_RECALIBRATE_FAILED = (1126),
+    ERROR_DISK_OPERATION_FAILED = (1127),
+    ERROR_DISK_RESET_FAILED = (1128),
+    ERROR_EOM_OVERFLOW = (1129),
+    ERROR_NOT_ENOUGH_SERVER_MEMORY = (1130),
+    ERROR_POSSIBLE_DEADLOCK = (1131),
+    ERROR_MAPPED_ALIGNMENT = (1132),
+    ERROR_SET_POWER_STATE_VETOED = (1140),
+    ERROR_SET_POWER_STATE_FAILED = (1141),
+    ERROR_OLD_WIN_VERSION = (1150),
+    ERROR_APP_WRONG_OS = (1151),
+    ERROR_SINGLE_INSTANCE_APP = (1152),
+    ERROR_RMODE_APP = (1153),
+    ERROR_INVALID_DLL = (1154),
+    ERROR_NO_ASSOCIATION = (1155),
+    ERROR_DDE_FAIL = (1156),
+    ERROR_DLL_NOT_FOUND = (1157),
+    ERROR_BAD_USERNAME = (2202),
+    ERROR_NOT_CONNECTED = (2250),
+    ERROR_OPEN_FILES = (2401),
+    ERROR_ACTIVE_CONNECTIONS = (2402),
+    ERROR_DEVICE_IN_USE = (2404),
+    ERROR_BAD_DEVICE = (1200),
+    ERROR_CONNECTION_UNAVAIL = (1201),
+    ERROR_DEVICE_ALREADY_REMEMBERED = (1202),
+    ERROR_NO_NET_OR_BAD_PATH = (1203),
+    ERROR_BAD_PROVIDER = (1204),
+    ERROR_CANNOT_OPEN_PROFILE = (1205),
+    ERROR_BAD_PROFILE = (1206),
+    ERROR_NOT_CONTAINER = (1207),
+    ERROR_EXTENDED_ERROR = (1208),
+    ERROR_INVALID_GROUPNAME = (1209),
+    ERROR_INVALID_COMPUTERNAME = (1210),
+    ERROR_INVALID_EVENTNAME = (1211),
+    ERROR_INVALID_DOMAINNAME = (1212),
+    ERROR_INVALID_SERVICENAME = (1213),
+    ERROR_INVALID_NETNAME = (1214),
+    ERROR_INVALID_SHARENAME = (1215),
+    ERROR_INVALID_PASSWORDNAME = (1216),
+    ERROR_INVALID_MESSAGENAME = (1217),
+    ERROR_INVALID_MESSAGEDEST = (1218),
+    ERROR_SESSION_CREDENTIAL_CONFLICT = (1219),
+    ERROR_REMOTE_SESSION_LIMIT_EXCEEDED = (1220),
+    ERROR_DUP_DOMAINNAME = (1221),
+    ERROR_NO_NETWORK = (1222),
+    ERROR_CANCELLED = (1223),
+    ERROR_USER_MAPPED_FILE = (1224),
+    ERROR_CONNECTION_REFUSED = (1225),
+    ERROR_GRACEFUL_DISCONNECT = (1226),
+    ERROR_ADDRESS_ALREADY_ASSOCIATED = (1227),
+    ERROR_ADDRESS_NOT_ASSOCIATED = (1228),
+    ERROR_CONNECTION_INVALID = (1229),
+    ERROR_CONNECTION_ACTIVE = (1230),
+    ERROR_NETWORK_UNREACHABLE = (1231),
+    ERROR_HOST_UNREACHABLE = (1232),
+    ERROR_PROTOCOL_UNREACHABLE = (1233),
+    ERROR_PORT_UNREACHABLE = (1234),
+    ERROR_REQUEST_ABORTED = (1235),
+    ERROR_CONNECTION_ABORTED = (1236),
+    ERROR_RETRY = (1237),
+    ERROR_CONNECTION_COUNT_LIMIT = (1238),
+    ERROR_LOGIN_TIME_RESTRICTION = (1239),
+    ERROR_LOGIN_WKSTA_RESTRICTION = (1240),
+    ERROR_INCORRECT_ADDRESS = (1241),
+    ERROR_ALREADY_REGISTERED = (1242),
+    ERROR_SERVICE_NOT_FOUND = (1243),
+    ERROR_NOT_AUTHENTICATED = (1244),
+    ERROR_NOT_LOGGED_ON = (1245),
+    ERROR_CONTINUE = (1246),
+    ERROR_ALREADY_INITIALIZED = (1247),
+    ERROR_NO_MORE_DEVICES = (1248),
+    ERROR_NOT_ALL_ASSIGNED = (1300),
+    ERROR_SOME_NOT_MAPPED = (1301),
+    ERROR_NO_QUOTAS_FOR_ACCOUNT = (1302),
+    ERROR_LOCAL_USER_SESSION_KEY = (1303),
+    ERROR_NULL_LM_PASSWORD = (1304),
+    ERROR_UNKNOWN_REVISION = (1305),
+    ERROR_REVISION_MISMATCH = (1306),
+    ERROR_INVALID_OWNER = (1307),
+    ERROR_INVALID_PRIMARY_GROUP = (1308),
+    ERROR_NO_IMPERSONATION_TOKEN = (1309),
+    ERROR_CANT_DISABLE_MANDATORY = (1310),
+    ERROR_NO_LOGON_SERVERS = (1311),
+    ERROR_NO_SUCH_LOGON_SESSION = (1312),
+    ERROR_NO_SUCH_PRIVILEGE = (1313),
+    ERROR_PRIVILEGE_NOT_HELD = (1314),
+    ERROR_INVALID_ACCOUNT_NAME = (1315),
+    ERROR_USER_EXISTS = (1316),
+    ERROR_NO_SUCH_USER = (1317),
+    ERROR_GROUP_EXISTS = (1318),
+    ERROR_NO_SUCH_GROUP = (1319),
+    ERROR_MEMBER_IN_GROUP = (1320),
+    ERROR_MEMBER_NOT_IN_GROUP = (1321),
+    ERROR_LAST_ADMIN = (1322),
+    ERROR_WRONG_PASSWORD = (1323),
+    ERROR_ILL_FORMED_PASSWORD = (1324),
+    ERROR_PASSWORD_RESTRICTION = (1325),
+    ERROR_LOGON_FAILURE = (1326),
+    ERROR_ACCOUNT_RESTRICTION = (1327),
+    ERROR_INVALID_LOGON_HOURS = (1328),
+    ERROR_INVALID_WORKSTATION = (1329),
+    ERROR_PASSWORD_EXPIRED = (1330),
+    ERROR_ACCOUNT_DISABLED = (1331),
+    ERROR_NONE_MAPPED = (1332),
+    ERROR_TOO_MANY_LUIDS_REQUESTED = (1333),
+    ERROR_LUIDS_EXHAUSTED = (1334),
+    ERROR_INVALID_SUB_AUTHORITY = (1335),
+    ERROR_INVALID_ACL = (1336),
+    ERROR_INVALID_SID = (1337),
+    ERROR_INVALID_SECURITY_DESCR = (1338),
+    ERROR_BAD_INHERITANCE_ACL = (1340),
+    ERROR_SERVER_DISABLED = (1341),
+    ERROR_SERVER_NOT_DISABLED = (1342),
+    ERROR_INVALID_ID_AUTHORITY = (1343),
+    ERROR_ALLOTTED_SPACE_EXCEEDED = (1344),
+    ERROR_INVALID_GROUP_ATTRIBUTES = (1345),
+    ERROR_BAD_IMPERSONATION_LEVEL = (1346),
+    ERROR_CANT_OPEN_ANONYMOUS = (1347),
+    ERROR_BAD_VALIDATION_CLASS = (1348),
+    ERROR_BAD_TOKEN_TYPE = (1349),
+    ERROR_NO_SECURITY_ON_OBJECT = (1350),
+    ERROR_CANT_ACCESS_DOMAIN_INFO = (1351),
+    ERROR_INVALID_SERVER_STATE = (1352),
+    ERROR_INVALID_DOMAIN_STATE = (1353),
+    ERROR_INVALID_DOMAIN_ROLE = (1354),
+    ERROR_NO_SUCH_DOMAIN = (1355),
+    ERROR_DOMAIN_EXISTS = (1356),
+    ERROR_DOMAIN_LIMIT_EXCEEDED = (1357),
+    ERROR_INTERNAL_DB_CORRUPTION = (1358),
+    ERROR_INTERNAL_ERROR = (1359),
+    ERROR_GENERIC_NOT_MAPPED = (1360),
+    ERROR_BAD_DESCRIPTOR_FORMAT = (1361),
+    ERROR_NOT_LOGON_PROCESS = (1362),
+    ERROR_LOGON_SESSION_EXISTS = (1363),
+    ERROR_NO_SUCH_PACKAGE = (1364),
+    ERROR_BAD_LOGON_SESSION_STATE = (1365),
+    ERROR_LOGON_SESSION_COLLISION = (1366),
+    ERROR_INVALID_LOGON_TYPE = (1367),
+    ERROR_CANNOT_IMPERSONATE = (1368),
+    ERROR_RXACT_INVALID_STATE = (1369),
+    ERROR_RXACT_COMMIT_FAILURE = (1370),
+    ERROR_SPECIAL_ACCOUNT = (1371),
+    ERROR_SPECIAL_GROUP = (1372),
+    ERROR_SPECIAL_USER = (1373),
+    ERROR_MEMBERS_PRIMARY_GROUP = (1374),
+    ERROR_TOKEN_ALREADY_IN_USE = (1375),
+    ERROR_NO_SUCH_ALIAS = (1376),
+    ERROR_MEMBER_NOT_IN_ALIAS = (1377),
+    ERROR_MEMBER_IN_ALIAS = (1378),
+    ERROR_ALIAS_EXISTS = (1379),
+    ERROR_LOGON_NOT_GRANTED = (1380),
+    ERROR_TOO_MANY_SECRETS = (1381),
+    ERROR_SECRET_TOO_LONG = (1382),
+    ERROR_INTERNAL_DB_ERROR = (1383),
+    ERROR_TOO_MANY___FILE___IDS = (1384),
+    ERROR_LOGON_TYPE_NOT_GRANTED = (1385),
+    ERROR_NT_CROSS_ENCRYPTION_REQUIRED = (1386),
+    ERROR_NO_SUCH_MEMBER = (1387),
+    ERROR_INVALID_MEMBER = (1388),
+    ERROR_TOO_MANY_SIDS = (1389),
+    ERROR_LM_CROSS_ENCRYPTION_REQUIRED = (1390),
+    ERROR_NO_INHERITANCE = (1391),
+    ERROR_FILE_CORRUPT = (1392),
+    ERROR_DISK_CORRUPT = (1393),
+    ERROR_NO_USER_SESSION_KEY = (1394),
+    ERROR_LICENSE_QUOTA_EXCEEDED = (1395),
+    ERROR_INVALID_WINDOW_HANDLE = (1400),
+    ERROR_INVALID_MENU_HANDLE = (1401),
+    ERROR_INVALID_CURSOR_HANDLE = (1402),
+    ERROR_INVALID_ACCEL_HANDLE = (1403),
+    ERROR_INVALID_HOOK_HANDLE = (1404),
+    ERROR_INVALID_DWP_HANDLE = (1405),
+    ERROR_TLW_WITH_WSCHILD = (1406),
+    ERROR_CANNOT_FIND_WND_CLASS = (1407),
+    ERROR_WINDOW_OF_OTHER_THREAD = (1408),
+    ERROR_HOTKEY_ALREADY_REGISTERED = (1409),
+    ERROR_CLASS_ALREADY_EXISTS = (1410),
+    ERROR_CLASS_DOES_NOT_EXIST = (1411),
+    ERROR_CLASS_HAS_WINDOWS = (1412),
+    ERROR_INVALID_INDEX = (1413),
+    ERROR_INVALID_ICON_HANDLE = (1414),
+    ERROR_PRIVATE_DIALOG_INDEX = (1415),
+    ERROR_LISTBOX_ID_NOT_FOUND = (1416),
+    ERROR_NO_WILDCARD_CHARACTERS = (1417),
+    ERROR_CLIPBOARD_NOT_OPEN = (1418),
+    ERROR_HOTKEY_NOT_REGISTERED = (1419),
+    ERROR_WINDOW_NOT_DIALOG = (1420),
+    ERROR_CONTROL_ID_NOT_FOUND = (1421),
+    ERROR_INVALID_COMBOBOX_MESSAGE = (1422),
+    ERROR_WINDOW_NOT_COMBOBOX = (1423),
+    ERROR_INVALID_EDIT_HEIGHT = (1424),
+    ERROR_DC_NOT_FOUND = (1425),
+    ERROR_INVALID_HOOK_FILTER = (1426),
+    ERROR_INVALID_FILTER_PROC = (1427),
+    ERROR_HOOK_NEEDS_HMOD = (1428),
+    ERROR_GLOBAL_ONLY_HOOK = (1429),
+    ERROR_JOURNAL_HOOK_SET = (1430),
+    ERROR_HOOK_NOT_INSTALLED = (1431),
+    ERROR_INVALID_LB_MESSAGE = (1432),
+    ERROR_SETCOUNT_ON_BAD_LB = (1433),
+    ERROR_LB_WITHOUT_TABSTOPS = (1434),
+    ERROR_DESTROY_OBJECT_OF_OTHER_THREAD = (1435),
+    ERROR_CHILD_WINDOW_MENU = (1436),
+    ERROR_NO_SYSTEM_MENU = (1437),
+    ERROR_INVALID_MSGBOX_STYLE = (1438),
+    ERROR_INVALID_SPI_VALUE = (1439),
+    ERROR_SCREEN_ALREADY_LOCKED = (1440),
+    ERROR_HWNDS_HAVE_DIFF_PARENT = (1441),
+    ERROR_NOT_CHILD_WINDOW = (1442),
+    ERROR_INVALID_GW_COMMAND = (1443),
+    ERROR_INVALID_THREAD_ID = (1444),
+    ERROR_NON_MDICHILD_WINDOW = (1445),
+    ERROR_POPUP_ALREADY_ACTIVE = (1446),
+    ERROR_NO_SCROLLBARS = (1447),
+    ERROR_INVALID_SCROLLBAR_RANGE = (1448),
+    ERROR_INVALID_SHOWWIN_COMMAND = (1449),
+    ERROR_NO_SYSTEM_RESOURCES = (1450),
+    ERROR_NONPAGED_SYSTEM_RESOURCES = (1451),
+    ERROR_PAGED_SYSTEM_RESOURCES = (1452),
+    ERROR_WORKING_SET_QUOTA = (1453),
+    ERROR_PAGEFILE_QUOTA = (1454),
+    ERROR_COMMITMENT_LIMIT = (1455),
+    ERROR_MENU_ITEM_NOT_FOUND = (1456),
+    ERROR_EVENTLOG_FILE_CORRUPT = (1500),
+    ERROR_EVENTLOG_CANT_START = (1501),
+    ERROR_LOG_FILE_FULL = (1502),
+    ERROR_EVENTLOG_FILE_CHANGED = (1503),
+    RPC_S_INVALID_STRING_BINDING = (1700),
+    RPC_S_WRONG_KIND_OF_BINDING = (1701),
+    RPC_S_INVALID_BINDING = (1702),
+    RPC_S_PROTSEQ_NOT_SUPPORTED = (1703),
+    RPC_S_INVALID_RPC_PROTSEQ = (1704),
+    RPC_S_INVALID_STRING_UUID = (1705),
+    RPC_S_INVALID_ENDPOINT_FORMAT = (1706),
+    RPC_S_INVALID_NET_ADDR = (1707),
+    RPC_S_NO_ENDPOINT_FOUND = (1708),
+    RPC_S_INVALID_TIMEOUT = (1709),
+    RPC_S_OBJECT_NOT_FOUND = (1710),
+    RPC_S_ALREADY_REGISTERED = (1711),
+    RPC_S_TYPE_ALREADY_REGISTERED = (1712),
+    RPC_S_ALREADY_LISTENING = (1713),
+    RPC_S_NO_PROTSEQS_REGISTERED = (1714),
+    RPC_S_NOT_LISTENING = (1715),
+    RPC_S_UNKNOWN_MGR_TYPE = (1716),
+    RPC_S_UNKNOWN_IF = (1717),
+    RPC_S_NO_BINDINGS = (1718),
+    RPC_S_NO_PROTSEQS = (1719),
+    RPC_S_CANT_CREATE_ENDPOINT = (1720),
+    RPC_S_OUT_OF_RESOURCES = (1721),
+    RPC_S_SERVER_UNAVAILABLE = (1722),
+    RPC_S_SERVER_TOO_BUSY = (1723),
+    RPC_S_INVALID_NETWORK_OPTIONS = (1724),
+    RPC_S_NO_CALL_ACTIVE = (1725),
+    RPC_S_CALL_FAILED = (1726),
+    RPC_S_CALL_FAILED_DNE = (1727),
+    RPC_S_PROTOCOL_ERROR = (1728),
+    RPC_S_UNSUPPORTED_TRANS_SYN = (1730),
+    RPC_S_UNSUPPORTED_TYPE = (1732),
+    RPC_S_INVALID_TAG = (1733),
+    RPC_S_INVALID_BOUND = (1734),
+    RPC_S_NO_ENTRY_NAME = (1735),
+    RPC_S_INVALID_NAME_SYNTAX = (1736),
+    RPC_S_UNSUPPORTED_NAME_SYNTAX = (1737),
+    RPC_S_UUID_NO_ADDRESS = (1739),
+    RPC_S_DUPLICATE_ENDPOINT = (1740),
+    RPC_S_UNKNOWN_AUTHN_TYPE = (1741),
+    RPC_S_MAX_CALLS_TOO_SMALL = (1742),
+    RPC_S_STRING_TOO_LONG = (1743),
+    RPC_S_PROTSEQ_NOT_FOUND = (1744),
+    RPC_S_PROCNUM_OUT_OF_RANGE = (1745),
+    RPC_S_BINDING_HAS_NO_AUTH = (1746),
+    RPC_S_UNKNOWN_AUTHN_SERVICE = (1747),
+    RPC_S_UNKNOWN_AUTHN_LEVEL = (1748),
+    RPC_S_INVALID_AUTH_IDENTITY = (1749),
+    RPC_S_UNKNOWN_AUTHZ_SERVICE = (1750),
+    EPT_S_INVALID_ENTRY = (1751),
+    EPT_S_CANT_PERFORM_OP = (1752),
+    EPT_S_NOT_REGISTERED = (1753),
+    RPC_S_NOTHING_TO_EXPORT = (1754),
+    RPC_S_INCOMPLETE_NAME = (1755),
+    RPC_S_INVALID_VERS_OPTION = (1756),
+    RPC_S_NO_MORE_MEMBERS = (1757),
+    RPC_S_NOT_ALL_OBJS_UNEXPORTED = (1758),
+    RPC_S_INTERFACE_NOT_FOUND = (1759),
+    RPC_S_ENTRY_ALREADY_EXISTS = (1760),
+    RPC_S_ENTRY_NOT_FOUND = (1761),
+    RPC_S_NAME_SERVICE_UNAVAILABLE = (1762),
+    RPC_S_INVALID_NAF_ID = (1763),
+    RPC_S_CANNOT_SUPPORT = (1764),
+    RPC_S_NO___FILE___AVAILABLE = (1765),
+    RPC_S_INTERNAL_ERROR = (1766),
+    RPC_S_ZERO_DIVIDE = (1767),
+    RPC_S_ADDRESS_ERROR = (1768),
+    RPC_S_FP_DIV_ZERO = (1769),
+    RPC_S_FP_UNDERFLOW = (1770),
+    RPC_S_FP_OVERFLOW = (1771),
+    RPC_X_NO_MORE_ENTRIES = (1772),
+    RPC_X_SS_CHAR_TRANS_OPEN_FAIL = (1773),
+    RPC_X_SS_CHAR_TRANS_SHORT_FILE = (1774),
+    RPC_X_SS_IN_NULL___FILE__ = (1775),
+    RPC_X_SS___FILE___DAMAGED = (1777),
+    RPC_X_SS_HANDLES_MISMATCH = (1778),
+    RPC_X_SS_CANNOT_GET_CALL_HANDLE = (1779),
+    RPC_X_NULL_REF_POINTER = (1780),
+    RPC_X_ENUM_VALUE_OUT_OF_RANGE = (1781),
+    RPC_X_BYTE_COUNT_TOO_SMALL = (1782),
+    RPC_X_BAD_STUB_DATA = (1783),
+    ERROR_INVALID_USER_BUFFER = (1784),
+    ERROR_UNRECOGNIZED_MEDIA = (1785),
+    ERROR_NO_TRUST_LSA_SECRET = (1786),
+    ERROR_NO_TRUST_SAM_ACCOUNT = (1787),
+    ERROR_TRUSTED_DOMAIN_FAILURE = (1788),
+    ERROR_TRUSTED_RELATIONSHIP_FAILURE = (1789),
+    ERROR_TRUST_FAILURE = (1790),
+    RPC_S_CALL_IN_PROGRESS = (1791),
+    ERROR_NETLOGON_NOT_STARTED = (1792),
+    ERROR_ACCOUNT_EXPIRED = (1793),
+    ERROR_REDIRECTOR_HAS_OPEN_HANDLES = (1794),
+    ERROR_PRINTER_DRIVER_ALREADY_INSTALLED = (1795),
+    ERROR_UNKNOWN_PORT = (1796),
+    ERROR_UNKNOWN_PRINTER_DRIVER = (1797),
+    ERROR_UNKNOWN_PRINTPROCESSOR = (1798),
+    ERROR_INVALID_SEPARATOR_FILE = (1799),
+    ERROR_INVALID_PRIORITY = (1800),
+    ERROR_INVALID_PRINTER_NAME = (1801),
+    ERROR_PRINTER_ALREADY_EXISTS = (1802),
+    ERROR_INVALID_PRINTER_COMMAND = (1803),
+    ERROR_INVALID_DATATYPE = (1804),
+    ERROR_INVALID_ENVIRONMENT = (1805),
+    RPC_S_NO_MORE_BINDINGS = (1806),
+    ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = (1807),
+    ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT = (1808),
+    ERROR_NOLOGON_SERVER_TRUST_ACCOUNT = (1809),
+    ERROR_DOMAIN_TRUST_INCONSISTENT = (1810),
+    ERROR_SERVER_HAS_OPEN_HANDLES = (1811),
+    ERROR_RESOURCE_DATA_NOT_FOUND = (1812),
+    ERROR_RESOURCE_TYPE_NOT_FOUND = (1813),
+    ERROR_RESOURCE_NAME_NOT_FOUND = (1814),
+    ERROR_RESOURCE_LANG_NOT_FOUND = (1815),
+    ERROR_NOT_ENOUGH_QUOTA = (1816),
+    RPC_S_NO_INTERFACES = (1817),
+    RPC_S_CALL_CANCELLED = (1818),
+    RPC_S_BINDING_INCOMPLETE = (1819),
+    RPC_S_COMM_FAILURE = (1820),
+    RPC_S_UNSUPPORTED_AUTHN_LEVEL = (1821),
+    RPC_S_NO_PRINC_NAME = (1822),
+    RPC_S_NOT_RPC_ERROR = (1823),
+    RPC_S_UUID_LOCAL_ONLY = (1824),
+    RPC_S_SEC_PKG_ERROR = (1825),
+    RPC_S_NOT_CANCELLED = (1826),
+    RPC_X_INVALID_ES_ACTION = (1827),
+    RPC_X_WRONG_ES_VERSION = (1828),
+    RPC_X_WRONG_STUB_VERSION = (1829),
+    RPC_S_GROUP_MEMBER_NOT_FOUND = (1898),
+    EPT_S_CANT_CREATE = (1899),
+    RPC_S_INVALID_OBJECT = (1900),
+    ERROR_INVALID_TIME = (1901),
+    ERROR_INVALID_FORM_NAME = (1902),
+    ERROR_INVALID_FORM_SIZE = (1903),
+    ERROR_ALREADY_WAITING = (1904),
+    ERROR_PRINTER_DELETED = (1905),
+    ERROR_INVALID_PRINTER_STATE = (1906),
+    ERROR_PASSWORD_MUST_CHANGE = (1907),
+    ERROR_DOMAIN_CONTROLLER_NOT_FOUND = (1908),
+    ERROR_ACCOUNT_LOCKED_OUT = (1909),
+    ERROR_NO_BROWSER_SERVERS_FOUND = (6118),
+    ERROR_INVALID_PIXEL_FORMAT = (2000),
+    ERROR_BAD_DRIVER = (2001),
+    ERROR_INVALID_WINDOW_STYLE = (2002),
+    ERROR_METAFILE_NOT_SUPPORTED = (2003),
+    ERROR_TRANSFORM_NOT_SUPPORTED = (2004),
+    ERROR_CLIPPING_NOT_SUPPORTED = (2005),
+    ERROR_UNKNOWN_PRINT_MONITOR = (3000),
+    ERROR_PRINTER_DRIVER_IN_USE = (3001),
+    ERROR_SPOOL_FILE_NOT_FOUND = (3002),
+    ERROR_SPL_NO_STARTDOC = (3003),
+    ERROR_SPL_NO_ADDJOB = (3004),
+    ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED = (3005),
+    ERROR_PRINT_MONITOR_ALREADY_INSTALLED = (3006),
+    ERROR_WINS_INTERNAL = (4000),
+    ERROR_CAN_NOT_DEL_LOCAL_WINS = (4001),
+    ERROR_STATIC_INIT = (4002),
+    ERROR_INC_BACKUP = (4003),
+    ERROR_FULL_BACKUP = (4004),
+    ERROR_REC_NON_EXISTENT = (4005),
+    ERROR_RPL_NOT_ALLOWED = (4006),
+    MAX_PATH = (260),
+    LF_FACESIZE = (32),
+    LF_FULLFACESIZE = (64),
+    ELF_VENDOR_SIZE = (4),
+    SECURITY_STATIC_TRACKING = (0),
+    SECURITY_DYNAMIC_TRACKING = (1),
+    MAX_DEFAULTCHAR = (2),
+    MAX_LEADBYTES = (12),
+    EXCEPTION_MAXIMUM_PARAMETERS = (15),
+    CCHDEVICENAME = (32),
+    CCHFORMNAME = (32),
+    MENU_TEXT_LEN = (40),
+    MAX_LANA = (254),
+    NCBNAMSZ = (16),
+    NETBIOS_NAME_LEN = (16),
+    OFS_MAXPATHNAME = (128),
+    MAX_TAB_STOPS = (32),
+    ANYSIZE_ARRAY = (1),
+    RAS_MaxCallbackNumber = (128),
+    RAS_MaxDeviceName = (128),
+    RAS_MaxDeviceType = (16),
+    RAS_MaxEntryName = (256),
+    RAS_MaxIpAddress = (15),
+    RAS_MaxIpxAddress = (21),
+    RAS_MaxPhoneNumber = (128),
+    UNLEN = (256),
+    PWLEN = (256),
+    CNLEN = (15),
+    DNLEN = (15),
+    MAXDWORD = (0xFFFFFFFF),
+    MAXWORD = (0xFFFF),
+    MAXBYTE = (0xFF),
+    MINCHAR = (0x80),
+    MAXCHAR = (0x7F),
+    MINSHORT = (0x8000),
+    MAXSHORT = (0x7FFF),
+    MINLONG = (0x80000000),
+    MAXLONG = (0x7FFFFFFF),
+    FILE_BEGIN = (0),
+    FILE_CURRENT = (1),
+    FILE_END = (2),
+    OF_READ = (0),
+    OF_READWRITE = (2),
+    OF_WRITE = (1),
+    OF_SHARE_COMPAT = (0),
+    OF_SHARE_DENY_NONE = (64),
+    OF_SHARE_DENY_READ = (48),
+    OF_SHARE_DENY_WRITE = (32),
+    OF_SHARE_EXCLUSIVE = (16),
+    OF_CANCEL = (2048),
+    OF_CREATE = (4096),
+    OF_DELETE = (512),
+    OF_EXIST = (16384),
+    OF_PARSE = (256),
+    OF_PROMPT = (8192),
+    OF_REOPEN = (32768),
+    OF_VERIFY = (1024),
+    HKL_NEXT = (1),
+    HKL_PREV = (0),
+    KLF_REORDER = (8),
+    KLF_UNLOADPREVIOUS = (4),
+    KLF_ACTIVATE = (1),
+    KLF_NOTELLSHELL = (128),
+    KLF_REPLACELANG = (16),
+    KLF_SUBSTITUTE_OK = (2),
+    MF_BITMAP = (0x4),
+    MF_DISABLED = (0x2),
+    MF_ENABLED = (0),
+    MF_GRAYED = (0x1),
+    MF_HELP = (0x4000),
+    MF_MENUBARBREAK = (0x20),
+    MF_MENUBREAK = (0x40),
+    MF_MOUSESELECT = (0x8000),
+    MF_OWNERDRAW = (0x100),
+    MF_POPUP = (0x10),
+    MF_SEPARATOR = (0x800),
+    MF_STRING = (0),
+    MF_SYSMENU = (0x2000),
+    MF_USECHECKBITMAPS = (0x200),
+    BLACKNESS = (0x00000042),
+    NOTSRCERASE = (0x001100A6),
+    NOTSRCCOPY = (0x00330008),
+    SRCERASE = (0x00440328),
+    DSTINVERT = (0x00550009),
+    PATINVERT = (0x005A0049),
+    SRCINVERT = (0x00660046),
+    SRCAND = (0x008800C6),
+    MERGEPAINT = (0x00BB0226),
+    MERGECOPY = (0x00C000CA),
+    SRCCOPY = (0x00CC0020),
+    SRCPAINT = (0x00EE0086),
+    PATCOPY = (0x00F00021),
+    PATPAINT = (0x00FB0A09),
+    WHITENESS = (0x00FF0062),
+    R2_BLACK = (1),
+    R2_COPYPEN = (13),
+    R2_MASKNOTPEN = (3),
+    R2_MASKPEN = (9),
+    R2_MASKPENNOT = (5),
+    R2_MERGENOTPEN = (12),
+    R2_MERGEPEN = (15),
+    R2_MERGEPENNOT = (14),
+    R2_NOP = (11),
+    R2_NOT = (6),
+    R2_NOTCOPYPEN = (4),
+    R2_NOTMASKPEN = (8),
+    R2_NOTMERGEPEN = (2),
+    R2_NOTXORPEN = (10),
+    R2_WHITE = (16),
+    R2_XORPEN = (7),
+    BSF_FLUSHDISK = (4),
+    BSF_FORCEIFHUNG = (32),
+    BSF_IGNORECURRENTTASK = (2),
+    BSF_NOHANG = (8),
+    BSF_POSTMESSAGE = (16),
+    BSF_QUERY = (1),
+    BSM_ALLCOMPONENTS = (0),
+    BSM_APPLICATIONS = (8),
+    BSM_INSTALLABLEDRIVERS = (4),
+    BSM_NETDRIVER = (2),
+    BSM_VXDS = (1),
+    BROADCAST_QUERY_DENY = (1112363332),
+    NMPWAIT_NOWAIT = (1),
+    NMPWAIT_WAIT_FOREVER = -((1)),
+    NMPWAIT_USE_DEFAULT_WAIT = (0),
+    MDITILE_SKIPDISABLED = (2),
+    MDITILE_HORIZONTAL = (1),
+    MDITILE_VERTICAL = (0),
+    HCBT_ACTIVATE = (5),
+    HCBT_CLICKSKIPPED = (6),
+    HCBT_CREATEWND = (3),
+    HCBT_DESTROYWND = (4),
+    HCBT_KEYSKIPPED = (7),
+    HCBT_MINMAX = (1),
+    HCBT_MOVESIZE = (0),
+    HCBT_QS = (2),
+    HCBT_SETFOCUS = (9),
+    HCBT_SYSCOMMAND = (8),
+    DM_BITSPERPEL = (0x40000),
+    DM_PELSWIDTH = (0x80000),
+    DM_PELSHEIGHT = (0x100000),
+    DM_DISPLAYFLAGS = (0x200000),
+    DM_DISPLAYFREQUENCY = (0x400000),
+    CDS_UPDATEREGISTRY = (1),
+    CDS_TEST = (2),
+    DISP_CHANGE_SUCCESSFUL = (0),
+    DISP_CHANGE_RESTART = (1),
+    DISP_CHANGE_BADFLAGS = -((4)),
+    DISP_CHANGE_FAILED = -((1)),
+    DISP_CHANGE_BADMODE = -((2)),
+    DISP_CHANGE_NOTUPDATED = -((3)),
+    SERVICE_NO_CHANGE = -((1)),
+    SERVICE_WIN32_OWN_PROCESS = (16),
+    SERVICE_WIN32_SHARE_PROCESS = (32),
+    SERVICE_KERNEL_DRIVER = (1),
+    SERVICE_FILE_SYSTEM_DRIVER = (2),
+    SERVICE_INTERACTIVE_PROCESS = (256),
+    SERVICE_BOOT_START = (0),
+    SERVICE_SYSTEM_START = (1),
+    SERVICE_AUTO_START = (2),
+    SERVICE_DEMAND_START = (3),
+    SERVICE_DISABLED = (4),
+    SERVICE_STOPPED = (1),
+    SERVICE_START_PENDING = (2),
+    SERVICE_STOP_PENDING = (3),
+    SERVICE_RUNNING = (4),
+    SERVICE_CONTINUE_PENDING = (5),
+    SERVICE_PAUSE_PENDING = (6),
+    SERVICE_PAUSED = (7),
+    SERVICE_ACCEPT_STOP = (1),
+    SERVICE_ACCEPT_PAUSE_CONTINUE = (2),
+    SERVICE_ACCEPT_SHUTDOWN = (4),
+    BST_CHECKED = (1),
+    BST_INDETERMINATE = (2),
+    BST_UNCHECKED = (0),
+    BST_FOCUS = (8),
+    BST_PUSHED = (4),
+    MF_BYCOMMAND = (0),
+    MF_BYPOSITION = (0x400),
+    MF_CHECKED = (0x8),
+    MF_UNCHECKED = (0),
+    MF_HILITE = (0x80),
+    MF_UNHILITE = (0),
+    CWP_ALL = (0),
+    CWP_SKIPINVISIBLE = (1),
+    CWP_SKIPDISABLED = (2),
+    CWP_SKIPTRANSPARENT = (4),
+    CE_BREAK = (16),
+    CE_DNS = (2048),
+    CE_FRAME = (8),
+    CE_IOE = (1024),
+    CE_MODE = (32768),
+    CE_OOP = (4096),
+    CE_OVERRUN = (2),
+    CE_PTO = (512),
+    CE_RXOVER = (1),
+    CE_RXPARITY = (4),
+    CE_TXFULL = (256),
+    RGN_AND = (1),
+    RGN_COPY = (5),
+    RGN_DIFF = (4),
+    RGN_OR = (2),
+    RGN_XOR = (3),
+    NULLREGION = (1),
+    SIMPLEREGION = (2),
+    COMPLEXREGION = (3),
+    ERROR = (0),
+    CDERR_DIALOGFAILURE = (0xffff),
+    CDERR_FINDRESFAILURE = (6),
+    CDERR_INITIALIZATION = (2),
+    CDERR_LOADRESFAILURE = (7),
+    CDERR_LOADSTRFAILURE = (5),
+    CDERR_LOCKRESFAILURE = (8),
+    CDERR_MEMALLOCFAILURE = (9),
+    CDERR_MEMLOCKFAILURE = (10),
+    CDERR_NOHINSTANCE = (4),
+    CDERR_NOHOOK = (11),
+    CDERR_NOTEMPLATE = (3),
+    CDERR_REGISTERMSGFAIL = (12),
+    CDERR_STRUCTSIZE = (1),
+    PDERR_CREATEICFAILURE = (0x1000)+(10),
+    PDERR_DEFAULTDIFFERENT = (0x1000)+(12),
+    PDERR_DNDMMISMATCH = (0x1000)+(9),
+    PDERR_GETDEVMODEFAIL = (0x1000)+(5),
+    PDERR_INITFAILURE = (0x1000)+(6),
+    PDERR_LOADDRVFAILURE = (0x1000)+(4),
+    PDERR_NODEFAULTPRN = (0x1000)+(8),
+    PDERR_NODEVICES = (0x1000)+(7),
+    PDERR_PARSEFAILURE = (0x1000)+(2),
+    PDERR_PRINTERNOTFOUND = (0x1000)+(11),
+    PDERR_RETDEFFAILURE = (0x1000)+(3),
+    PDERR_SETUPFAILURE = (0x1000)+(1),
+    CFERR_MAXLESSTHANMIN = (0x2000)+(2),
+    CFERR_NOFONTS = (0x2000)+(1),
+    FNERR_BUFFERTOOSMALL = (0x3000)+(3),
+    FNERR_INVALIDFILENAME = (0x3000)+(2),
+    FNERR_SUBCLASSFAILURE = (0x3000)+(1),
+    FRERR_BUFFERLENGTHZERO = (0x4000)+(1),
+    LOCALE_SYSTEM_DEFAULT = (0x800),
+    LOCALE_USER_DEFAULT = (0x400),
+    NORM_IGNORECASE = (1),
+    NORM_IGNOREKANATYPE = (65536),
+    NORM_IGNORENONSPACE = (2),
+    NORM_IGNORESYMBOLS = (4),
+    NORM_IGNOREWIDTH = (131072),
+    SORT_STRINGSORT = (4096),
+    LCMAP_BYTEREV = (2048),
+    LCMAP_FULLWIDTH = (8388608),
+    LCMAP_HALFWIDTH = (4194304),
+    LCMAP_HIRAGANA = (1048576),
+    LCMAP_KATAKANA = (2097152),
+    LCMAP_LOWERCASE = (256),
+    LCMAP_SORTKEY = (1024),
+    LCMAP_UPPERCASE = (512),
+    DBG_CONTINUE = (0x10002),
+    DBG_CONTROL_BREAK = (0x40010008),
+    DBG_CONTROL_C = (0x40010005),
+    DBG_EXCEPTION_NOT_HANDLED = (0x80010001),
+    DBG_TERMINATE_THREAD = (0x40010003),
+    DBG_TERMINATE_PROCESS = (0x40010004),
+    SERVICE_CONTROL_STOP = (1),
+    SERVICE_CONTROL_PAUSE = (2),
+    SERVICE_CONTROL_CONTINUE = (3),
+    SERVICE_CONTROL_INTERROGATE = (4),
+    SERVICE_CONTROL_SHUTDOWN = (5),
+    IMAGE_BITMAP = (0),
+    IMAGE_CURSOR = (2),
+    IMAGE_ENHMETAFILE = (1),
+    IMAGE_ICON = (1),
+    LR_COPYDELETEORG = (8),
+    LR_COPYRETURNORG = (4),
+    LR_MONOCHROME = (1),
+    LR_CREATEDIBSECTION = (8192),
+    LR_DEFAULTSIZE = (64),
+    DF_ALLOWOTHERACCOUNTHOOK = (0x1),
+    DESKTOP_CREATEMENU = (0x4),
+    DESKTOP_CREATEWINDOW = (0x2),
+    DESKTOP_ENUMERATE = (0x40),
+    DESKTOP_HOOKCONTROL = (0x8),
+    DESKTOP_JOURNALPLAYBACK = (0x20),
+    DESKTOP_JOURNALRECORD = (0x10),
+    DESKTOP_READOBJECTS = (0x1),
+    DESKTOP_SWITCHDESKTOP = (0x100),
+    DESKTOP_WRITEOBJECTS = (0x80),
+    WSF_VISIBLE = (0x1),
+    CBM_INIT = (0x4),
+    DIB_PAL_COLORS = (1),
+    DIB_RGB_COLORS = (0),
+    GENERIC_READ = (0x80000000),
+    GENERIC_WRITE = (0x40000000),
+    GENERIC_EXECUTE = (0x20000000),
+    FILE_READ_DATA = (0x0001),
+    FILE_LIST_DIRECTORY = (0x0001),
+    FILE_WRITE_DATA = (0x0002),
+    FILE_ADD_FILE = (0x0002),
+    FILE_APPEND_DATA = (0x0004),
+    FILE_ADD_SUBDIRECTORY = (0x0004),
+    FILE_CREATE_PIPE_INSTANCE = (0x0004),
+    FILE_READ_EA = (0x0008),
+    FILE_READ_PROPERTIES = (FILE_READ_EA),
+    FILE_WRITE_EA = (0x0010),
+    FILE_WRITE_PROPERTIES = (FILE_WRITE_EA),
+    FILE_EXECUTE = (0x0020),
+    FILE_TRAVERSE = (0x0020),
+    FILE_DELETE_CHILD = (0x0040),
+    FILE_READ_ATTRIBUTES = (0x0080),
+    FILE_WRITE_ATTRIBUTES = (0x0100),
+    FILE_SHARE_DELETE = (4),
+    FILE_SHARE_READ = (1),
+    FILE_SHARE_WRITE = (2),
+    CONSOLE_TEXTMODE_BUFFER = (1),
+    CREATE_NEW = (1),
+    CREATE_ALWAYS = (2),
+    OPEN_EXISTING = (3),
+    OPEN_ALWAYS = (4),
+    TRUNCATE_EXISTING = (5),
+    INVALID_FILE_ATTRIBUTE = (-1),
+    FILE_ATTRIBUTE_ARCHIVE = (32),
+    FILE_ATTRIBUTE_COMPRESSED = (2048),
+    FILE_ATTRIBUTE_NORMAL = (128),
+    FILE_ATTRIBUTE_DIRECTORY = (16),
+    FILE_ATTRIBUTE_HIDDEN = (2),
+    FILE_ATTRIBUTE_READONLY = (1),
+    FILE_ATTRIBUTE_SYSTEM = (4),
+    FILE_ATTRIBUTE_TEMPORARY = (256),
+    FILE_FLAG_WRITE_THROUGH = (2147483648),
+    FILE_FLAG_OVERLAPPED = (1073741824),
+    FILE_FLAG_NO_BUFFERING = (536870912),
+    FILE_FLAG_RANDOM_ACCESS = (268435456),
+    FILE_FLAG_SEQUENTIAL_SCAN = (134217728),
+    FILE_FLAG_DELETE_ON_CLOSE = (67108864),
+    FILE_FLAG_BACKUP_SEMANTICS = (33554432),
+    FILE_FLAG_POSIX_SEMANTICS = (16777216),
+    SECURITY_ANONYMOUS = (0),
+    SECURITY_IDENTIFICATION = (65536),
+    SECURITY_IMPERSONATION = (131072),
+    SECURITY_DELEGATION = (196608),
+    SECURITY___FILE___TRACKING = (262144),
+    SECURITY_EFFECTIVE_ONLY = (524288),
+    SECURITY_SQOS_PRESENT = (1048576),
+    SEC_COMMIT = (134217728),
+    SEC_IMAGE = (16777216),
+    SEC_NOCACHE = (268435456),
+    SEC_RESERVE = (67108864),
+    PAGE_READONLY = (2),
+    PAGE_READWRITE = (4),
+    PAGE_WRITECOPY = (8),
+    PAGE_EXECUTE = (16),
+    PAGE_EXECUTE_READ = (32),
+    PAGE_EXECUTE_READWRITE = (64),
+    PAGE_EXECUTE_WRITECOPY = (128),
+    PAGE_GUARD = (256),
+    PAGE_NOACCESS = (1),
+    PAGE_NOCACHE = (512),
+    MEM_COMMIT = (4096),
+    MEM_FREE = (65536),
+    MEM_RESERVE = (8192),
+    MEM_IMAGE = (16777216),
+    MEM_MAPPED = (262144),
+    MEM_PRIVATE = (131072),
+    MEM_DECOMMIT = (16384),
+    MEM_RELEASE = (32768),
+    MEM_TOP_DOWN = (1048576),
+    EXCEPTION_GUARD_PAGE = (0x80000001),
+    SECTION_EXTEND_SIZE = (0x10),
+    SECTION_MAP_READ = (0x4),
+    SECTION_MAP_WRITE = (0x2),
+    SECTION_QUERY = (0x1),
+    SECTION_ALL_ACCESS = (0xf001f),
+    FW_DONTCARE = (0),
+    FW_THIN = (100),
+    FW_EXTRALIGHT = (200),
+    FW_LIGHT = (300),
+    FW_NORMAL = (400),
+    FW_REGULAR = (FW_NORMAL),
+    FW_MEDIUM = (500),
+    FW_SEMIBOLD = (600),
+    FW_BOLD = (700),
+    FW_EXTRABOLD = (800),
+    FW_HEAVY = (900),
+    ANSI_CHARSET = (0),
+    DEFAULT_CHARSET = (1),
+    SYMBOL_CHARSET = (2),
+    SHIFTJIS_CHARSET = (128),
+    HANGEUL_CHARSET = (129),
+    GB2312_CHARSET = (134),
+    CHINESEBIG5_CHARSET = (136),
+    GREEK_CHARSET = (161),
+    TURKISH_CHARSET = (162),
+    HEBREW_CHARSET = (177),
+    ARABIC_CHARSET = (178),
+    BALTIC_CHARSET = (186),
+    RUSSIAN_CHARSET = (204),
+    THAI_CHARSET = (222),
+    EASTEUROPE_CHARSET = (238),
+    OEM_CHARSET = (255),
+    OUT_DEFAULT_PRECIS = (0),
+    OUT_STRING_PRECIS = (1),
+    OUT_CHARACTER_PRECIS = (2),
+    OUT_STROKE_PRECIS = (3),
+    OUT_TT_PRECIS = (4),
+    OUT_DEVICE_PRECIS = (5),
+    OUT_RASTER_PRECIS = (6),
+    OUT_TT_ONLY_PRECIS = (7),
+    OUT_OUTLINE_PRECIS = (8),
+    CLIP_DEFAULT_PRECIS = (0),
+    CLIP_CHARACTER_PRECIS = (1),
+    CLIP_STROKE_PRECIS = (2),
+    CLIP_MASK = (15),
+    CLIP_LH_ANGLES = (16),
+    CLIP_TT_ALWAYS = (32),
+    CLIP_EMBEDDED = (128),
+    DEFAULT_QUALITY = (0),
+    DRAFT_QUALITY = (1),
+    PROOF_QUALITY = (2),
+    DEFAULT_PITCH = (0),
+    FIXED_PITCH = (1),
+    VARIABLE_PITCH = (2),
+    FF_DECORATIVE = (80),
+    FF_DONTCARE = (0),
+    FF_MODERN = (48),
+    FF_ROMAN = (16),
+    FF_SCRIPT = (64),
+    FF_SWISS = (32),
+    HS_BDIAGONAL = (3),
+    HS_CROSS = (4),
+    HS_DIAGCROSS = (5),
+    HS_FDIAGONAL = (2),
+    HS_HORIZONTAL = (0),
+    HS_VERTICAL = (1),
+    LR_DEFAULTCOLOR = (0),
+    LR_LOADREALSIZE = (128),
+    MAILSLOT_WAIT_FOREVER = (0xffffffff),
+    MAILSLOT_NO_MESSAGE = (0xffffffff),
+    CMB_MASKED = (2),
+    PIPE_ACCESS_DUPLEX = (3),
+    PIPE_ACCESS_INBOUND = (1),
+    PIPE_ACCESS_OUTBOUND = (2),
+    WRITE_DAC = (0x40000),
+    WRITE_OWNER = (0x80000),
+    ACCESS_SYSTEM_SECURITY = (0x1000000),
+    PIPE_TYPE_BYTE = (0),
+    PIPE_TYPE_MESSAGE = (4),
+    PIPE_READMODE_BYTE = (0),
+    PIPE_READMODE_MESSAGE = (2),
+    PIPE_WAIT = (0),
+    PIPE_NOWAIT = (1),
+    PS_GEOMETRIC = (65536),
+    PS_COSMETIC = (0),
+    PS_ALTERNATE = (8),
+    PS_SOLID = (0),
+    PS_DASH = (1),
+    PS_DOT = (2),
+    PS_DASHDOT = (3),
+    PS_DASHDOTDOT = (4),
+    PS_NULL = (5),
+    PS_USERSTYLE = (7),
+    PS_INSIDEFRAME = (6),
+    PS_ENDCAP_ROUND = (0),
+    PS_ENDCAP_SQUARE = (256),
+    PS_ENDCAP_FLAT = (512),
+    PS_JOIN_BEVEL = (4096),
+    PS_JOIN_MITER = (8192),
+    PS_JOIN_ROUND = (0),
+    PS_STYLE_MASK = (15),
+    PS_ENDCAP_MASK = (3840),
+    PS_TYPE_MASK = (983040),
+    ALTERNATE = (1),
+    WINDING = (2),
+    CREATE_DEFAULT_ERROR_MODE = (67108864),
+    CREATE_NEW_CONSOLE = (16),
+    CREATE_NEW_PROCESS_GROUP = (512),
+    CREATE_NO_WINDOW = (0x8000000),
+    CREATE_SEPARATE_WOW_VDM = (2048),
+    CREATE_SUSPENDED = (4),
+    CREATE_UNICODE_ENVIRONMENT = (1024),
+    DEBUG_PROCESS = (1),
+    DEBUG_ONLY_THIS_PROCESS = (2),
+    DETACHED_PROCESS = (8),
+    HIGH_PRIORITY_CLASS = (128),
+    IDLE_PRIORITY_CLASS = (64),
+    NORMAL_PRIORITY_CLASS = (32),
+    REALTIME_PRIORITY_CLASS = (256),
+    SERVICE_ALL_ACCESS = (0xf01ff),
+    SERVICE_CHANGE_CONFIG = (2),
+    SERVICE_ENUMERATE_DEPENDENTS = (8),
+    SERVICE_INTERROGATE = (128),
+    SERVICE_PAUSE_CONTINUE = (64),
+    SERVICE_QUERY_CONFIG = (1),
+    SERVICE_QUERY_STATUS = (4),
+    SERVICE_START = (16),
+    SERVICE_STOP = (32),
+    SERVICE_USER_DEFINED_CONTROL = (256),
+    SERVICE_DELETE = (0x10000),
+    SERVICE_READ_CONTROL = (0x20000),
+    SERVICE_GENERIC_EXECUTE = (0x20000000),
+    SERVICE_ERROR_IGNORE = (0),
+    SERVICE_ERROR_NORMAL = (1),
+    SERVICE_ERROR_SEVERE = (2),
+    SERVICE_ERROR_CRITICAL = (3),
+    TAPE_FIXED_PARTITIONS = (0),
+    TAPE_INITIATOR_PARTITIONS = (0x2),
+    TAPE_SELECT_PARTITIONS = (0x1),
+    TAPE_FILEMARKS = (0x1),
+    TAPE_LONG_FILEMARKS = (0x3),
+    TAPE_SETMARKS = (0),
+    TAPE_SHORT_FILEMARKS = (0x2),
+    CW_USEDEFAULT = (0x80000000),
+    WS_BORDER = (0x800000),
+    WS_CAPTION = (0xc00000),
+    WS_CHILD = (0x40000000),
+    WS_CHILDWINDOW = (0x40000000),
+    WS_CLIPCHILDREN = (0x2000000),
+    WS_CLIPSIBLINGS = (0x4000000),
+    WS_DISABLED = (0x8000000),
+    WS_DLGFRAME = (0x400000),
+    WS_GROUP = (0x20000),
+    WS_HSCROLL = (0x100000),
+    WS_ICONIC = (0x20000000),
+    WS_MAXIMIZE = (0x1000000),
+    WS_MAXIMIZEBOX = (0x10000),
+    WS_MINIMIZE = (0x20000000),
+    WS_MINIMIZEBOX = (0x20000),
+    WS_OVERLAPPED = (0),
+    WS_OVERLAPPEDWINDOW = (0xcf0000),
+    WS_POPUP = (0x80000000),
+    WS_POPUPWINDOW = (0x80880000),
+    WS_SIZEBOX = (0x40000),
+    WS_SYSMENU = (0x80000),
+    WS_TABSTOP = (0x10000),
+    WS_THICKFRAME = (0x40000),
+    WS_TILED = (0),
+    WS_TILEDWINDOW = (0xcf0000),
+    WS_VISIBLE = (0x10000000),
+    WS_VSCROLL = (0x200000),
+    MDIS_ALLCHILDSTYLES = (0x1),
+    BS_3STATE = (0x5),
+    BS_AUTO3STATE = (0x6),
+    BS_AUTOCHECKBOX = (0x3),
+    BS_AUTORADIOBUTTON = (0x9),
+    BS_BITMAP = (0x80),
+    BS_BOTTOM = (0x800),
+    BS_CENTER = (0x300),
+    BS_CHECKBOX = (0x2),
+    BS_DEFPUSHBUTTON = (0x1),
+    BS_GROUPBOX = (0x7),
+    BS_ICON = (0x40),
+    BS_LEFT = (0x100),
+    BS_LEFTTEXT = (0x20),
+    BS_MULTILINE = (0x2000),
+    BS_NOTIFY = (0x4000),
+    BS_OWNERDRAW = (0xb),
+    BS_PUSHBUTTON = (0),
+    BS_PUSHLIKE = (0x1000),
+    BS_RADIOBUTTON = (0x4),
+    BS_RIGHT = (0x200),
+    BS_RIGHTBUTTON = (0x20),
+    BS_TEXT = (0),
+    BS_TOP = (0x400),
+    BS_USERBUTTON = (0x8),
+    BS_VCENTER = (0xc00),
+    CBS_AUTOHSCROLL = (0x40),
+    CBS_DISABLENOSCROLL = (0x800),
+    CBS_DROPDOWN = (0x2),
+    CBS_DROPDOWNLIST = (0x3),
+    CBS_HASSTRINGS = (0x200),
+    CBS_LOWERCASE = (0x4000),
+    CBS_NOINTEGRALHEIGHT = (0x400),
+    CBS_OEMCONVERT = (0x80),
+    CBS_OWNERDRAWFIXED = (0x10),
+    CBS_OWNERDRAWVARIABLE = (0x20),
+    CBS_SIMPLE = (0x1),
+    CBS_SORT = (0x100),
+    CBS_UPPERCASE = (0x2000),
+    ES_AUTOHSCROLL = (0x80),
+    ES_AUTOVSCROLL = (0x40),
+    ES_CENTER = (0x1),
+    ES_LEFT = (0),
+    ES_LOWERCASE = (0x10),
+    ES_MULTILINE = (0x4),
+    ES_NOHIDESEL = (0x100),
+    ES_NUMBER = (0x2000),
+    ES_OEMCONVERT = (0x400),
+    ES_PASSWORD = (0x20),
+    ES_READONLY = (0x800),
+    ES_RIGHT = (0x2),
+    ES_UPPERCASE = (0x8),
+    ES_WANTRETURN = (0x1000),
+    LBS_DISABLENOSCROLL = (0x1000),
+    LBS_EXTENDEDSEL = (0x800),
+    LBS_HASSTRINGS = (0x40),
+    LBS_MULTICOLUMN = (0x200),
+    LBS_MULTIPLESEL = (0x8),
+    LBS_NODATA = (0x2000),
+    LBS_NOINTEGRALHEIGHT = (0x100),
+    LBS_NOREDRAW = (0x4),
+    LBS_NOSEL = (0x4000),
+    LBS_NOTIFY = (0x1),
+    LBS_OWNERDRAWFIXED = (0x10),
+    LBS_OWNERDRAWVARIABLE = (0x20),
+    LBS_SORT = (0x2),
+    LBS_STANDARD = (0xa00003),
+    LBS_USETABSTOPS = (0x80),
+    LBS_WANTKEYBOARDINPUT = (0x400),
+    SBS_BOTTOMALIGN = (0x4),
+    SBS_HORZ = (0),
+    SBS_LEFTALIGN = (0x2),
+    SBS_RIGHTALIGN = (0x4),
+    SBS_SIZEBOX = (0x8),
+    SBS_SIZEBOXBOTTOMRIGHTALIGN = (0x4),
+    SBS_SIZEBOXTOPLEFTALIGN = (0x2),
+    SBS_SIZEGRIP = (0x10),
+    SBS_TOPALIGN = (0x2),
+    SBS_VERT = (0x1),
+    SS_BITMAP = (0xe),
+    SS_BLACKFRAME = (0x7),
+    SS_BLACKRECT = (0x4),
+    SS_CENTER = (0x1),
+    SS_CENTERIMAGE = (0x200),
+    SS_ENHMETAFILE = (0xf),
+    SS_ETCHEDFRAME = (0x12),
+    SS_ETCHEDHORZ = (0x10),
+    SS_ETCHEDVERT = (0x11),
+    SS_GRAYFRAME = (0x8),
+    SS_GRAYRECT = (0x5),
+    SS_ICON = (0x3),
+    SS_LEFT = (0),
+    SS_LEFTNOWORDWRAP = (0xc),
+    SS_NOPREFIX = (0x80),
+    SS_NOTIFY = (0x100),
+    SS_OWNERDRAW = (0xd),
+    SS_REALSIZEIMAGE = (0x800),
+    SS_RIGHT = (0x2),
+    SS_RIGHTJUST = (0x400),
+    SS_SIMPLE = (0xb),
+    SS_SUNKEN = (0x1000),
+    SS_USERITEM = (0xa),
+    SS_WHITEFRAME = (0x9),
+    SS_WHITERECT = (0x6),
+    DS_3DLOOK = (0x4),
+    DS_ABSALIGN = (0x1),
+    DS_CENTER = (0x800),
+    DS_CENTERMOUSE = (0x1000),
+    DS___FILE__HELP = (0x2000),
+    DS_CONTROL = (0x400),
+    DS_FIXEDSYS = (0x8),
+    DS_LOCALEDIT = (0x20),
+    DS_MODALFRAME = (0x80),
+    DS_NOFAILCREATE = (0x10),
+    DS_NOIDLEMSG = (0x100),
+    DS_SETFONT = (0x40),
+    DS_SETFOREGROUND = (0x200),
+    DS_SYSMODAL = (0x2),
+    WS_EX_ACCEPTFILES = (0x10),
+    WS_EX_APPWINDOW = (0x40000),
+    WS_EX_CLIENTEDGE = (0x200),
+    WS_EX___FILE__HELP = (0x400),
+    WS_EX_CONTROLPARENT = (0x10000),
+    WS_EX_DLGMODALFRAME = (0x1),
+    WS_EX_LEFT = (0),
+    WS_EX_LEFTSCROLLBAR = (0x4000),
+    WS_EX_LTRREADING = (0),
+    WS_EX_MDICHILD = (0x40),
+    WS_EX_NOPARENTNOTIFY = (0x4),
+    WS_EX_OVERLAPPEDWINDOW = (0x300),
+    WS_EX_PALETTEWINDOW = (0x188),
+    WS_EX_RIGHT = (0x1000),
+    WS_EX_RIGHTSCROLLBAR = (0),
+    WS_EX_RTLREADING = (0x2000),
+    WS_EX_STATICEDGE = (0x20000),
+    WS_EX_TOOLWINDOW = (0x80),
+    WS_EX_TOPMOST = (0x8),
+    WS_EX_TRANSPARENT = (0x20),
+    WS_EX_WINDOWEDGE = (0x100),
+    WINSTA_ACCESSCLIPBOARD = (0x4),
+    WINSTA_ACCESSGLOBALATOMS = (0x20),
+    WINSTA_CREATEDESKTOP = (0x8),
+    WINSTA_ENUMDESKTOPS = (0x1),
+    WINSTA_ENUMERATE = (0x100),
+    WINSTA_EXITWINDOWS = (0x40),
+    WINSTA_READATTRIBUTES = (0x2),
+    WINSTA_READSCREEN = (0x200),
+    WINSTA_WRITEATTRIBUTES = (0x10),
+    WH_CALLWNDPROC = (4),
+    WH_CALLWNDPROCRET = (12),
+    WH_CBT = (5),
+    WH_DEBUG = (9),
+    WH_GETMESSAGE = (3),
+    WH_JOURNALPLAYBACK = (1),
+    WH_JOURNALRECORD = (0),
+    WH_KEYBOARD = (2),
+    WH_MOUSE = (7),
+    WH_MSGFILTER = -((1)),
+    WH_SHELL = (10),
+    WH_SYSMSGFILTER = (6),
+    WH_FOREGROUNDIDLE = (11),
+    DDD_RAW_TARGET_PATH = (1),
+    DDD_REMOVE_DEFINITION = (2),
+    DDD_EXACT_MATCH_ON_REMOVE = (4),
+    DC_BINNAMES = (12),
+    DC_BINS = (6),
+    DC_COPIES = (18),
+    DC_DRIVER = (11),
+    DC_DATATYPE_PRODUCED = (21),
+    DC_DUPLEX = (7),
+    DC_EMF_COMPLIANT = (20),
+    DC_ENUMRESOLUTIONS = (13),
+    DC_EXTRA = (9),
+    DC_FIELDS = (1),
+    DC_FILEDEPENDENCIES = (14),
+    DC_MAXEXTENT = (5),
+    DC_MINEXTENT = (4),
+    DC_ORIENTATION = (17),
+    DC_PAPERNAMES = (16),
+    DC_PAPERS = (2),
+    DC_PAPERSIZE = (3),
+    DC_SIZE = (8),
+    DC_TRUETYPE = (15),
+    DCTT_BITMAP = (0x1),
+    DCTT_DOWNLOAD = (0x2),
+    DCTT_SUBDEV = (0x4),
+    DC_VERSION = (10),
+    DC_BINADJUST = (19),
+    DDL_ARCHIVE = (32),
+    DDL_DIRECTORY = (16),
+    DDL_DRIVES = (16384),
+    DDL_EXCLUSIVE = (32768),
+    DDL_HIDDEN = (2),
+    DDL_READONLY = (1),
+    DDL_READWRITE = (0),
+    DDL_SYSTEM = (4),
+    DDL_POSTMSGS = (8192),
+    DLL_PROCESS_ATTACH = (1),
+    DLL_THREAD_ATTACH = (2),
+    DLL_PROCESS_DETACH = (0),
+    DLL_THREAD_DETACH = (3),
+    DM_IN_BUFFER = (8),
+    DM_MODIFY = (8),
+    DM_IN_PROMPT = (4),
+    DM_PROMPT = (4),
+    DM_OUT_BUFFER = (2),
+    DM_COPY = (2),
+    DM_UPDATE = (1),
+    IDANI_OPEN = (1),
+    IDANI_CLOSE = (2),
+    DC_ACTIVE = (1),
+    DC_SMALLCAP = (2),
+    BDR_RAISEDINNER = (4),
+    BDR_SUNKENINNER = (8),
+    BDR_RAISEDOUTER = (1),
+    BDR_SUNKENOUTER = (1),
+    EDGE_BUMP = (9),
+    EDGE_ETCHED = (6),
+    EDGE_RAISED = (5),
+    EDGE_SUNKEN = (10),
+    BF_ADJUST = (8192),
+    BF_BOTTOM = (8),
+    BF_BOTTOMLEFT = (9),
+    BF_BOTTOMRIGHT = (12),
+    BF_DIAGONAL = (16),
+    BF_DIAGONAL_ENDBOTTOMLEFT = (25),
+    BF_DIAGONAL_ENDBOTTOMRIGHT = (28),
+    BF_DIAGONAL_ENDTOPLEFT = (19),
+    BF_DIAGONAL_ENDTOPRIGHT = (22),
+    BF_FLAT = (16384),
+    BF_LEFT = (1),
+    BF_MIDDLE = (2048),
+    BF_MONO = (32768),
+    BF_RECT = (15),
+    BF_RIGHT = (4),
+    BF_SOFT = (4096),
+    BF_TOP = (2),
+    BF_TOPLEFT = (3),
+    BF_TOPRIGHT = (6),
+    DFC_BUTTON = (4),
+    DFC_CAPTION = (1),
+    DFC_MENU = (2),
+    DFC_SCROLL = (3),
+    DFCS_BUTTON3STATE = (8),
+    DFCS_BUTTONCHECK = (0),
+    DFCS_BUTTONPUSH = (16),
+    DFCS_BUTTONRADIO = (4),
+    DFCS_BUTTONRADIOIMAGE = (1),
+    DFCS_BUTTONRADIOMASK = (2),
+    DFCS_CAPTIONCLOSE = (0),
+    DFCS_CAPTIONHELP = (4),
+    DFCS_CAPTIONMAX = (2),
+    DFCS_CAPTIONMIN = (1),
+    DFCS_CAPTIONRESTORE = (3),
+    DFCS_MENUARROW = (0),
+    DFCS_MENUBULLET = (2),
+    DFCS_MENUCHECK = (1),
+    DFCS_SCROLLCOMBOBOX = (5),
+    DFCS_SCROLLDOWN = (1),
+    DFCS_SCROLLLEFT = (2),
+    DFCS_SCROLLRIGHT = (3),
+    DFCS_SCROLLSIZEGRIP = (8),
+    DFCS_SCROLLUP = (0),
+    DFCS_ADJUSTRECT = (8192),
+    DFCS_CHECKED = (1024),
+    DFCS_FLAT = (16384),
+    DFCS_INACTIVE = (256),
+    DFCS_MONO = (32768),
+    DFCS_PUSHED = (512),
+    DI_COMPAT = (4),
+    DI_DEFAULTSIZE = (8),
+    DI_IMAGE = (2),
+    DI_MASK = (1),
+    DI_NORMAL = (3),
+    DST_BITMAP = (4),
+    DST_COMPLEX = (0),
+    DST_ICON = (3),
+    DST_PREFIXTEXT = (2),
+    DST_TEXT = (1),
+    DSS_NORMAL = (0),
+    DSS_UNION = (16),
+    DSS_DISABLED = (32),
+    DSS_MONO = (128),
+    SBT_NOBORDERS = (256),
+    SBT_OWNERDRAW = (4096),
+    SBT_POPOUT = (512),
+    SBT_RTLREADING = (1024),
+    DT_BOTTOM = (8),
+    DT_CALCRECT = (1024),
+    DT_CENTER = (1),
+    DT_EDITCONTROL = (8192),
+    DT_END_ELLIPSIS = (32768),
+    DT_PATH_ELLIPSIS = (16384),
+    DT_EXPANDTABS = (64),
+    DT_EXTERNALLEADING = (512),
+    DT_LEFT = (0),
+    DT_MODIFYSTRING = (65536),
+    DT_NOCLIP = (256),
+    DT_NOPREFIX = (2048),
+    DT_RIGHT = (2),
+    DT_RTLREADING = (131072),
+    DT_SINGLELINE = (32),
+    DT_TABSTOP = (128),
+    DT_TOP = (0),
+    DT_VCENTER = (4),
+    DT_WORDBREAK = (16),
+    DT_INTERNAL = (4096),
+    DUPLICATE_CLOSE_SOURCE = (1),
+    DUPLICATE_SAME_ACCESS = (2),
+    FILE_MAP_ALL_ACCESS = (0xf001f),
+    FILE_MAP_READ = (4),
+    FILE_MAP_WRITE = (2),
+    FILE_MAP_COPY = (1),
+    FILE_MAP_EXECUTE = (0x20),
+    MUTEX_ALL_ACCESS = (0x1f0001),
+    MUTEX_MODIFY_STATE = (1),
+    SYNCHRONIZE = (0x100000),
+    SEMAPHORE_ALL_ACCESS = (0x1f0003),
+    SEMAPHORE_MODIFY_STATE = (2),
+    EVENT_ALL_ACCESS = (0x1f0003),
+    EVENT_MODIFY_STATE = (2),
+    KEY_ALL_ACCESS = (0xf003f),
+    KEY_CREATE_LINK = (32),
+    KEY_CREATE_SUB_KEY = (4),
+    KEY_ENUMERATE_SUB_KEYS = (8),
+    KEY_EXECUTE = (0x20019),
+    KEY_NOTIFY = (16),
+    KEY_QUERY_VALUE = (1),
+    KEY_READ = (0x20019),
+    KEY_SET_VALUE = (2),
+    KEY_WRITE = (0x20006),
+    PROCESS_ALL_ACCESS = (0x1f0fff),
+    PROCESS_CREATE_PROCESS = (128),
+    PROCESS_CREATE_THREAD = (2),
+    PROCESS_DUP_HANDLE = (64),
+    PROCESS_QUERY_INFORMATION = (1024),
+    PROCESS_SET_INFORMATION = (512),
+    PROCESS_TERMINATE = (1),
+    PROCESS_VM_OPERATION = (8),
+    PROCESS_VM_READ = (16),
+    PROCESS_VM_WRITE = (32),
+    THREAD_ALL_ACCESS = (0x1f03ff),
+    THREAD_DIRECT_IMPERSONATION = (512),
+    THREAD_GET___FILE__ = (8),
+    THREAD_IMPERSONATE = (256),
+    THREAD_QUERY_INFORMATION = (64),
+    THREAD_SET___FILE__ = (16),
+    THREAD_SET_INFORMATION = (32),
+    THREAD_SET_THREAD_TOKEN = (128),
+    THREAD_SUSPEND_RESUME = (2),
+    THREAD_TERMINATE = (1),
+    WB_ISDELIMITER = (2),
+    WB_LEFT = (0),
+    WB_RIGHT = (1),
+    SB_BOTH = (3),
+    SB_CTL = (2),
+    SB_HORZ = (0),
+    SB_VERT = (1),
+    ESB_DISABLE_BOTH = (3),
+    ESB_DISABLE_DOWN = (2),
+    ESB_DISABLE_LEFT = (1),
+    ESB_DISABLE_LTUP = (1),
+    ESB_DISABLE_RIGHT = (2),
+    ESB_DISABLE_RTDN = (2),
+    ESB_DISABLE_UP = (1),
+    ESB_ENABLE_BOTH = (0),
+    SB_LINEUP = (0),
+    SB_LINEDOWN = (1),
+    SB_LINELEFT = (0),
+    SB_LINERIGHT = (1),
+    SB_PAGEUP = (2),
+    SB_PAGEDOWN = (3),
+    SB_PAGELEFT = (2),
+    SB_PAGERIGHT = (3),
+    SB_THUMBPOSITION = (4),
+    SB_THUMBTRACK = (5),
+    SB_ENDSCROLL = (8),
+    SB_LEFT = (6),
+    SB_RIGHT = (7),
+    SB_BOTTOM = (7),
+    SB_TOP = (6),
+    ENUM_ALL_CALENDARS = -((1)),
+    DATE_SHORTDATE = (1),
+    DATE_LONGDATE = (2),
+    SERVICE_ACTIVE = (1),
+    SERVICE_INACTIVE = (2),
+    DEVICE_FONTTYPE = (2),
+    RASTER_FONTTYPE = (1),
+    TRUETYPE_FONTTYPE = (4),
+    OBJ_BRUSH = (2),
+    OBJ_PEN = (1),
+    OBJ_PAL = (5),
+    OBJ_FONT = (6),
+    OBJ_BITMAP = (7),
+    OBJ_EXTPEN = (11),
+    OBJ_REGION = (8),
+    OBJ_DC = (3),
+    OBJ_MEMDC = (10),
+    OBJ_METAFILE = (9),
+    OBJ_METADC = (4),
+    OBJ_ENHMETAFILE = (13),
+    OBJ_ENHMETADC = (12),
+    SERVICE_WIN32 = (48),
+    SERVICE_DRIVER = (11),
+    CP_INSTALLED = (1),
+    CP_SUPPORTED = (2),
+    LCID_INSTALLED = (1),
+    LCID_SUPPORTED = (2),
+    TAPE_ERASE_LONG = (0x1),
+    TAPE_ERASE_SHORT = (0),
+    SP_ERROR = -((1)),
+    SP_OUTOFDISK = -((4)),
+    SP_OUTOFMEMORY = -((5)),
+    SP_USERABORT = -((3)),
+    PHYSICALWIDTH = (110),
+    PHYSICALHEIGHT = (111),
+    PHYSICALOFFSETX = (112),
+    PHYSICALOFFSETY = (113),
+    SCALINGFACTORX = (114),
+    SCALINGFACTORY = (115),
+    QUERYESCSUPPORT = (8),
+    cABORTDOC = (2),
+    cENDDOC = (11),
+    GETPHYSPAGESIZE = (12),
+    GETPRINTINGOFFSET = (13),
+    GETSCALINGFACTOR = (14),
+    NEWFRAME = (1),
+    NEXTBAND = (3),
+    PASSTHROUGH = (19),
+    cSETABORTPROC = (9),
+    cSTARTDOC = (10),
+    CLRDTR = (6),
+    CLRRTS = (4),
+    SETDTR = (5),
+    SETRTS = (3),
+    SETXOFF = (1),
+    SETXON = (2),
+    SETBREAK = (8),
+    CLRBREAK = (9),
+    EWX_FORCE = (4),
+    EWX_LOGOFF = (0),
+    EWX_POWEROFF = (8),
+    EWX_REBOOT = (2),
+    EWX_SHUTDOWN = (1),
+    FLOODFILLBORDER = (0),
+    FLOODFILLSURFACE = (1),
+    ETO_CLIPPED = (4),
+    ETO_GLYPH_INDEX = (16),
+    ETO_OPAQUE = (2),
+    ETO_RTLREADING = (128),
+    FOREGROUND_BLUE = (1),
+    FOREGROUND_GREEN = (2),
+    FOREGROUND_RED = (4),
+    FOREGROUND_INTENSITY = (8),
+    BACKGROUND_BLUE = (16),
+    BACKGROUND_GREEN = (32),
+    BACKGROUND_RED = (64),
+    BACKGROUND_INTENSITY = (128),
+    FILE_NOTIFY_CHANGE_FILE_NAME = (1),
+    FILE_NOTIFY_CHANGE_DIR_NAME = (2),
+    FILE_NOTIFY_CHANGE_ATTRIBUTES = (4),
+    FILE_NOTIFY_CHANGE_SIZE = (8),
+    FILE_NOTIFY_CHANGE_LAST_WRITE = (16),
+    FILE_NOTIFY_CHANGE_SECURITY = (256),
+    MAP_FOLDCZONE = (16),
+    MAP_FOLDDIGITS = (128),
+    MAP_PRECOMPOSED = (32),
+    MAP_COMPOSITE = (64),
+    HC_ACTION = (0),
+    FORMAT_MESSAGE_ALLOCATE_BUFFER = (256),
+    FORMAT_MESSAGE_IGNORE_INSERTS = (512),
+    FORMAT_MESSAGE_FROM_STRING = (1024),
+    FORMAT_MESSAGE_FROM_HMODULE = (2048),
+    FORMAT_MESSAGE_FROM_SYSTEM = (4096),
+    FORMAT_MESSAGE_ARGUMENT_ARRAY = (8192),
+    FORMAT_MESSAGE_MAX_WIDTH_MASK = (255),
+    GDICOMMENT_WINDOWS_METAFILE = -((2147483647)),
+    GDICOMMENT_BEGINGROUP = (2),
+    GDICOMMENT_ENDGROUP = (3),
+    GDICOMMENT_MULTIFORMATS = (1073741828),
+    GDICOMMENT_IDENTIFIER = (1128875079),
+    CTRL_C_EVENT = (0),
+    CTRL_BREAK_EVENT = (1),
+    CTRL_CLOSE_EVENT = (2),
+    CTRL_LOGOFF_EVENT = (5),
+    CTRL_SHUTDOWN_EVENT = (6),
+    AD_COUNTERCLOCKWISE = (1),
+    AD_CLOCKWISE = (2),
+    SCS_32BIT_BINARY = (0),
+    SCS_DOS_BINARY = (1),
+    SCS_OS216_BINARY = (5),
+    SCS_PIF_BINARY = (3),
+    SCS_POSIX_BINARY = (4),
+    SCS_WOW_BINARY = (2),
+    DCB_DISABLE = (8),
+    DCB_ENABLE = (4),
+    DCB_RESET = (1),
+    DCB_SET = (3),
+    DCB_ACCUMULATE = (2),
+    GCP_DBCS = (1),
+    GCP_ERROR = (0x8000),
+    GCP_CLASSIN = (0x80000),
+    GCP_DIACRITIC = (256),
+    GCP_DISPLAYZWG = (0x400000),
+    GCP_GLYPHSHAPE = (16),
+    GCP_JUSTIFY = (0x10000),
+    GCP_JUSTIFYIN = (0x200000),
+    GCP_KASHIDA = (1024),
+    GCP_LIGATE = (32),
+    GCP_MAXEXTENT = (0x100000),
+    GCP_NEUTRALOVERRIDE = (0x2000000),
+    GCP_NUMERICOVERRIDE = (0x1000000),
+    GCP_NUMERICSLATIN = (0x4000000),
+    GCP_NUMERICSLOCAL = (0x8000000),
+    GCP_REORDER = (2),
+    GCP_SYMSWAPOFF = (0x800000),
+    GCP_USEKERNING = (8),
+    FLI_GLYPHS = (0x40000),
+    FLI_MASK = (0x103b),
+    GCW_ATOM = -((32)),
+    GCL_CBCLSEXTRA = -((20)),
+    GCL_CBWNDEXTRA = -((18)),
+    GCL_HBRBACKGROUND = -((10)),
+    GCL_HCURSOR = -((12)),
+    GCL_HICON = -((14)),
+    GCL_HICONSM = -((34)),
+    GCL_HMODULE = -((16)),
+    GCL_MENUNAME = -((8)),
+    GCL_STYLE = -((26)),
+    GCL_WNDPROC = -((24)),
+    CF_BITMAP = (2),
+    CF_DIB = (8),
+    CF_PALETTE = (9),
+    CF_ENHMETAFILE = (14),
+    CF_METAFILEPICT = (3),
+    CF_OEMTEXT = (7),
+    CF_TEXT = (1),
+    CF_UNICODETEXT = (13),
+    CF_DIF = (5),
+    CF_DSPBITMAP = (130),
+    CF_DSPENHMETAFILE = (142),
+    CF_DSPMETAFILEPICT = (131),
+    CF_DSPTEXT = (129),
+    CF_GDIOBJFIRST = (768),
+    CF_GDIOBJLAST = (1023),
+    CF_HDROP = (15),
+    CF_LOCALE = (16),
+    CF_OWNERDISPLAY = (128),
+    CF_PENDATA = (10),
+    CF_PRIVATEFIRST = (512),
+    CF_PRIVATELAST = (767),
+    CF_RIFF = (11),
+    CF_SYLK = (4),
+    CF_WAVE = (12),
+    CF_TIFF = (6),
+    EV_BREAK = (64),
+    EV_CTS = (8),
+    EV_DSR = (16),
+    EV_ERR = (128),
+    EV_EVENT1 = (2048),
+    EV_EVENT2 = (4096),
+    EV_PERR = (512),
+    EV_RING = (256),
+    EV_RLSD = (32),
+    EV_RX80FULL = (1024),
+    EV_RXCHAR = (1),
+    EV_RXFLAG = (2),
+    EV_TXEMPTY = (4),
+    MS_CTS_ON = (0x10),
+    MS_DSR_ON = (0x20),
+    MS_RING_ON = (0x40),
+    MS_RLSD_ON = (0x80),
+    MAX_COMPUTERNAME_LENGTH = (15),
+    ENABLE_LINE_INPUT = (2),
+    ENABLE_ECHO_INPUT = (4),
+    ENABLE_PROCESSED_INPUT = (1),
+    ENABLE_WINDOW_INPUT = (8),
+    ENABLE_MOUSE_INPUT = (16),
+    ENABLE_PROCESSED_OUTPUT = (1),
+    ENABLE_WRAP_AT_EOL_OUTPUT = (2),
+    CP_ACP = (0),
+    CP_MACCP = (2),
+    CP_OEMCP = (1),
+    CP_UTF8 = 65001,
+    DATE_USE_ALT_CALENDAR = (4),
+    DCX_WINDOW = (0x1),
+    DCX_CACHE = (0x2),
+    DCX_PARENTCLIP = (0x20),
+    DCX_CLIPSIBLINGS = (0x10),
+    DCX_CLIPCHILDREN = (0x8),
+    DCX_NORESETATTRS = (0x4),
+    DCX_LOCKWINDOWUPDATE = (0x400),
+    DCX_EXCLUDERGN = (0x40),
+    DCX_INTERSECTRGN = (0x80),
+    DCX_VALIDATE = (0x200000),
+    DRIVERVERSION = (0),
+    TECHNOLOGY = (2),
+    DT_PLOTTER = (0),
+    DT_RASDISPLAY = (1),
+    DT_RASPRINTER = (2),
+    DT_RASCAMERA = (3),
+    DT_CHARSTREAM = (4),
+    DT_METAFILE = (5),
+    DT_DISPFILE = (6),
+    HORZSIZE = (4),
+    VERTSIZE = (6),
+    HORZRES = (8),
+    VERTRES = (10),
+    LOGPIXELSX = (88),
+    LOGPIXELSY = (90),
+    BITSPIXEL = (12),
+    PLANES = (14),
+    NUMBRUSHES = (16),
+    NUMPENS = (18),
+    NUMFONTS = (22),
+    NUMCOLORS = (24),
+    ASPECTX = (40),
+    ASPECTY = (42),
+    ASPECTXY = (44),
+    PDEVICESIZE = (26),
+    CLIPCAPS = (36),
+    SIZEPALETTE = (104),
+    NUMRESERVED = (106),
+    COLORRES = (108),
+    VREFRESH = (116),
+    DESKTOPHORZRES = (118),
+    DESKTOPVERTRES = (117),
+    BLTALIGNMENT = (119),
+    RASTERCAPS = (38),
+    RC_BANDING = (2),
+    RC_BITBLT = (1),
+    RC_BITMAP64 = (8),
+    RC_DI_BITMAP = (128),
+    RC_DIBTODEV = (512),
+    RC_FLOODFILL = (4096),
+    RC_GDI20_OUTPUT = (16),
+    RC_PALETTE = (256),
+    RC_SCALING = (4),
+    RC_STRETCHBLT = (2048),
+    RC_STRETCHDIB = (8192),
+    CURVECAPS = (28),
+    CC_NONE = (0),
+    CC_CIRCLES = (1),
+    CC_PIE = (2),
+    CC_CHORD = (4),
+    CC_ELLIPSES = (8),
+    CC_WIDE = (16),
+    CC_STYLED = (32),
+    CC_WIDESTYLED = (64),
+    CC_INTERIORS = (128),
+    CC_ROUNDRECT = (256),
+    LINECAPS = (30),
+    LC_NONE = (0),
+    LC_POLYLINE = (2),
+    LC_MARKER = (4),
+    LC_POLYMARKER = (8),
+    LC_WIDE = (16),
+    LC_STYLED = (32),
+    LC_WIDESTYLED = (64),
+    LC_INTERIORS = (128),
+    POLYGONALCAPS = (32),
+    PC_NONE = (0),
+    PC_POLYGON = (1),
+    PC_RECTANGLE = (2),
+    PC_WINDPOLYGON = (4),
+    PC_SCANLINE = (8),
+    PC_WIDE = (16),
+    PC_STYLED = (32),
+    PC_WIDESTYLED = (64),
+    PC_INTERIORS = (128),
+    TEXTCAPS = (34),
+    TC_OP_CHARACTER = (1),
+    TC_OP_STROKE = (2),
+    TC_CP_STROKE = (4),
+    TC_CR_90 = (8),
+    TC_CR_ANY = (16),
+    TC_SF_X_YINDEP = (32),
+    TC_SA_DOUBLE = (64),
+    TC_SA_INTEGER = (128),
+    TC_SA_CONTIN = (256),
+    TC_EA_DOUBLE = (512),
+    TC_IA_ABLE = (1024),
+    TC_UA_ABLE = (2048),
+    TC_SO_ABLE = (4096),
+    TC_RA_ABLE = (8192),
+    TC_VA_ABLE = (16384),
+    TC_RESERVED = (32768),
+    TC_SCROLLBLT = (65536),
+    PC_PATHS = (512),
+    DRIVE_REMOVABLE = (2),
+    DRIVE_FIXED = (3),
+    DRIVE_REMOTE = (4),
+    DRIVE_CDROM = (5),
+    DRIVE_RAMDISK = (6),
+    DRIVE_UNKNOWN = (0),
+    DRIVE_NO_ROOT_DIR = (1),
+    EXCEPTION_ACCESS_VIOLATION = (0xc0000005),
+    EXCEPTION_BREAKPOINT = (0x80000003),
+    EXCEPTION_DATATYPE_MISALIGNMENT = (0x80000002),
+    EXCEPTION_SINGLE_STEP = (0x80000004),
+    EXCEPTION_ARRAY_BOUNDS_EXCEEDED = (0xc000008c),
+    EXCEPTION_FLT_DENORMAL_OPERAND = (0xc000008d),
+    EXCEPTION_FLT_DIVIDE_BY_ZERO = (0xc000008e),
+    EXCEPTION_FLT_INEXACT_RESULT = (0xc000008f),
+    EXCEPTION_FLT_INVALID_OPERATION = (0xc0000090),
+    EXCEPTION_FLT_OVERFLOW = (0xc0000091),
+    EXCEPTION_FLT_STACK_CHECK = (0xc0000092),
+    EXCEPTION_FLT_UNDERFLOW = (0xc0000093),
+    EXCEPTION_INT_DIVIDE_BY_ZERO = (0xc0000094),
+    EXCEPTION_INT_OVERFLOW = (0xc0000095),
+    EXCEPTION_INVALID_HANDLE = (0xc0000008),
+    EXCEPTION_PRIV_INSTRUCTION = (0xc0000096),
+    EXCEPTION_NONCONTINUABLE_EXCEPTION = (0xc0000025),
+    EXCEPTION_NONCONTINUABLE = (0x1),
+    EXCEPTION_STACK_OVERFLOW = (0xc00000fd),
+    EXCEPTION_INVALID_DISPOSITION = (0xc0000026),
+    FILE_TYPE_UNKNOWN = (0),
+    FILE_TYPE_DISK = (1),
+    FILE_TYPE_CHAR = (2),
+    FILE_TYPE_PIPE = (3),
+    GGO_BITMAP = (1),
+    GGO_NATIVE = (2),
+    GGO_METRICS = (0),
+    GGO_GRAY2_BITMAP = (4),
+    GGO_GRAY4_BITMAP = (5),
+    GGO_GRAY8_BITMAP = (6),
+    GDI_ERROR = (0xffffffff),
+    GM_COMPATIBLE = (1),
+    GM_ADVANCED = (2),
+    HANDLE_FLAG_INHERIT = (1),
+    HANDLE_FLAG_PROTECT_FROM_CLOSE = (2),
+}
+char* RT_ACCELERATOR = cast(char*) ((9));
+char* RT_BITMAP = cast(char*) ((2));
+char* RT_DIALOG = cast(char*) ((5));
+char* RT_FONT = cast(char*) ((8));
+char* RT_FONTDIR = cast(char*) ((7));
+char* RT_MENU = cast(char*) ((4));
+char* RT_RCDATA = cast(char*) ((10));
+char* RT_STRING = cast(char*) ((6));
+char* RT_MESSAGETABLE = cast(char*) ((11));
+char* RT_CURSOR = cast(char*) ((1));
+char* RT_GROUP_CURSOR = cast(char*) ((12));
+char* RT_ICON = cast(char*) ((3));
+char* RT_GROUP_ICON = cast(char*) ((13));
+char* RT_VERSION = cast(char*) ((16));
+char* IDC_ARROW = cast(char*) ((32512));
+char* IDC_IBEAM = cast(char*) ((32513));
+char* IDC_WAIT = cast(char*) ((32514));
+char* IDC_CROSS = cast(char*) ((32515));
+char* IDC_UPARROW = cast(char*) ((32516));
+char* IDC_SIZENWSE = cast(char*) ((32642));
+char* IDC_SIZENESW = cast(char*) ((32643));
+char* IDC_SIZEWE = cast(char*) ((32644));
+char* IDC_SIZENS = cast(char*) ((32645));
+char* IDC_SIZEALL = cast(char*) ((32646));
+char* IDC_NO = cast(char*) ((32648));
+char* IDC_APPSTARTING = cast(char*) ((32650));
+char* IDC_HELP = cast(char*) ((32651));
+char* IDI_APPLICATION = cast(char*) ((32512));
+char* IDI_HAND = cast(char*) ((32513));
+char* IDI_QUESTION = cast(char*) ((32514));
+char* IDI_EXCLAMATION = cast(char*) ((32515));
+char* IDI_ASTERISK = cast(char*) ((32516));
+char* IDI_WINLOGO = cast(char*) ((32517));
+char* IDC_SIZE = cast(char*) ((32640));
+char* IDC_ICON = cast(char*) ((32641));
+enum : DWORD {
+    MM_ANISOTROPIC = (8),
+    MM_HIENGLISH = (5),
+    MM_HIMETRIC = (3),
+    MM_ISOTROPIC = (7),
+    MM_LOENGLISH = (4),
+    MM_LOMETRIC = (2),
+    MM_TEXT = (1),
+    MM_TWIPS = (6),
+    GMDI_GOINTOPOPUPS = (0x2),
+    GMDI_USEDISABLED = (0x1),
+    PM_NOREMOVE = (0),
+    PM_REMOVE = (1),
+    PM_NOYIELD = (2),
+    PIPE_CLIENT_END = (0),
+    PIPE_SERVER_END = (1),
+    GW_HWNDNEXT = (2),
+    GW_HWNDPREV = (3),
+    GW_CHILD = (5),
+    GW_HWNDFIRST = (0),
+    GW_HWNDLAST = (1),
+    GW_OWNER = (4),
+    PT_MOVETO = (6),
+    PT_LINETO = (2),
+    PT_BEZIERTO = (4),
+    PT_CLOSEFIGURE = (1),
+    SHUTDOWN_NORETRY = (1),
+    QS_ALLEVENTS = (191),
+    QS_ALLINPUT = (255),
+    QS_HOTKEY = (128),
+    QS_INPUT = (7),
+    QS_KEY = (1),
+    QS_MOUSE = (6),
+    QS_MOUSEBUTTON = (4),
+    QS_MOUSEMOVE = (2),
+    QS_PAINT = (32),
+    QS_POSTMESSAGE = (8),
+    QS_SENDMESSAGE = (64),
+    QS_TIMER = (16),
+    SIF_ALL = (23),
+    SIF_PAGE = (2),
+    SIF_POS = (4),
+    SIF_RANGE = (1),
+    SIF_DISABLENOSCROLL = (8),
+    STD_INPUT_HANDLE = -(10),
+    STD_OUTPUT_HANDLE = -(11),
+    STD_ERROR_HANDLE = -(12),
+    BLACK_BRUSH = (4),
+    DKGRAY_BRUSH = (3),
+    GRAY_BRUSH = (2),
+    HOLLOW_BRUSH = (5),
+    LTGRAY_BRUSH = (1),
+    NULL_BRUSH = (5),
+    WHITE_BRUSH = (0),
+    BLACK_PEN = (7),
+    NULL_PEN = (8),
+    WHITE_PEN = (6),
+    ANSI_FIXED_FONT = (11),
+    ANSI_VAR_FONT = (12),
+    DEVICE_DEFAULT_FONT = (14),
+    DEFAULT_GUI_FONT = (17),
+    OEM_FIXED_FONT = (10),
+    SYSTEM_FONT = (13),
+    SYSTEM_FIXED_FONT = (16),
+    DEFAULT_PALETTE = (15),
+    CT_CTYPE1 = (1),
+    CT_CTYPE2 = (2),
+    CT_CTYPE3 = (4),
+    C1_UPPER = (1),
+    C1_LOWER = (2),
+    C1_DIGIT = (4),
+    C1_SPACE = (8),
+    C1_PUNCT = (16),
+    C1_CNTRL = (32),
+    C1_BLANK = (64),
+    C1_XDIGIT = (128),
+    C1_ALPHA = (256),
+    C2_LEFTTORIGHT = (1),
+    C2_RIGHTTOLEFT = (2),
+    C2_EUROPENUMBER = (3),
+    C2_EUROPESEPARATOR = (4),
+    C2_EUROPETERMINATOR = (5),
+    C2_ARABICNUMBER = (6),
+    C2_COMMONSEPARATOR = (7),
+    C2_BLOCKSEPARATOR = (8),
+    C2_SEGMENTSEPARATOR = (9),
+    C2_WHITESPACE = (10),
+    C2_OTHERNEUTRAL = (11),
+    C2_NOTAPPLICABLE = (0),
+    C3_NONSPACING = (1),
+    C3_DIACRITIC = (2),
+    C3_VOWELMARK = (4),
+    C3_SYMBOL = (8),
+    C3_KATAKANA = (16),
+    C3_HIRAGANA = (32),
+    C3_HALFWIDTH = (64),
+    C3_FULLWIDTH = (128),
+    C3_IDEOGRAPH = (256),
+    C3_KASHIDA = (512),
+    C3_ALPHA = (32768),
+    C3_NOTAPPLICABLE = (0),
+    COLOR_3DDKSHADOW = (21),
+    COLOR_3DFACE = (15),
+    COLOR_3DHILIGHT = (20),
+    COLOR_3DLIGHT = (22),
+    COLOR_BTNHILIGHT = (20),
+    COLOR_3DSHADOW = (16),
+    COLOR_ACTIVEBORDER = (10),
+    COLOR_ACTIVECAPTION = (2),
+    COLOR_APPWORKSPACE = (12),
+    COLOR_BACKGROUND = (1),
+    COLOR_DESKTOP = (1),
+    COLOR_BTNFACE = (15),
+    COLOR_BTNHIGHLIGHT = (20),
+    COLOR_BTNSHADOW = (16),
+    COLOR_BTNTEXT = (18),
+    COLOR_CAPTIONTEXT = (9),
+    COLOR_GRAYTEXT = (17),
+    COLOR_HIGHLIGHT = (13),
+    COLOR_HIGHLIGHTTEXT = (14),
+    COLOR_INACTIVEBORDER = (11),
+    COLOR_INACTIVECAPTION = (3),
+    COLOR_INACTIVECAPTIONTEXT = (19),
+    COLOR_INFOBK = (24),
+    COLOR_INFOTEXT = (23),
+    COLOR_MENU = (4),
+    COLOR_MENUTEXT = (7),
+    COLOR_SCROLLBAR = (0),
+    COLOR_WINDOW = (5),
+    COLOR_WINDOWFRAME = (6),
+    COLOR_WINDOWTEXT = (8),
+    SM_CYMIN = (29),
+    SM_CXMIN = (28),
+    SM_ARRANGE = (56),
+    SM_CLEANBOOT = (67),
+    SM_CMETRICS = (76),
+    SM_CMOUSEBUTTONS = (43),
+    SM_CXBORDER = (5),
+    SM_CYBORDER = (6),
+    SM_CXCURSOR = (13),
+    SM_CYCURSOR = (14),
+    SM_CXDLGFRAME = (7),
+    SM_CYDLGFRAME = (8),
+    SM_CXDOUBLECLK = (36),
+    SM_CYDOUBLECLK = (37),
+    SM_CXDRAG = (68),
+    SM_CYDRAG = (69),
+    SM_CXEDGE = (45),
+    SM_CYEDGE = (46),
+    SM_CXFIXEDFRAME = (7),
+    SM_CYFIXEDFRAME = (8),
+    SM_CXFRAME = (32),
+    SM_CYFRAME = (33),
+    SM_CXFULLSCREEN = (16),
+    SM_CYFULLSCREEN = (17),
+    SM_CXHSCROLL = (21),
+    SM_CYHSCROLL = (3),
+    SM_CXHTHUMB = (10),
+    SM_CXICON = (11),
+    SM_CYICON = (12),
+    SM_CXICONSPACING = (38),
+    SM_CYICONSPACING = (39),
+    SM_CXMAXIMIZED = (61),
+    SM_CYMAXIMIZED = (62),
+    SM_CXMAXTRACK = (59),
+    SM_CYMAXTRACK = (60),
+    SM_CXMENUCHECK = (71),
+    SM_CYMENUCHECK = (72),
+    SM_CXMENUSIZE = (54),
+    SM_CYMENUSIZE = (55),
+    SM_CXMINIMIZED = (57),
+    SM_CYMINIMIZED = (58),
+    SM_CXMINSPACING = (47),
+    SM_CYMINSPACING = (48),
+    SM_CXMINTRACK = (34),
+    SM_CYMINTRACK = (35),
+    SM_CXSCREEN = (0),
+    SM_CYSCREEN = (1),
+    SM_CXSIZE = (30),
+    SM_CYSIZE = (31),
+    SM_CXSIZEFRAME = (32),
+    SM_CYSIZEFRAME = (33),
+    SM_CXSMICON = (49),
+    SM_CYSMICON = (50),
+    SM_CXSMSIZE = (52),
+    SM_CYSMSIZE = (53),
+    SM_CXVSCROLL = (2),
+    SM_CYVSCROLL = (20),
+    SM_CYVTHUMB = (9),
+    SM_CYCAPTION = (4),
+    SM_CYKANJIWINDOW = (18),
+    SM_CYMENU = (15),
+    SM_CYSMCAPTION = (51),
+    SM_DBCSENABLED = (42),
+    SM_DEBUG = (22),
+    SM_MENUDROPALIGNMENT = (40),
+    SM_MIDEASTENABLED = (74),
+    SM_MOUSEPRESENT = (19),
+    SM_MOUSEWHEELPRESENT = (75),
+    SM_NETWORK = (63),
+    SM_PENWINDOWS = (41),
+    SM_SECURE = (44),
+    SM_SHOWSOUNDS = (70),
+    SM_SLOWMACHINE = (73),
+    SM_SWAPBUTTON = (23),
+    ARW_BOTTOMLEFT = (0),
+    ARW_BOTTOMRIGHT = (0x1),
+    ARW_HIDE = (0x8),
+    ARW_TOPLEFT = (0x2),
+    ARW_TOPRIGHT = (0x3),
+    ARW_DOWN = (0x4),
+    ARW_LEFT = (0),
+    ARW_RIGHT = (0),
+    ARW_UP = (0x4),
+    SYSPAL_NOSTATIC = (2),
+    SYSPAL_STATIC = (1),
+    SYSPAL_ERROR = (0),
+    GET_TAPE_MEDIA_INFORMATION = (0),
+    GET_TAPE_DRIVE_INFORMATION = (1),
+    SET_TAPE_MEDIA_INFORMATION = (0),
+    SET_TAPE_DRIVE_INFORMATION = (1),
+    TAPE_ABSOLUTE_POSITION = (0),
+    TAPE_LOGICAL_POSITION = (0x1),
+    TA_BASELINE = (24),
+    TA_BOTTOM = (8),
+    TA_TOP = (0),
+    TA_CENTER = (6),
+    TA_LEFT = (0),
+    TA_RIGHT = (2),
+    TA_RTLREADING = (256),
+    TA_NOUPDATECP = (0),
+    TA_UPDATECP = (1),
+    VTA_BASELINE = (24),
+    VTA_CENTER = (6),
+    THREAD_PRIORITY_ABOVE_NORMAL = (1),
+    THREAD_PRIORITY_BELOW_NORMAL = -((1)),
+    THREAD_PRIORITY_HIGHEST = (2),
+    THREAD_PRIORITY_IDLE = -((15)),
+    THREAD_PRIORITY_LOWEST = -((2)),
+    THREAD_PRIORITY_NORMAL = (0),
+    THREAD_PRIORITY_TIME_CRITICAL = (15),
+    THREAD_PRIORITY_ERROR_RETURN = (2147483647),
+    TLS_MINIMUM_AVAILABLE = (64),
+    TIME_NOMINUTESORSECONDS = (1),
+    TIME_NOSECONDS = (2),
+    TIME_NOTIMEMARKER = (4),
+    TIME_FORCE24HOURFORMAT = (8),
+    TIME_ZONE_ID_INVALID = -(1),
+    TIME_ZONE_ID_UNKNOWN = (0),
+    TIME_ZONE_ID_STANDARD = (1),
+    TIME_ZONE_ID_DAYLIGHT = (2),
+    UOI_FLAGS = (1),
+    UOI_NAME = (2),
+    UOI_TYPE = (3),
+    FS_CASE_IS_PRESERVED = (2),
+    FS_CASE_SENSITIVE = (1),
+    FS_UNICODE_STORED_ON_DISK = (4),
+    FS_PERSISTENT_ACLS = (8),
+    FS_FILE_COMPRESSION = (16),
+    FS_VOL_IS_COMPRESSED = (32768),
+    GWL_EXSTYLE = -((20)),
+    GWL_STYLE = -((16)),
+    GWL_WNDPROC = -((4)),
+    GWL_HINSTANCE = -((6)),
+    GWL_HWNDPARENT = -((8)),
+    GWL_ID = -((12)),
+    GWL_USERDATA = -((21)),
+    DWL_DLGPROC = (4),
+    DWL_MSGRESULT = (0),
+    DWL_USER = (8),
+    GMEM_FIXED = (0),
+    GMEM_MOVEABLE = (2),
+    GPTR = (64),
+    GHND = (66),
+    GMEM_DDESHARE = (8192),
+    GMEM_DISCARDABLE = (256),
+    GMEM_LOWER = (4096),
+    GMEM_NOCOMPACT = (16),
+    GMEM_NODISCARD = (32),
+    GMEM_NOT_BANKED = (4096),
+    GMEM_NOTIFY = (16384),
+    GMEM_SHARE = (8192),
+    GMEM_ZEROINIT = (64),
+    GMEM_DISCARDED = (16384),
+    GMEM_INVALID_HANDLE = (32768),
+    GMEM_LOCKCOUNT = (255),
+    HEAP_GENERATE_EXCEPTIONS = (4),
+    HEAP_NO_SERIALIZE = (1),
+    HEAP_ZERO_MEMORY = (8),
+    STATUS_NO_MEMORY = (0xc0000017),
+    STATUS_ACCESS_VIOLATION = (0xc0000005),
+    HEAP_REALLOC_IN_PLACE_ONLY = (16),
+    ILC_COLOR = (0),
+    ILC_COLOR4 = (4),
+    ILC_COLOR8 = (8),
+    ILC_COLOR16 = (16),
+    ILC_COLOR24 = (24),
+    ILC_COLOR32 = (32),
+    ILC_COLORDDB = (254),
+    ILC_MASK = (1),
+    ILC_PALETTE = (2048),
+    ILD_BLEND25 = (2),
+    ILD_BLEND50 = (4),
+    ILD_SELECTED = (4),
+    ILD_BLEND = (4),
+    ILD_FOCUS = (2),
+    ILD_MASK = (16),
+    ILD_NORMAL = (0),
+    ILD_TRANSPARENT = (1),
+    CLR_NONE = (0xffffffff),
+    CLR_DEFAULT = (0xff000000),
+    CLR_INVALID = (0xFFFFFFFF),
+    LR_LOADFROMFILE = (16),
+    LR_LOADMAP3DCOLORS = (4096),
+    LR_LOADTRANSPARENT = (32),
+    IME_CONFIG_GENERAL = (1),
+    IME_CONFIG_REGISTERWORD = (2),
+    IME_CONFIG_SELECTDICTIONARY = (3),
+    GCL_CONVERSION = (1),
+    GCL_REVERSECONVERSION = (2),
+    GCL_REVERSE_LENGTH = (3),
+    GGL_LEVEL = (1),
+    GGL_INDEX = (2),
+    GGL_STRING = (3),
+    GGL_PRIVATE = (4),
+    GL_LEVEL_ERROR = (2),
+    GL_LEVEL_FATAL = (1),
+    GL_LEVEL_INFORMATION = (4),
+    GL_LEVEL_NOGUIDELINE = (0),
+    GL_LEVEL_WARNING = (3),
+    GL_ID_CANNOTSAVE = (17),
+    GL_ID_NOCONVERT = (32),
+    GL_ID_NODICTIONARY = (16),
+    GL_ID_NOMODULE = (1),
+    GL_ID_READINGCONFLICT = (35),
+    GL_ID_TOOMANYSTROKE = (34),
+    GL_ID_TYPINGERROR = (33),
+    GL_ID_UNKNOWN = (0),
+    GL_ID_INPUTREADING = (36),
+    GL_ID_INPUTRADICAL = (37),
+    GL_ID_INPUTCODE = (38),
+    GL_ID_CHOOSECANDIDATE = (40),
+    GL_ID_REVERSECONVERSION = (41),
+    IGP_PROPERTY = (4),
+    IGP_CONVERSION = (8),
+    IGP_SENTENCE = (12),
+    IGP_UI = (16),
+    IGP_SETCOMPSTR = (20),
+    IGP_SELECT = (24),
+    IME_PROP_AT_CARET = (65536),
+    IME_PROP_SPECIAL_UI = (131072),
+    IME_PROP_CANDLIST_START_FROM_1 = (262144),
+    IME_PROP_UNICODE = (524288),
+    UI_CAP_2700 = (1),
+    UI_CAP_ROT90 = (2),
+    UI_CAP_ROTANY = (4),
+    SCS_CAP_COMPSTR = (1),
+    SCS_CAP_MAKEREAD = (2),
+    SELECT_CAP_CONVERSION = (1),
+    SELECT_CAP_SENTENCE = (2),
+    NI_CHANGECANDIDATELIST = (19),
+    NI_CLOSECANDIDATE = (17),
+    NI_COMPOSITIONSTR = (21),
+    NI_OPENCANDIDATE = (16),
+    NI_SELECTCANDIDATESTR = (18),
+    NI_SETCANDIDATE_PAGESIZE = (23),
+    NI_SETCANDIDATE_PAGESTART = (22),
+    CPS_CANCEL = (4),
+    CPS_COMPLETE = (1),
+    CPS_CONVERT = (2),
+    CPS_REVERT = (3),
+    SCS_SETSTR = (9),
+    SCS_CHANGEATTR = (18),
+    SCS_CHANGECLAUSE = (36),
+    IME_REGWORD_STYLE_EUDC = (1),
+    IME_REGWORD_STYLE_USER_FIRST = (0x80000000),
+    IME_REGWORD_STYLE_USER_LAST = -((1)),
+    SECURITY_DESCRIPTOR_REVISION = (1),
+    IS_TEXT_UNICODE_ASCII16 = (1),
+    IS_TEXT_UNICODE_REVERSE_ASCII16 = (16),
+    IS_TEXT_UNICODE_STATISTICS = (2),
+    IS_TEXT_UNICODE_REVERSE_STATISTICS = (32),
+    IS_TEXT_UNICODE_CONTROLS = (4),
+    IS_TEXT_UNICODE_REVERSE_CONTROLS = (64),
+    IS_TEXT_UNICODE_SIGNATURE = (8),
+    IS_TEXT_UNICODE_REVERSE_SIGNATURE = (128),
+    IS_TEXT_UNICODE_ILLEGAL_CHARS = (256),
+    IS_TEXT_UNICODE_ODD_LENGTH = (512),
+    IS_TEXT_UNICODE_NULL_BYTES = (4096),
+    IS_TEXT_UNICODE_UNICODE_MASK = (15),
+    IS_TEXT_UNICODE_REVERSE_MASK = (240),
+    IS_TEXT_UNICODE_NOT_UNICODE_MASK = (3840),
+    IS_TEXT_UNICODE_NOT_ASCII_MASK = (61440),
+    HC_GETNEXT = (1),
+    HC_SKIP = (2),
+    HC_SYSMODALOFF = (5),
+    HC_SYSMODALON = (4),
+    HC_NOREMOVE = (3),
+    KEYEVENTF_EXTENDEDKEY = (1),
+    KEYEVENTF_KEYUP = (2),
+    OBM_BTNCORNERS = (32758),
+    OBM_BTSIZE = (32761),
+    OBM_CHECK = (32760),
+    OBM_CHECKBOXES = (32759),
+    OBM_CLOSE = (32754),
+    OBM_COMBO = (32738),
+    OBM_DNARROW = (32752),
+    OBM_DNARROWD = (32742),
+    OBM_DNARROWI = (32736),
+    OBM_LFARROW = (32750),
+    OBM_LFARROWI = (32734),
+    OBM_LFARROWD = (32740),
+    OBM_MNARROW = (32739),
+    OBM_OLD_CLOSE = (32767),
+    OBM_OLD_DNARROW = (32764),
+    OBM_OLD_LFARROW = (32762),
+    OBM_OLD_REDUCE = (32757),
+    OBM_OLD_RESTORE = (32755),
+    OBM_OLD_RGARROW = (32763),
+    OBM_OLD_UPARROW = (32765),
+    OBM_OLD_ZOOM = (32756),
+    OBM_REDUCE = (32749),
+    OBM_REDUCED = (32746),
+    OBM_RESTORE = (32747),
+    OBM_RESTORED = (32744),
+    OBM_RGARROW = (32751),
+    OBM_RGARROWD = (32741),
+    OBM_RGARROWI = (32735),
+    OBM_SIZE = (32766),
+    OBM_UPARROW = (32753),
+    OBM_UPARROWD = (32743),
+    OBM_UPARROWI = (32737),
+    OBM_ZOOM = (32748),
+    OBM_ZOOMD = (32745),
+    DONT_RESOLVE_DLL_REFERENCES = (1),
+    LOAD_LIBRARY_AS_DATAFILE = (2),
+    LOAD_WITH_ALTERED_SEARCH_PATH = (8),
+    LPTR = (64),
+    LHND = (66),
+    NONZEROLHND = (2),
+    NONZEROLPTR = (0),
+    LMEM_NONZEROLHND = (2),
+    LMEM_NONZEROLPTR = (0),
+    LMEM_FIXED = (0),
+    LMEM_MOVEABLE = (2),
+    LMEM_NOCOMPACT = (16),
+    LMEM_NODISCARD = (32),
+    LMEM_ZEROINIT = (64),
+    LMEM_MODIFY = (128),
+    LMEM_LOCKCOUNT = (255),
+    LMEM_DISCARDABLE = (3840),
+    LMEM_DISCARDED = (16384),
+    LMEM_INVALID_HANDLE = (32768),
+    LOCKFILE_FAIL_IMMEDIATELY = (1),
+    LOCKFILE_EXCLUSIVE_LOCK = (2),
+    MB_USERICON = (0x80),
+    MB_ICONASTERISK = (0x40),
+    MB_ICONEXCLAMATION = (0x30),
+    MB_ICONWARNING = (0x30),
+    MB_ICONERROR = (0x10),
+    MB_ICONHAND = (0x10),
+    MB_ICONQUESTION = (0x20),
+    MB_OK = (0),
+    MB_ABORTRETRYIGNORE = (0x2),
+    MB_APPLMODAL = (0),
+    MB_DEFAULT_DESKTOP_ONLY = (0x20000),
+    MB_HELP = (0x4000),
+    MB_RIGHT = (0x80000),
+    MB_RTLREADING = (0x100000),
+    MB_TOPMOST = (0x40000),
+    MB_DEFBUTTON1 = (0),
+    MB_DEFBUTTON2 = (0x100),
+    MB_DEFBUTTON3 = (0x200),
+    MB_DEFBUTTON4 = (0x300),
+    MB_ICONINFORMATION = (0x40),
+    MB_ICONSTOP = (0x10),
+    MB_OKCANCEL = (0x1),
+    MB_RETRYCANCEL = (0x5),
+    MB_SERVICE_NOTIFICATION = (0x40000),
+    MB_SETFOREGROUND = (0x10000),
+    MB_SYSTEMMODAL = (0x1000),
+    MB_TASKMODAL = (0x2000),
+    MB_YESNO = (0x4),
+    MB_YESNOCANCEL = (0x3),
+    IDABORT = (3),
+    IDCANCEL = (2),
+    IDCLOSE = (8),
+    IDHELP = (9),
+    IDIGNORE = (5),
+    IDNO = (7),
+    IDOK = (1),
+    IDRETRY = (4),
+    IDYES = (6),
+    MSGF_DIALOGBOX = (0),
+    MSGF_MENU = (2),
+    MSGF_NEXTWINDOW = (6),
+    MSGF_SCROLLBAR = (5),
+    MSGF_MAINLOOP = (8),
+    MSGF_USER = (4096),
+    MWT_IDENTITY = (1),
+    MWT_LEFTMULTIPLY = (2),
+    MWT_RIGHTMULTIPLY = (3),
+    MOUSEEVENTF_ABSOLUTE = (32768),
+    MOUSEEVENTF_MOVE = (1),
+    MOUSEEVENTF_LEFTDOWN = (2),
+    MOUSEEVENTF_LEFTUP = (4),
+    MOUSEEVENTF_RIGHTDOWN = (8),
+    MOUSEEVENTF_RIGHTUP = (16),
+    MOUSEEVENTF_MIDDLEDOWN = (32),
+    MOUSEEVENTF_MIDDLEUP = (64),
+    MOVEFILE_REPLACE_EXISTING = (1),
+    MOVEFILE_COPY_ALLOWED = (2),
+    MOVEFILE_DELAY_UNTIL_REBOOT = (4),
+    MOVEFILE_WRITE_THROUGH = (8),
+    WAIT_OBJECT_0 = (0),
+    WAIT_ABANDONED_0 = (0x80),
+    WAIT_TIMEOUT = (0x102),
+    WAIT_IO_COMPLETION = (0xc0),
+    WAIT_ABANDONED = (0x80),
+    WAIT_FAILED = (0xffffffff),
+    MAXIMUM_WAIT_OBJECTS = (0x40),
+    MAXIMUM_SUSPEND_COUNT = (0x7f),
+    MB_PRECOMPOSED = (1),
+    MB_COMPOSITE = (2),
+    MB_ERR_INVALID_CHARS = (8),
+    MB_USEGLYPHCHARS = (4),
+    TOKEN_ADJUST_DEFAULT = (128),
+    TOKEN_ADJUST_GROUPS = (64),
+    TOKEN_ADJUST_PRIVILEGES = (32),
+    TOKEN_ALL_ACCESS = (0xf00ff),
+    TOKEN_ASSIGN_PRIMARY = (1),
+    TOKEN_DUPLICATE = (2),
+    TOKEN_EXECUTE = (0x20000),
+    TOKEN_IMPERSONATE = (4),
+    TOKEN_QUERY = (8),
+    TOKEN_QUERY_SOURCE = (16),
+    TOKEN_READ = (0x20008),
+    TOKEN_WRITE = (0x200e0),
+    SC_MANAGER_ALL_ACCESS = (0xf003f),
+    SC_MANAGER_CONNECT = (1),
+    SC_MANAGER_CREATE_SERVICE = (2),
+    SC_MANAGER_ENUMERATE_SERVICE = (4),
+    SC_MANAGER_LOCK = (8),
+    SC_MANAGER_QUERY_LOCK_STATUS = (16),
+    SC_MANAGER_MODIFY_BOOT_CONFIG = (32),
+    TAPE_FORMAT = (0x5),
+    TAPE_LOAD = (0),
+    TAPE_LOCK = (0x3),
+    TAPE_TENSION = (0x2),
+    TAPE_UNLOAD = (0x1),
+    TAPE_UNLOCK = (0x4),
+    IS_PSREBOOTSYSTEM = (3),
+    IS_PSRESTARTWINDOWS = (2),
+    PSPCB_CREATE = (2),
+    PSPCB_RELEASE = (1),
+    PURGE_TXABORT = (1),
+    PURGE_RXABORT = (2),
+    PURGE_TXCLEAR = (4),
+    PURGE_RXCLEAR = (8),
+    OWNER_SECURITY_INFORMATION = (0x1),
+    GROUP_SECURITY_INFORMATION = (0x2),
+    DACL_SECURITY_INFORMATION = (0x4),
+    SACL_SECURITY_INFORMATION = (0x8),
+    EVENTLOG_FORWARDS_READ = (4),
+    EVENTLOG_BACKWARDS_READ = (8),
+    EVENTLOG_SEEK_READ = (2),
+    EVENTLOG_SEQUENTIAL_READ = (1),
+    EVENTLOG_ERROR_TYPE = (1),
+    EVENTLOG_WARNING_TYPE = (2),
+    EVENTLOG_INFORMATION_TYPE = (4),
+    EVENTLOG_AUDIT_SUCCESS = (8),
+    EVENTLOG_AUDIT_FAILURE = (16),
+    RDW_ERASE = (4),
+    RDW_FRAME = (1024),
+    RDW_INTERNALPAINT = (2),
+    RDW_INVALIDATE = (1),
+    RDW_NOERASE = (32),
+    RDW_NOFRAME = (2048),
+    RDW_NOINTERNALPAINT = (16),
+    RDW_VALIDATE = (8),
+    RDW_ERASENOW = (512),
+    RDW_UPDATENOW = (256),
+    RDW_ALLCHILDREN = (128),
+    RDW_NOCHILDREN = (64),
+/*
+    //
+    HKEY_CLASSES_ROOT = (0x80000000),
+    HKEY_CURRENT_USER = (0x80000001),
+    HKEY_LOCAL_MACHINE = (0x80000002),
+    HKEY_USERS = (0x80000003),
+    HKEY_PERFORMANCE_DATA = (0x80000004),
+    HKEY_CURRENT_CONFIG = (0x80000005),
+    HKEY_DYN_DATA = (0x80000006),
+*/
+    REG_OPTION_VOLATILE = (0x1),
+    REG_OPTION_NON_VOLATILE = (0),
+    REG_CREATED_NEW_KEY = (0x1),
+    REG_OPENED_EXISTING_KEY = (0x2),
+    REG_BINARY = (3),
+    REG_DWORD = (4),
+    REG_DWORD_LITTLE_ENDIAN = (4),
+    REG_DWORD_BIG_ENDIAN = (5),
+    REG_EXPAND_SZ = (2),
+    REG_FULL_RESOURCE_DESCRIPTOR = (9),
+    REG_LINK = (6),
+    REG_MULTI_SZ = (7),
+    REG_NONE = (0),
+    REG_RESOURCE_LIST = (8),
+    REG_RESOURCE_REQUIREMENTS_LIST = (10),
+    REG_SZ = (1),
+    MOD_ALT = (1),
+    MOD_CONTROL = (2),
+    MOD_SHIFT = (4),
+    MOD_WIN = (8),
+    IDHOT_SNAPDESKTOP = -((2)),
+    IDHOT_SNAPWINDOW = -((1)),
+    REG_NOTIFY_CHANGE_NAME = (0x1),
+    REG_NOTIFY_CHANGE_ATTRIBUTES = (0x2),
+    REG_NOTIFY_CHANGE_LAST_SET = (0x4),
+    REG_NOTIFY_CHANGE_SECURITY = (0x8),
+    SW_ERASE = (4),
+    SW_INVALIDATE = (2),
+    SW_SCROLLCHILDREN = (1),
+    SMTO_ABORTIFHUNG = (2),
+    SMTO_BLOCK = (1),
+    SMTO_NORMAL = (0),
+    OPAQUE = (2),
+    TRANSPARENT = (1),
+    SLE_ERROR = (1),
+    SLE_MINORERROR = (2),
+    SLE_WARNING = (3),
+    SEM_FAILCRITICALERRORS = (1),
+    SEM_NOALIGNMENTFAULTEXCEPT = (4),
+    SEM_NOGPFAULTERRORBOX = (2),
+    SEM_NOOPENFILEERRORBOX = (32768),
+    ICM_ON = (2),
+    ICM_OFF = (1),
+    ICM_QUERY = (3),
+    LOCALE_ILANGUAGE = (1),
+    LOCALE_SLANGUAGE = (2),
+    LOCALE_SENGLANGUAGE = (4097),
+    LOCALE_SABBREVLANGNAME = (3),
+    LOCALE_SNATIVELANGNAME = (4),
+    LOCALE_ICOUNTRY = (5),
+    LOCALE_SCOUNTRY = (6),
+    LOCALE_SENGCOUNTRY = (4098),
+    LOCALE_SABBREVCTRYNAME = (7),
+    LOCALE_SNATIVECTRYNAME = (8),
+    LOCALE_IDEFAULTLANGUAGE = (9),
+    LOCALE_IDEFAULTCOUNTRY = (10),
+    LOCALE_IDEFAULTANSICODEPAGE = (4100),
+    LOCALE_IDEFAULTCODEPAGE = (11),
+    LOCALE_SLIST = (12),
+    LOCALE_IMEASURE = (13),
+    LOCALE_SDECIMAL = (14),
+    LOCALE_STHOUSAND = (15),
+    LOCALE_SGROUPING = (16),
+    LOCALE_IDIGITS = (17),
+    LOCALE_ILZERO = (18),
+    LOCALE_INEGNUMBER = (4112),
+    LOCALE_SCURRENCY = (20),
+    LOCALE_SMONDECIMALSEP = (22),
+    LOCALE_SMONTHOUSANDSEP = (23),
+    LOCALE_SMONGROUPING = (24),
+    LOCALE_ICURRDIGITS = (25),
+    LOCALE_ICURRENCY = (27),
+    LOCALE_INEGCURR = (28),
+    LOCALE_SDATE = (29),
+    LOCALE_STIME = (30),
+    LOCALE_STIMEFORMAT = (4099),
+    LOCALE_SSHORTDATE = (31),
+    LOCALE_SLONGDATE = (32),
+    LOCALE_IDATE = (33),
+    LOCALE_ILDATE = (34),
+    LOCALE_ITIME = (35),
+    LOCALE_ITLZERO = (37),
+    LOCALE_IDAYLZERO = (38),
+    LOCALE_IMONLZERO = (39),
+    LOCALE_S1159 = (40),
+    LOCALE_S2359 = (41),
+    LOCALE_ICALENDARTYPE = (4105),
+    LOCALE_IOPTIONALCALENDAR = (4107),
+    LOCALE_IFIRSTDAYOFWEEK = (4108),
+    LOCALE_IFIRSTWEEKOFYEAR = (4109),
+    LOCALE_SDAYNAME1 = (42),
+    LOCALE_SDAYNAME2 = (43),
+    LOCALE_SDAYNAME3 = (44),
+    LOCALE_SDAYNAME4 = (45),
+    LOCALE_SDAYNAME5 = (46),
+    LOCALE_SDAYNAME6 = (47),
+    LOCALE_SDAYNAME7 = (48),
+    LOCALE_SABBREVDAYNAME1 = (49),
+    LOCALE_SABBREVDAYNAME2 = (50),
+    LOCALE_SABBREVDAYNAME3 = (51),
+    LOCALE_SABBREVDAYNAME4 = (52),
+    LOCALE_SABBREVDAYNAME5 = (53),
+    LOCALE_SABBREVDAYNAME6 = (54),
+    LOCALE_SABBREVDAYNAME7 = (55),
+    LOCALE_SMONTHNAME1 = (56),
+    LOCALE_SMONTHNAME2 = (57),
+    LOCALE_SMONTHNAME3 = (58),
+    LOCALE_SMONTHNAME4 = (59),
+    LOCALE_SMONTHNAME5 = (60),
+    LOCALE_SMONTHNAME6 = (61),
+    LOCALE_SMONTHNAME7 = (62),
+    LOCALE_SMONTHNAME8 = (63),
+    LOCALE_SMONTHNAME9 = (64),
+    LOCALE_SMONTHNAME10 = (65),
+    LOCALE_SMONTHNAME11 = (66),
+    LOCALE_SMONTHNAME12 = (67),
+    LOCALE_SMONTHNAME13 = (4110),
+    LOCALE_SABBREVMONTHNAME1 = (68),
+    LOCALE_SABBREVMONTHNAME2 = (69),
+    LOCALE_SABBREVMONTHNAME3 = (70),
+    LOCALE_SABBREVMONTHNAME4 = (71),
+    LOCALE_SABBREVMONTHNAME5 = (72),
+    LOCALE_SABBREVMONTHNAME6 = (73),
+    LOCALE_SABBREVMONTHNAME7 = (74),
+    LOCALE_SABBREVMONTHNAME8 = (75),
+    LOCALE_SABBREVMONTHNAME9 = (76),
+    LOCALE_SABBREVMONTHNAME10 = (77),
+    LOCALE_SABBREVMONTHNAME11 = (78),
+    LOCALE_SABBREVMONTHNAME12 = (79),
+    LOCALE_SABBREVMONTHNAME13 = (4111),
+    LOCALE_SPOSITIVESIGN = (80),
+    LOCALE_SNEGATIVESIGN = (81),
+    LOCALE_IPOSSIGNPOSN = (82),
+    LOCALE_INEGSIGNPOSN = (83),
+    LOCALE_IPOSSYMPRECEDES = (84),
+    LOCALE_IPOSSEPBYSPACE = (85),
+    LOCALE_INEGSYMPRECEDES = (86),
+    LOCALE_INEGSEPBYSPACE = (87),
+    LOCALE_NOUSEROVERRIDE = (0x80000000),
+    CAL_ICALINTVALUE = (1),
+    CAL_IYEAROFFSETRANGE = (3),
+    CAL_SABBREVDAYNAME1 = (14),
+    CAL_SABBREVDAYNAME2 = (15),
+    CAL_SABBREVDAYNAME3 = (16),
+    CAL_SABBREVDAYNAME4 = (17),
+    CAL_SABBREVDAYNAME5 = (18),
+    CAL_SABBREVDAYNAME6 = (19),
+    CAL_SABBREVDAYNAME7 = (20),
+    CAL_SABBREVMONTHNAME1 = (34),
+    CAL_SABBREVMONTHNAME2 = (35),
+    CAL_SABBREVMONTHNAME3 = (36),
+    CAL_SABBREVMONTHNAME4 = (37),
+    CAL_SABBREVMONTHNAME5 = (38),
+    CAL_SABBREVMONTHNAME6 = (39),
+    CAL_SABBREVMONTHNAME7 = (40),
+    CAL_SABBREVMONTHNAME8 = (41),
+    CAL_SABBREVMONTHNAME9 = (42),
+    CAL_SABBREVMONTHNAME10 = (43),
+    CAL_SABBREVMONTHNAME11 = (44),
+    CAL_SABBREVMONTHNAME12 = (45),
+    CAL_SABBREVMONTHNAME13 = (46),
+    CAL_SCALNAME = (2),
+    CAL_SDAYNAME1 = (7),
+    CAL_SDAYNAME2 = (8),
+    CAL_SDAYNAME3 = (9),
+    CAL_SDAYNAME4 = (10),
+    CAL_SDAYNAME5 = (11),
+    CAL_SDAYNAME6 = (12),
+    CAL_SDAYNAME7 = (13),
+    CAL_SERASTRING = (4),
+    CAL_SLONGDATE = (6),
+    CAL_SMONTHNAME1 = (21),
+    CAL_SMONTHNAME2 = (22),
+    CAL_SMONTHNAME3 = (23),
+    CAL_SMONTHNAME4 = (24),
+    CAL_SMONTHNAME5 = (25),
+    CAL_SMONTHNAME6 = (26),
+    CAL_SMONTHNAME7 = (27),
+    CAL_SMONTHNAME8 = (28),
+    CAL_SMONTHNAME9 = (29),
+    CAL_SMONTHNAME10 = (30),
+    CAL_SMONTHNAME11 = (31),
+    CAL_SMONTHNAME12 = (32),
+    CAL_SMONTHNAME13 = (33),
+    CAL_SSHORTDATE = (5),
+    PROCESS_SET_QUOTA = (256),
+    BLACKONWHITE = (1),
+    COLORONCOLOR = (3),
+    HALFTONE = (4),
+    STRETCH_ANDSCANS = (1),
+    STRETCH_DELETESCANS = (3),
+    STRETCH_HALFTONE = (4),
+    STRETCH_ORSCANS = (2),
+    WHITEONBLACK = (2),
+    OCR_NORMAL = (32512),
+    OCR_IBEAM = (32513),
+    OCR_WAIT = (32514),
+    OCR_CROSS = (32515),
+    OCR_UP = (32516),
+    OCR_SIZE = (32640),
+    OCR_ICON = (32641),
+    OCR_SIZENWSE = (32642),
+    OCR_SIZENESW = (32643),
+    OCR_SIZEWE = (32644),
+    OCR_SIZENS = (32645),
+    OCR_SIZEALL = (32646),
+    OCR_NO = (32648),
+    OCR_APPSTARTING = (32650),
+    TAPE_ABSOLUTE_BLOCK = (0x1),
+    TAPE_LOGICAL_BLOCK = (0x2),
+    TAPE_REWIND = (0),
+    TAPE_SPACE_END_OF_DATA = (0x4),
+    TAPE_SPACE_FILEMARKS = (0x6),
+    TAPE_SPACE_RELATIVE_BLOCKS = (0x5),
+    TAPE_SPACE_SEQUENTIAL_FMKS = (0x7),
+    TAPE_SPACE_SEQUENTIAL_SMKS = (0x9),
+    TAPE_SPACE_SETMARKS = (0x8),
+    EXCEPTION_EXECUTE_HANDLER = (1),
+    EXCEPTION_CONTINUE_EXECUTION = -((1)),
+    EXCEPTION_CONTINUE_SEARCH = (0),
+    SWP_DRAWFRAME = (32),
+    SWP_FRAMECHANGED = (32),
+    SWP_HIDEWINDOW = (128),
+    SWP_NOACTIVATE = (16),
+    SWP_NOCOPYBITS = (256),
+    SWP_NOMOVE = (2),
+    SWP_NOSIZE = (1),
+    SWP_NOREDRAW = (8),
+    SWP_NOZORDER = (4),
+    SWP_SHOWWINDOW = (64),
+    SWP_NOOWNERZORDER = (512),
+    SWP_NOREPOSITION = (512),
+    SWP_NOSENDCHANGING = (1024),
+    HSHELL_ACTIVATESHELLWINDOW = (3),
+    HSHELL_GETMINRECT = (5),
+    HSHELL_LANGUAGE = (8),
+    HSHELL_REDRAW = (6),
+    HSHELL_TASKMAN = (7),
+    HSHELL_WINDOWACTIVATED = (4),
+    HSHELL_WINDOWCREATED = (1),
+    HSHELL_WINDOWDESTROYED = (2),
+    SW_HIDE = (0),
+    SW_MAXIMIZE = (3),
+    SW_MINIMIZE = (6),
+    SW_NORMAL = (1),
+    SW_RESTORE = (9),
+    SW_SHOW = (5),
+    SW_SHOWDEFAULT = (10),
+    SW_SHOWMAXIMIZED = (3),
+    SW_SHOWMINIMIZED = (2),
+    SW_SHOWMINNOACTIVE = (7),
+    SW_SHOWNA = (8),
+    SW_SHOWNOACTIVATE = (4),
+    SW_SHOWNORMAL = (1),
+    WPF_RESTORETOMAXIMIZED = (2),
+    WPF_SETMINPOSITION = (1),
+    INFINITE = (0xFFFFFFFF),
+    SPI_GETACCESSTIMEOUT = (60),
+    SPI_GETANIMATION = (72),
+    SPI_GETBEEP = (1),
+    SPI_GETBORDER = (5),
+    SPI_GETDEFAULTINPUTLANG = (89),
+    SPI_GETDRAGFULLWINDOWS = (38),
+    SPI_GETFASTTASKSWITCH = (35),
+    SPI_GETFILTERKEYS = (50),
+    SPI_GETFONTSMOOTHING = (74),
+    SPI_GETGRIDGRANULARITY = (18),
+    SPI_GETHIGHCONTRAST = (66),
+    SPI_GETICONMETRICS = (45),
+    SPI_GETICONTITLELOGFONT = (31),
+    SPI_GETICONTITLEWRAP = (25),
+    SPI_GETKEYBOARDDELAY = (22),
+    SPI_GETKEYBOARDPREF = (68),
+    SPI_GETKEYBOARDSPEED = (10),
+    SPI_GETLOWPOWERACTIVE = (83),
+    SPI_GETLOWPOWERTIMEOUT = (79),
+    SPI_GETMENUDROPALIGNMENT = (27),
+    SPI_GETMINIMIZEDMETRICS = (43),
+    SPI_GETMOUSE = (3),
+    SPI_GETMOUSEKEYS = (54),
+    SPI_GETMOUSETRAILS = (94),
+    SPI_GETNONCLIENTMETRICS = (41),
+    SPI_GETPOWEROFFACTIVE = (84),
+    SPI_GETPOWEROFFTIMEOUT = (80),
+    SPI_GETSCREENREADER = (70),
+    SPI_GETSCREENSAVEACTIVE = (16),
+    SPI_GETSCREENSAVETIMEOUT = (14),
+    SPI_GETSERIALKEYS = (62),
+    SPI_GETSHOWSOUNDS = (56),
+    SPI_GETSOUNDSENTRY = (64),
+    SPI_GETSTICKYKEYS = (58),
+    SPI_GETTOGGLEKEYS = (52),
+    SPI_GETWINDOWSEXTENSION = (92),
+    SPI_GETWORKAREA = (48),
+    SPI_ICONHORIZONTALSPACING = (13),
+    SPI_ICONVERTICALSPACING = (24),
+    SPI_LANGDRIVER = (12),
+    SPI_SCREENSAVERRUNNING = (97),
+    SPI_SETACCESSTIMEOUT = (61),
+    SPI_SETANIMATION = (73),
+    SPI_SETBEEP = (2),
+    SPI_SETBORDER = (6),
+    SPI_SETDEFAULTINPUTLANG = (90),
+    SPI_SETDESKPATTERN = (21),
+    SPI_SETDESKWALLPAPER = (20),
+    SPI_SETDOUBLECLICKTIME = (32),
+    SPI_SETDOUBLECLKHEIGHT = (30),
+    SPI_SETDOUBLECLKWIDTH = (29),
+    SPI_SETDRAGFULLWINDOWS = (37),
+    SPI_SETDRAGHEIGHT = (77),
+    SPI_SETDRAGWIDTH = (76),
+    SPI_SETFASTTASKSWITCH = (36),
+    SPI_SETFILTERKEYS = (51),
+    SPI_SETFONTSMOOTHING = (75),
+    SPI_SETGRIDGRANULARITY = (19),
+    SPI_SETHANDHELD = (78),
+    SPI_SETHIGHCONTRAST = (67),
+    SPI_SETICONMETRICS = (46),
+    SPI_SETICONTITLELOGFONT = (34),
+    SPI_SETICONTITLEWRAP = (26),
+    SPI_SETKEYBOARDDELAY = (23),
+    SPI_SETKEYBOARDPREF = (69),
+    SPI_SETKEYBOARDSPEED = (11),
+    SPI_SETLANGTOGGLE = (91),
+    SPI_SETLOWPOWERACTIVE = (85),
+    SPI_SETLOWPOWERTIMEOUT = (81),
+    SPI_SETMENUDROPALIGNMENT = (28),
+    SPI_SETMINIMIZEDMETRICS = (44),
+    SPI_SETMOUSE = (4),
+    SPI_SETMOUSEBUTTONSWAP = (33),
+    SPI_SETMOUSEKEYS = (55),
+    SPI_SETMOUSETRAILS = (93),
+    SPI_SETNONCLIENTMETRICS = (42),
+    SPI_SETPENWINDOWS = (49),
+    SPI_SETPOWEROFFACTIVE = (86),
+    SPI_SETPOWEROFFTIMEOUT = (82),
+    SPI_SETSCREENREADER = (71),
+    SPI_SETSCREENSAVEACTIVE = (17),
+    SPI_SETSCREENSAVETIMEOUT = (15),
+    SPI_SETSERIALKEYS = (63),
+    SPI_SETSHOWSOUNDS = (57),
+    SPI_SETSOUNDSENTRY = (65),
+    SPI_SETSTICKYKEYS = (59),
+    SPI_SETTOGGLEKEYS = (53),
+    SPI_SETWORKAREA = (47),
+    SPIF_UPDATEINIFILE = (1),
+    SPIF_SENDWININICHANGE = (2),
+    SPIF_SENDCHANGE = (2),
+    TPM_CENTERALIGN = (0x4),
+    TPM_LEFTALIGN = (0),
+    TPM_RIGHTALIGN = (0x8),
+    TPM_LEFTBUTTON = (0),
+    TPM_RIGHTBUTTON = (0x2),
+    TPM_HORIZONTAL = (0),
+    TPM_VERTICAL = (0x40),
+    TCI_SRCCHARSET = (1),
+    TCI_SRCCODEPAGE = (2),
+    TCI_SRCFONTSIG = (3),
+    VFFF_ISSHAREDFILE = (1),
+    VFF_CURNEDEST = (1),
+    VFF_FILEINUSE = (2),
+    VFF_BUFFTOOSMALL = (4),
+    VIFF_FORCEINSTALL = (1),
+    VIFF_DONTDELETEOLD = (2),
+    VIF_TEMPFILE = (0x1),
+    VIF_MISMATCH = (0x2),
+    VIF_SRCOLD = (0x4),
+    VIF_DIFFLANG = (0x8),
+    VIF_DIFFCODEPG = (0x10),
+    VIF_DIFFTYPE = (0x20),
+    VIF_WRITEPROT = (0x40),
+    VIF_FILEINUSE = (0x80),
+    VIF_OUTOFSPACE = (0x100),
+    VIF_ACCESSVIOLATION = (0x200),
+    VIF_SHARINGVIOLATION = (0x400),
+    VIF_CANNOTCREATE = (0x800),
+    VIF_CANNOTDELETE = (0x1000),
+    VIF_CANNOTDELETECUR = (0x4000),
+    VIF_CANNOTRENAME = (0x2000),
+    VIF_OUTOFMEMORY = (0x8000),
+    VIF_CANNOTREADSRC = (0x10000),
+    VIF_CANNOTREADDST = (0x20000),
+    VIF_BUFFTOOSMALL = (0x40000),
+    WC_COMPOSITECHECK = (512),
+    WC_DISCARDNS = (16),
+    WC_SEPCHARS = (32),
+    WC_DEFAULTCHAR = (64),
+    HELP_COMMAND = (0x102),
+    HELP_CONTENTS = (0x3),
+    HELP___FILE__ = (0x1),
+    HELP___FILE__POPUP = (0x8),
+    HELP_FORCEFILE = (0x9),
+    HELP_HELPONHELP = (0x4),
+    HELP_INDEX = (0x3),
+    HELP_KEY = (0x101),
+    HELP_MULTIKEY = (0x201),
+    HELP_PARTIALKEY = (0x105),
+    HELP_QUIT = (0x2),
+    HELP_SETCONTENTS = (0x5),
+    HELP_SETINDEX = (0x5),
+    HELP___FILE__MENU = (0xa),
+    HELP_FINDER = (0xb),
+    HELP_WM_HELP = (0xc),
+    HELP_TCARD = (0x8000),
+    HELP_TCARD_DATA = (0x10),
+    HELP_TCARD_OTHER_CALLER = (0x11),
+    CONNECT_UPDATE_PROFILE = (1),
+    RESOURCETYPE_DISK = (1),
+    RESOURCETYPE_PRINT = (2),
+    RESOURCETYPE_ANY = (0),
+    RESOURCE_CONNECTED = (1),
+    RESOURCE_GLOBALNET = (2),
+    RESOURCE_REMEMBERED = (3),
+    RESOURCEUSAGE_CONNECTABLE = (1),
+    RESOURCEUSAGE_CONTAINER = (2),
+    WN_BAD_NETNAME = (0x43),
+    WN_EXTENDED_ERROR = (0x4b8),
+    WN_MORE_DATA = (0xea),
+    WN_NO_NETWORK = (0x4c6),
+    WN_SUCCESS = (0),
+    WN_ACCESS_DENIED = (0x5),
+    WN_BAD_PROVIDER = (0x4b4),
+    WN_NOT_AUTHENTICATED = (0x4dc),
+    UNIVERSAL_NAME_INFO_LEVEL = (1),
+    REMOTE_NAME_INFO_LEVEL = (2),
+    STILL_ACTIVE = (0x103),
+    SP_SERIALCOMM = (0x1),
+    BAUD_075 = (0x1),
+    BAUD_110 = (0x2),
+    BAUD_134_5 = (0x4),
+    BAUD_150 = (0x8),
+    BAUD_300 = (0x10),
+    BAUD_600 = (0x20),
+    BAUD_1200 = (0x40),
+    BAUD_1800 = (0x80),
+    BAUD_2400 = (0x100),
+    BAUD_4800 = (0x200),
+    BAUD_7200 = (0x400),
+    BAUD_9600 = (0x800),
+    BAUD_14400 = (0x1000),
+    BAUD_19200 = (0x2000),
+    BAUD_38400 = (0x4000),
+    BAUD_56K = (0x8000),
+    BAUD_57600 = (0x40000),
+    BAUD_115200 = (0x20000),
+    BAUD_128K = (0x10000),
+    BAUD_USER = (0x10000000),
+    PST_FAX = (0x21),
+    PST_LAT = (0x101),
+    PST_MODEM = (0x6),
+    PST_NETWORK_BRIDGE = (0x100),
+    PST_PARALLELPORT = (0x2),
+    PST_RS232 = (0x1),
+    PST_RS422 = (0x3),
+    PST_RS423 = (0x4),
+    PST_RS449 = (0x5),
+    PST_SCANNER = (0x22),
+    PST_TCPIP_TELNET = (0x102),
+    PST_UNSPECIFIED = (0),
+    PST_X25 = (0x103),
+    PCF_16BITMODE = (0x200),
+    PCF_DTRDSR = (0x1),
+    PCF_INTTIMEOUTS = (0x80),
+    PCF_PARITY_CHECK = (0x8),
+    PCF_RLSD = (0x4),
+    PCF_RTSCTS = (0x2),
+    PCF_SETXCHAR = (0x20),
+    PCF_SPECIALCHARS = (0x100),
+    PCF_TOTALTIMEOUTS = (0x40),
+    PCF_XONXOFF = (0x10),
+    SP_BAUD = (0x2),
+    SP_DATABITS = (0x4),
+    SP_HANDSHAKING = (0x10),
+    SP_PARITY = (0x1),
+    SP_PARITY_CHECK = (0x20),
+    SP_RLSD = (0x40),
+    SP_STOPBITS = (0x8),
+    DATABITS_5 = (1),
+    DATABITS_6 = (2),
+    DATABITS_7 = (4),
+    DATABITS_8 = (8),
+    DATABITS_16 = (16),
+    DATABITS_16X = (32),
+    STOPBITS_10 = (1),
+    STOPBITS_15 = (2),
+    STOPBITS_20 = (4),
+    PARITY_NONE = (256),
+    PARITY_ODD = (512),
+    PARITY_EVEN = (1024),
+    PARITY_MARK = (2048),
+    PARITY_SPACE = (4096),
+    COMMPROP_INITIALIZED = (0xe73cf52e),
+    CBR_110 = (110),
+    CBR_300 = (300),
+    CBR_600 = (600),
+    CBR_1200 = (1200),
+    CBR_2400 = (2400),
+    CBR_4800 = (4800),
+    CBR_9600 = (9600),
+    CBR_14400 = (14400),
+    CBR_19200 = (19200),
+    CBR_38400 = (38400),
+    CBR_56000 = (56000),
+    CBR_57600 = (57600),
+    CBR_115200 = (115200),
+    CBR_128000 = (128000),
+    CBR_256000 = (256000),
+    DTR_CONTROL_DISABLE = (0),
+    DTR_CONTROL_ENABLE = (1),
+    DTR_CONTROL_HANDSHAKE = (2),
+    RTS_CONTROL_DISABLE = (0),
+    RTS_CONTROL_ENABLE = (1),
+    RTS_CONTROL_HANDSHAKE = (2),
+    RTS_CONTROL_TOGGLE = (3),
+    EVENPARITY = (2),
+    MARKPARITY = (3),
+    NOPARITY = (0),
+    ODDPARITY = (1),
+    SPACEPARITY = (4),
+    ONESTOPBIT = (0),
+    ONE5STOPBITS = (1),
+    TWOSTOPBITS = (2),
+    CREATE_PROCESS_DEBUG_EVENT = (3),
+    CREATE_THREAD_DEBUG_EVENT = (2),
+    EXCEPTION_DEBUG_EVENT = (1),
+    EXIT_PROCESS_DEBUG_EVENT = (5),
+    EXIT_THREAD_DEBUG_EVENT = (4),
+    LOAD_DLL_DEBUG_EVENT = (6),
+    OUTPUT_DEBUG_STRING_EVENT = (8),
+    UNLOAD_DLL_DEBUG_EVENT = (7),
+    RIP_EVENT = (9),
+    PROCESS_HEAP_REGION = (1),
+    PROCESS_HEAP_UNCOMMITTED_RANGE = (2),
+    PROCESS_HEAP_ENTRY_BUSY = (4),
+    PROCESS_HEAP_ENTRY_MOVEABLE = (16),
+    PROCESS_HEAP_ENTRY_DDESHARE = (32),
+    HINSTANCE_ERROR = (32),
+    BACKUP_DATA = (1),
+    BACKUP_EA_DATA = (2),
+    BACKUP_SECURITY_DATA = (3),
+    BACKUP_ALTERNATE_DATA = (4),
+    BACKUP_LINK = (5),
+    STREAM_MODIFIED_WHEN_READ = (1),
+    STREAM_CONTAINS_SECURITY = (2),
+    STARTF_USESHOWWINDOW = (1),
+    STARTF_USEPOSITION = (4),
+    STARTF_USESIZE = (2),
+    STARTF_USECOUNTCHARS = (8),
+    STARTF_USEFILLATTRIBUTE = (16),
+    STARTF_RUNFULLSCREEN = (32),
+    STARTF_FORCEONFEEDBACK = (64),
+    STARTF_FORCEOFFFEEDBACK = (128),
+    STARTF_USESTDHANDLES = (256),
+    STARTF_USEHOTKEY = (512),
+    VER_PLATFORM_WIN32s = (0),
+    VER_PLATFORM_WIN32_WINDOWS = (1),
+    VER_PLATFORM_WIN32_NT = (2),
+    MAXPROPPAGES = (100),
+    PSP_DEFAULT = (0),
+    PSP_DLGINDIRECT = (1),
+    PSP_HASHELP = (32),
+    PSP_USECALLBACK = (128),
+    PSP_USEHICON = (2),
+    PSP_USEICONID = (4),
+    PSP_USEREFPARENT = (64),
+    PSP_USETITLE = (8),
+    PSP_RTLREADING = (16),
+    PSH_DEFAULT = (0),
+    PSH_HASHELP = (512),
+    PSH_MODELESS = (1024),
+    PSH_NOAPPLYNOW = (128),
+    PSH_PROPSHEETPAGE = (8),
+    PSH_PROPTITLE = (1),
+    PSH_USECALLBACK = (256),
+    PSH_USEHICON = (2),
+    PSH_USEICONID = (4),
+    PSH_USEPSTARTPAGE = (64),
+    PSH_WIZARD = (32),
+    PSH_RTLREADING = (2048),
+    PSCB_INITIALIZED = (1),
+    PSCB_PRECREATE = (2),
+    PSNRET_NOERROR = (0),
+    PSNRET_INVALID_NOCHANGEPAGE = (2),
+    PSBTN_APPLYNOW = (4),
+    PSBTN_BACK = (0),
+    PSBTN_CANCEL = (5),
+    PSBTN_FINISH = (2),
+    PSBTN_HELP = (6),
+    PSBTN_NEXT = (1),
+    PSBTN_OK = (3),
+    PSWIZB_BACK = (1),
+    PSWIZB_NEXT = (2),
+    PSWIZB_FINISH = (4),
+    PSWIZB_DISABLEDFINISH = (8),
+    ID_PSREBOOTSYSTEM = (3),
+    ID_PSRESTARTWINDOWS = (2),
+    WIZ_BODYCX = (184),
+    WIZ_BODYX = (92),
+    WIZ_CXBMP = (80),
+    WIZ_CXDLG = (276),
+    WIZ_CYDLG = (140),
+}
+char* VS_FILE_INFO = cast(char*) ((16));
+enum : DWORD {
+    VS_VERSION_INFO = (1),
+    VS_FF_DEBUG = (0x1),
+    VS_FF_INFOINFERRED = (0x10),
+    VS_FF_PATCHED = (0x4),
+    VS_FF_PRERELEASE = (0x2),
+    VS_FF_PRIVATEBUILD = (0x8),
+    VS_FF_SPECIALBUILD = (0x20),
+    VOS_UNKNOWN = (0),
+    VOS_DOS = (0x10000),
+    VOS_OS216 = (0x20000),
+    VOS_OS232 = (0x30000),
+    VOS_NT = (0x40000),
+    VOS_DOS_WINDOWS16 = (0x10001),
+    VOS_DOS_WINDOWS32 = (0x10004),
+    VOS_OS216_PM16 = (0x20002),
+    VOS_OS232_PM32 = (0x30003),
+    VOS_NT_WINDOWS32 = (0x40004),
+    VFT_UNKNOWN = (0),
+    VFT_APP = (0x1),
+    VFT_DLL = (0x2),
+    VFT_DRV = (0x3),
+    VFT_FONT = (0x4),
+    VFT_VXD = (0x5),
+    VFT_STATIC_LIB = (0x7),
+    VFT2_UNKNOWN = (0),
+    VFT2_DRV_PRINTER = (0x1),
+    VFT2_DRV_KEYBOARD = (0x2),
+    VFT2_DRV_LANGUAGE = (0x3),
+    VFT2_DRV_DISPLAY = (0x4),
+    VFT2_DRV_MOUSE = (0x5),
+    VFT2_DRV_NETWORK = (0x6),
+    VFT2_DRV_SYSTEM = (0x7),
+    VFT2_DRV_INSTALLABLE = (0x8),
+    VFT2_DRV_SOUND = (0x9),
+    VFT2_FONT_RASTER = (0x1),
+    VFT2_FONT_VECTOR = (0x2),
+    VFT2_FONT_TRUETYPE = (0x3),
+    PAN_ANY = (0),
+    PAN_NO_FIT = (1),
+    PAN_FAMILY_TEXT_DISPLAY = (2),
+    PAN_FAMILY_SCRIPT = (3),
+    PAN_FAMILY_DECORATIVE = (4),
+    PAN_FAMILY_PICTORIAL = (5),
+    PAN_SERIF_COVE = (2),
+    PAN_SERIF_OBTUSE_COVE = (3),
+    PAN_SERIF_SQUARE_COVE = (4),
+    PAN_SERIF_OBTUSE_SQUARE_COVE = (5),
+    PAN_SERIF_SQUARE = (6),
+    PAN_SERIF_THIN = (7),
+    PAN_SERIF_BONE = (8),
+    PAN_SERIF_EXAGGERATED = (9),
+    PAN_SERIF_TRIANGLE = (10),
+    PAN_SERIF_NORMAL_SANS = (11),
+    PAN_SERIF_OBTUSE_SANS = (12),
+    PAN_SERIF_PERP_SANS = (13),
+    PAN_SERIF_FLARED = (14),
+    PAN_SERIF_ROUNDED = (15),
+    PAN_WEIGHT_VERY_LIGHT = (2),
+    PAN_WEIGHT_LIGHT = (3),
+    PAN_WEIGHT_THIN = (4),
+    PAN_WEIGHT_BOOK = (5),
+    PAN_WEIGHT_MEDIUM = (6),
+    PAN_WEIGHT_DEMI = (7),
+    PAN_WEIGHT_BOLD = (8),
+    PAN_WEIGHT_HEAVY = (9),
+    PAN_WEIGHT_BLACK = (10),
+    PAN_WEIGHT_NORD = (11),
+    PAN_PROP_OLD_STYLE = (2),
+    PAN_PROP_MODERN = (3),
+    PAN_PROP_EVEN_WIDTH = (4),
+    PAN_PROP_EXPANDED = (5),
+    PAN_PROP_CONDENSED = (6),
+    PAN_PROP_VERY_EXPANDED = (7),
+    PAN_PROP_VERY_CONDENSED = (8),
+    PAN_PROP_MONOSPACED = (9),
+    PAN_CONTRAST_NONE = (2),
+    PAN_CONTRAST_VERY_LOW = (3),
+    PAN_CONTRAST_LOW = (4),
+    PAN_CONTRAST_MEDIUM_LOW = (5),
+    PAN_CONTRAST_MEDIUM = (6),
+    PAN_CONTRAST_MEDIUM_HIGH = (7),
+    PAN_CONTRAST_HIGH = (8),
+    PAN_CONTRAST_VERY_HIGH = (9),
+    PAN_STROKE_GRADUAL_DIAG = (2),
+    PAN_STROKE_GRADUAL_TRAN = (3),
+    PAN_STROKE_GRADUAL_VERT = (4),
+    PAN_STROKE_GRADUAL_HORZ = (5),
+    PAN_STROKE_RAPID_VERT = (6),
+    PAN_STROKE_RAPID_HORZ = (7),
+    PAN_STROKE_INSTANT_VERT = (8),
+    PAN_STRAIGHT_ARMS_HORZ = (2),
+    PAN_STRAIGHT_ARMS_WEDGE = (3),
+    PAN_STRAIGHT_ARMS_VERT = (4),
+    PAN_STRAIGHT_ARMS_SINGLE_SERIF = (5),
+    PAN_STRAIGHT_ARMS_DOUBLE_SERIF = (6),
+    PAN_BENT_ARMS_HORZ = (7),
+    PAN_BENT_ARMS_VERT = (9),
+    PAN_BENT_ARMS_WEDGE = (8),
+    PAN_BENT_ARMS_SINGLE_SERIF = (10),
+    PAN_BENT_ARMS_DOUBLE_SERIF = (11),
+    PAN_LETT_NORMAL_CONTACT = (2),
+    PAN_LETT_NORMAL_WEIGHTED = (3),
+    PAN_LETT_NORMAL_BOXED = (4),
+    PAN_LETT_NORMAL_FLATTENED = (5),
+    PAN_LETT_NORMAL_ROUNDED = (6),
+    PAN_LETT_NORMAL_OFF_CENTER = (7),
+    PAN_LETT_NORMAL_SQUARE = (8),
+    PAN_LETT_OBLIQUE_CONTACT = (9),
+    PAN_LETT_OBLIQUE_WEIGHTED = (10),
+    PAN_LETT_OBLIQUE_BOXED = (11),
+    PAN_LETT_OBLIQUE_FLATTENED = (12),
+    PAN_LETT_OBLIQUE_ROUNDED = (13),
+    PAN_LETT_OBLIQUE_OFF_CENTER = (14),
+    PAN_LETT_OBLIQUE_SQUARE = (15),
+    PAN_MIDLINE_STANDARD_TRIMMED = (2),
+    PAN_MIDLINE_STANDARD_POINTED = (3),
+    PAN_MIDLINE_STANDARD_SERIFED = (4),
+    PAN_MIDLINE_HIGH_TRIMMED = (5),
+    PAN_MIDLINE_HIGH_POINTED = (6),
+    PAN_MIDLINE_HIGH_SERIFED = (7),
+    PAN_MIDLINE_CONSTANT_TRIMMED = (8),
+    PAN_MIDLINE_CONSTANT_POINTED = (9),
+    PAN_MIDLINE_CONSTANT_SERIFED = (10),
+    PAN_MIDLINE_LOW_TRIMMED = (11),
+    PAN_MIDLINE_LOW_POINTED = (12),
+    PAN_MIDLINE_LOW_SERIFED = (13),
+    PAN_XHEIGHT_CONSTANT_SMALL = (2),
+    PAN_XHEIGHT_CONSTANT_STD = (3),
+    PAN_XHEIGHT_CONSTANT_LARGE = (4),
+    PAN_XHEIGHT_DUCKING_SMALL = (5),
+    PAN_XHEIGHT_DUCKING_STD = (6),
+    PAN_XHEIGHT_DUCKING_LARGE = (7),
+    PC_EXPLICIT = (2),
+    PC_NOCOLLAPSE = (4),
+    PC_RESERVED = (1),
+    BS_DIBPATTERN = (5),
+    BS_DIBPATTERN8X8 = (8),
+    BS_DIBPATTERNPT = (6),
+    BS_HATCHED = (2),
+    BS_HOLLOW = (1),
+    BS_NULL = (1),
+    BS_PATTERN = (3),
+    BS_PATTERN8X8 = (7),
+    BS_SOLID = (0),
+    DM_ORIENTATION = (0x1),
+    DM_PAPERSIZE = (0x2),
+    DM_PAPERLENGTH = (0x4),
+    DM_PAPERWIDTH = (0x8),
+    DM_SCALE = (0x10),
+    DM_COPIES = (0x100),
+    DM_DEFAULTSOURCE = (0x200),
+    DM_PRINTQUALITY = (0x400),
+    DM_COLOR = (0x800),
+    DM_DUPLEX = (0x1000),
+    DM_YRESOLUTION = (0x2000),
+    DM_TTOPTION = (0x4000),
+    DM_COLLATE = (0x8000),
+    DM_FORMNAME = (0x10000),
+    DM_LOGPIXELS = (0x20000),
+    DM_ICMMETHOD = (0x800000),
+    DM_ICMINTENT = (0x1000000),
+    DM_MEDIATYPE = (0x2000000),
+    DM_DITHERTYPE = (0x4000000),
+    DMORIENT_LANDSCAPE = (2),
+    DMORIENT_PORTRAIT = (1),
+    DMPAPER_LETTER = (1),
+    DMPAPER_LEGAL = (5),
+    DMPAPER_A4 = (9),
+    DMPAPER_CSHEET = (24),
+    DMPAPER_DSHEET = (25),
+    DMPAPER_ESHEET = (26),
+    DMPAPER_LETTERSMALL = (2),
+    DMPAPER_TABLOID = (3),
+    DMPAPER_LEDGER = (4),
+    DMPAPER_STATEMENT = (6),
+    DMPAPER_EXECUTIVE = (7),
+    DMPAPER_A3 = (8),
+    DMPAPER_A4SMALL = (10),
+    DMPAPER_A5 = (11),
+    DMPAPER_B4 = (12),
+    DMPAPER_B5 = (13),
+    DMPAPER_FOLIO = (14),
+    DMPAPER_QUARTO = (15),
+    DMPAPER_10X14 = (16),
+    DMPAPER_11X17 = (17),
+    DMPAPER_NOTE = (18),
+    DMPAPER_ENV_9 = (19),
+    DMPAPER_ENV_10 = (20),
+    DMPAPER_ENV_11 = (21),
+    DMPAPER_ENV_12 = (22),
+    DMPAPER_ENV_14 = (23),
+    DMPAPER_ENV_DL = (27),
+    DMPAPER_ENV_C5 = (28),
+    DMPAPER_ENV_C3 = (29),
+    DMPAPER_ENV_C4 = (30),
+    DMPAPER_ENV_C6 = (31),
+    DMPAPER_ENV_C65 = (32),
+    DMPAPER_ENV_B4 = (33),
+    DMPAPER_ENV_B5 = (34),
+    DMPAPER_ENV_B6 = (35),
+    DMPAPER_ENV_ITALY = (36),
+    DMPAPER_ENV_MONARCH = (37),
+    DMPAPER_ENV_PERSONAL = (38),
+    DMPAPER_FANFOLD_US = (39),
+    DMPAPER_FANFOLD_STD_GERMAN = (40),
+    DMPAPER_FANFOLD_LGL_GERMAN = (41),
+    DMRES_HIGH = -((4)),
+    DMRES_MEDIUM = -((3)),
+    DMRES_LOW = -((2)),
+    DMRES_DRAFT = -((1)),
+    DMCOLOR_COLOR = (2),
+    DMCOLOR_MONOCHROME = (1),
+    DMDUP_SIMPLEX = (1),
+    DMDUP_HORIZONTAL = (3),
+    DMDUP_VERTICAL = (2),
+    DMTT_BITMAP = (1),
+    DMTT_DOWNLOAD = (2),
+    DMTT_SUBDEV = (3),
+    DMCOLLATE_TRUE = (1),
+    DMCOLLATE_FALSE = (0),
+    DM_GRAYSCALE = (1),
+    DM_INTERLACED = (2),
+    DMICMMETHOD_NONE = (1),
+    DMICMMETHOD_SYSTEM = (2),
+    DMICMMETHOD_DRIVER = (3),
+    DMICMMETHOD_DEVICE = (4),
+    DMICMMETHOD_USER = (256),
+    DMICM_SATURATE = (1),
+    DMICM_CONTRAST = (2),
+    DMICM_COLORMETRIC = (3),
+    DMICM_USER = (256),
+    DMMEDIA_STANDARD = (1),
+    DMMEDIA_GLOSSY = (3),
+    DMMEDIA_TRANSPARENCY = (2),
+    DMMEDIA_USER = (256),
+    DMDITHER_NONE = (1),
+    DMDITHER_COARSE = (2),
+    DMDITHER_FINE = (3),
+    DMDITHER_LINEART = (4),
+    DMDITHER_GRAYSCALE = (10),
+    DMDITHER_USER = (256),
+    RDH_RECTANGLES = (1),
+    TT_POLYGON_TYPE = (24),
+    TT_PRIM_LINE = (1),
+    TT_PRIM_QSPLINE = (2),
+    GCPCLASS_ARABIC = (2),
+    GCPCLASS_HEBREW = (2),
+    GCPCLASS_LATIN = (1),
+    GCPCLASS_LATINNUMBER = (5),
+    GCPCLASS_LOCALNUMBER = (4),
+    GCPCLASS_LATINNUMERICSEPARATOR = (7),
+    GCPCLASS_LATINNUMERICTERMINATOR = (6),
+    GCPCLASS_NEUTRAL = (3),
+    GCPCLASS_NUMERICSEPARATOR = (8),
+    GCPCLASS_PREBOUNDLTR = (128),
+    GCPCLASS_PREBOUNDRTL = (64),
+    GCPCLASS_POSTBOUNDLTR = (32),
+    GCPCLASS_POSTBOUNDRTL = (16),
+    GCPGLYPH_LINKBEFORE = (32768),
+    GCPGLYPH_LINKAFTER = (16384),
+    TT_AVAILABLE = (1),
+    TT_ENABLED = (2),
+    CA_NEGATIVE = (1),
+    CA_LOG_FILTER = (2),
+    ILLUMINANT_DEVICE_DEFAULT = (0),
+    ILLUMINANT_A = (1),
+    ILLUMINANT_B = (2),
+    ILLUMINANT_C = (3),
+    ILLUMINANT_D50 = (4),
+    ILLUMINANT_D55 = (5),
+    ILLUMINANT_D65 = (6),
+    ILLUMINANT_D75 = (7),
+    ILLUMINANT_F2 = (8),
+    ILLUMINANT_TUNGSTEN = (1),
+    ILLUMINANT_DAYLIGHT = (3),
+    ILLUMINANT_FLUORESCENT = (8),
+    ILLUMINANT_NTSC = (3),
+    DI_APPBANDING = (1),
+    EMR_HEADER = (1),
+    ENHMETA_SIGNATURE = (1179469088),
+    ENM_CHANGE = (1),
+    ENM_CORRECTTEXT = (4194304),
+    ENM_DROPFILES = (1048576),
+    ENM_KEYEVENTS = (65536),
+    ENM_MOUSEEVENTS = (131072),
+    ENM_PROTECTED = (2097152),
+    ENM_REQUESTRESIZE = (262144),
+    ENM_SCROLL = (4),
+    ENM_SELCHANGE = (524288),
+    ENM_UPDATE = (2),
+    ENM_NONE = (0),
+    ES_DISABLENOSCROLL = (8192),
+    ES_EX_NOCALLOLEINIT = (16777216),
+    ES_NOIME = (524288),
+    ES_SAVESEL = (32768),
+    ES_SELFIME = (262144),
+    ES_SUNKEN = (16384),
+    ES_VERTICAL = (4194304),
+    ES_SELECTIONBAR = (16777216),
+    ECOOP_SET = (1),
+    ECOOP_OR = (2),
+    ECOOP_AND = (3),
+    ECOOP_XOR = (4),
+    ECO_AUTOWORDSELECTION = (1),
+    ECO_AUTOVSCROLL = (64),
+    ECO_AUTOHSCROLL = (128),
+    ECO_NOHIDESEL = (256),
+    ECO_READONLY = (2048),
+    ECO_WANTRETURN = (4096),
+    ECO_SAVESEL = (32768),
+    ECO_SELECTIONBAR = (16777216),
+    ECO_VERTICAL = (4194304),
+    SCF_WORD = (2),
+    SCF_SELECTION = (1),
+    SF_TEXT = (1),
+    SF_RTF = (2),
+    SF_RTFNOOBJS = (3),
+    SF_TEXTIZED = (4),
+    SFF_SELECTION = (32768),
+    SFF_PLAINRTF = (16384),
+    WB_CLASSIFY = (3),
+    WB_LEFTBREAK = (6),
+    WB_PREVBREAK = (6),
+    WB_MOVEWORDLEFT = (4),
+    WB_MOVEWORDPREV = (4),
+    WB_MOVEWORDRIGHT = (5),
+    WB_MOVEWORDNEXT = (5),
+    WB_RIGHTBREAK = (7),
+    WB_NEXTBREAK = (7),
+    PC_LEADING = (2),
+    PC_FOLLOWING = (1),
+    PC_DELIMITER = (4),
+    PC_OVERFLOW = (3),
+    WBF_WORDWRAP = (16),
+    WBF_WORDBREAK = (32),
+    WBF_OVERFLOW = (64),
+    WBF_LEVEL1 = (128),
+    WBF_LEVEL2 = (256),
+    WBF_CUSTOM = (512),
+    WBF_BREAKAFTER = (64),
+    WBF_BREAKLINE = (32),
+    WBF_ISWHITE = (16),
+    CFM_BOLD = (1),
+    CFM_COLOR = (1073741824),
+    CFM_FACE = (536870912),
+    CFM_ITALIC = (2),
+    CFM_OFFSET = (268435456),
+    CFM_PROTECTED = (16),
+    CFM_SIZE = (0x80000000),
+    CFM_STRIKEOUT = (8),
+    CFM_UNDERLINE = (4),
+    CFE_AUTOCOLOR = (1073741824),
+    CFE_BOLD = (1),
+    CFE_ITALIC = (2),
+    CFE_STRIKEOUT = (8),
+    CFE_UNDERLINE = (4),
+    CFE_PROTECTED = (16),
+    PFM_ALIGNMENT = (8),
+    PFM_NUMBERING = (32),
+    PFM_OFFSET = (4),
+    PFM_OFFSETINDENT = (0x80000000),
+    PFM_RIGHTINDENT = (2),
+    PFM_STARTINDENT = (1),
+    PFM_TABSTOPS = (16),
+    PFN_BULLET = (1),
+    PFA_LEFT = (1),
+    PFA_RIGHT = (2),
+    PFA_CENTER = (3),
+    SEL_EMPTY = (0),
+    SEL_TEXT = (1),
+    SEL_OBJECT = (2),
+    SEL_MULTICHAR = (4),
+    SEL_MULTIOBJECT = (8),
+}
+const {
+char* CF_RTF = ("Rich Text Format");
+char* CF_RETEXTOBJ = ("RichEdit Text and Objects");
+}
+enum : DWORD {
+    ODT_BUTTON = (4),
+    ODT_COMBOBOX = (3),
+    ODT_LISTBOX = (2),
+    ODT_LISTVIEW = (102),
+    ODT_MENU = (1),
+    ODT_STATIC = (5),
+    ODT_TAB = (101),
+    ODT_HEADER = (100),
+    ODA_DRAWENTIRE = (1),
+    ODA_FOCUS = (4),
+    ODA_SELECT = (2),
+    ODS_CHECKED = (8),
+    ODS_COMBOBOXEDIT = (4096),
+    ODS_DEFAULT = (32),
+    ODS_DISABLED = (4),
+    ODS_FOCUS = (16),
+    ODS_GRAYED = (2),
+    ODS_SELECTED = (1),
+}
+const {
+char* ANIMATE_CLASSW = ("SysAnimate32");
+char* HOTKEY_CLASSW = ("msctls_hotkey32");
+char* PROGRESS_CLASSW = ("msctls_progress32");
+char* STATUSCLASSNAMEW = ("msctls_statusbar32");
+char* TOOLBARCLASSNAMEW = ("ToolbarWindow32");
+char* TOOLTIPS_CLASSW = ("tooltips_class32");
+char* TRACKBAR_CLASSW = ("msctls_trackbar32");
+char* UPDOWN_CLASSW = ("msctls_updown32");
+char* WC_HEADERW = ("SysHeader32");
+char* WC_LISTVIEWW = ("SysListView32");
+char* WC_TABCONTROLW = ("SysTabControl32");
+char* WC_TREEVIEWW = ("SysTreeView32");
+}
+enum : DWORD {
+    CCS_ADJUSTABLE = (0x20),
+    CCS_BOTTOM = (0x3),
+    CCS_NODIVIDER = (0x40),
+    CCS_NOMOVEY = (0x2),
+    CCS_NOPARENTALIGN = (0x8),
+    CCS_NORESIZE = (0x4),
+    CCS_TOP = (0x1),
+}
+const {
+char* ANIMATE_CLASSA = ("SysAnimate32");
+char* HOTKEY_CLASSA = ("msctls_hotkey32");
+char* PROGRESS_CLASSA = ("msctls_progress32");
+char* STATUSCLASSNAMEA = ("msctls_statusbar32");
+char* TOOLBARCLASSNAMEA = ("ToolbarWindow32");
+char* TOOLTIPS_CLASSA = ("tooltips_class32");
+char* TRACKBAR_CLASSA = ("msctls_trackbar32");
+char* UPDOWN_CLASSA = ("msctls_updown32");
+char* WC_HEADERA = ("SysHeader32");
+char* WC_LISTVIEWA = ("SysListView32");
+char* WC_TABCONTROLA = ("SysTabControl32");
+char* WC_TREEVIEWA = ("SysTreeView32");
+char* ANIMATE_CLASS = (ANIMATE_CLASSA);
+char* HOTKEY_CLASS = (HOTKEY_CLASSA);
+char* PROGRESS_CLASS = (PROGRESS_CLASSA);
+char* STATUSCLASSNAME = (STATUSCLASSNAMEA);
+char* TOOLBARCLASSNAME = (TOOLBARCLASSNAMEA);
+char* TOOLTIPS_CLASS = (TOOLTIPS_CLASSA);
+char* TRACKBAR_CLASS = (TRACKBAR_CLASSA);
+char* UPDOWN_CLASS = (UPDOWN_CLASSA);
+char* WC_HEADER = (WC_HEADERA);
+char* WC_LISTVIEW = (WC_LISTVIEWA);
+char* WC_TABCONTROL = (WC_TABCONTROLA);
+char* WC_TREEVIEW = (WC_TREEVIEWA);
+}
+enum : DWORD {
+    HDS_BUTTONS = (2),
+    HDS_HIDDEN = (8),
+    HDS_HORZ = (0),
+    HDI_BITMAP = (16),
+    HDI_FORMAT = (4),
+    HDI_HEIGHT = (1),
+    HDI_LPARAM = (8),
+    HDI_TEXT = (2),
+    HDI_WIDTH = (1),
+    HDF_CENTER = (2),
+    HDF_LEFT = (0),
+    HDF_RIGHT = (1),
+    HDF_RTLREADING = (4),
+    HDF_BITMAP = (8192),
+    HDF_OWNERDRAW = (32768),
+    HDF_STRING = (16384),
+    HDF_JUSTIFYMASK = (3),
+    HHT_NOWHERE = (1),
+    HHT_ONDIVIDER = (4),
+    HHT_ONDIVOPEN = (8),
+    HHT_ONHEADER = (2),
+    HHT_TOLEFT = (2048),
+    HHT_TORIGHT = (1024),
+    HINST_COMMCTRL = -(1),
+    IDB_STD_LARGE_COLOR = (1),
+    IDB_STD_SMALL_COLOR = (0),
+    IDB_VIEW_LARGE_COLOR = (5),
+    IDB_VIEW_SMALL_COLOR = (4),
+    STD_COPY = (1),
+    STD_CUT = (0),
+    STD_DELETE = (5),
+    STD_FILENEW = (6),
+    STD_FILEOPEN = (7),
+    STD_FILESAVE = (8),
+    STD_FIND = (12),
+    STD_HELP = (11),
+    STD_PASTE = (2),
+    STD_PRINT = (14),
+    STD_PRINTPRE = (9),
+    STD_PROPERTIES = (10),
+    STD_REDOW = (4),
+    STD_REPLACE = (13),
+    STD_UNDO = (3),
+    VIEW_LARGEICONS = (0),
+    VIEW_SMALLICONS = (1),
+    VIEW_LIST = (2),
+    VIEW_DETAILS = (3),
+    VIEW_SORTNAME = (4),
+    VIEW_SORTSIZE = (5),
+    VIEW_SORTDATE = (6),
+    VIEW_SORTTYPE = (7),
+    TBSTYLE_ALTDRAG = (1024),
+    TBSTYLE_TOOLTIPS = (256),
+    TBSTYLE_WRAPABLE = (512),
+    TBSTYLE_BUTTON = (0),
+    TBSTYLE_CHECK = (2),
+    TBSTYLE_CHECKGROUP = (6),
+    TBSTYLE_GROUP = (4),
+    TBSTYLE_SEP = (1),
+    TBSTATE_CHECKED = (1),
+    TBSTATE_ENABLED = (4),
+    TBSTATE_HIDDEN = (8),
+    TBSTATE_INDETERMINATE = (16),
+    TBSTATE_PRESSED = (2),
+    TBSTATE_WRAP = (32),
+    TTS_ALWAYSTIP = (1),
+    TTS_NOPREFIX = (2),
+    TTF_IDISHWND = (1),
+    TTF_CENTERTIP = (2),
+    TTF_RTLREADING = (4),
+    TTF_SUBCLASS = (16),
+    TTDT_AUTOMATIC = (0),
+    TTDT_AUTOPOP = (2),
+    TTDT_INITIAL = (3),
+    TTDT_RESHOW = (1),
+    SBARS_SIZEGRIP = (256),
+    DL_MOVECURSOR = (3),
+    DL_COPYCURSOR = (2),
+    DL_STOPCURSOR = (1),
+    UDS_ALIGNLEFT = (8),
+    UDS_ALIGNRIGHT = (4),
+    UDS_ARROWKEYS = (32),
+    UDS_AUTOBUDDY = (16),
+    UDS_HORZ = (64),
+    UDS_NOTHOUSANDS = (128),
+    UDS_SETBUDDYINT = (2),
+    UDS_WRAP = (1),
+    UD_MAXVAL = (32767),
+    UD_MINVAL = -((32767)),
+    HOTKEYF_ALT = (4),
+    HOTKEYF_CONTROL = (2),
+    HOTKEYF_EXT = (8),
+    HOTKEYF_SHIFT = (1),
+    HKCOMB_A = (8),
+    HKCOMB_C = (4),
+    HKCOMB_CA = (64),
+    HKCOMB_NONE = (1),
+    HKCOMB_S = (2),
+    HKCOMB_SA = (32),
+    HKCOMB_SC = (16),
+    HKCOMB_SCA = (128),
+    TBS_HORZ = (0),
+    TBS_VERT = (2),
+    TBS_AUTOTICKS = (1),
+    TBS_NOTICKS = (16),
+    TBS_TOP = (4),
+    TBS_BOTTOM = (0),
+    TBS_LEFT = (4),
+    TBS_RIGHT = (0),
+    TBS_BOTH = (8),
+    TBS_ENABLESELRANGE = (32),
+    TBS_FIXEDLENGTH = (64),
+    TBS_NOTHUMB = (128),
+    TB_BOTTOM = (7),
+    TB_ENDTRACK = (8),
+    TB_LINEDOWN = (1),
+    TB_LINEUP = (0),
+    TB_PAGEDOWN = (3),
+    TB_PAGEUP = (2),
+    TB_THUMBPOSITION = (4),
+    TB_THUMBTRACK = (5),
+    TB_TOP = (6),
+    LVS_ALIGNLEFT = (2048),
+    LVS_ALIGNTOP = (0),
+    LVS_AUTOARRANGE = (256),
+    LVS_EDITLABELS = (512),
+    LVS_ICON = (0),
+    LVS_LIST = (3),
+    LVS_NOCOLUMNHEADER = (16384),
+    LVS_NOLABELWRAP = (128),
+    LVS_NOSCROLL = (8192),
+    LVS_NOSORTHEADER = (32768),
+    LVS_OWNERDRAWFIXED = (1024),
+    LVS_REPORT = (1),
+    LVS_SHAREIMAGELISTS = (64),
+    LVS_SHOWSELALWAYS = (8),
+    LVS_SINGLESEL = (4),
+    LVS_SMALLICON = (2),
+    LVS_SORTASCENDING = (16),
+    LVS_SORTDESCENDING = (32),
+    LVS_TYPESTYLEMASK = (64512),
+    LVSIL_NORMAL = (0),
+    LVSIL_SMALL = (1),
+    LVSIL_STATE = (2),
+    LVIS_CUT = (4),
+    LVIS_DROPHILITED = (8),
+    LVIS_FOCUSED = (1),
+    LVIS_SELECTED = (2),
+    LVIS_OVERLAYMASK = (3840),
+    LVIS_STATEIMAGEMASK = (61440),
+}
+const {
+    LPWSTR LPSTR_TEXTCALLBACKW = cast(LPWSTR)(-(1));
+    LPSTR  LPSTR_TEXTCALLBACKA = cast(LPSTR)(-(1));
+    version(Win32SansUnicode){
+        alias LPSTR_TEXTCALLBACKA LPSTR_TEXTCALLBACK;
+    }
+    else{
+        alias LPSTR_TEXTCALLBACKW LPSTR_TEXTCALLBACK;
+    }
+}
+enum : DWORD {
+    LVIF_TEXT = (1),
+    LVIF_IMAGE = (2),
+    LVIF_PARAM = (4),
+    LVIF_STATE = (8),
+    LVIF_DI_SETITEM = (4096),
+    LVNI_ABOVE = (256),
+    LVNI_ALL = (0),
+    LVNI_BELOW = (512),
+    LVNI_TOLEFT = (1024),
+    LVNI_TORIGHT = (2048),
+    LVNI_CUT = (4),
+    LVNI_DROPHILITED = (8),
+    LVNI_FOCUSED = (1),
+    LVNI_SELECTED = (2),
+    LVFI_PARAM = (1),
+    LVFI_PARTIAL = (8),
+    LVFI_STRING = (2),
+    LVFI_WRAP = (32),
+    LVFI_NEARESTXY = (64),
+    LVHT_ABOVE = (8),
+    LVHT_BELOW = (16),
+    LVHT_NOWHERE = (1),
+    LVHT_ONITEMICON = (2),
+    LVHT_ONITEMLABEL = (4),
+    LVHT_ONITEMSTATEICON = (8),
+    LVHT_TOLEFT = (64),
+    LVHT_TORIGHT = (32),
+    LVCF_FMT = (1),
+    LVCF_SUBITEM = (8),
+    LVCF_TEXT = (4),
+    LVCF_WIDTH = (2),
+    LVCFMT_CENTER = (2),
+    LVCFMT_LEFT = (0),
+    LVCFMT_RIGHT = (1),
+    LVIR_BOUNDS = (0),
+    LVIR_ICON = (1),
+    LVIR_LABEL = (2),
+    LVIR_SELECTBOUNDS = (3),
+    LVA_ALIGNLEFT = (1),
+    LVA_ALIGNTOP = (2),
+    LVA_DEFAULT = (0),
+    LVA_SNAPTOGRID = (5),
+    LVSCW_AUTOSIZE = -((1)),
+    LVSCW_AUTOSIZE_USEHEADER = -((2)),
+    TVS_DISABLEDRAGDROP = (16),
+    TVS_EDITLABELS = (8),
+    TVS_HASBUTTONS = (1),
+    TVS_HASLINES = (2),
+    TVS_LINESATROOT = (4),
+    TVS_SHOWSELALWAYS = (32),
+    TVIS_BOLD = (16),
+    TVIS_CUT = (4),
+    TVIS_DROPHILITED = (8),
+    TVIS_EXPANDED = (32),
+    TVIS_EXPANDEDONCE = (64),
+    TVIS_FOCUSED = (1),
+    TVIS_OVERLAYMASK = (3840),
+    TVIS_SELECTED = (2),
+    TVIS_STATEIMAGEMASK = (61440),
+    TVIS_USERMASK = (61440),
+    TVIF_CHILDREN = (64),
+    TVIF_HANDLE = (16),
+    TVIF_IMAGE = (2),
+    TVIF_PARAM = (4),
+    TVIF_SELECTEDIMAGE = (32),
+    TVIF_STATE = (8),
+    TVIF_TEXT = (1),
+    I_CHILDRENCALLBACK = -((1)),
+    I_IMAGECALLBACK = -((1)),
+}
+
+struct TREEITEM
+{
+}
+
+alias TREEITEM* HTREEITEM;
+alias TREEITEM TTREEITEM;
+alias TREEITEM* PTREEITEM;
+enum : DWORD {
+    TVI_ROOT = (0xFFFF0000),
+    TVI_FIRST = (0xFFFF0001),
+    TVI_LAST = (0xFFFF0002),
+    TVI_SORT = (0xFFFF0003),
+    TVHT_ABOVE = (256),
+    TVHT_BELOW = (512),
+    TVHT_NOWHERE = (1),
+    TVHT_ONITEM = (70),
+    TVHT_ONITEMBUTTON = (16),
+    TVHT_ONITEMICON = (2),
+    TVHT_ONITEMINDENT = (8),
+    TVHT_ONITEMLABEL = (4),
+    TVHT_ONITEMRIGHT = (32),
+    TVHT_ONITEMSTATEICON = (64),
+    TVHT_TOLEFT = (2048),
+    TVHT_TORIGHT = (1024),
+    TVE_COLLAPSE = (1),
+    TVE_COLLAPSERESET = (32768),
+    TVE_EXPAND = (2),
+    TVE_TOGGLE = (3),
+    TVSIL_NORMAL = (0),
+    TVSIL_STATE = (2),
+    TVGN_CARET = (9),
+    TVGN_CHILD = (4),
+    TVGN_DROPHILITE = (8),
+    TVGN_FIRSTVISIBLE = (5),
+    TVGN_NEXT = (1),
+    TVGN_NEXTVISIBLE = (6),
+    TVGN_PARENT = (3),
+    TVGN_PREVIOUS = (2),
+    TVGN_PREVIOUSVISIBLE = (7),
+    TVGN_ROOT = (0),
+    TVC_BYKEYBOARD = (2),
+    TVC_BYMOUSE = (1),
+    TVC_UNKNOWN = (0),
+    TCS_BUTTONS = (256),
+    TCS_FIXEDWIDTH = (1024),
+    TCS_FOCUSNEVER = (32768),
+    TCS_FOCUSONBUTTONDOWN = (4096),
+    TCS_FORCEICONLEFT = (16),
+    TCS_FORCELABELLEFT = (32),
+    TCS_MULTILINE = (512),
+    TCS_OWNERDRAWFIXED = (8192),
+    TCS_RAGGEDRIGHT = (2048),
+    TCS_RIGHTJUSTIFY = (0),
+    TCS_SINGLELINE = (0),
+    TCS_TABS = (0),
+    TCS_TOOLTIPS = (16384),
+    TCIF_TEXT = (1),
+    TCIF_IMAGE = (2),
+    TCIF_PARAM = (8),
+    TCIF_RTLREADING = (4),
+    TCHT_NOWHERE = (1),
+    TCHT_ONITEM = (6),
+    TCHT_ONITEMICON = (2),
+    TCHT_ONITEMLABEL = (4),
+    ACS_AUTOPLAY = (4),
+    ACS_CENTER = (1),
+    ACS_TRANSPARENT = (2),
+    DIALOPTION_BILLING = (64),
+    DIALOPTION_QUIET = (128),
+    DIALOPTION_DIALTONE = (256),
+    MDMVOLFLAG_LOW = (1),
+    MDMVOLFLAG_MEDIUM = (2),
+    MDMVOLFLAG_HIGH = (4),
+    MDMVOL_LOW = (0),
+    MDMVOL_MEDIUM = (1),
+    MDMVOL_HIGH = (2),
+    MDMSPKRFLAG_OFF = (1),
+    MDMSPKRFLAG_DIAL = (2),
+    MDMSPKRFLAG_ON = (4),
+    MDMSPKRFLAG_CALLSETUP = (8),
+    MDMSPKR_OFF = (0),
+    MDMSPKR_DIAL = (1),
+    MDMSPKR_ON = (2),
+    MDMSPKR_CALLSETUP = (3),
+    MDM_BLIND_DIAL = (512),
+    MDM_CCITT_OVERRIDE = (64),
+    MDM_CELLULAR = (8),
+    MDM_COMPRESSION = (1),
+    MDM_ERROR_CONTROL = (2),
+    MDM_FLOWCONTROL_HARD = (16),
+    MDM_FLOWCONTROL_SOFT = (32),
+    MDM_FORCED_EC = (4),
+    MDM_SPEED_ADJUST = (128),
+    MDM_TONE_DIAL = (256),
+    MDM_V23_OVERRIDE = (1024),
+    LANG_BULGARIAN = (2),
+    LANG_CHINESE = (4),
+    LANG_CROATIAN = (26),
+    LANG_CZECH = (5),
+    LANG_DANISH = (6),
+    LANG_DUTCH = (19),
+    LANG_ENGLISH = (9),
+    LANG_FINNISH = (11),
+    LANG_FRENCH = (12),
+    LANG_GERMAN = (7),
+    LANG_GREEK = (8),
+    LANG_HUNGARIAN = (14),
+    LANG_ICELANDIC = (15),
+    LANG_ITALIAN = (16),
+    LANG_JAPANESE = (17),
+    LANG_KOREAN = (18),
+    LANG_NEUTRAL = (0),
+    LANG_NORWEGIAN = (20),
+    LANG_POLISH = (21),
+    LANG_PORTUGUESE = (22),
+    LANG_ROMANIAN = (24),
+    LANG_RUSSIAN = (25),
+    LANG_SLOVAK = (27),
+    LANG_SLOVENIAN = (36),
+    LANG_SPANISH = (10),
+    LANG_SWEDISH = (29),
+    LANG_TURKISH = (31),
+    SUBLANG_CHINESE_SIMPLIFIED = (2),
+    SUBLANG_CHINESE_TRADITIONAL = (1),
+    SUBLANG_CHINESE_HONGKONG = (3),
+    SUBLANG_CHINESE_SINGAPORE = (4),
+    SUBLANG_DEFAULT = (1),
+    SUBLANG_DUTCH = (1),
+    SUBLANG_DUTCH_BELGIAN = (2),
+    SUBLANG_ENGLISH_AUS = (3),
+    SUBLANG_ENGLISH_CAN = (4),
+    SUBLANG_ENGLISH_EIRE = (6),
+    SUBLANG_ENGLISH_NZ = (5),
+    SUBLANG_ENGLISH_UK = (2),
+    SUBLANG_ENGLISH_US = (1),
+    SUBLANG_FRENCH = (1),
+    SUBLANG_FRENCH_BELGIAN = (2),
+    SUBLANG_FRENCH_CANADIAN = (3),
+    SUBLANG_FRENCH_SWISS = (4),
+    SUBLANG_GERMAN = (1),
+    SUBLANG_GERMAN_AUSTRIAN = (3),
+    SUBLANG_GERMAN_SWISS = (2),
+    SUBLANG_ITALIAN = (1),
+    SUBLANG_ITALIAN_SWISS = (2),
+    SUBLANG_NEUTRAL = (0),
+    SUBLANG_NORWEGIAN_BOKMAL = (1),
+    SUBLANG_NORWEGIAN_NYNORSK = (2),
+    SUBLANG_PORTUGUESE = (2),
+    SUBLANG_PORTUGUESE_BRAZILIAN = (1),
+    SUBLANG_SPANISH = (1),
+    SUBLANG_SPANISH_MEXICAN = (2),
+    SUBLANG_SPANISH_MODERN = (3),
+    SUBLANG_SYS_DEFAULT = (2),
+    NLS_VALID_LOCALE_MASK = (1048575),
+    SORT_DEFAULT = (0),
+    SORT_JAPANESE_XJIS = (0),
+    SORT_JAPANESE_UNICODE = (1),
+    SORT_CHINESE_BIG5 = (0),
+    SORT_CHINESE_UNICODE = (1),
+    SORT_KOREAN_KSC = (0),
+    SORT_KOREAN_UNICODE = (1),
+    PROCESSOR_INTEL_386 = (386),
+    PROCESSOR_INTEL_486 = (486),
+    PROCESSOR_INTEL_PENTIUM = (586),
+    PROCESSOR_MIPS_R4000 = (4000),
+    PROCESSOR_ALPHA_21064 = (21064),
+    COMPRESSION_FORMAT_NONE = (0),
+    COMPRESSION_FORMAT_DEFAULT = (1),
+    COMPRESSION_FORMAT_LZNT1 = (2),
+    TAPE_DRIVE_COMPRESSION = (131072),
+    TAPE_DRIVE_ECC = (65536),
+    TAPE_DRIVE_ERASE_BOP_ONLY = (64),
+    TAPE_DRIVE_ERASE_LONG = (32),
+    TAPE_DRIVE_ERASE_IMMEDIATE = (128),
+    TAPE_DRIVE_ERASE_SHORT = (16),
+    TAPE_DRIVE_FIXED = (1),
+    TAPE_DRIVE_FIXED_BLOCK = (1024),
+    TAPE_DRIVE_INITIATOR = (4),
+    TAPE_DRIVE_PADDING = (262144),
+    TAPE_DRIVE_GET_ABSOLUTE_BLK = (1048576),
+    TAPE_DRIVE_GET_LOGICAL_BLK = (2097152),
+    TAPE_DRIVE_REPORT_SMKS = (524288),
+    TAPE_DRIVE_SELECT = (2),
+    TAPE_DRIVE_SET_EOT_WZ_SIZE = (4194304),
+    TAPE_DRIVE_TAPE_CAPACITY = (256),
+    TAPE_DRIVE_TAPE_REMAINING = (512),
+    TAPE_DRIVE_VARIABLE_BLOCK = (2048),
+    TAPE_DRIVE_WRITE_PROTECT = (4096),
+    TAPE_DRIVE_ABS_BLK_IMMED = -((2147475456)),
+    TAPE_DRIVE_ABSOLUTE_BLK = -((2147479552)),
+    TAPE_DRIVE_END_OF_DATA = -((2147418112)),
+    TAPE_DRIVE_FILEMARKS = -((2147221504)),
+    TAPE_DRIVE_LOAD_UNLOAD = -((2147483647)),
+    TAPE_DRIVE_LOAD_UNLD_IMMED = -((2147483616)),
+    TAPE_DRIVE_LOCK_UNLOCK = -((2147483644)),
+    TAPE_DRIVE_LOCK_UNLK_IMMED = -((2147483520)),
+    TAPE_DRIVE_LOG_BLK_IMMED = -((2147450880)),
+    TAPE_DRIVE_LOGICAL_BLK = -((2147467264)),
+    TAPE_DRIVE_RELATIVE_BLKS = -((2147352576)),
+    TAPE_DRIVE_REVERSE_POSITION = -((2143289344)),
+    TAPE_DRIVE_REWIND_IMMEDIATE = -((2147483640)),
+    TAPE_DRIVE_SEQUENTIAL_FMKS = -((2146959360)),
+    TAPE_DRIVE_SEQUENTIAL_SMKS = -((2145386496)),
+    TAPE_DRIVE_SET_BLOCK_SIZE = -((2147483632)),
+    TAPE_DRIVE_SET_COMPRESSION = -((2147483136)),
+    TAPE_DRIVE_SET_ECC = -((2147483392)),
+    TAPE_DRIVE_SET_PADDING = -((2147482624)),
+    TAPE_DRIVE_SET_REPORT_SMKS = -((2147481600)),
+    TAPE_DRIVE_SETMARKS = -((2146435072)),
+    TAPE_DRIVE_SPACE_IMMEDIATE = -((2139095040)),
+    TAPE_DRIVE_TENSION = -((2147483646)),
+    TAPE_DRIVE_TENSION_IMMED = -((2147483584)),
+    TAPE_DRIVE_WRITE_FILEMARKS = -((2113929216)),
+    TAPE_DRIVE_WRITE_LONG_FMKS = -((2013265920)),
+    TAPE_DRIVE_WRITE_MARK_IMMED = -((1879048192)),
+    TAPE_DRIVE_WRITE_SETMARKS = -((2130706432)),
+    TAPE_DRIVE_WRITE_SHORT_FMKS = -((2080374784)),
+    STANDARD_RIGHTS_REQUIRED = (0xf0000),
+    STANDARD_RIGHTS_WRITE = (0x20000),
+    STANDARD_RIGHTS_READ = (0x20000),
+    STANDARD_RIGHTS_EXECUTE = (0x20000),
+    STANDARD_RIGHTS_ALL = (0x1f0000),
+    SPECIFIC_RIGHTS_ALL = (0xffff),
+    MAXIMUM_ALLOWED = (0x2000000),
+    GENERIC_ALL = (0x10000000),
+    SECURITY_NULL_RID = (0),
+    SECURITY_WORLD_RID = (0),
+    SECURITY_LOCAL_RID = (0),
+    SECURITY_CREATOR_OWNER_RID = (0),
+    SECURITY_CREATOR_GROUP_RID = (0x1),
+    SECURITY_DIALUP_RID = (0x1),
+    SECURITY_NETWORK_RID = (0x2),
+    SECURITY_BATCH_RID = (0x3),
+    SECURITY_INTERACTIVE_RID = (0x4),
+    SECURITY_LOGON_IDS_RID = (0x5),
+    SECURITY_LOGON_IDS_RID_COUNT = (0x3),
+    SECURITY_SERVICE_RID = (0x6),
+    SECURITY_LOCAL_SYSTEM_RID = (0x12),
+    SECURITY_BUILTIN_DOMAIN_RID = (0x20),
+    DOMAIN_USER_RID_ADMIN = (0x1f4),
+    DOMAIN_USER_RID_GUEST = (0x1f5),
+    DOMAIN_GROUP_RID_ADMINS = (0x200),
+    DOMAIN_GROUP_RID_USERS = (0x201),
+    DOMAIN_ALIAS_RID_ADMINS = (0x220),
+    DOMAIN_ALIAS_RID_USERS = (0x221),
+    DOMAIN_ALIAS_RID_GUESTS = (0x222),
+    DOMAIN_ALIAS_RID_POWER_USERS = (0x223),
+    DOMAIN_ALIAS_RID_ACCOUNT_OPS = (0x224),
+    DOMAIN_ALIAS_RID_SYSTEM_OPS = (0x225),
+    DOMAIN_ALIAS_RID_PRINT_OPS = (0x226),
+    DOMAIN_ALIAS_RID_BACKUP_OPS = (0x227),
+    DOMAIN_ALIAS_RID_REPLICATOR = (0x228),
+    SE_GROUP_MANDATORY = (0x1),
+    SE_GROUP_ENABLED_BY_DEFAULT = (0x2),
+    SE_GROUP_ENABLED = (0x4),
+    SE_GROUP_OWNER = (0x8),
+    SE_GROUP_LOGON_ID = (0xc0000000),
+    ACL_REVISION = (2),
+    ACCESS_ALLOWED_ACE_TYPE = (0x0),
+    ACCESS_DENIED_ACE_TYPE = (0x1),
+    SYSTEM_AUDIT_ACE_TYPE = (0x2),
+    SYSTEM_ALARM_ACE_TYPE = (0x3),
+    OBJECT_INHERIT_ACE = (0x1),
+    CONTAINER_INHERIT_ACE = (0x2),
+    NO_PROPAGATE_INHERIT_ACE = (0x4),
+    INHERIT_ONLY_ACE = (0x8),
+    SUCCESSFUL_ACCESS_ACE_FLAG = (0x40),
+    FAILED_ACCESS_ACE_FLAG = (0x80),
+    SECURITY_DESCRIPTOR_MIN_LENGTH = (20),
+    SE_OWNER_DEFAULTED = (1),
+    SE_GROUP_DEFAULTED = (2),
+    SE_DACL_PRESENT = (4),
+    SE_DACL_DEFAULTED = (8),
+    SE_SACL_PRESENT = (16),
+    SE_SACL_DEFAULTED = (32),
+    SE_SELF_RELATIVE = (32768),
+    SE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x1),
+    SE_PRIVILEGE_ENABLED = (0x2),
+    SE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000),
+    PRIVILEGE_SET_ALL_NECESSARY = (0x1),
+    OFN_ALLOWMULTISELECT = (0x200),
+    OFN_CREATEPROMPT = (0x2000),
+    OFN_ENABLEHOOK = (0x20),
+    OFN_ENABLETEMPLATE = (0x40),
+    OFN_ENABLETEMPLATEHANDLE = (0x80),
+    OFN_EXPLORER = (0x80000),
+    OFN_EXTENSIONDIFFERENT = (0x400),
+    OFN_FILEMUSTEXIST = (0x1000),
+    OFN_HIDEREADONLY = (0x4),
+    OFN_LONGNAMES = (0x200000),
+    OFN_NOCHANGEDIR = (0x8),
+    OFN_NODEREFERENCELINKS = (0x100000),
+    OFN_NOLONGNAMES = (0x40000),
+    OFN_NONETWORKBUTTON = (0x20000),
+    OFN_NOREADONLYRETURN = (0x8000),
+    OFN_NOTESTFILECREATE = (0x10000),
+    OFN_NOVALIDATE = (0x100),
+    OFN_OVERWRITEPROMPT = (0x2),
+    OFN_PATHMUSTEXIST = (0x800),
+    OFN_READONLY = (0x1),
+    OFN_SHAREAWARE = (0x4000),
+    OFN_SHOWHELP = (0x10),
+    OFN_SHAREFALLTHROUGH = (0x2),
+    OFN_SHARENOWARN = (0x1),
+    OFN_SHAREWARN = (0),
+    CDN_INITDONE = (0xfffffda7),
+    CDN_SELCHANGE = (0xfffffda6),
+    CDN_FOLDERCHANGE = (0xfffffda5),
+    CDN_SHAREVIOLATION = (0xfffffda4),
+    CDN_HELP = (0xfffffda3),
+    CDN_FILEOK = (0xfffffda2),
+    CDN_TYPECHANGE = (0xfffffda1),
+    CDM_GETFILEPATH = (0x465),
+    CDM_GETFOLDERIDLIST = (0x467),
+    CDM_GETFOLDERPATH = (0x466),
+    CDM_GETSPEC = (0x464),
+    CDM_HIDECONTROL = (0x469),
+    CDM_SETCONTROLTEXT = (0x468),
+    CDM_SETDEFEXT = (0x46a),
+    CC_ENABLEHOOK = (0x10),
+    CC_ENABLETEMPLATE = (0x20),
+    CC_ENABLETEMPLATEHANDLE = (0x40),
+    CC_FULLOPEN = (0x2),
+    CC_PREVENTFULLOPEN = (0x4),
+    CC_RGBINIT = (0x1),
+    CC_SHOWHELP = (0x8),
+    CC_SOLIDCOLOR = (0x80),
+    FR_DIALOGTERM = (0x40),
+    FR_DOWN = (0x1),
+    FR_ENABLEHOOK = (0x100),
+    FR_ENABLETEMPLATE = (0x200),
+    FR_ENABLETEMPLATEHANDLE = (0x2000),
+    FR_FINDNEXT = (0x8),
+    FR_HIDEUPDOWN = (0x4000),
+    FR_HIDEMATCHCASE = (0x8000),
+    FR_HIDEWHOLEWORD = (0x10000),
+    FR_MATCHCASE = (0x4),
+    FR_NOMATCHCASE = (0x800),
+    FR_NOUPDOWN = (0x400),
+    FR_NOWHOLEWORD = (0x1000),
+    FR_REPLACE = (0x10),
+    FR_REPLACEALL = (0x20),
+    FR_SHOWHELP = (0x80),
+    FR_WHOLEWORD = (0x2),
+    CF_APPLY = (0x200),
+    CF_ANSIONLY = (0x400),
+    CF_BOTH = (0x3),
+    CF_TTONLY = (0x40000),
+    CF_EFFECTS = (0x100),
+    CF_ENABLEHOOK = (0x8),
+    CF_ENABLETEMPLATE = (0x10),
+    CF_ENABLETEMPLATEHANDLE = (0x20),
+    CF_FIXEDPITCHONLY = (0x4000),
+    CF_FORCEFONTEXIST = (0x10000),
+    CF_INITTOLOGFONTSTRUCT = (0x40),
+    CF_LIMITSIZE = (0x2000),
+    CF_NOOEMFONTS = (0x800),
+    CF_NOFACESEL = (0x80000),
+    CF_NOSCRIPTSEL = (0x800000),
+    CF_NOSTYLESEL = (0x100000),
+    CF_NOSIZESEL = (0x200000),
+    CF_NOSIMULATIONS = (0x1000),
+    CF_NOVECTORFONTS = (0x800),
+    CF_NOVERTFONTS = (0x1000000),
+    CF_PRINTERFONTS = (0x2),
+    CF_SCALABLEONLY = (0x20000),
+    CF_SCREENFONTS = (0x1),
+    CF_SCRIPTSONLY = (0x400),
+    CF_SELECTSCRIPT = (0x400000),
+    CF_SHOWHELP = (0x4),
+    CF_USESTYLE = (0x80),
+    CF_WYSIWYG = (0x8000),
+    BOLD_FONTTYPE = (0x100),
+    ITALIC_FONTTYPE = (0x200),
+    PRINTER_FONTTYPE = (0x4000),
+    REGULAR_FONTTYPE = (0x400),
+    SCREEN_FONTTYPE = (0x2000),
+    SIMULATED_FONTTYPE = (0x8000),
+}
+const {
+char* COLOROKSTRINGW = ("commdlg_ColorOK");
+char* FILEOKSTRINGW = ("commdlg_FileNameOK");
+char* FINDMSGSTRINGW = ("commdlg_FindReplace");
+char* HELPMSGSTRINGW = ("commdlg_help");
+char* LBSELCHSTRINGW = ("commdlg_LBSelChangedNotify");
+char* SETRGBSTRINGW = ("commdlg_SetRGBColor");
+char* SHAREVISTRINGW = ("commdlg_ShareViolation");
+char* COLOROKSTRINGA = ("commdlg_ColorOK");
+char* FILEOKSTRINGA = ("commdlg_FileNameOK");
+char* FINDMSGSTRINGA = ("commdlg_FindReplace");
+char* HELPMSGSTRINGA = ("commdlg_help");
+char* LBSELCHSTRINGA = ("commdlg_LBSelChangedNotify");
+char* SETRGBSTRINGA = ("commdlg_SetRGBColor");
+char* SHAREVISTRINGA = ("commdlg_ShareViolation");
+char* COLOROKSTRING = (COLOROKSTRINGA);
+char* FILEOKSTRING = (FILEOKSTRINGA);
+char* FINDMSGSTRING = (FINDMSGSTRINGA);
+char* HELPMSGSTRING = (HELPMSGSTRINGA);
+char* LBSELCHSTRING = (LBSELCHSTRINGA);
+char* SETRGBSTRING = (SETRGBSTRINGA);
+char* SHAREVISTRING = (SHAREVISTRINGA);
+}
+
+const {
+HWND HWND_DESKTOP = cast(HWND) 0;
+HWND HWND_BOTTOM = cast(HWND) 1;
+HWND HWND_NOTOPMOST = cast(HWND) -2;
+HWND HWND_TOP = cast(HWND) 0;
+HWND HWND_TOPMOST = cast(HWND) -1;
+HWND HWND_BROADCAST = cast(HWND) 0xFFFF;
+}
+
+enum : DWORD {
+    CD_LBSELCHANGE = (0),
+    CD_LBSELADD = (2),
+    CD_LBSELSUB = (1),
+    CD_LBSELNOITEMS = -((1)),
+    DN_DEFAULTPRN = (1),
+    PD_ALLPAGES = (0),
+    PD_COLLATE = (16),
+    PD_DISABLEPRINTTOFILE = (524288),
+    PD_ENABLEPRINTHOOK = (4096),
+    PD_ENABLEPRINTTEMPLATE = (16384),
+    PD_ENABLEPRINTTEMPLATEHANDLE = (65536),
+    PD_ENABLESETUPHOOK = (8192),
+    PD_ENABLESETUPTEMPLATE = (32768),
+    PD_ENABLESETUPTEMPLATEHANDLE = (131072),
+    PD_HIDEPRINTTOFILE = (1048576),
+    PD_NOPAGENUMS = (8),
+    PD_NOSELECTION = (4),
+    PD_NOWARNING = (128),
+    PD_PAGENUMS = (2),
+    PD_PRINTSETUP = (64),
+    PD_PRINTTOFILE = (32),
+    PD_RETURNDC = (256),
+    PD_RETURNDEFAULT = (1024),
+    PD_RETURNIC = (512),
+    PD_SELECTION = (1),
+    PD_SHOWHELP = (2048),
+    PD_USEDEVMODECOPIES = (262144),
+    PD_USEDEVMODECOPIESANDCOLLATE = (262144),
+    PSD_DEFAULTMINMARGINS = (0),
+    PSD_DISABLEMARGINS = (16),
+    PSD_DISABLEORIENTATION = (256),
+    PSD_DISABLEPAGEPAINTING = (524288),
+    PSD_DISABLEPAPER = (512),
+    PSD_DISABLEPRINTER = (32),
+    PSD_ENABLEPAGEPAINTHOOK = (262144),
+    PSD_ENABLEPAGESETUPHOOK = (8192),
+    PSD_ENABLEPAGESETUPTEMPLATE = (32768),
+    PSD_ENABLEPAGESETUPTEMPLATEHANDLE = (131072),
+    PSD_INHUNDREDTHSOFMILLIMETERS = (8),
+    PSD_INTHOUSANDTHSOFINCHES = (4),
+    PSD_INWININIINTLMEASURE = (0),
+    PSD_MARGINS = (2),
+    PSD_MINMARGINS = (1),
+    PSD_NOWARNING = (128),
+    PSD_RETURNDEFAULT = (1024),
+    PSD_SHOWHELP = (2048),
+    SW_OTHERUNZOOM = (4),
+    SW_OTHERZOOM = (2),
+    SW_PARENTCLOSING = (1),
+    SW_PARENTOPENING = (3),
+    VK_LBUTTON = (1),
+    VK_RBUTTON = (2),
+    VK_CANCEL = (3),
+    VK_MBUTTON = (4),
+    VK_BACK = (8),
+    VK_TAB = (9),
+    VK_CLEAR = (12),
+    VK_RETURN = (13),
+    VK_SHIFT = (16),
+    VK_CONTROL = (17),
+    VK_MENU = (18),
+    VK_PAUSE = (19),
+    VK_CAPITAL = (20),
+    VK_ESCAPE = (27),
+    VK_SPACE = (32),
+    VK_PRIOR = (33),
+    VK_NEXT = (34),
+    VK_END = (35),
+    VK_HOME = (36),
+    VK_LEFT = (37),
+    VK_UP = (38),
+    VK_RIGHT = (39),
+    VK_DOWN = (40),
+    VK_SELECT = (41),
+    VK_PRINT = (42),
+    VK_EXECUTE = (43),
+    VK_SNAPSHOT = (44),
+    VK_INSERT = (45),
+    VK_DELETE = (46),
+    VK_HELP = (47),
+    VK_0 = (48),
+    VK_1 = (49),
+    VK_2 = (50),
+    VK_3 = (51),
+    VK_4 = (52),
+    VK_5 = (53),
+    VK_6 = (54),
+    VK_7 = (55),
+    VK_8 = (56),
+    VK_9 = (57),
+    VK_A = (65),
+    VK_B = (66),
+    VK_C = (67),
+    VK_D = (68),
+    VK_E = (69),
+    VK_F = (70),
+    VK_G = (71),
+    VK_H = (72),
+    VK_I = (73),
+    VK_J = (74),
+    VK_K = (75),
+    VK_L = (76),
+    VK_M = (77),
+    VK_N = (78),
+    VK_O = (79),
+    VK_P = (80),
+    VK_Q = (81),
+    VK_R = (82),
+    VK_S = (83),
+    VK_T = (84),
+    VK_U = (85),
+    VK_V = (86),
+    VK_W = (87),
+    VK_X = (88),
+    VK_Y = (89),
+    VK_Z = (90),
+    VK_NUMPAD0 = (96),
+    VK_NUMPAD1 = (97),
+    VK_NUMPAD2 = (98),
+    VK_NUMPAD3 = (99),
+    VK_NUMPAD4 = (100),
+    VK_NUMPAD5 = (101),
+    VK_NUMPAD6 = (102),
+    VK_NUMPAD7 = (103),
+    VK_NUMPAD8 = (104),
+    VK_NUMPAD9 = (105),
+    VK_MULTIPLY = (106),
+    VK_ADD = (107),
+    VK_SEPARATOR = (108),
+    VK_SUBTRACT = (109),
+    VK_DECIMAL = (110),
+    VK_DIVIDE = (111),
+    VK_F1 = (112),
+    VK_F2 = (113),
+    VK_F3 = (114),
+    VK_F4 = (115),
+    VK_F5 = (116),
+    VK_F6 = (117),
+    VK_F7 = (118),
+    VK_F8 = (119),
+    VK_F9 = (120),
+    VK_F10 = (121),
+    VK_F11 = (122),
+    VK_F12 = (123),
+    VK_F13 = (124),
+    VK_F14 = (125),
+    VK_F15 = (126),
+    VK_F16 = (127),
+    VK_F17 = (128),
+    VK_F18 = (129),
+    VK_F19 = (130),
+    VK_F20 = (131),
+    VK_F21 = (132),
+    VK_F22 = (133),
+    VK_F23 = (134),
+    VK_F24 = (135),
+    VK_NUMLOCK = (144),
+    VK_SCROLL = (145),
+    VK_LSHIFT = (160),
+    VK_LCONTROL = (162),
+    VK_LMENU = (164),
+    VK_RSHIFT = (161),
+    VK_RCONTROL = (163),
+    VK_RMENU = (165),
+    VK_PROCESSKEY = (229),
+    KF_ALTDOWN = (8192),
+    KF_DLGMODE = (2048),
+    KF_EXTENDED = (256),
+    KF_MENUMODE = (4096),
+    KF_REPEAT = (16384),
+    KF_UP = (32768),
+    KL_NAMELENGTH = (9),
+    WA_ACTIVE = (1),
+    WA_CLICKACTIVE = (2),
+    WA_INACTIVE = (0),
+    PWR_CRITICALRESUME = (3),
+    PWR_SUSPENDREQUEST = (1),
+    PWR_SUSPENDRESUME = (2),
+    PWR_FAIL = -((1)),
+    PWR_OK = (1),
+    NF_QUERY = (3),
+    NF_REQUERY = (4),
+    NFR_ANSI = (1),
+    NFR_UNICODE = (2),
+    WMSZ_BOTTOM = (6),
+    WMSZ_BOTTOMLEFT = (7),
+    WMSZ_BOTTOMRIGHT = (8),
+    WMSZ_LEFT = (1),
+    WMSZ_RIGHT = (2),
+    WMSZ_TOP = (3),
+    WMSZ_TOPLEFT = (4),
+    WMSZ_TOPRIGHT = (5),
+    MA_ACTIVATE = (1),
+    MA_ACTIVATEANDEAT = (2),
+    MA_NOACTIVATE = (3),
+    MA_NOACTIVATEANDEAT = (4),
+    SIZE_MAXHIDE = (4),
+    SIZE_MAXIMIZED = (2),
+    SIZE_MAXSHOW = (3),
+    SIZE_MINIMIZED = (1),
+    SIZE_RESTORED = (0),
+    WVR_ALIGNTOP = (16),
+    WVR_ALIGNLEFT = (32),
+    WVR_ALIGNBOTTOM = (64),
+    WVR_ALIGNRIGHT = (128),
+    WVR_HREDRAW = (256),
+    WVR_VREDRAW = (512),
+    WVR_REDRAW = (768),
+    WVR_VALIDRECTS = (1024),
+    HTBOTTOM = (15),
+    HTBOTTOMLEFT = (16),
+    HTBOTTOMRIGHT = (17),
+    HTCAPTION = (2),
+    HTCLIENT = (1),
+    HTERROR = -((2)),
+    HTGROWBOX = (4),
+    HTHSCROLL = (6),
+    HTLEFT = (10),
+    HTMENU = (5),
+    HTNOWHERE = (0),
+    HTREDUCE = (8),
+    HTRIGHT = (11),
+    HTSIZE = (4),
+    HTSYSMENU = (3),
+    HTTOP = (12),
+    HTTOPLEFT = (13),
+    HTTOPRIGHT = (14),
+    HTTRANSPARENT = -((1)),
+    HTVSCROLL = (7),
+    HTZOOM = (9),
+    MK_CONTROL = (8),
+    MK_LBUTTON = (1),
+    MK_MBUTTON = (16),
+    MK_RBUTTON = (2),
+    MK_SHIFT = (4),
+    CS_BYTEALIGNCLIENT = (4096),
+    CS_BYTEALIGNWINDOW = (8192),
+    CS_CLASSDC = (64),
+    CS_DBLCLKS = (8),
+    CS_GLOBALCLASS = (16384),
+    CS_HREDRAW = (2),
+    CS_KEYCVTWINDOW = (4),
+    CS_NOCLOSE = (512),
+    CS_NOKEYCVT = (256),
+    CS_OWNDC = (32),
+    CS_PARENTDC = (128),
+    CS_SAVEBITS = (2048),
+    CS_VREDRAW = (1),
+    DLGWINDOWEXTRA = (30),
+    FALT = (16),
+    FCONTROL = (8),
+    FNOINVERT = (2),
+    FSHIFT = (4),
+    FVIRTKEY = (1),
+    MIIM_CHECKMARKS = (8),
+    MIIM_DATA = (32),
+    MIIM_ID = (2),
+    MIIM_STATE = (1),
+    MIIM_SUBMENU = (4),
+    MIIM_TYPE = (16),
+    MFT_BITMAP = (0x4),
+    MFT_MENUBARBREAK = (0x20),
+    MFT_MENUBREAK = (0x40),
+    MFT_OWNERDRAW = (0x100),
+    MFT_RADIOCHECK = (0x200),
+    MFT_RIGHTJUSTIFY = (0x4000),
+    MFT_SEPARATOR = (0x800),
+    MFT_STRING = (0),
+    MFS_CHECKED = (0x8),
+    MFS_DEFAULT = (0x1000),
+    MFS_DISABLED = (0x3),
+    MFS_ENABLED = (0),
+    MFS_GRAYED = (0x3),
+    MFS_HILITE = (0x80),
+    MFS_UNCHECKED = (0),
+    MFS_UNHILITE = (0),
+    SERKF_AVAILABLE = (2),
+    SERKF_INDICATOR = (4),
+    SERKF_SERIALKEYSON = (1),
+    FKF_AVAILABLE = (2),
+    FKF_CLICKON = (64),
+    FKF_FILTERKEYSON = (1),
+    FKF_HOTKEYACTIVE = (4),
+    FKF_HOTKEYSOUND = (16),
+    FKF_CONFIRMHOTKEY = (8),
+    FKF_INDICATOR = (32),
+    HELPINFO_MENUITEM = (2),
+    HELPINFO_WINDOW = (1),
+    PRF_CHECKVISIBLE = (0x1),
+    PRF_CHILDREN = (0x10),
+    PRF_CLIENT = (0x4),
+    PRF_ERASEBKGND = (0x8),
+    PRF_NONCLIENT = (0x2),
+    PRF_OWNED = (0x20),
+    SC_CLOSE = (61536),
+    SC___FILE__HELP = (61824),
+    SC_DEFAULT = (61792),
+    SC_HOTKEY = (61776),
+    SC_HSCROLL = (61568),
+    SC_KEYMENU = (61696),
+    SC_MAXIMIZE = (61488),
+    SC_ZOOM = (61488),
+    SC_MINIMIZE = (61472),
+    SC_ICON = (61472),
+    SC_MONITORPOWER = (61808),
+    SC_MOUSEMENU = (61584),
+    SC_MOVE = (61456),
+    SC_NEXTWINDOW = (61504),
+    SC_PREVWINDOW = (61520),
+    SC_RESTORE = (61728),
+    SC_SCREENSAVE = (61760),
+    SC_SIZE = (61440),
+    SC_TASKLIST = (61744),
+    SC_VSCROLL = (61552),
+    DC_HASDEFID = (21323),
+    DLGC_BUTTON = (8192),
+    DLGC_DEFPUSHBUTTON = (16),
+    DLGC_HASSETSEL = (8),
+    DLGC_RADIOBUTTON = (64),
+    DLGC_STATIC = (256),
+    DLGC_UNDEFPUSHBUTTON = (32),
+    DLGC_WANTALLKEYS = (4),
+    DLGC_WANTARROWS = (1),
+    DLGC_WANTCHARS = (128),
+    DLGC_WANTMESSAGE = (4),
+    DLGC_WANTTAB = (2),
+    EC_LEFTMARGIN = (1),
+    EC_RIGHTMARGIN = (2),
+    EC_USEFONTINFO = (65535),
+    LB_ERR = -((1)),
+    LB_ERRSPACE = -((2)),
+    LB_OKAY = (0),
+    CB_ERR = -((1)),
+    CB_ERRSPACE = -((2)),
+    IMC_GETCANDIDATEPOS = (7),
+    IMC_GETCOMPOSITIONFONT = (9),
+    IMC_GETCOMPOSITIONWINDOW = (11),
+    IMC_GETSTATUSWINDOWPOS = (15),
+    IMC_CLOSESTATUSWINDOW = (33),
+    IMC_OPENSTATUSWINDOW = (34),
+    IMC_SETCANDIDATEPOS = (8),
+    IMC_SETCOMPOSITIONFONT = (10),
+    IMC_SETCOMPOSITIONWINDOW = (12),
+    IMC_SETSTATUSWINDOWPOS = (16),
+    IMN_CHANGECANDIDATE = (3),
+    IMN_CLOSECANDIDATE = (4),
+    IMN_CLOSESTATUSWINDOW = (1),
+    IMN_GUIDELINE = (13),
+    IMN_OPENCANDIDATE = (5),
+    IMN_OPENSTATUSWINDOW = (2),
+    IMN_SETCANDIDATEPOS = (9),
+    IMN_SETCOMPOSITIONFONT = (10),
+    IMN_SETCOMPOSITIONWINDOW = (11),
+    IMN_SETCONVERSIONMODE = (6),
+    IMN_SETOPENSTATUS = (8),
+    IMN_SETSENTENCEMODE = (7),
+    IMN_SETSTATUSWINDOWPOS = (12),
+    IMN_PRIVATE = (14),
+    SKF_AUDIBLEFEEDBACK = (64),
+    SKF_AVAILABLE = (2),
+    SKF_CONFIRMHOTKEY = (8),
+    SKF_HOTKEYACTIVE = (4),
+    SKF_HOTKEYSOUND = (16),
+    SKF_INDICATOR = (32),
+    SKF_STICKYKEYSON = (1),
+    SKF_TRISTATE = (128),
+    SKF_TWOKEYSOFF = (256),
+    MKF_AVAILABLE = (2),
+    MKF_CONFIRMHOTKEY = (8),
+    MKF_HOTKEYACTIVE = (4),
+    MKF_HOTKEYSOUND = (16),
+    MKF_INDICATOR = (32),
+    MKF_MOUSEKEYSON = (1),
+    MKF_MODIFIERS = (64),
+    MKF_REPLACENUMBERS = (128),
+    SSF_AVAILABLE = (2),
+    SSF_SOUNDSENTRYON = (1),
+    SSTF_BORDER = (2),
+    SSTF_CHARS = (1),
+    SSTF_DISPLAY = (3),
+    SSTF_NONE = (0),
+    SSGF_DISPLAY = (3),
+    SSGF_NONE = (0),
+    SSWF_CUSTOM = (4),
+    SSWF_DISPLAY = (3),
+    SSWF_NONE = (0),
+    SSWF_TITLE = (1),
+    SSWF_WINDOW = (2),
+    ATF_ONOFFFEEDBACK = (2),
+    ATF_TIMEOUTON = (1),
+    HCF_AVAILABLE = (2),
+    HCF_CONFIRMHOTKEY = (8),
+    HCF_HIGHCONTRASTON = (1),
+    HCF_HOTKEYACTIVE = (4),
+    HCF_HOTKEYAVAILABLE = (64),
+    HCF_HOTKEYSOUND = (16),
+    HCF_INDICATOR = (32),
+    TKF_AVAILABLE = (2),
+    TKF_CONFIRMHOTKEY = (8),
+    TKF_HOTKEYACTIVE = (4),
+    TKF_HOTKEYSOUND = (16),
+    TKF_TOGGLEKEYSON = (1),
+    PP_DISPLAYERRORS = (1),
+    RESOURCEDISPLAYTYPE_DOMAIN = (1),
+    RESOURCEDISPLAYTYPE_FILE = (4),
+    RESOURCEDISPLAYTYPE_GENERIC = (0),
+    RESOURCEDISPLAYTYPE_GROUP = (5),
+    RESOURCEDISPLAYTYPE_SERVER = (2),
+    RESOURCEDISPLAYTYPE_SHARE = (3),
+    CAPSLOCK_ON = (128),
+    ENHANCED_KEY = (256),
+    LEFT_ALT_PRESSED = (2),
+    LEFT_CTRL_PRESSED = (8),
+    NUMLOCK_ON = (32),
+    RIGHT_ALT_PRESSED = (1),
+    RIGHT_CTRL_PRESSED = (4),
+    SCROLLLOCK_ON = (64),
+    SHIFT_PRESSED = (16),
+    FROM_LEFT_1ST_BUTTON_PRESSED = (1),
+    RIGHTMOST_BUTTON_PRESSED = (2),
+    FROM_LEFT_2ND_BUTTON_PRESSED = (4),
+    FROM_LEFT_3RD_BUTTON_PRESSED = (8),
+    FROM_LEFT_4TH_BUTTON_PRESSED = (16),
+    DOUBLE_CLICK = (2),
+    MOUSE_MOVED = (1),
+    KEY_EVENT = (1),
+    _MOUSE_EVENT = (2),
+    cMOUSE_EVENT = (2),
+    WINDOW_BUFFER_SIZE_EVENT = (4),
+    MENU_EVENT = (8),
+    FOCUS_EVENT = (16),
+    BI_RGB = (0),
+    BI_RLE8 = (1),
+    BI_RLE4 = (2),
+    BI_BITFIELDS = (3),
+    PFD_DRAW_TO_WINDOW = (0x4),
+    PFD_DRAW_TO_BITMAP = (0x8),
+    PFD_SUPPORT_GDI = (0x10),
+    PFD_SUPPORT_OPENGL = (0x20),
+    PFD_DOUBLEBUFFER = (0x1),
+    PFD_STEREO = (0x2),
+    PFD_DOUBLEBUFFER_DONTCARE = (0x40000000),
+    PFD_STEREO_DONTCARE = (0x80000000),
+    PFD_TYPE_RGBA = (0),
+    PFD_TYPE_COLORINDEX = (1),
+    PFD_MAIN_PLANE = (0),
+    PFD_OVERLAY_PLANE = (1),
+    PFD_UNDERLAY_PLANE = -((1)),
+    WGL_FONT_LINES = (0),
+    WGL_FONT_POLYGONS = (1),
+    PFD_GENERIC_FORMAT = (0x40),
+    PFD_NEED_PALETTE = (0x80),
+    PFD_NEED_SYSTEM_PALETTE = (0x100),
+    PFD_SWAP_COPY = (0x400),
+    PFD_SWAP_EXCHANGE = (0x200),
+    TMPF_FIXED_PITCH = (0x1),
+    TMPF_VECTOR = (0x2),
+    TMPF_TRUETYPE = (0x4),
+    TMPF_DEVICE = (0x8),
+    SE_ERR_SHARE = (26),
+    SE_ERR_ASSOCINCOMPLETE = (27),
+    SE_ERR_DDETIMEOUT = (28),
+    SE_ERR_DDEFAIL = (29),
+    SE_ERR_DDEBUSY = (30),
+    SE_ERR_NOASSOC = (31),
+    XCLASS_BOOL = (0x1000),
+    XCLASS_DATA = (0x2000),
+    XCLASS_FLAGS = (0x4000),
+    XCLASS_MASK = (0xfc00),
+    XCLASS_NOTIFICATION = (0x8000),
+    XTYPF_NOBLOCK = (0x0002),
+    XTYP_ADVDATA = (0x4010),
+    XTYP_ADVREQ = (0x2022),
+    XTYP_ADVSTART = (0x1030),
+    XTYP_ADVSTOP = (0x8040),
+    XTYP_CONNECT = (0x1062),
+    XTYP_CONNECT_CONFIRM = (0x8072),
+    XTYP_DISCONNECT = (0x80c2),
+    XTYP_EXECUTE = (0x4050),
+    XTYP_POKE = (0x4090),
+    XTYP_REQUEST = (0x20b0),
+    XTYP_WILDCONNECT = (0x20E2),
+    XTYP_REGISTER = (0x80A2),
+    XTYP_ERROR = (0x8002),
+    XTYP_XACT_COMPLETE = (0x8080),
+    XTYP_UNREGISTER = (0x80D2),
+    DMLERR_DLL_USAGE = (0x4004),
+    DMLERR_INVALIDPARAMETER = (0x4006),
+    DMLERR_NOTPROCESSED = (0x4009),
+    DMLERR_POSTMSG_FAILED = (0x400c),
+    DMLERR_SERVER_DIED = (0x400e),
+    DMLERR_SYS_ERROR = (0x400f),
+    DMLERR_BUSY = (0x4001),
+    DMLERR_DATAACKTIMEOUT = (0x4002),
+    DMLERR_ADVACKTIMEOUT = (0x4000),
+    DMLERR_DLL_NOT_INITIALIZED = (0x4003),
+    DMLERR_LOW_MEMORY = (0x4007),
+    DMLERR_MEMORY_ERROR = (0x4008),
+    DMLERR_POKEACKTIMEOUT = (0x400b),
+    DMLERR_NO_CONV_ESTABLISHED = (0x400a),
+    DMLERR_REENTRANCY = (0x400d),
+    DMLERR_UNFOUND_QUEUE_ID = (0x4011),
+    DMLERR_UNADVACKTIMEOUT = (0x4010),
+    DMLERR_EXECACKTIMEOUT = (0x4005),
+    DDE_FACK = (0x8000),
+    DDE_FNOTPROCESSED = (0x0000),
+    DNS_REGISTER = (0x0001),
+    DNS_UNREGISTER = (0x0002),
+    CP_WINANSI = (1004),
+    CP_WINUNICODE = (1200),
+    APPCLASS_STANDARD = (0x00000000),
+    BKMODE_LAST = (2),
+    CTLCOLOR_MSGBOX = (0),
+    CTLCOLOR_EDIT = (1),
+    CTLCOLOR_LISTBOX = (2),
+    CTLCOLOR_BTN = (3),
+    CTLCOLOR_DLG = (4),
+    CTLCOLOR_SCROLLBAR = (5),
+    CTLCOLOR_STATIC = (6),
+    CTLCOLOR_MAX = (7),
+    META_SETMAPMODE = (0x0103),
+    META_SETWINDOWORG = (0x020B),
+    META_SETWINDOWEXT = (0x020C),
+    POLYFILL_LAST = (2),
+    STATUS_WAIT_0 = (0x00000000),
+    STATUS_ABANDONED_WAIT_0 = (0x00000080),
+    STATUS_USER_APC = (0x000000C0),
+    STATUS_TIMEOUT = (0x00000102),
+    STATUS_PENDING = (0x00000103),
+    STATUS_GUARD_PAGE_VIOLATION = (0x80000001),
+    STATUS_DATATYPE_MISALIGNMENT = (0x80000002),
+    STATUS_BREAKPOINT = (0x80000003),
+    STATUS_SINGLE_STEP = (0x80000004),
+    STATUS_IN_PAGE_ERROR = (0xC0000006),
+    STATUS_INVALID_HANDLE = (0xC0000008),
+    STATUS_ILLEGAL_INSTRUCTION = (0xC000001D),
+    STATUS_NONCONTINUABLE_EXCEPTION = (0xC0000025),
+    STATUS_INVALID_DISPOSITION = (0xC0000026),
+    STATUS_ARRAY_BOUNDS_EXCEEDED = (0xC000008C),
+    STATUS_FLOAT_DENORMAL_OPERAND = (0xC000008D),
+    STATUS_FLOAT_DIVIDE_BY_ZERO = (0xC000008E),
+    STATUS_FLOAT_INEXACT_RESULT = (0xC000008F),
+    STATUS_FLOAT_INVALID_OPERATION = (0xC0000090),
+    STATUS_FLOAT_OVERFLOW = (0xC0000091),
+    STATUS_FLOAT_STACK_CHECK = (0xC0000092),
+    STATUS_FLOAT_UNDERFLOW = (0xC0000093),
+    STATUS_INTEGER_DIVIDE_BY_ZERO = (0xC0000094),
+    STATUS_INTEGER_OVERFLOW = (0xC0000095),
+    STATUS_PRIVILEGED_INSTRUCTION = (0xC0000096),
+    STATUS_STACK_OVERFLOW = (0xC00000FD),
+    STATUS_CONTROL_C_EXIT = (0xC000013A),
+    PROCESSOR_ARCHITECTURE_INTEL = (0),
+    PROCESSOR_ARCHITECTURE_MIPS = (1),
+    PROCESSOR_ARCHITECTURE_ALPHA = (2),
+    PROCESSOR_ARCHITECTURE_PPC = (3),
+    SIZEFULLSCREEN = (SIZE_MAXIMIZED),
+    SIZENORMAL = (SIZE_RESTORED),
+    SIZEICONIC = (SIZE_MINIMIZED),
+    SIZE_OF_80387_REGISTERS = (80),
+    __FILE___i386 = (0x10000),
+    __FILE___CONTROL = (__FILE___i386) | (1),
+    __FILE___INTEGER = (__FILE___i386) | (2),
+    __FILE___SEGMENTS = (__FILE___i386) | (4),
+    __FILE___FLOATING_POINT = (__FILE___i386) | (8),
+    __FILE___DEBUG_REGISTERS = (__FILE___i386) | (0x10),
+    __FILE___FULL = ((__FILE___CONTROL) | (__FILE___INTEGER)) | (__FILE___SEGMENTS),
+    FLAG_TRACE_BIT = (0x100),
+    __FILE___DEBUGGER = (__FILE___FULL) | (__FILE___FLOATING_POINT),
+    FILTER_TEMP_DUPLICATE_ACCOUNT = (0x0001),
+    FILTER_NORMAL_ACCOUNT = (0x0002),
+    FILTER_INTERDOMAIN_TRUST_ACCOUNT = (0x0008),
+    FILTER_WORKSTATION_TRUST_ACCOUNT = (0x0010),
+    FILTER_SERVER_TRUST_ACCOUNT = (0x0020),
+    LOGON32_LOGON_INTERACTIVE = (0x02),
+    LOGON32_LOGON_BATCH = (0x04),
+    LOGON32_LOGON_SERVICE = (0x05),
+    LOGON32_PROVIDER_DEFAULT = (0x00),
+    LOGON32_PROVIDER_WINNT35 = (0x01),
+    QID_SYNC = (0xFFFFFFFF),
+    IMAGE_DOS_SIGNATURE = (0x5a4d),
+    IMAGE_NT_SIGNATURE = (0x4550),
+    SEVERITY_SUCCESS = (0),
+    SEVERITY_ERROR = (1),
+    VT_EMPTY = (0),
+    VT_NULL = (1),
+    VT_I2 = (2),
+    VT_I4 = (3),
+    VT_R4 = (4),
+    VT_R8 = (5),
+    VT_BSTR = (8),
+    VT_ERROR = (10),
+    VT_BOOL = (11),
+    VT_UI1 = (17),
+    VT_BYREF = (0x4000),
+    VT_RESERVED = (0x8000),
+    FACILITY_WINDOWS = (8),
+    FACILITY_STORAGE = (3),
+    FACILITY_RPC = (1),
+    FACILITY_SSPI = (9),
+    FACILITY_WIN32 = (7),
+    FACILITY_CONTROL = (10),
+    FACILITY_NULL = (0),
+    FACILITY_INTERNET = (12),
+    FACILITY_ITF = (4),
+    FACILITY_DISPATCH = (2),
+    FACILITY_CERT = (11),
+    ACM_OPENW = (1127),
+    ACM_OPENA = (1124),
+    ACM_OPEN = (ACM_OPENA),
+    ACM_PLAY = (1125),
+    ACM_STOP = (1126),
+    ACN_START = (1),
+    ACN_STOP = (2),
+    BM_CLICK = (245),
+    BM_GETCHECK = (240),
+    BM_GETIMAGE = (246),
+    BM_GETSTATE = (242),
+    BM_SETCHECK = (241),
+    BM_SETIMAGE = (247),
+    BM_SETSTATE = (243),
+    BM_SETSTYLE = (244),
+    BN_CLICKED = (0),
+    BN_DBLCLK = (5),
+    BN_DISABLE = (4),
+    BN_DOUBLECLICKED = (5),
+    BN_HILITE = (2),
+    BN_KILLFOCUS = (7),
+    BN_PAINT = (1),
+    BN_PUSHED = (2),
+    BN_SETFOCUS = (6),
+    BN_UNHILITE = (3),
+    BN_UNPUSHED = (3),
+    CB_ADDSTRING = (323),
+    CB_DELETESTRING = (324),
+    CB_DIR = (325),
+    CB_FINDSTRING = (332),
+    CB_FINDSTRINGEXACT = (344),
+    CB_GETCOUNT = (326),
+    CB_GETCURSEL = (327),
+    CB_GETDROPPEDCONTROLRECT = (338),
+    CB_GETDROPPEDSTATE = (343),
+    CB_GETDROPPEDWIDTH = (351),
+    CB_GETEDITSEL = (320),
+    CB_GETEXTENDEDUI = (342),
+    CB_GETHORIZONTALEXTENT = (349),
+    CB_GETITEMDATA = (336),
+    CB_GETITEMHEIGHT = (340),
+    CB_GETLBTEXT = (328),
+    CB_GETLBTEXTLEN = (329),
+    CB_GETLOCALE = (346),
+    CB_GETTOPINDEX = (347),
+    CB_INITSTORAGE = (353),
+    CB_INSERTSTRING = (330),
+    CB_LIMITTEXT = (321),
+    CB_RESETCONTENT = (331),
+    CB_SELECTSTRING = (333),
+    CB_SETCURSEL = (334),
+    CB_SETDROPPEDWIDTH = (352),
+    CB_SETEDITSEL = (322),
+    CB_SETEXTENDEDUI = (341),
+    CB_SETHORIZONTALEXTENT = (350),
+    CB_SETITEMDATA = (337),
+    CB_SETITEMHEIGHT = (339),
+    CB_SETLOCALE = (345),
+    CB_SETTOPINDEX = (348),
+    CB_SHOWDROPDOWN = (335),
+    CBN_CLOSEUP = (8),
+    CBN_DBLCLK = (2),
+    CBN_DROPDOWN = (7),
+    CBN_EDITCHANGE = (5),
+    CBN_EDITUPDATE = (6),
+    CBN_ERRSPACE = -((1)),
+    CBN_KILLFOCUS = (4),
+    CBN_SELCHANGE = (1),
+    CBN_SELENDCANCEL = (10),
+    CBN_SELENDOK = (9),
+    CBN_SETFOCUS = (3),
+    DL_BEGINDRAG = (1157),
+    DL_CANCELDRAG = (1160),
+    DL_DRAGGING = (1158),
+    DL_DROPPED = (1159),
+    DM_GETDEFID = (1024),
+    DM_REPOSITION = (1026),
+    DM_SETDEFID = (1025),
+    EM_CANPASTE = (1074),
+    EM_CANUNDO = (198),
+    EM_CHARFROMPOS = (215),
+    EM_DISPLAYBAND = (1075),
+    EM_EMPTYUNDOBUFFER = (205),
+    EM_EXGETSEL = (1076),
+    EM_EXLIMITTEXT = (1077),
+    EM_EXLINEFROMCHAR = (1078),
+    EM_EXSETSEL = (1079),
+    EM_FINDTEXT = (1080),
+    EM_FINDTEXTEX = (1103),
+    EM_FINDWORDBREAK = (1100),
+    EM_FMTLINES = (200),
+    EM_FORMATRANGE = (1081),
+    EM_GETCHARFORMAT = (1082),
+    EM_GETEVENTMASK = (1083),
+    EM_GETFIRSTVISIBLELINE = (206),
+    EM_GETHANDLE = (189),
+    EM_GETLIMITTEXT = (213),
+    EM_GETLINE = (196),
+    EM_GETLINECOUNT = (186),
+    EM_GETMARGINS = (212),
+    EM_GETMODIFY = (184),
+    EM_GETIMECOLOR = (1129),
+    EM_GETIMEOPTIONS = (1131),
+    EM_GETOPTIONS = (1102),
+    EM_GETOLEINTERFACE = (1084),
+    EM_GETPARAFORMAT = (1085),
+    EM_GETPASSWORDCHAR = (210),
+    EM_GETPUNCTUATION = (1125),
+    EM_GETRECT = (178),
+    EM_GETSEL = (176),
+    EM_GETSELTEXT = (1086),
+    EM_GETTEXTRANGE = (1099),
+    EM_GETTHUMB = (190),
+    EM_GETWORDBREAKPROC = (209),
+    EM_GETWORDBREAKPROCEX = (1104),
+    EM_GETWORDWRAPMODE = (1127),
+    EM_HIDESELECTION = (1087),
+    EM_LIMITTEXT = (197),
+    EM_LINEFROMCHAR = (201),
+    EM_LINEINDEX = (187),
+    EM_LINELENGTH = (193),
+    EM_LINESCROLL = (182),
+    EM_PASTESPECIAL = (1088),
+    EM_POSFROMCHAR = (214),
+    EM_REPLACESEL = (194),
+    EM_REQUESTRESIZE = (1089),
+    EM_SCROLL = (181),
+    EM_SCROLLCARET = (183),
+    EM_SELECTIONTYPE = (1090),
+    EM_SETBKGNDCOLOR = (1091),
+    EM_SETCHARFORMAT = (1092),
+    EM_SETEVENTMASK = (1093),
+    EM_SETHANDLE = (188),
+    EM_SETIMECOLOR = (1128),
+    EM_SETIMEOPTIONS = (1130),
+    EM_SETLIMITTEXT = (197),
+    EM_SETMARGINS = (211),
+    EM_SETMODIFY = (185),
+    EM_SETOLECALLBACK = (1094),
+    EM_SETOPTIONS = (1101),
+    EM_SETPARAFORMAT = (1095),
+    EM_SETPASSWORDCHAR = (204),
+    EM_SETPUNCTUATION = (1124),
+    EM_SETREADONLY = (207),
+    EM_SETRECT = (179),
+    EM_SETRECTNP = (180),
+    EM_SETSEL = (177),
+    EM_SETTABSTOPS = (203),
+    EM_SETTARGETDEVICE = (1096),
+    EM_SETWORDBREAKPROC = (208),
+    EM_SETWORDBREAKPROCEX = (1105),
+    EM_SETWORDWRAPMODE = (1126),
+    EM_STREAMIN = (1097),
+    EM_STREAMOUT = (1098),
+    EM_UNDO = (199),
+    EN_CHANGE = (768),
+    EN_CORRECTTEXT = (1797),
+    EN_DROPFILES = (1795),
+    EN_ERRSPACE = (1280),
+    EN_HSCROLL = (1537),
+    EN_IMECHANGE = (1799),
+    EN_KILLFOCUS = (512),
+    EN_MAXTEXT = (1281),
+    EN_MSGFILTER = (1792),
+    EN_OLEOPFAILED = (1801),
+    EN_PROTECTED = (1796),
+    EN_REQUESTRESIZE = (1793),
+    EN_SAVECLIPBOARD = (1800),
+    EN_SELCHANGE = (1794),
+    EN_SETFOCUS = (256),
+    EN_STOPNOUNDO = (1798),
+    EN_UPDATE = (1024),
+    EN_VSCROLL = (1538),
+    HDM_DELETEITEM = (4610),
+    HDM_GETITEMW = (4619),
+    HDM_INSERTITEMW = (4618),
+    HDM_SETITEMW = (4620),
+    HDM_GETITEMA = (4611),
+    HDM_INSERTITEMA = (4609),
+    HDM_SETITEMA = (4612),
+    HDM_GETITEM = (HDM_GETITEMA),
+    HDM_INSERTITEM = (HDM_INSERTITEMA),
+    HDM_SETITEM = (HDM_SETITEMA),
+    HDM_GETITEMCOUNT = (4608),
+    HDM_HITTEST = (4614),
+    HDM_LAYOUT = (4613),
+    HDN_BEGINTRACKW = -((326)),
+    HDN_DIVIDERDBLCLICKW = -((325)),
+    HDN_ENDTRACKW = -((327)),
+    HDN_ITEMCHANGEDW = -((321)),
+    HDN_ITEMCHANGINGW = -((320)),
+    HDN_ITEMCLICKW = -((322)),
+    HDN_ITEMDBLCLICKW = -((323)),
+    HDN_TRACKW = -((328)),
+    HDN_BEGINTRACKA = -((306)),
+    HDN_DIVIDERDBLCLICKA = -((305)),
+    HDN_ENDTRACKA = -((307)),
+    HDN_ITEMCHANGEDA = -((301)),
+    HDN_ITEMCHANGINGA = -((300)),
+    HDN_ITEMCLICKA = -((302)),
+    HDN_ITEMDBLCLICKA = -((303)),
+    HDN_TRACKA = -((308)),
+    HDN_BEGINTRACK = (HDN_BEGINTRACKA),
+    HDN_DIVIDERDBLCLICK = (HDN_DIVIDERDBLCLICKA),
+    HDN_ENDTRACK = (HDN_ENDTRACKA),
+    HDN_ITEMCHANGED = (HDN_ITEMCHANGEDA),
+    HDN_ITEMCHANGING = (HDN_ITEMCHANGINGA),
+    HDN_ITEMCLICK = (HDN_ITEMCLICKA),
+    HDN_ITEMDBLCLICK = (HDN_ITEMDBLCLICKA),
+    HDN_TRACK = (HDN_TRACKA),
+    HKM_GETHOTKEY = (1026),
+    HKM_SETHOTKEY = (1025),
+    HKM_SETRULES = (1027),
+    LB_ADDFILE = (406),
+    LB_ADDSTRING = (384),
+    LB_DELETESTRING = (386),
+    LB_DIR = (397),
+    LB_FINDSTRING = (399),
+    LB_FINDSTRINGEXACT = (418),
+    LB_GETANCHORINDEX = (413),
+    LB_GETCARETINDEX = (415),
+    LB_GETCOUNT = (395),
+    LB_GETCURSEL = (392),
+    LB_GETHORIZONTALEXTENT = (403),
+    LB_GETITEMDATA = (409),
+    LB_GETITEMHEIGHT = (417),
+    LB_GETITEMRECT = (408),
+    LB_GETLOCALE = (422),
+    LB_GETSEL = (391),
+    LB_GETSELCOUNT = (400),
+    LB_GETSELITEMS = (401),
+    LB_GETTEXT = (393),
+    LB_GETTEXTLEN = (394),
+    LB_GETTOPINDEX = (398),
+    LB_INITSTORAGE = (424),
+    LB_INSERTSTRING = (385),
+    LB_ITEMFROMPOINT = (425),
+    LB_RESETCONTENT = (388),
+    LB_SELECTSTRING = (396),
+    LB_SELITEMRANGE = (411),
+    LB_SELITEMRANGEEX = (387),
+    LB_SETANCHORINDEX = (412),
+    LB_SETCARETINDEX = (414),
+    LB_SETCOLUMNWIDTH = (405),
+    LB_SETCOUNT = (423),
+    LB_SETCURSEL = (390),
+    LB_SETHORIZONTALEXTENT = (404),
+    LB_SETITEMDATA = (410),
+    LB_SETITEMHEIGHT = (416),
+    LB_SETLOCALE = (421),
+    LB_SETSEL = (389),
+    LB_SETTABSTOPS = (402),
+    LB_SETTOPINDEX = (407),
+    LBN_DBLCLK = (2),
+    LBN_ERRSPACE = -((2)),
+    LBN_KILLFOCUS = (5),
+    LBN_SELCANCEL = (3),
+    LBN_SELCHANGE = (1),
+    LBN_SETFOCUS = (4),
+    LVM_ARRANGE = (4118),
+    LVM_CREATEDRAGIMAGE = (4129),
+    LVM_DELETEALLITEMS = (4105),
+    LVM_DELETECOLUMN = (4124),
+    LVM_DELETEITEM = (4104),
+    LVM_ENSUREVISIBLE = (4115),
+    LVM_GETBKCOLOR = (4096),
+    LVM_GETCALLBACKMASK = (4106),
+    LVM_GETCOLUMNWIDTH = (4125),
+    LVM_GETCOUNTPERPAGE = (4136),
+    LVM_GETEDITCONTROL = (4120),
+    LVM_GETIMAGELIST = (4098),
+    LVM_EDITLABELW = (4214),
+    LVM_FINDITEMW = (4179),
+    LVM_GETCOLUMNW = (4191),
+    LVM_GETISEARCHSTRINGW = (4213),
+    LVM_GETITEMW = (4171),
+    LVM_GETITEMTEXTW = (4211),
+    LVM_GETSTRINGWIDTHW = (4183),
+    LVM_INSERTCOLUMNW = (4193),
+    LVM_INSERTITEMW = (4173),
+    LVM_SETCOLUMNW = (4192),
+    LVM_SETITEMW = (4172),
+    LVM_SETITEMTEXTW = (4212),
+    LVM_EDITLABELA = (4119),
+    LVM_FINDITEMA = (4109),
+    LVM_GETCOLUMNA = (4121),
+    LVM_GETISEARCHSTRINGA = (4148),
+    LVM_GETITEMA = (4101),
+    LVM_GETITEMTEXTA = (4141),
+    LVM_GETSTRINGWIDTHA = (4113),
+    LVM_INSERTCOLUMNA = (4123),
+    LVM_INSERTITEMA = (4103),
+    LVM_SETCOLUMNA = (4122),
+    LVM_SETITEMA = (4102),
+    LVM_SETITEMTEXTA = (4142),
+    LVM_EDITLABEL = (LVM_EDITLABELA),
+    LVM_FINDITEM = (LVM_FINDITEMA),
+    LVM_GETCOLUMN = (LVM_GETCOLUMNA),
+    LVM_GETISEARCHSTRING = (LVM_GETISEARCHSTRINGA),
+    LVM_GETITEM = (LVM_GETITEMA),
+    LVM_GETITEMTEXT = (LVM_GETITEMTEXTA),
+    LVM_GETSTRINGWIDTH = (LVM_GETSTRINGWIDTHA),
+    LVM_INSERTCOLUMN = (LVM_INSERTCOLUMNA),
+    LVM_INSERTITEM = (LVM_INSERTITEMA),
+    LVM_SETCOLUMN = (LVM_SETCOLUMNA),
+    LVM_SETITEM = (LVM_SETITEMA),
+    LVM_SETITEMTEXT = (LVM_SETITEMTEXTA),
+    LVM_GETITEMCOUNT = (4100),
+    LVM_GETITEMPOSITION = (4112),
+    LVM_GETITEMRECT = (4110),
+    LVM_GETITEMSPACING = (4147),
+    LVM_GETITEMSTATE = (4140),
+    LVM_GETNEXTITEM = (4108),
+    LVM_GETORIGIN = (4137),
+    LVM_GETSELECTEDCOUNT = (4146),
+    LVM_GETTEXTBKCOLOR = (4133),
+    LVM_GETTEXTCOLOR = (4131),
+    LVM_GETTOPINDEX = (4135),
+    LVM_GETVIEWRECT = (4130),
+    LVM_HITTEST = (4114),
+    LVM_REDRAWITEMS = (4117),
+    LVM_SCROLL = (4116),
+    LVM_SETBKCOLOR = (4097),
+    LVM_SETCALLBACKMASK = (4107),
+    LVM_SETCOLUMNWIDTH = (4126),
+    LVM_SETIMAGELIST = (4099),
+    LVM_SETITEMCOUNT = (4143),
+    LVM_SETITEMPOSITION = (4111),
+    LVM_SETITEMPOSITION32 = (4145),
+    LVM_SETITEMSTATE = (4139),
+    LVM_SETTEXTBKCOLOR = (4134),
+    LVM_SETTEXTCOLOR = (4132),
+    LVM_SORTITEMS = (4144),
+    LVM_UPDATE = (4138),
+    LVN_BEGINDRAG = -((109)),
+    LVN_BEGINRDRAG = -((111)),
+    LVN_COLUMNCLICK = -((108)),
+    LVN_DELETEALLITEMS = -((104)),
+    LVN_DELETEITEM = -((103)),
+    LVN_BEGINLABELEDITW = -((175)),
+    LVN_ENDLABELEDITW = -((176)),
+    LVN_GETDISPINFOW = -((177)),
+    LVN_SETDISPINFOW = -((178)),
+    LVN_BEGINLABELEDITA = -((105)),
+    LVN_ENDLABELEDITA = -((106)),
+    LVN_GETDISPINFOA = -((150)),
+    LVN_SETDISPINFOA = -((151)),
+    LVN_BEGINLABELEDIT = (LVN_BEGINLABELEDITA),
+    LVN_ENDLABELEDIT = (LVN_ENDLABELEDITA),
+    LVN_GETDISPINFO = (LVN_GETDISPINFOA),
+    LVN_SETDISPINFO = (LVN_SETDISPINFOA),
+    LVN_INSERTITEM = -((102)),
+    LVN_ITEMCHANGED = -((101)),
+    LVN_ITEMCHANGING = -((100)),
+    LVN_KEYDOWN = -((155)),
+    NM_CLICK = -((2)),
+    NM_DBLCLK = -((3)),
+    NM_KILLFOCUS = -((8)),
+    NM_OUTOFMEMORY = -((1)),
+    NM_RCLICK = -((5)),
+    NM_RDBLCLK = -((6)),
+    NM_RETURN = -((4)),
+    NM_SETFOCUS = -((7)),
+    PBM_DELTAPOS = (1027),
+    PBM_SETPOS = (1026),
+    PBM_SETRANGE = (1025),
+    PBM_SETSTEP = (1028),
+    PBM_STEPIT = (1029),
+    PSM_ADDPAGE = (1127),
+    PSM_APPLY = (1134),
+    PSM_CANCELTOCLOSE = (1131),
+    PSM_CHANGED = (1128),
+    PSM_GETTABCONTROL = (1140),
+    PSM_GETCURRENTPAGEHWND = (1142),
+    PSM_ISDIALOGMESSAGE = (1141),
+    PSM_PRESSBUTTON = (1137),
+    PSM_QUERYSIBLINGS = (1132),
+    PSM_REBOOTSYSTEM = (1130),
+    PSM_REMOVEPAGE = (1126),
+    PSM_RESTARTWINDOWS = (1129),
+    PSM_SETCURSEL = (1125),
+    PSM_SETCURSELID = (1138),
+    PSM_SETFINISHTEXTW = (1145),
+    PSM_SETTITLEW = (1144),
+    PSM_SETFINISHTEXTA = (1139),
+    PSM_SETTITLEA = (1135),
+    PSM_SETFINISHTEXT = (PSM_SETFINISHTEXTA),
+    PSM_SETTITLE = (PSM_SETTITLEA),
+    PSM_SETWIZBUTTONS = (1136),
+    PSM_UNCHANGED = (1133),
+    PSN_APPLY = -((202)),
+    PSN_HELP = -((205)),
+    PSN_KILLACTIVE = -((201)),
+    PSN_QUERYCANCEL = -((209)),
+    PSN_RESET = -((203)),
+    PSN_SETACTIVE = -((200)),
+    PSN_WIZBACK = -((206)),
+    PSN_WIZFINISH = -((208)),
+    PSN_WIZNEXT = -((207)),
+    SB_GETBORDERS = (1031),
+    SB_GETPARTS = (1030),
+    SB_GETRECT = (1034),
+    SB_GETTEXTW = (1037),
+    SB_GETTEXTLENGTHW = (1036),
+    SB_SETTEXTW = (1035),
+    SB_GETTEXTA = (1026),
+    SB_GETTEXTLENGTHA = (1027),
+    SB_SETTEXTA = (1025),
+    SB_GETTEXT = (SB_GETTEXTA),
+    SB_GETTEXTLENGTH = (SB_GETTEXTLENGTHA),
+    SB_SETTEXT = (SB_SETTEXTA),
+    SB_SETMINHEIGHT = (1032),
+    SB_SETPARTS = (1028),
+    SB_SIMPLE = (1033),
+    SBM_ENABLE_ARROWS = (228),
+    SBM_GETPOS = (225),
+    SBM_GETRANGE = (227),
+    SBM_GETSCROLLINFO = (234),
+    SBM_SETPOS = (224),
+    SBM_SETRANGE = (226),
+    SBM_SETRANGEREDRAW = (230),
+    SBM_SETSCROLLINFO = (233),
+    STM_GETICON = (369),
+    STM_GETIMAGE = (371),
+    STM_SETICON = (368),
+    STM_SETIMAGE = (370),
+    STN_CLICKED = (0),
+    STN_DBLCLK = (1),
+    STN_DISABLE = (3),
+    STN_ENABLE = (2),
+    TB_ADDBITMAP = (1043),
+    TB_ADDBUTTONS = (1044),
+    TB_AUTOSIZE = (1057),
+    TB_BUTTONCOUNT = (1048),
+    TB_BUTTONSTRUCTSIZE = (1054),
+    TB_CHANGEBITMAP = (1067),
+    TB_CHECKBUTTON = (1026),
+    TB_COMMANDTOINDEX = (1049),
+    TB_CUSTOMIZE = (1051),
+    TB_DELETEBUTTON = (1046),
+    TB_ENABLEBUTTON = (1025),
+    TB_GETBITMAP = (1068),
+    TB_GETBITMAPFLAGS = (1065),
+    TB_GETBUTTON = (1047),
+    TB_ADDSTRINGW = (1101),
+    TB_GETBUTTONTEXTW = (1099),
+    TB_SAVERESTOREW = (1100),
+    TB_ADDSTRINGA = (1052),
+    TB_GETBUTTONTEXTA = (1069),
+    TB_SAVERESTOREA = (1050),
+    TB_ADDSTRING = (TB_ADDSTRINGA),
+    TB_GETBUTTONTEXT = (TB_GETBUTTONTEXTA),
+    TB_SAVERESTORE = (TB_SAVERESTOREA),
+    TB_GETITEMRECT = (1053),
+    TB_GETROWS = (1064),
+    TB_GETSTATE = (1042),
+    TB_GETTOOLTIPS = (1059),
+    TB_HIDEBUTTON = (1028),
+    TB_INDETERMINATE = (1029),
+    TB_INSERTBUTTON = (1045),
+    TB_ISBUTTONCHECKED = (1034),
+    TB_ISBUTTONENABLED = (1033),
+    TB_ISBUTTONHIDDEN = (1036),
+    TB_ISBUTTONINDETERMINATE = (1037),
+    TB_ISBUTTONPRESSED = (1035),
+    TB_PRESSBUTTON = (1027),
+    TB_SETBITMAPSIZE = (1056),
+    TB_SETBUTTONSIZE = (1055),
+    TB_SETCMDID = (1066),
+    TB_SETPARENT = (1061),
+    TB_SETROWS = (1063),
+    TB_SETSTATE = (1041),
+    TB_SETTOOLTIPS = (1060),
+    TBM_CLEARSEL = (1043),
+    TBM_CLEARTICS = (1033),
+    TBM_GETCHANNELRECT = (1050),
+    TBM_GETLINESIZE = (1048),
+    TBM_GETNUMTICS = (1040),
+    TBM_GETPAGESIZE = (1046),
+    TBM_GETPOS = (1024),
+    TBM_GETPTICS = (1038),
+    TBM_GETRANGEMAX = (1026),
+    TBM_GETRANGEMIN = (1025),
+    TBM_GETSELEND = (1042),
+    TBM_GETSELSTART = (1041),
+    TBM_GETTHUMBLENGTH = (1052),
+    TBM_GETTHUMBRECT = (1049),
+    TBM_GETTIC = (1027),
+    TBM_GETTICPOS = (1039),
+    TBM_SETLINESIZE = (1047),
+    TBM_SETPAGESIZE = (1045),
+    TBM_SETPOS = (1029),
+    TBM_SETRANGE = (1030),
+    TBM_SETRANGEMAX = (1032),
+    TBM_SETRANGEMIN = (1031),
+    TBM_SETSEL = (1034),
+    TBM_SETSELEND = (1036),
+    TBM_SETSELSTART = (1035),
+    TBM_SETTHUMBLENGTH = (1051),
+    TBM_SETTIC = (1028),
+    TBM_SETTICFREQ = (1044),
+    TBN_BEGINADJUST = -((703)),
+    TBN_BEGINDRAG = -((701)),
+    TBN_CUSTHELP = -((709)),
+    TBN_ENDADJUST = -((704)),
+    TBN_ENDDRAG = -((702)),
+    TBN_GETBUTTONINFOW = -((720)),
+    TBN_GETBUTTONINFOA = -((700)),
+    TBN_GETBUTTONINFO = (TBN_GETBUTTONINFOA),
+    TBN_QUERYDELETE = -((707)),
+    TBN_QUERYINSERT = -((706)),
+    TBN_RESET = -((705)),
+    TBN_TOOLBARCHANGE = -((708)),
+    TCM_ADJUSTRECT = (4904),
+    TCM_DELETEALLITEMS = (4873),
+    TCM_DELETEITEM = (4872),
+    TCM_GETCURFOCUS = (4911),
+    TCM_GETCURSEL = (4875),
+    TCM_GETIMAGELIST = (4866),
+    TCM_GETITEMW = (4924),
+    TCM_INSERTITEMW = (4926),
+    TCM_SETITEMW = (4925),
+    TCM_GETITEMA = (4869),
+    TCM_INSERTITEMA = (4871),
+    TCM_SETITEMA = (4870),
+    TCM_GETITEM = (TCM_GETITEMA),
+    TCM_INSERTITEM = (TCM_INSERTITEMA),
+    TCM_SETITEM = (TCM_SETITEMA),
+    TCM_GETITEMCOUNT = (4868),
+    TCM_GETITEMRECT = (4874),
+    TCM_GETROWCOUNT = (4908),
+    TCM_GETTOOLTIPS = (4909),
+    TCM_HITTEST = (4877),
+    TCM_REMOVEIMAGE = (4906),
+    TCM_SETCURFOCUS = (4912),
+    TCM_SETCURSEL = (4876),
+    TCM_SETIMAGELIST = (4867),
+    TCM_SETITEMEXTRA = (4878),
+    TCM_SETITEMSIZE = (4905),
+    TCM_SETPADDING = (4907),
+    TCM_SETTOOLTIPS = (4910),
+    TCN_KEYDOWN = -((550)),
+    TCN_SELCHANGE = -((551)),
+    TCN_SELCHANGING = -((552)),
+    TTM_ACTIVATE = (1025),
+    TTM_ADDTOOLW = (1074),
+    TTM_DELTOOLW = (1075),
+    TTM_ENUMTOOLSW = (1082),
+    TTM_GETCURRENTTOOLW = (1083),
+    TTM_GETTEXTW = (1080),
+    TTM_GETTOOLINFOW = (1077),
+    TTM_HITTESTW = (1079),
+    TTM_NEWTOOLRECTW = (1076),
+    TTM_SETTOOLINFOW = (1078),
+    TTM_UPDATETIPTEXTW = (1081),
+    TTM_ADDTOOLA = (1028),
+    TTM_DELTOOLA = (1029),
+    TTM_ENUMTOOLSA = (1038),
+    TTM_GETCURRENTTOOLA = (1039),
+    TTM_GETTEXTA = (1035),
+    TTM_GETTOOLINFOA = (1032),
+    TTM_HITTESTA = (1034),
+    TTM_NEWTOOLRECTA = (1030),
+    TTM_SETTOOLINFOA = (1033),
+    TTM_UPDATETIPTEXTA = (1036),
+    TTM_ADDTOOL = (TTM_ADDTOOLA),
+    TTM_DELTOOL = (TTM_DELTOOLA),
+    TTM_ENUMTOOLS = (TTM_ENUMTOOLSA),
+    TTM_GETCURRENTTOOL = (TTM_GETCURRENTTOOLA),
+    TTM_GETTEXT = (TTM_GETTEXTA),
+    TTM_GETTOOLINFO = (TTM_GETTOOLINFOA),
+    TTM_HITTEST = (TTM_HITTESTA),
+    TTM_NEWTOOLRECT = (TTM_NEWTOOLRECTA),
+    TTM_SETTOOLINFO = (TTM_SETTOOLINFOA),
+    TTM_UPDATETIPTEXT = (TTM_UPDATETIPTEXTA),
+    TTM_GETTOOLCOUNT = (1037),
+    TTM_RELAYEVENT = (1031),
+    TTM_SETDELAYTIME = (1027),
+    TTM_WINDOWFROMPOINT = (1040),
+    TTN_NEEDTEXTW = -((530)),
+    TTN_NEEDTEXTA = -((520)),
+    TTN_NEEDTEXT = (TTN_NEEDTEXTA),
+    TTN_POP = -((522)),
+    TTN_SHOW = -((521)),
+    TVM_CREATEDRAGIMAGE = (4370),
+    TVM_DELETEITEM = (4353),
+    TVM_ENDEDITLABELNOW = (4374),
+    TVM_ENSUREVISIBLE = (4372),
+    TVM_EXPAND = (4354),
+    TVM_GETCOUNT = (4357),
+    TVM_GETEDITCONTROL = (4367),
+    TVM_GETIMAGELIST = (4360),
+    TVM_GETINDENT = (4358),
+    TVM_GETITEMRECT = (4356),
+    TVM_GETNEXTITEM = (4362),
+    TVM_GETVISIBLECOUNT = (4368),
+    TVM_HITTEST = (4369),
+    TVM_EDITLABELW = (4417),
+    TVM_GETISEARCHSTRINGW = (4416),
+    TVM_GETITEMW = (4414),
+    TVM_INSERTITEMW = (4402),
+    TVM_SETITEMW = (4415),
+    TVM_EDITLABELA = (4366),
+    TVM_GETISEARCHSTRINGA = (4375),
+    TVM_GETITEMA = (4364),
+    TVM_INSERTITEMA = (4352),
+    TVM_SETITEMA = (4365),
+    TVM_EDITLABEL = (TVM_EDITLABELA),
+    TVM_GETISEARCHSTRING = (TVM_GETISEARCHSTRINGA),
+    TVM_GETITEM = (TVM_GETITEMA),
+    TVM_INSERTITEM = (TVM_INSERTITEMA),
+    TVM_SETITEM = (TVM_SETITEMA),
+    TVM_SELECTITEM = (4363),
+    TVM_SETIMAGELIST = (4361),
+    TVM_SETINDENT = (4359),
+    TVM_SORTCHILDREN = (4371),
+    TVM_SORTCHILDRENCB = (4373),
+    TVN_KEYDOWN = -((412)),
+    TVN_BEGINDRAGW = -((456)),
+    TVN_BEGINLABELEDITW = -((459)),
+    TVN_BEGINRDRAGW = -((457)),
+    TVN_DELETEITEMW = -((458)),
+    TVN_ENDLABELEDITW = -((460)),
+    TVN_GETDISPINFOW = -((452)),
+    TVN_ITEMEXPANDEDW = -((455)),
+    TVN_ITEMEXPANDINGW = -((454)),
+    TVN_SELCHANGEDW = -((451)),
+    TVN_SELCHANGINGW = -((450)),
+    TVN_SETDISPINFOW = -((453)),
+    TVN_BEGINDRAGA = -((407)),
+    TVN_BEGINLABELEDITA = -((410)),
+    TVN_BEGINRDRAGA = -((408)),
+    TVN_DELETEITEMA = -((409)),
+    TVN_ENDLABELEDITA = -((411)),
+    TVN_GETDISPINFOA = -((403)),
+    TVN_ITEMEXPANDEDA = -((406)),
+    TVN_ITEMEXPANDINGA = -((405)),
+    TVN_SELCHANGEDA = -((402)),
+    TVN_SELCHANGINGA = -((401)),
+    TVN_SETDISPINFOA = -((404)),
+    TVN_BEGINDRAG = (TVN_BEGINDRAGA),
+    TVN_BEGINLABELEDIT = (TVN_BEGINLABELEDITA),
+    TVN_BEGINRDRAG = (TVN_BEGINRDRAGA),
+    TVN_DELETEITEM = (TVN_DELETEITEMA),
+    TVN_ENDLABELEDIT = (TVN_ENDLABELEDITA),
+    TVN_GETDISPINFO = (TVN_GETDISPINFOA),
+    TVN_ITEMEXPANDED = (TVN_ITEMEXPANDEDA),
+    TVN_ITEMEXPANDING = (TVN_ITEMEXPANDINGA),
+    TVN_SELCHANGED = (TVN_SELCHANGEDA),
+    TVN_SELCHANGING = (TVN_SELCHANGINGA),
+    TVN_SETDISPINFO = (TVN_SETDISPINFOA),
+    UDM_GETACCEL = (1132),
+    UDM_GETBASE = (1134),
+    UDM_GETBUDDY = (1130),
+    UDM_GETPOS = (1128),
+    UDM_GETRANGE = (1126),
+    UDM_SETACCEL = (1131),
+    UDM_SETBASE = (1133),
+    UDM_SETBUDDY = (1129),
+    UDM_SETPOS = (1127),
+    UDM_SETRANGE = (1125),
+    UDN_DELTAPOS = -((722)),
+    WM_ACTIVATE = (6),
+    WM_ACTIVATEAPP = (28),
+    WM_ASKCBFORMATNAME = (780),
+    WM_CANCELJOURNAL = (75),
+    WM_CANCELMODE = (31),
+    WM_CAPTURECHANGED = (533),
+    WM_CHANGECBCHAIN = (781),
+    WM_CHAR = (258),
+    WM_CHARTOITEM = (47),
+    WM_CHILDACTIVATE = (34),
+    WM_CHOOSEFONT_GETLOGFONT = (1025),
+    WM_CHOOSEFONT_SETLOGFONT = (1125),
+    WM_CHOOSEFONT_SETFLAGS = (1126),
+    WM_CLEAR = (771),
+    WM_CLOSE = (16),
+    WM_COMMAND = (273),
+    WM_COMPACTING = (65),
+    WM_COMPAREITEM = (57),
+    WM___FILE__MENU = (123),
+    WM_COPY = (769),
+    WM_COPYDATA = (74),
+    WM_CREATE = (1),
+    WM_CTLCOLORBTN = (309),
+    WM_CTLCOLORDLG = (310),
+    WM_CTLCOLOREDIT = (307),
+    WM_CTLCOLORLISTBOX = (308),
+    WM_CTLCOLORMSGBOX = (306),
+    WM_CTLCOLORSCROLLBAR = (311),
+    WM_CTLCOLORSTATIC = (312),
+    WM_CUT = (768),
+    WM_DEADCHAR = (259),
+    WM_DELETEITEM = (45),
+    WM_DESTROY = (2),
+    WM_DESTROYCLIPBOARD = (775),
+    WM_DEVICECHANGE = (537),
+    WM_DEVMODECHANGE = (27),
+    WM_DISPLAYCHANGE = (126),
+    WM_DRAWCLIPBOARD = (776),
+    WM_DRAWITEM = (43),
+    WM_DROPFILES = (563),
+    WM_ENABLE = (10),
+    WM_ENDSESSION = (22),
+    WM_ENTERIDLE = (289),
+    WM_ENTERMENULOOP = (529),
+    WM_ENTERSIZEMOVE = (561),
+    WM_ERASEBKGND = (20),
+    WM_EXITMENULOOP = (530),
+    WM_EXITSIZEMOVE = (562),
+    WM_FONTCHANGE = (29),
+    WM_GETDLGCODE = (135),
+    WM_GETFONT = (49),
+    WM_GETHOTKEY = (51),
+    WM_GETICON = (127),
+    WM_GETMINMAXINFO = (36),
+    WM_GETTEXT = (13),
+    WM_GETTEXTLENGTH = (14),
+    WM_HELP = (83),
+    WM_HOTKEY = (786),
+    WM_HSCROLL = (276),
+    WM_HSCROLLCLIPBOARD = (782),
+    WM_ICONERASEBKGND = (39),
+    WM_IME_CHAR = (646),
+    WM_IME_COMPOSITION = (271),
+    WM_IME_COMPOSITIONFULL = (644),
+    WM_IME_CONTROL = (643),
+    WM_IME_ENDCOMPOSITION = (270),
+    WM_IME_KEYDOWN = (656),
+    WM_IME_KEYUP = (657),
+    WM_IME_NOTIFY = (642),
+    WM_IME_SELECT = (645),
+    WM_IME_SET__FILE__ = (641),
+    WM_IME_STARTCOMPOSITION = (269),
+    WM_INITDIALOG = (272),
+    WM_INITMENU = (278),
+    WM_INITMENUPOPUP = (279),
+    WM_INPUTLANGCHANGE = (81),
+    WM_INPUTLANGCHANGEREQUEST = (80),
+    WM_KEYDOWN = (256),
+    WM_KEYUP = (257),
+    WM_KILLFOCUS = (8),
+    WM_LBUTTONDBLCLK = (515),
+    WM_LBUTTONDOWN = (513),
+    WM_LBUTTONUP = (514),
+    WM_MBUTTONDBLCLK = (521),
+    WM_MBUTTONDOWN = (519),
+    WM_MBUTTONUP = (520),
+    WM_MDIACTIVATE = (546),
+    WM_MDICASCADE = (551),
+    WM_MDICREATE = (544),
+    WM_MDIDESTROY = (545),
+    WM_MDIGETACTIVE = (553),
+    WM_MDIICONARRANGE = (552),
+    WM_MDIMAXIMIZE = (549),
+    WM_MDINEXT = (548),
+    WM_MDIREFRESHMENU = (564),
+    WM_MDIRESTORE = (547),
+    WM_MDISETMENU = (560),
+    WM_MDITILE = (550),
+    WM_MEASUREITEM = (44),
+    WM_MENUCHAR = (288),
+    WM_MENUSELECT = (287),
+    WM_MOUSEACTIVATE = (33),
+    WM_MOUSEMOVE = (512),
+    WM_MOUSEWHEEL = 0x020A,
+    WM_MOVE = (3),
+    WM_MOVING = (534),
+    WM_NCACTIVATE = (134),
+    WM_NCCALCSIZE = (131),
+    WM_NCCREATE = (129),
+    WM_NCDESTROY = (130),
+    WM_NCHITTEST = (132),
+    WM_NCLBUTTONDBLCLK = (163),
+    WM_NCLBUTTONDOWN = (161),
+    WM_NCLBUTTONUP = (162),
+    WM_NCMBUTTONDBLCLK = (169),
+    WM_NCMBUTTONDOWN = (167),
+    WM_NCMBUTTONUP = (168),
+    WM_NCMOUSEMOVE = (160),
+    WM_NCPAINT = (133),
+    WM_NCRBUTTONDBLCLK = (166),
+    WM_NCRBUTTONDOWN = (164),
+    WM_NCRBUTTONUP = (165),
+    WM_NEXTDLGCTL = (40),
+    WM_NOTIFY = (78),
+    WM_NOTIFYFORMAT = (85),
+    WM_NULL = (0),
+    WM_PAINT = (15),
+    WM_PAINTCLIPBOARD = (777),
+    WM_PAINTICON = (38),
+    WM_PALETTECHANGED = (785),
+    WM_PALETTEISCHANGING = (784),
+    WM_PARENTNOTIFY = (528),
+    WM_PASTE = (770),
+    WM_PENWINFIRST = (896),
+    WM_PENWINLAST = (911),
+    WM_POWER = (72),
+    WM_POWERBROADCAST = (536),
+    WM_PRINT = (791),
+    WM_PRINTCLIENT = (792),
+    WM_PSD_ENVSTAMPRECT = (1029),
+    WM_PSD_FULLPAGERECT = (1025),
+    WM_PSD_GREEKTEXTRECT = (1028),
+    WM_PSD_MARGINRECT = (1027),
+    WM_PSD_MINMARGINRECT = (1026),
+    WM_PSD_PAGESETUPDLG = (1024),
+    WM_PSD_YAFULLPAGERECT = (1030),
+    WM_QUERYDRAGICON = (55),
+    WM_QUERYENDSESSION = (17),
+    WM_QUERYNEWPALETTE = (783),
+    WM_QUERYOPEN = (19),
+    WM_QUEUESYNC = (35),
+    WM_QUIT = (18),
+    WM_RBUTTONDBLCLK = (518),
+    WM_RBUTTONDOWN = (516),
+    WM_RBUTTONUP = (517),
+    WM_RENDERALLFORMATS = (774),
+    WM_RENDERFORMAT = (773),
+    WM_SETCURSOR = (32),
+    WM_SETFOCUS = (7),
+    WM_SETFONT = (48),
+    WM_SETHOTKEY = (50),
+    WM_SETICON = (128),
+    WM_SETREDRAW = (11),
+    WM_SETTEXT = (12),
+    WM_SETTINGCHANGE = (26),
+    WM_SHOWWINDOW = (24),
+    WM_SIZE = (5),
+    WM_SIZECLIPBOARD = (779),
+    WM_SIZING = (532),
+    WM_SPOOLERSTATUS = (42),
+    WM_STYLECHANGED = (125),
+    WM_STYLECHANGING = (124),
+    WM_SYSCHAR = (262),
+    WM_SYSCOLORCHANGE = (21),
+    WM_SYSCOMMAND = (274),
+    WM_SYSDEADCHAR = (263),
+    WM_SYSKEYDOWN = (260),
+    WM_SYSKEYUP = (261),
+    WM_TCARD = (82),
+    WM_TIMECHANGE = (30),
+    WM_TIMER = (275),
+    WM_UNDO = (772),
+    WM_USER = (1024),
+    WM_USERCHANGED = (84),
+    WM_VKEYTOITEM = (46),
+    WM_VSCROLL = (277),
+    WM_VSCROLLCLIPBOARD = (778),
+    WM_WINDOWPOSCHANGED = (71),
+    WM_WINDOWPOSCHANGING = (70),
+    WM_WININICHANGE = (26),
+    WM_KEYFIRST = (256),
+    WM_KEYLAST = (264),
+    WM_MOUSEFIRST = (512),
+    WM_MOUSELAST = (521),
+}
+struct VA_LIST
+{
+}
+
+
+struct ABC
+{
+    int abcA;
+    UINT abcB;
+    int abcC;
+}
+
+alias ABC* LPABC;
+alias ABC _ABC;
+alias ABC TABC;
+alias ABC* PABC;
+
+struct ABCFLOAT
+{
+    FLOAT abcfA;
+    FLOAT abcfB;
+    FLOAT abcfC;
+}
+
+alias ABCFLOAT* LPABCFLOAT;
+alias ABCFLOAT _ABCFLOAT;
+alias ABCFLOAT TABCFLOAT;
+alias ABCFLOAT* PABCFLOAT;
+
+struct ACCEL
+{
+    ubyte fVirt;
+    ushort key;
+    ushort cmd;
+}
+
+alias ACCEL* LPACCEL;
+alias ACCEL _ACCEL;
+alias ACCEL TACCEL;
+alias ACCEL* PACCEL;
+
+struct ACE_HEADER
+{
+    ubyte AceType;
+    ubyte AceFlags;
+    ushort AceSize;
+}
+
+alias ACE_HEADER _ACE_HEADER;
+alias ACE_HEADER TACE_HEADER;
+alias ACE_HEADER* PACE_HEADER;
+alias DWORD ACCESS_MASK;
+alias ACCESS_MASK REGSAM;
+
+struct ACCESS_ALLOWED_ACE
+{
+    ACE_HEADER Header;
+    ACCESS_MASK Mask;
+    DWORD SidStart;
+}
+
+alias ACCESS_ALLOWED_ACE _ACCESS_ALLOWED_ACE;
+alias ACCESS_ALLOWED_ACE TACCESS_ALLOWED_ACE;
+alias ACCESS_ALLOWED_ACE* PACCESS_ALLOWED_ACE;
+
+struct ACCESS_DENIED_ACE
+{
+    ACE_HEADER Header;
+    ACCESS_MASK Mask;
+    DWORD SidStart;
+}
+
+alias ACCESS_DENIED_ACE _ACCESS_DENIED_ACE;
+alias ACCESS_DENIED_ACE TACCESS_DENIED_ACE;
+
+struct ACCESSTIMEOUT
+{
+    UINT cbSize;
+    DWORD dwFlags;
+    DWORD iTimeOutMSec;
+}
+
+alias ACCESSTIMEOUT _ACCESSTIMEOUT;
+alias ACCESSTIMEOUT TACCESSTIMEOUT;
+alias ACCESSTIMEOUT* PACCESSTIMEOUT;
+
+struct ACL
+{
+    ubyte AclRevision;
+    ubyte Sbz1;
+    ushort AclSize;
+    ushort AceCount;
+    ushort Sbz2;
+}
+
+alias ACL* PACL;
+alias ACL _ACL;
+alias ACL TACL;
+
+struct ACL_REVISION_INFORMATION
+{
+    DWORD AclRevision;
+}
+
+alias ACL_REVISION_INFORMATION _ACL_REVISION_INFORMATION;
+alias ACL_REVISION_INFORMATION TACLREVISIONINFORMATION;
+alias ACL_REVISION_INFORMATION* PACLREVISIONINFORMATION;
+
+struct ACL_SIZE_INFORMATION
+{
+    DWORD AceCount;
+    DWORD AclBytesInUse;
+    DWORD AclBytesFree;
+}
+
+alias ACL_SIZE_INFORMATION _ACL_SIZE_INFORMATION;
+alias ACL_SIZE_INFORMATION TACLSIZEINFORMATION;
+alias ACL_SIZE_INFORMATION* PACLSIZEINFORMATION;
+
+struct ACTION_HEADER
+{
+    ULONG transport_id;
+    USHORT action_code;
+    USHORT reserved;
+}
+
+alias ACTION_HEADER _ACTION_HEADER;
+alias ACTION_HEADER TACTIONHEADER;
+alias ACTION_HEADER* PACTIONHEADER;
+
+struct ADAPTER_STATUS
+{
+    UCHAR[1 + 5] adapter_address;
+    UCHAR rev_major;
+    UCHAR reserved0;
+    UCHAR adapter_type;
+    UCHAR rev_minor;
+    ushort duration;
+    ushort frmr_recv;
+    ushort frmr_xmit;
+    ushort iframe_recv_err;
+    ushort xmit_aborts;
+    DWORD xmit_success;
+    DWORD recv_success;
+    ushort iframe_xmit_err;
+    ushort recv_buff_unavail;
+    ushort t1_timeouts;
+    ushort ti_timeouts;
+    DWORD reserved1;
+    ushort free_ncbs;
+    ushort max_cfg_ncbs;
+    ushort max_ncbs;
+    ushort xmit_buf_unavail;
+    ushort max_dgram_size;
+    ushort pending_sess;
+    ushort max_cfg_sess;
+    ushort max_sess;
+    ushort max_sess_pkt_size;
+    ushort name_count;
+}
+
+alias ADAPTER_STATUS _ADAPTER_STATUS;
+alias ADAPTER_STATUS TADAPTERSTATUS;
+alias ADAPTER_STATUS* PADAPTERSTATUS;
+
+struct ADDJOB_INFO_1
+{
+    LPTSTR Path;
+    DWORD JobId;
+}
+
+alias ADDJOB_INFO_1 _ADDJOB_INFO_1;
+alias ADDJOB_INFO_1 TADDJOB_INFO_1;
+alias ADDJOB_INFO_1* PADDJOB_INFO_1;
+
+struct ANIMATIONINFO
+{
+    UINT cbSize;
+    int iMinAnimate;
+}
+
+alias ANIMATIONINFO* LPANIMATIONINFO;
+alias ANIMATIONINFO _ANIMATIONINFO;
+alias ANIMATIONINFO TANIMATIONINFO;
+alias ANIMATIONINFO* PANIMATIONINFO;
+
+struct RECT
+{
+    LONG left;
+    LONG top;
+    LONG right;
+    LONG bottom;
+}
+
+alias RECT* LPCRECT;
+alias RECT* LPRECT;
+alias RECT _RECT;
+alias RECT TRECT;
+alias RECT* PRECT;
+
+struct RECTL
+{
+    LONG left;
+    LONG top;
+    LONG right;
+    LONG bottom;
+}
+
+alias RECTL _RECTL;
+alias RECTL TRECTL;
+alias RECTL* PRECTL;
+alias RECTL* LPRECTL;
+alias RECTL* LPCRECTL;
+
+struct APPBARDATA
+{
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uCallbackMessage;
+    UINT uEdge;
+    RECT rc;
+    LPARAM lParam;
+}
+
+alias APPBARDATA _APPBARDATA;
+alias APPBARDATA TAPPBARDATA;
+alias APPBARDATA* PAPPBARDATA;
+
+struct BITMAP
+{
+    LONG bmType;
+    LONG bmWidth;
+    LONG bmHeight;
+    LONG bmWidthBytes;
+    ushort bmPlanes;
+    ushort bmBitsPixel;
+    LPVOID bmBits;
+}
+
+alias BITMAP* PBITMAP;
+alias BITMAP* NPBITMAP;
+alias BITMAP* LPBITMAP;
+alias BITMAP TAGBITMAP;
+alias BITMAP TBITMAP;
+
+struct BITMAPCOREHEADER
+{
+    DWORD bcSize;
+    ushort bcWidth;
+    ushort bcHeight;
+    ushort bcPlanes;
+    ushort bcBitCount;
+}
+
+alias BITMAPCOREHEADER TAGBITMAPCOREHEADER;
+alias BITMAPCOREHEADER TBITMAPCOREHEADER;
+alias BITMAPCOREHEADER* PBITMAPCOREHEADER;
+
+struct RGBTRIPLE
+{
+    ubyte rgbtBlue;
+    ubyte rgbtGreen;
+    ubyte rgbtRed;
+}
+
+alias RGBTRIPLE TAGRGBTRIPLE;
+alias RGBTRIPLE TRGBTRIPLE;
+alias RGBTRIPLE* PRGBTRIPLE;
+
+struct BITMAPCOREINFO
+{
+    BITMAPCOREHEADER bmciHeader;
+    RGBTRIPLE[1 + 0] bmciColors;
+}
+
+alias BITMAPCOREINFO* PBITMAPCOREINFO;
+alias BITMAPCOREINFO* LPBITMAPCOREINFO;
+alias BITMAPCOREINFO _BITMAPCOREINFO;
+alias BITMAPCOREINFO TBITMAPCOREINFO;
+
+struct BITMAPINFOHEADER
+{
+    DWORD biSize;
+    LONG biWidth;
+    LONG biHeight;
+    ushort biPlanes;
+    ushort biBitCount;
+    DWORD biCompression;
+    DWORD biSizeImage;
+    LONG biXPelsPerMeter;
+    LONG biYPelsPerMeter;
+    DWORD biClrUsed;
+    DWORD biClrImportant;
+}
+
+alias BITMAPINFOHEADER* LPBITMAPINFOHEADER;
+alias BITMAPINFOHEADER TBITMAPINFOHEADER;
+alias BITMAPINFOHEADER* PBITMAPINFOHEADER;
+
+struct RGBQUAD
+{
+    ubyte rgbBlue;
+    ubyte rgbGreen;
+    ubyte rgbRed;
+    ubyte rgbReserved;
+}
+
+alias RGBQUAD TAGRGBQUAD;
+alias RGBQUAD TRGBQUAD;
+alias RGBQUAD* PRGBQUAD;
+
+struct BITMAPINFO
+{
+    BITMAPINFOHEADER bmiHeader;
+    RGBQUAD[1 + 0] bmiColors;
+}
+
+alias BITMAPINFO* LPBITMAPINFO;
+alias BITMAPINFO* PBITMAPINFO;
+alias BITMAPINFO TBITMAPINFO;
+alias int FXPT2DOT30;
+alias FXPT2DOT30* LPFXPT2DOT30;
+alias FXPT2DOT30 TPFXPT2DOT30;
+alias FXPT2DOT30* PPFXPT2DOT30;
+
+struct CIEXYZ
+{
+    FXPT2DOT30 ciexyzX;
+    FXPT2DOT30 ciexyzY;
+    FXPT2DOT30 ciexyzZ;
+}
+
+alias CIEXYZ TAGCIEXYZ;
+alias CIEXYZ* LPCIEXYZ;
+alias CIEXYZ TPCIEXYZ;
+alias CIEXYZ* PCIEXYZ;
+
+struct CIEXYZTRIPLE
+{
+    CIEXYZ ciexyzRed;
+    CIEXYZ ciexyzGreen;
+    CIEXYZ ciexyzBlue;
+}
+
+alias CIEXYZTRIPLE TAGCIEXYZTRIPLE;
+alias CIEXYZTRIPLE* LPCIEXYZTRIPLE;
+alias CIEXYZTRIPLE TCIEXYZTRIPLE;
+alias CIEXYZTRIPLE* PCIEXYZTRIPLE;
+
+struct BITMAPV4HEADER
+{
+    DWORD bV4Size;
+    LONG bV4Width;
+    LONG bV4Height;
+    ushort bV4Planes;
+    ushort bV4BitCount;
+    DWORD bV4V4Compression;
+    DWORD bV4SizeImage;
+    LONG bV4XPelsPerMeter;
+    LONG bV4YPelsPerMeter;
+    DWORD bV4ClrUsed;
+    DWORD bV4ClrImportant;
+    DWORD bV4RedMask;
+    DWORD bV4GreenMask;
+    DWORD bV4BlueMask;
+    DWORD bV4AlphaMask;
+    DWORD bV4CSType;
+    CIEXYZTRIPLE bV4Endpoints;
+    DWORD bV4GammaRed;
+    DWORD bV4GammaGreen;
+    DWORD bV4GammaBlue;
+}
+
+alias BITMAPV4HEADER* LPBITMAPV4HEADER;
+alias BITMAPV4HEADER TBITMAPV4HEADER;
+alias BITMAPV4HEADER* PBITMAPV4HEADER;
+
+align(1) struct BITMAPFILEHEADER
+{
+    ushort bfType;
+    DWORD bfSize;
+    ushort bfReserved1;
+    ushort bfReserved2;
+    DWORD bfOffBits;
+}
+
+
+struct BLOB
+{
+    ULONG cbSize;
+    ubyte* pBlobData;
+}
+
+alias BLOB _BLOB;
+alias BLOB TBLOB;
+alias BLOB* PBLOB;
+
+align(1) struct SHITEMID
+{
+    USHORT cb;
+    ubyte[1 + 0] abID;
+}
+
+alias SHITEMID* LPSHITEMID;
+alias SHITEMID* LPCSHITEMID;
+alias SHITEMID _SHITEMID;
+alias SHITEMID TSHITEMID;
+alias SHITEMID* PSHITEMID;
+
+struct ITEMIDLIST
+{
+    SHITEMID mkid;
+}
+
+alias ITEMIDLIST* LPITEMIDLIST;
+alias ITEMIDLIST* LPCITEMIDLIST;
+alias ITEMIDLIST _ITEMIDLIST;
+alias ITEMIDLIST TITEMIDLIST;
+alias ITEMIDLIST* PITEMIDLIST;
+
+struct BROWSEINFOA
+{
+    HWND hwndOwner;
+    LPCITEMIDLIST pidlRoot;
+    LPSTR pszDisplayName;
+    LPCSTR lpszTitle;
+    UINT ulFlags;
+    BFFCALLBACK lpfn;
+    LPARAM lParam;
+    int iImage;
+}
+struct BROWSEINFOW
+{
+    HWND hwndOwner;
+    LPCITEMIDLIST pidlRoot;
+    LPWSTR pszDisplayName;
+    LPCWSTR lpszTitle;
+    UINT ulFlags;
+    BFFCALLBACK lpfn;
+    LPARAM lParam;
+    int iImage;
+}
+version( Win32SansUnicode )
+{
+    alias BROWSEINFOA BROWSEINFO;
+}
+else
+{
+    alias BROWSEINFOW BROWSEINFO;
+}
+alias BROWSEINFO* PBROWSEINFO, LPBROWSEINFO;
+
+struct FILETIME
+{
+    DWORD dwLowDateTime;
+    DWORD dwHighDateTime;
+}
+
+alias FILETIME* LPFILETIME;
+alias FILETIME _FILETIME;
+alias FILETIME TFILETIME;
+alias FILETIME* PFILETIME;
+
+struct BY_HANDLE_FILE_INFORMATION
+{
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD dwVolumeSerialNumber;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD nNumberOfLinks;
+    DWORD nFileIndexHigh;
+    DWORD nFileIndexLow;
+}
+
+alias BY_HANDLE_FILE_INFORMATION* LPBY_HANDLE_FILE_INFORMATION;
+alias BY_HANDLE_FILE_INFORMATION _BY_HANDLE_FILE_INFORMATION;
+alias BY_HANDLE_FILE_INFORMATION TBYHANDLEFILEINFORMATION;
+alias BY_HANDLE_FILE_INFORMATION* PBYHANDLEFILEINFORMATION;
+
+struct FIXED
+{
+    ushort fract;
+    short value;
+}
+
+alias FIXED _FIXED;
+alias FIXED TFIXED;
+alias FIXED* PFIXED;
+
+struct POINT
+{
+    LONG x;
+    LONG y;
+}
+
+alias POINT* LPPOINT;
+alias POINT TAGPOINT;
+alias POINT TPOINT;
+alias POINT* PPOINT;
+
+struct POINTFX
+{
+    FIXED x;
+    FIXED y;
+}
+
+alias POINTFX TAGPOINTFX;
+alias POINTFX TPOINTFX;
+alias POINTFX* PPOINTFX;
+
+struct POINTL
+{
+    LONG x;
+    LONG y;
+}
+
+alias POINTL _POINTL;
+alias POINTL TPOINTL;
+alias POINTL* PPOINTL;
+
+struct TSMALLPOINT
+{
+    byte X, Y;
+}
+
+
+struct POINTS
+{
+    SHORT x;
+    SHORT y;
+}
+
+alias POINTS TAGPOINTS;
+alias POINTS TPOINTS;
+alias POINTS* PPOINTS;
+
+struct CANDIDATEFORM
+{
+    DWORD dwIndex;
+    DWORD dwStyle;
+    POINT ptCurrentPos;
+    RECT rcArea;
+}
+
+alias CANDIDATEFORM* LPCANDIDATEFORM;
+alias CANDIDATEFORM _TAGCANDIDATEFORM;
+alias CANDIDATEFORM TCANDIDATEFORM;
+alias CANDIDATEFORM* PCANDIDATEFORM;
+
+struct CANDIDATELIST
+{
+    DWORD dwSize;
+    DWORD dwStyle;
+    DWORD dwCount;
+    DWORD dwSelection;
+    DWORD dwPageStart;
+    DWORD dwPageSize;
+    DWORD[1 + 0] dwOffset;
+}
+
+alias CANDIDATELIST* LPCANDIDATELIST;
+alias CANDIDATELIST _TAGCANDIDATELIST;
+alias CANDIDATELIST TCANDIDATELIST;
+alias CANDIDATELIST* PCANDIDATELIST;
+
+struct CREATESTRUCT
+{
+    LPVOID lpCreateParams;
+    HINST hInstance;
+    HMENU hMenu;
+    HWND hwndParent;
+    int cy;
+    int cx;
+    int y;
+    int x;
+    LONG style;
+    LPCTSTR lpszName;
+    LPCTSTR lpszClass;
+    DWORD dwExStyle;
+}
+
+alias CREATESTRUCT* LPCREATESTRUCT;
+alias CREATESTRUCT TAGCREATESTRUCT;
+alias CREATESTRUCT TCREATESTRUCT;
+alias CREATESTRUCT* PCREATESTRUCT;
+
+struct CBT_CREATEWND
+{
+    LPCREATESTRUCT lpcs;
+    HWND hwndInsertAfter;
+}
+
+alias CBT_CREATEWND TAGCBT_CREATEWND;
+alias CBT_CREATEWND TCBT_CREATEWND;
+alias CBT_CREATEWND* PCBT_CREATEWND;
+
+struct CBTACTIVATESTRUCT
+{
+    WINBOOL fMouse;
+    HWND hWndActive;
+}
+
+alias CBTACTIVATESTRUCT TAGCBTACTIVATESTRUCT;
+alias CBTACTIVATESTRUCT TCBTACTIVATESTRUCT;
+alias CBTACTIVATESTRUCT* PCBTACTIVATESTRUCT;
+
+struct CHAR_INFO
+{
+
+    union
+    {
+        struct
+        {
+            WCHAR UnicodeChar;
+            ushort Attributes;
+        }
+        struct
+        {
+            char AsciiChar;
+        }
+    }
+}
+
+alias CHAR_INFO _CHAR_INFO;
+alias CHAR_INFO TCHAR_INFO;
+alias CHAR_INFO* PCHAR_INFO;
+
+struct CHARFORMAT
+{
+    UINT cbSize;
+    DWORD dwMask;
+    DWORD dwEffects;
+    LONG yHeight;
+    LONG yOffset;
+    COLORREF crTextColor;
+    ubyte bCharSet;
+    ubyte bPitchAndFamily;
+    TCHAR[1 + LF_FACESIZE-1] szFaceName;
+}
+
+alias CHARFORMAT _CHARFORMAT;
+alias CHARFORMAT TCHARFORMAT;
+alias CHARFORMAT* PCHARFORMAT;
+
+struct CHARRANGE
+{
+    LONG cpMin;
+    LONG cpMax;
+}
+
+alias CHARRANGE _CHARRANGE;
+alias CHARRANGE TCHARRANGE;
+alias CHARRANGE* PCHARRANGE;
+
+struct CHARSET
+{
+    DWORD[1 + 2] aflBlock;
+    DWORD flLang;
+}
+
+alias CHARSET TAGCHARSET;
+alias CHARSET TCHARSET;
+alias CHARSET* PCHARSET;
+
+struct FONTSIGNATURE
+{
+    DWORD[1 + 3] fsUsb;
+    DWORD[1 + 1] fsCsb;
+}
+
+alias FONTSIGNATURE* LPFONTSIGNATURE;
+alias FONTSIGNATURE TAGFONTSIGNATURE;
+alias FONTSIGNATURE TFONTSIGNATURE;
+alias FONTSIGNATURE* PFONTSIGNATURE;
+
+struct CHARSETINFO
+{
+    UINT ciCharset;
+    UINT ciACP;
+    FONTSIGNATURE fs;
+}
+
+alias CHARSETINFO* LPCHARSETINFO;
+alias CHARSETINFO TCHARSETINFO;
+alias CHARSETINFO* PCHARSETINFO;
+
+struct CHOOSECOLORA {
+    DWORD        lStructSize;
+    HWND         hwndOwner;
+    HWND         hInstance;
+    COLORREF     rgbResult;
+    COLORREF*    lpCustColors;
+    DWORD        Flags;
+    LPARAM       lCustData;
+    LPCCHOOKPROC lpfnHook;
+    LPCSTR      lpTemplateName;
+}
+alias CHOOSECOLORA* PCHOOSECOLORA, LPCHOOSECOLORA;
+struct CHOOSECOLORW {
+    DWORD        lStructSize;
+    HWND         hwndOwner;
+    HWND         hInstance;
+    COLORREF     rgbResult;
+    COLORREF*    lpCustColors;
+    DWORD        Flags;
+    LPARAM       lCustData;
+    LPCCHOOKPROC lpfnHook;
+    LPCWSTR      lpTemplateName;
+}
+alias CHOOSECOLORW* PCHOOSECOLORW, LPCHOOSECOLORW;
+version(Win32SansUnicode)
+{
+    alias CHOOSECOLORA CHOOSECOLOR;
+}
+else
+{
+    alias CHOOSECOLORW CHOOSECOLOR;
+}
+alias CHOOSECOLOR* PCHOOSECOLOR, LPCHOOSECOLOR;
+
+struct LOGFONTA
+{
+    LONG lfHeight;
+    LONG lfWidth;
+    LONG lfEscapement;
+    LONG lfOrientation;
+    LONG lfWeight;
+    ubyte lfItalic;
+    ubyte lfUnderline;
+    ubyte lfStrikeOut;
+    ubyte lfCharSet;
+    ubyte lfOutPrecision;
+    ubyte lfClipPrecision;
+    ubyte lfQuality;
+    ubyte lfPitchAndFamily;
+    ubyte[1 + LF_FACESIZE-1] lfFaceName;
+}
+
+alias LOGFONTA  TLOGFONTA;
+alias LOGFONTA* PLOGFONTA;
+alias LOGFONTA* LPLOGFONTA;
+
+struct LOGFONTW
+{
+    LONG lfHeight;
+    LONG lfWidth;
+    LONG lfEscapement;
+    LONG lfOrientation;
+    LONG lfWeight;
+    ubyte lfItalic;
+    ubyte lfUnderline;
+    ubyte lfStrikeOut;
+    ubyte lfCharSet;
+    ubyte lfOutPrecision;
+    ubyte lfClipPrecision;
+    ubyte lfQuality;
+    ubyte lfPitchAndFamily;
+    WCHAR lfFaceName[LF_FACESIZE] = 0;
+};
+
+alias LOGFONTW  TLOGFONTW;
+alias LOGFONTW* LPLOGFONTW;
+alias LOGFONTW* PLOGFONTW;
+
+version( Win32SansUnicode ){
+    alias LOGFONTA  LOGFONT;
+    alias LOGFONTA  TLOGFONT;
+    alias LOGFONTA* PLOGFONT;
+    alias LOGFONTA* LPLOGFONT;
+}
+else{
+    alias LOGFONTW  LOGFONT;
+    alias LOGFONTW  TLOGFONT;
+    alias LOGFONTW* PLOGFONT;
+    alias LOGFONTW* LPLOGFONT;
+}
+
+struct CHOOSEFONTA {
+    DWORD        lStructSize;
+    HWND         hwndOwner;
+    HDC          hDC;
+    LPLOGFONTA   lpLogFont;
+    INT          iPointSize;
+    DWORD        Flags;
+    DWORD        rgbColors;
+    LPARAM       lCustData;
+    LPCFHOOKPROC lpfnHook;
+    LPCSTR       lpTemplateName;
+    HINSTANCE    hInstance;
+    LPSTR        lpszStyle;
+    WORD         nFontType;
+    WORD         ___MISSING_ALIGNMENT__;
+    INT          nSizeMin;
+    INT          nSizeMax;
+}
+alias CHOOSEFONTA* PCHOOSEFONTA;
+alias CHOOSEFONTA* LPCHOOSEFONTA;
+
+struct CHOOSEFONTW {
+    DWORD        lStructSize;
+    HWND         hwndOwner;
+    HDC          hDC;
+    LOGFONTW*    lpLogFont;
+    INT          iPointSize;
+    DWORD        Flags;
+    DWORD        rgbColors;
+    LPARAM       lCustData;
+    LPCFHOOKPROC lpfnHook;
+    LPCWSTR      lpTemplateName;
+    HINSTANCE    hInstance;
+    LPWSTR       lpszStyle;
+    WORD         nFontType;
+    WORD         ___MISSING_ALIGNMENT__;
+    INT          nSizeMin;
+    INT          nSizeMax;
+}
+alias CHOOSEFONTW* PCHOOSEFONTW;
+alias CHOOSEFONTW* LPCHOOSEFONTW;
+
+version(Win32SansUnicode){
+    alias CHOOSEFONTA CHOOSEFONT;
+}else{
+    alias CHOOSEFONTW CHOOSEFONT;
+}
+
+alias CHOOSEFONT* LPCHOOSEFONT;
+alias CHOOSEFONT* PCHOOSEFONT;
+alias CHOOSEFONT TCHOOSEFONT;
+
+struct CIDA
+{
+    UINT cidl;
+    UINT[1 + 0] aoffset;
+}
+
+alias CIDA* LPIDA;
+alias CIDA _IDA;
+alias CIDA TIDA;
+alias CIDA* PIDA;
+
+struct CLIENTCREATESTRUCT
+{
+    HANDLE hWindowMenu;
+    UINT idFirstChild;
+}
+
+alias CLIENTCREATESTRUCT* LPCLIENTCREATESTRUCT;
+alias CLIENTCREATESTRUCT TAGCLIENTCREATESTRUCT;
+alias CLIENTCREATESTRUCT TCLIENTCREATESTRUCT;
+alias CLIENTCREATESTRUCT* PCLIENTCREATESTRUCT;
+
+struct CMINVOKECOMMANDINFO
+{
+    DWORD cbSize;
+    DWORD fMask;
+    HWND hwnd;
+    LPCSTR lpVerb;
+    LPCSTR lpParameters;
+    LPCSTR lpDirectory;
+    int nShow;
+    DWORD dwHotKey;
+    HANDLE hIcon;
+}
+
+alias CMINVOKECOMMANDINFO* LPCMINVOKECOMMANDINFO;
+alias CMINVOKECOMMANDINFO _CMINVOKECOMMANDINFO;
+alias CMINVOKECOMMANDINFO TCMINVOKECOMMANDINFO;
+alias CMINVOKECOMMANDINFO* PCMINVOKECOMMANDINFO;
+
+struct COLORADJUSTMENT
+{
+    ushort caSize;
+    ushort caFlags;
+    ushort caIlluminantIndex;
+    ushort caRedGamma;
+    ushort caGreenGamma;
+    ushort caBlueGamma;
+    ushort caReferenceBlack;
+    ushort caReferenceWhite;
+    SHORT caContrast;
+    SHORT caBrightness;
+    SHORT caColorfulness;
+    SHORT caRedGreenTint;
+}
+
+alias COLORADJUSTMENT* LPCOLORADJUSTMENT;
+alias COLORADJUSTMENT TAGCOLORADJUSTMENT;
+alias COLORADJUSTMENT TCOLORADJUSTMENT;
+alias COLORADJUSTMENT* PCOLORADJUSTMENT;
+
+struct COLORMAP
+{
+    COLORREF from;
+    COLORREF _to;
+}
+
+alias COLORMAP* LPCOLORMAP;
+alias COLORMAP _COLORMAP;
+alias COLORMAP TCOLORMAP;
+alias COLORMAP* PCOLORMAP;
+
+struct DCB
+{
+    DWORD DCBlength;
+    DWORD BaudRate;
+    int flag0;
+    ushort wReserved;
+    ushort XonLim;
+    ushort XoffLim;
+    ubyte ByteSize;
+    ubyte Parity;
+    ubyte StopBits;
+    char XonChar;
+    char XoffChar;
+    char ErrorChar;
+    char EofChar;
+    char EvtChar;
+    ushort wReserved1;
+}
+
+alias DCB* LPDCB;
+alias DCB _DCB;
+alias DCB TDCB;
+alias DCB* PDCB;
+enum : DWORD {
+    bm_DCB_fBinary = (0x1),
+    bp_DCB_fBinary = (0),
+    bm_DCB_fParity = (0x2),
+    bp_DCB_fParity = (1),
+    bm_DCB_fOutxCtsFlow = (0x4),
+    bp_DCB_fOutxCtsFlow = (2),
+    bm_DCB_fOutxDsrFlow = (0x8),
+    bp_DCB_fOutxDsrFlow = (3),
+    bm_DCB_fDtrControl = (0x30),
+    bp_DCB_fDtrControl = (4),
+    bm_DCB_fDsrSensitivity = (0x40),
+    bp_DCB_fDsrSensitivity = (6),
+    bm_DCB_fTXContinueOnXoff = (0x80),
+    bp_DCB_fTXContinueOnXoff = (7),
+    bm_DCB_fOutX = (0x100),
+    bp_DCB_fOutX = (8),
+    bm_DCB_fInX = (0x200),
+    bp_DCB_fInX = (9),
+    bm_DCB_fErrorChar = (0x400),
+    bp_DCB_fErrorChar = (10),
+    bm_DCB_fNull = (0x800),
+    bp_DCB_fNull = (11),
+    bm_DCB_fRtsControl = (0x3000),
+    bp_DCB_fRtsControl = (12),
+    bm_DCB_fAbortOnError = (0x4000),
+    bp_DCB_fAbortOnError = (14),
+    bm_DCB_fDummy2 = (0xFFFF8000),
+    bp_DCB_fDummy2 = (15),
+}
+
+struct COMMCONFIG
+{
+    DWORD dwSize;
+    ushort wVersion;
+    ushort wReserved;
+    DCB dcb;
+    DWORD dwProviderSubType;
+    DWORD dwProviderOffset;
+    DWORD dwProviderSize;
+    WCHAR[1 + 0] wcProviderData;
+}
+
+alias COMMCONFIG* LPCOMMCONFIG;
+alias COMMCONFIG _COMM_CONFIG;
+alias COMMCONFIG TCOMMCONFIG;
+alias COMMCONFIG* PCOMMCONFIG;
+
+struct COMMPROP
+{
+    ushort wPacketLength;
+    ushort wPacketVersion;
+    DWORD dwServiceMask;
+    DWORD dwReserved1;
+    DWORD dwMaxTxQueue;
+    DWORD dwMaxRxQueue;
+    DWORD dwMaxBaud;
+    DWORD dwProvSubType;
+    DWORD dwProvCapabilities;
+    DWORD dwSettableParams;
+    DWORD dwSettableBaud;
+    ushort wSettableData;
+    ushort wSettableStopParity;
+    DWORD dwCurrentTxQueue;
+    DWORD dwCurrentRxQueue;
+    DWORD dwProvSpec1;
+    DWORD dwProvSpec2;
+    WCHAR[1 + 0] wcProvChar;
+}
+
+alias COMMPROP* LPCOMMPROP;
+alias COMMPROP _COMMPROP;
+alias COMMPROP TCOMMPROP;
+alias COMMPROP* PCOMMPROP;
+
+struct COMMTIMEOUTS
+{
+    DWORD ReadIntervalTimeout;
+    DWORD ReadTotalTimeoutMultiplier;
+    DWORD ReadTotalTimeoutConstant;
+    DWORD WriteTotalTimeoutMultiplier;
+    DWORD WriteTotalTimeoutConstant;
+}
+
+alias COMMTIMEOUTS* LPCOMMTIMEOUTS;
+alias COMMTIMEOUTS _COMMTIMEOUTS;
+alias COMMTIMEOUTS TCOMMTIMEOUTS;
+alias COMMTIMEOUTS* PCOMMTIMEOUTS;
+
+struct COMPAREITEMSTRUCT
+{
+    UINT CtlType;
+    UINT CtlID;
+    HWND hwndItem;
+    UINT itemID1;
+    ULONG_PTR itemData1;
+    UINT itemID2;
+    ULONG_PTR itemData2;
+    DWORD dwLocaleId;
+}
+
+alias COMPAREITEMSTRUCT TAGCOMPAREITEMSTRUCT;
+alias COMPAREITEMSTRUCT TCOMPAREITEMSTRUCT;
+alias COMPAREITEMSTRUCT* PCOMPAREITEMSTRUCT;
+
+struct COMPCOLOR
+{
+    COLORREF crText;
+    COLORREF crBackground;
+    DWORD dwEffects;
+}
+
+alias COMPCOLOR TCOMPCOLOR;
+alias COMPCOLOR* PCOMPCOLOR;
+
+struct COMPOSITIONFORM
+{
+    DWORD dwStyle;
+    POINT ptCurrentPos;
+    RECT rcArea;
+}
+
+alias COMPOSITIONFORM* LPCOMPOSITIONFORM;
+alias COMPOSITIONFORM _TAGCOMPOSITIONFORM;
+alias COMPOSITIONFORM TCOMPOSITIONFORM;
+alias COMPOSITIONFORM* PCOMPOSITIONFORM;
+
+struct COMSTAT
+{
+    int flag0;
+    DWORD cbInQue;
+    DWORD cbOutQue;
+}
+
+alias COMSTAT* LPCOMSTAT;
+alias COMSTAT _COMSTAT;
+alias COMSTAT TCOMSTAT;
+alias COMSTAT* PCOMSTAT;
+enum : DWORD {
+    bm_COMSTAT_fCtsHold = (0x1),
+    bp_COMSTAT_fCtsHold = (0),
+    bm_COMSTAT_fDsrHold = (0x2),
+    bp_COMSTAT_fDsrHold = (1),
+    bm_COMSTAT_fRlsdHold = (0x4),
+    bp_COMSTAT_fRlsdHold = (2),
+    bm_COMSTAT_fXoffHold = (0x8),
+    bp_COMSTAT_fXoffHold = (3),
+    bm_COMSTAT_fXoffSent = (0x10),
+    bp_COMSTAT_fXoffSent = (4),
+    bm_COMSTAT_fEof = (0x20),
+    bp_COMSTAT_fEof = (5),
+    bm_COMSTAT_fTxim = (0x40),
+    bp_COMSTAT_fTxim = (6),
+    bm_COMSTAT_fReserved = (0xFFFFFF80),
+    bp_COMSTAT_fReserved = (7),
+}
+struct CONSOLE_CURSOR_INFO
+{
+    DWORD dwSize;
+    WINBOOL bVisible;
+}
+
+alias CONSOLE_CURSOR_INFO* PCONSOLE_CURSOR_INFO;
+alias CONSOLE_CURSOR_INFO _CONSOLE_CURSOR_INFO;
+alias CONSOLE_CURSOR_INFO TCONSOLECURSORINFO;
+alias CONSOLE_CURSOR_INFO* PCONSOLECURSORINFO;
+alias CONSOLE_CURSOR_INFO TCURSORINFO;
+
+struct COORD
+{
+    SHORT X;
+    SHORT Y;
+}
+
+alias COORD _COORD;
+alias COORD TCOORD;
+alias COORD* PCOORD;
+
+struct SMALL_RECT
+{
+    SHORT Left;
+    SHORT Top;
+    SHORT Right;
+    SHORT Bottom;
+}
+
+alias SMALL_RECT _SMALL_RECT;
+alias SMALL_RECT TSMALL_RECT;
+alias SMALL_RECT* PSMALL_RECT;
+
+align(1) struct CONSOLE_SCREEN_BUFFER_INFO
+{
+    COORD dwSize;
+    COORD dwCursorPosition;
+    ushort wAttributes;
+    SMALL_RECT srWindow;
+    COORD dwMaximumWindowSize;
+}
+
+alias CONSOLE_SCREEN_BUFFER_INFO* PCONSOLE_SCREEN_BUFFER_INFO;
+alias CONSOLE_SCREEN_BUFFER_INFO _CONSOLE_SCREEN_BUFFER_INFO;
+alias CONSOLE_SCREEN_BUFFER_INFO TCONSOLESCREENBUFFERINFO;
+alias CONSOLE_SCREEN_BUFFER_INFO* PCONSOLESCREENBUFFERINFO;
+
+struct FLOATING_SAVE_AREA
+{
+    DWORD ControlWord;
+    DWORD StatusWord;
+    DWORD TagWord;
+    DWORD ErrorOffset;
+    DWORD ErrorSelector;
+    DWORD DataOffset;
+    DWORD DataSelector;
+    ubyte[1 + 79] RegisterArea;
+    DWORD Cr0NpxState;
+}
+
+alias FLOATING_SAVE_AREA _FLOATING_SAVE_AREA;
+alias FLOATING_SAVE_AREA TFLOATINGSAVEAREA;
+alias FLOATING_SAVE_AREA* PFLOATINGSAVEAREA;
+
+enum : DWORD
+{
+//
+// The following flags control the contents of the CONTEXT structure.
+//
+    CONTEXT_i386 = 0x00010000,    // this assumes that i386 and
+    CONTEXT_i486 = 0x00010000,    // i486 have identical context records
+
+    CONTEXT_CONTROL =         (CONTEXT_i386 | 0x00000001), // SS:SP, CS:IP, FLAGS, BP
+    CONTEXT_INTEGER =         (CONTEXT_i386 | 0x00000002), // AX, BX, CX, DX, SI, DI
+    CONTEXT_SEGMENTS =        (CONTEXT_i386 | 0x00000004), // DS, ES, FS, GS
+    CONTEXT_FLOATING_POINT =  (CONTEXT_i386 | 0x00000008), // 387 state
+    CONTEXT_DEBUG_REGISTERS = (CONTEXT_i386 | 0x00000010), // DB 0-3,6,7
+
+    CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS),
+}
+
+struct CONTEXT
+{
+    DWORD ContextFlags;
+    DWORD Dr0;
+    DWORD Dr1;
+    DWORD Dr2;
+    DWORD Dr3;
+    DWORD Dr6;
+    DWORD Dr7;
+    FLOATING_SAVE_AREA FloatSave;
+    DWORD SegGs;
+    DWORD SegFs;
+    DWORD SegEs;
+    DWORD SegDs;
+    DWORD Edi;
+    DWORD Esi;
+    DWORD Ebx;
+    DWORD Edx;
+    DWORD Ecx;
+    DWORD Eax;
+    DWORD Ebp;
+    DWORD Eip;
+    DWORD SegCs;
+    DWORD EFlags;
+    DWORD Esp;
+    DWORD SegSs;
+}
+
+alias CONTEXT* LPCONTEXT;
+alias CONTEXT _CONTEXT;
+alias CONTEXT TCONTEXT;
+alias CONTEXT* PCONTEXT;
+
+struct LIST_ENTRY
+{
+    _LIST_ENTRY* Flink;
+    _LIST_ENTRY* Blink;
+}
+
+alias LIST_ENTRY _LIST_ENTRY;
+alias LIST_ENTRY TLISTENTRY;
+alias LIST_ENTRY* PLISTENTRY;
+
+align(1) struct CRITICAL_SECTION_DEBUG
+{
+    WORD _Type;
+    WORD CreatorBackTraceIndex;
+    _CRITICAL_SECTION* CriticalSection;
+    LIST_ENTRY ProcessLocksList;
+    DWORD EntryCount;
+    DWORD ContentionCount;
+    DWORD Flags;
+    WORD   CreatorBackTraceIndexHigh;
+    WORD   SpareWORD  ;
+}
+
+alias CRITICAL_SECTION_DEBUG* LPCRITICAL_SECTION_DEBUG;
+alias CRITICAL_SECTION_DEBUG* PCRITICAL_SECTION_DEBUG;
+alias CRITICAL_SECTION_DEBUG _CRITICAL_SECTION_DEBUG;
+alias CRITICAL_SECTION_DEBUG TCRITICALSECTIONDEBUG;
+alias CRITICAL_SECTION_DEBUG* PCRITICALSECTIONDEBUG;
+
+align(1) struct CRITICAL_SECTION
+{
+    PCRITICAL_SECTION_DEBUG DebugInfo;
+    LONG LockCount;
+    LONG RecursionCount;
+    HANDLE OwningThread;
+    HANDLE LockSemaphore;
+    DWORD Reserved;
+}
+
+alias CRITICAL_SECTION* LPCRITICAL_SECTION;
+alias CRITICAL_SECTION* PCRITICAL_SECTION;
+alias CRITICAL_SECTION _CRITICAL_SECTION;
+alias CRITICAL_SECTION TCRITICALSECTION;
+alias CRITICAL_SECTION* PCRITICALSECTION;
+
+alias ubyte SECURITY_CONTEXT_TRACKING_MODE;
+struct SECURITY_QUALITY_OF_SERVICE
+{
+    DWORD Length;
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+    SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode;
+    BOOLEAN EffectiveOnly;
+}
+
+alias SECURITY_QUALITY_OF_SERVICE* PSECURITY_QUALITY_OF_SERVICE;
+alias SECURITY_QUALITY_OF_SERVICE _SECURITY_QUALITY_OF_SERVICE;
+alias SECURITY_QUALITY_OF_SERVICE TSECURITYQUALITYOFSERVICE;
+alias SECURITY_QUALITY_OF_SERVICE* PSECURITYQUALITYOFSERVICE;
+
+struct CONVCONTEXT
+{
+    UINT cb;
+    UINT wFlags;
+    UINT wCountryID;
+    int iCodePage;
+    DWORD dwLangID;
+    DWORD dwSecurity;
+    SECURITY_QUALITY_OF_SERVICE qos;
+}
+
+alias CONVCONTEXT TAGCONVCONTEXT;
+alias CONVCONTEXT TCONVCONTEXT;
+alias CONVCONTEXT* PCONVCONTEXT;
+
+struct CONVINFO
+{
+    DWORD cb;
+    DWORD hUser;
+    HCONV hConvPartner;
+    HSZ hszSvcPartner;
+    HSZ hszServiceReq;
+    HSZ hszTopic;
+    HSZ hszItem;
+    UINT wFmt;
+    UINT wType;
+    UINT wStatus;
+    UINT wConvst;
+    UINT wLastError;
+    HCONVLIST hConvList;
+    CONVCONTEXT ConvCtxt;
+    HWND _hwnd;
+    HWND hwndPartner;
+}
+
+alias CONVINFO TAGCONVINFO;
+alias CONVINFO TCONVINFO;
+alias CONVINFO* PCONVINFO;
+
+struct COPYDATASTRUCT
+{
+    DWORD dwData;
+    DWORD cbData;
+    PVOID lpData;
+}
+
+alias COPYDATASTRUCT TAGCOPYDATASTRUCT;
+alias COPYDATASTRUCT TCOPYDATASTRUCT;
+alias COPYDATASTRUCT* PCOPYDATASTRUCT;
+
+struct CPINFO
+{
+    UINT MaxCharSize;
+    ubyte[1 + MAX_DEFAULTCHAR-1] DefaultChar;
+    ubyte[1 + MAX_LEADBYTES-1] LeadByte;
+}
+
+alias CPINFO* LPCPINFO;
+alias CPINFO _CPINFO;
+alias CPINFO TCPINFO;
+alias CPINFO* PCPINFO;
+
+struct CPLINFO
+{
+    int idIcon;
+    int idName;
+    int idInfo;
+    LONG lData;
+}
+
+alias CPLINFO TAGCPLINFO;
+alias CPLINFO TCPLINFO;
+alias CPLINFO* PCPLINFO;
+
+struct CREATE_PROCESS_DEBUG_INFO
+{
+    HANDLE hFile;
+    HANDLE hProcess;
+    HANDLE hThread;
+    LPVOID lpBaseOfImage;
+    DWORD dwDebugInfoFileOffset;
+    DWORD nDebugInfoSize;
+    LPVOID lpThreadLocalBase;
+    LPTHREAD_START_ROUTINE lpStartAddress;
+    LPVOID lpImageName;
+    ushort fUnicode;
+}
+
+alias CREATE_PROCESS_DEBUG_INFO _CREATE_PROCESS_DEBUG_INFO;
+alias CREATE_PROCESS_DEBUG_INFO TCREATEPROCESSDEBUGINFO;
+alias CREATE_PROCESS_DEBUG_INFO* PCREATEPROCESSDEBUGINFO;
+
+struct CREATE_THREAD_DEBUG_INFO
+{
+    HANDLE hThread;
+    LPVOID lpThreadLocalBase;
+    LPTHREAD_START_ROUTINE lpStartAddress;
+}
+
+alias CREATE_THREAD_DEBUG_INFO _CREATE_THREAD_DEBUG_INFO;
+alias CREATE_THREAD_DEBUG_INFO TCREATETHREADDEBUGINFO;
+alias CREATE_THREAD_DEBUG_INFO* PCREATETHREADDEBUGINFO;
+
+struct CURRENCYFMT
+{
+    UINT NumDigits;
+    UINT LeadingZero;
+    UINT Grouping;
+    LPTSTR lpDecimalSep;
+    LPTSTR lpThousandSep;
+    UINT NegativeOrder;
+    UINT PositiveOrder;
+    LPTSTR lpCurrencySymbol;
+}
+
+alias CURRENCYFMT _CURRENCYFMT;
+alias CURRENCYFMT TCURRENCYFMT;
+alias CURRENCYFMT* PCURRENCYFMT;
+
+struct CURSORSHAPE
+{
+    int xHotSpot;
+    int yHotSpot;
+    int cx;
+    int cy;
+    int cbWidth;
+    ubyte Planes;
+    ubyte BitsPixel;
+}
+
+alias CURSORSHAPE* LPCURSORSHAPE;
+alias CURSORSHAPE TAGCURSORSHAPE;
+alias CURSORSHAPE TCURSORSHAPE;
+alias CURSORSHAPE* PCURSORSHAPE;
+
+struct CWPRETSTRUCT
+{
+    LRESULT lResult;
+    LPARAM lParam;
+    WPARAM wParam;
+    DWORD message;
+    HWND hwnd;
+}
+
+alias CWPRETSTRUCT TAGCWPRETSTRUCT;
+alias CWPRETSTRUCT TCWPRETSTRUCT;
+alias CWPRETSTRUCT* PCWPRETSTRUCT;
+
+struct CWPSTRUCT
+{
+    LPARAM lParam;
+    WPARAM wParam;
+    UINT message;
+    HWND hwnd;
+}
+
+alias CWPSTRUCT TAGCWPSTRUCT;
+alias CWPSTRUCT TCWPSTRUCT;
+alias CWPSTRUCT* PCWPSTRUCT;
+
+struct DATATYPES_INFO_1
+{
+    LPTSTR pName;
+}
+
+alias DATATYPES_INFO_1 _DATATYPES_INFO_1;
+alias DATATYPES_INFO_1 TDATATYPESINFO1;
+alias DATATYPES_INFO_1* PDATATYPESINFO1;
+
+struct DDEACK
+{
+    ushort flag0;
+}
+
+alias DDEACK TDDEACK;
+alias DDEACK* PDDEACK;
+enum : DWORD {
+    bm_DDEACK_bAppReturnCode = (0xFF),
+    bp_DDEACK_bAppReturnCode = (0),
+    bm_DDEACK_reserved = (0x3F00),
+    bp_DDEACK_reserved = (8),
+    bm_DDEACK_fBusy = (0x4000),
+    bp_DDEACK_fBusy = (14),
+    bm_DDEACK_fAck = (0x8000),
+    bp_DDEACK_fAck = (15),
+}
+
+struct DDEADVISE
+{
+    ushort flag0;
+    short cfFormat;
+}
+
+alias DDEADVISE TDDEADVISE;
+alias DDEADVISE* PDDEADVISE;
+enum : DWORD {
+    bm_DDEADVISE_reserved = (0x3FFF),
+    bp_DDEADVISE_reserved = (0),
+    bm_DDEADVISE_fDeferUpd = (0x4000),
+    bp_DDEADVISE_fDeferUpd = (14),
+    bm_DDEADVISE_fAckReq = (0x8000),
+    bp_DDEADVISE_fAckReq = (15),
+}
+
+struct DDEDATA
+{
+    ushort flag0;
+    short  cfFormat;
+    ubyte[1 + 0] Value;
+}
+
+alias DDEDATA* PDDEDATA;
+enum : DWORD {
+    bm_DDEDATA_unused = (0xFFF),
+    bp_DDEDATA_unused = (0),
+    bm_DDEDATA_fResponse = (0x1000),
+    bp_DDEDATA_fResponse = (12),
+    bm_DDEDATA_fRelease = (0x2000),
+    bp_DDEDATA_fRelease = (13),
+    bm_DDEDATA_reserved = (0x4000),
+    bp_DDEDATA_reserved = (14),
+    bm_DDEDATA_fAckReq = (0x8000),
+    bp_DDEDATA_fAckReq = (15),
+}
+
+struct DDELN
+{
+    ushort flag0;
+    short cfFormat;
+}
+
+alias DDELN TDDELN;
+alias DDELN* PDDELN;
+enum : DWORD {
+    bm_DDELN_unused = (0x1FFF),
+    bp_DDELN_unused = (0),
+    bm_DDELN_fRelease = (0x2000),
+    bp_DDELN_fRelease = (13),
+    bm_DDELN_fDeferUpd = (0x4000),
+    bp_DDELN_fDeferUpd = (14),
+    bm_DDELN_fAckReq = (0x8000),
+    bp_DDELN_fAckReq = (15),
+}
+
+struct DDEML_MSG_HOOK_DATA
+{
+    UINT uiLo;
+    UINT uiHi;
+    DWORD cbData;
+    DWORD[1 + 7] Data;
+}
+
+alias DDEML_MSG_HOOK_DATA TAGDDEML_MSG_HOOK_DATA;
+alias DDEML_MSG_HOOK_DATA TDDEMLMSGHOOKDATA;
+alias DDEML_MSG_HOOK_DATA* PDDEMLMSGHOOKDATA;
+
+struct DDEPOKE
+{
+    ushort flag0;
+    short cfFormat;
+    ubyte[1 + 0] Value;
+}
+
+alias DDEPOKE TDDEPOKE;
+alias DDEPOKE* PDDEPOKE;
+enum : DWORD {
+    bm_DDEPOKE_unused = (0x1FFF),
+    bp_DDEPOKE_unused = (0),
+    bm_DDEPOKE_fRelease = (0x2000),
+    bp_DDEPOKE_fRelease = (13),
+    bm_DDEPOKE_fReserved = (0xC000),
+    bp_DDEPOKE_fReserved = (14),
+}
+struct DDEUP
+{
+    ushort flag0;
+    short cfFormat;
+    ubyte[1 + 0] rgb;
+}
+
+alias DDEUP TDDEUP;
+alias DDEUP* PDDEUP;
+
+enum : DWORD {
+    bm_DDEUP_unused = (0xFFF),
+    bp_DDEUP_unused = (0),
+    bm_DDEUP_fAck = (0x1000),
+    bp_DDEUP_fAck = (12),
+    bm_DDEUP_fRelease = (0x2000),
+    bp_DDEUP_fRelease = (13),
+    bm_DDEUP_fReserved = (0x4000),
+    bp_DDEUP_fReserved = (14),
+    bm_DDEUP_fAckReq = (0x8000),
+    bp_DDEUP_fAckReq = (15),
+}
+
+struct EXCEPTION_RECORD
+{
+    DWORD ExceptionCode;
+    DWORD ExceptionFlags;
+    _EXCEPTION_RECORD* ExceptionRecord;
+    PVOID ExceptionAddress;
+    DWORD NumberParameters;
+    DWORD[1 + EXCEPTION_MAXIMUM_PARAMETERS-1] ExceptionInformation;
+}
+
+alias EXCEPTION_RECORD* PEXCEPTION_RECORD;
+alias EXCEPTION_RECORD _EXCEPTION_RECORD;
+alias EXCEPTION_RECORD TEXCEPTIONRECORD;
+alias EXCEPTION_RECORD* PEXCEPTIONRECORD;
+
+struct EXCEPTION_DEBUG_INFO
+{
+    EXCEPTION_RECORD ExceptionRecord;
+    DWORD dwFirstChance;
+}
+
+alias EXCEPTION_DEBUG_INFO* PEXCEPTION_DEBUG_INFO;
+alias EXCEPTION_DEBUG_INFO _EXCEPTION_DEBUG_INFO;
+alias EXCEPTION_DEBUG_INFO TEXCEPTIONDEBUGINFO;
+alias EXCEPTION_DEBUG_INFO* PEXCEPTIONDEBUGINFO;
+
+struct EXIT_PROCESS_DEBUG_INFO
+{
+    DWORD dwExitCode;
+}
+
+alias EXIT_PROCESS_DEBUG_INFO _EXIT_PROCESS_DEBUG_INFO;
+alias EXIT_PROCESS_DEBUG_INFO TEXITPROCESSDEBUGINFO;
+alias EXIT_PROCESS_DEBUG_INFO* PEXITPROCESSDEBUGINFO;
+
+struct EXIT_THREAD_DEBUG_INFO
+{
+    DWORD dwExitCode;
+}
+
+alias EXIT_THREAD_DEBUG_INFO _EXIT_THREAD_DEBUG_INFO;
+alias EXIT_THREAD_DEBUG_INFO TEXITTHREADDEBUGINFO;
+alias EXIT_THREAD_DEBUG_INFO* PEXITTHREADDEBUGINFO;
+
+struct LOAD_DLL_DEBUG_INFO
+{
+    HANDLE hFile;
+    LPVOID lpBaseOfDll;
+    DWORD dwDebugInfoFileOffset;
+    DWORD nDebugInfoSize;
+    LPVOID lpImageName;
+    ushort fUnicode;
+}
+
+alias LOAD_DLL_DEBUG_INFO _LOAD_DLL_DEBUG_INFO;
+alias LOAD_DLL_DEBUG_INFO TLOADDLLDEBUGINFO;
+alias LOAD_DLL_DEBUG_INFO* PLOADDLLDEBUGINFO;
+
+struct UNLOAD_DLL_DEBUG_INFO
+{
+    LPVOID lpBaseOfDll;
+}
+
+alias UNLOAD_DLL_DEBUG_INFO _UNLOAD_DLL_DEBUG_INFO;
+alias UNLOAD_DLL_DEBUG_INFO TUNLOADDLLDEBUGINFO;
+alias UNLOAD_DLL_DEBUG_INFO* PUNLOADDLLDEBUGINFO;
+
+struct OUTPUT_DEBUG_STRING_INFO
+{
+    LPSTR lpDebugStringData;
+    ushort fUnicode;
+    ushort nDebugStringLength;
+}
+
+alias OUTPUT_DEBUG_STRING_INFO _OUTPUT_DEBUG_STRING_INFO;
+alias OUTPUT_DEBUG_STRING_INFO TOUTPUTDEBUGSTRINGINFO;
+alias OUTPUT_DEBUG_STRING_INFO* POUTPUTDEBUGSTRINGINFO;
+
+struct RIP_INFO
+{
+    DWORD dwError;
+    DWORD dwType;
+}
+
+alias RIP_INFO _RIP_INFO;
+alias RIP_INFO TRIPINFO;
+alias RIP_INFO* PRIPINFO;
+
+struct DEBUG_EVENT
+{
+    DWORD dwDebugEventCode;
+    DWORD dwProcessId;
+    DWORD dwThreadId;
+
+    union
+    {
+        struct
+        {
+            EXCEPTION_DEBUG_INFO Exception;
+        }
+        struct
+        {
+            CREATE_THREAD_DEBUG_INFO CreateThread;
+        }
+        struct
+        {
+            CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
+        }
+        struct
+        {
+            EXIT_THREAD_DEBUG_INFO ExitThread;
+        }
+        struct
+        {
+            EXIT_PROCESS_DEBUG_INFO ExitProcess;
+        }
+        struct
+        {
+            LOAD_DLL_DEBUG_INFO LoadDll;
+        }
+        struct
+        {
+            UNLOAD_DLL_DEBUG_INFO UnloadDll;
+        }
+        struct
+        {
+            OUTPUT_DEBUG_STRING_INFO DebugString;
+        }
+        struct
+        {
+            RIP_INFO RipInfo;
+        }
+    }
+}
+
+alias DEBUG_EVENT* LPDEBUG_EVENT;
+alias DEBUG_EVENT _DEBUG_EVENT;
+alias DEBUG_EVENT TDEBUGEVENT;
+alias DEBUG_EVENT* PDEBUGEVENT;
+
+struct DEBUGHOOKINFO
+{
+    DWORD idThread;
+    DWORD idThreadInstaller;
+    LPARAM lParam;
+    WPARAM wParam;
+    int code;
+}
+
+alias DEBUGHOOKINFO TAGDEBUGHOOKINFO;
+alias DEBUGHOOKINFO TDEBUGHOOKINFO;
+alias DEBUGHOOKINFO* PDEBUGHOOKINFO;
+
+struct DELETEITEMSTRUCT
+{
+    UINT CtlType;
+    UINT CtlID;
+    UINT itemID;
+    HWND hwndItem;
+    UINT itemData;
+}
+
+alias DELETEITEMSTRUCT TAGDELETEITEMSTRUCT;
+alias DELETEITEMSTRUCT TDELETEITEMSTRUCT;
+alias DELETEITEMSTRUCT* PDELETEITEMSTRUCT;
+
+struct DEV_BROADCAST_HDR
+{
+    ULONG dbch_size;
+    ULONG dbch_devicetype;
+    ULONG dbch_reserved;
+}
+
+alias DEV_BROADCAST_HDR* PDEV_BROADCAST_HDR;
+alias DEV_BROADCAST_HDR _DEV_BROADCAST_HDR;
+alias DEV_BROADCAST_HDR TDEVBROADCASTHDR;
+alias DEV_BROADCAST_HDR* PDEVBROADCASTHDR;
+
+struct DEV_BROADCAST_OEM
+{
+    ULONG dbco_size;
+    ULONG dbco_devicetype;
+    ULONG dbco_reserved;
+    ULONG dbco_identifier;
+    ULONG dbco_suppfunc;
+}
+
+alias DEV_BROADCAST_OEM* PDEV_BROADCAST_OEM;
+alias DEV_BROADCAST_OEM _DEV_BROADCAST_OEM;
+alias DEV_BROADCAST_OEM TDEVBROADCASTOEM;
+alias DEV_BROADCAST_OEM* PDEVBROADCASTOEM;
+
+struct DEV_BROADCAST_PORT
+{
+    ULONG dbcp_size;
+    ULONG dbcp_devicetype;
+    ULONG dbcp_reserved;
+    char[1 + 0] dbcp_name;
+}
+
+alias DEV_BROADCAST_PORT* PDEV_BROADCAST_PORT;
+alias DEV_BROADCAST_PORT _DEV_BROADCAST_PORT;
+alias DEV_BROADCAST_PORT TDEVBROADCASTPORT;
+alias DEV_BROADCAST_PORT* PDEVBROADCASTPORT;
+
+struct _DEV_BROADCAST_USERDEFINED
+{
+    _DEV_BROADCAST_HDR dbud_dbh;
+    char[1 + 0] dbud_szName;
+    ubyte[1 + 0] dbud_rgbUserDefined;
+}
+
+alias _DEV_BROADCAST_USERDEFINED TDEVBROADCASTUSERDEFINED;
+alias _DEV_BROADCAST_USERDEFINED* PDEVBROADCASTUSERDEFINED;
+
+struct DEV_BROADCAST_VOLUME
+{
+    ULONG dbcv_size;
+    ULONG dbcv_devicetype;
+    ULONG dbcv_reserved;
+    ULONG dbcv_unitmask;
+    USHORT dbcv_flags;
+}
+
+alias DEV_BROADCAST_VOLUME* PDEV_BROADCAST_VOLUME;
+alias DEV_BROADCAST_VOLUME _DEV_BROADCAST_VOLUME;
+alias DEV_BROADCAST_VOLUME TDEVBROADCASTVOLUME;
+alias DEV_BROADCAST_VOLUME* PDEVBROADCASTVOLUME;
+
+struct DEVMODE
+{
+    BCHAR[1 + CCHDEVICENAME-1] dmDeviceName;
+    ushort dmSpecVersion;
+    ushort dmDriverVersion;
+    ushort dmSize;
+    ushort dmDriverExtra;
+    DWORD dmFields;
+    int dmOrientation;
+    int dmPaperSize;
+    int dmPaperLength;
+    int dmPaperWidth;
+    int dmScale;
+    int dmCopies;
+    int dmDefaultSource;
+    int dmPrintQuality;
+    int dmColor;
+    int dmDuplex;
+    int dmYResolution;
+    int dmTTOption;
+    int dmCollate;
+    BCHAR[1 + CCHFORMNAME-1] dmFormName;
+    ushort dmLogPixels;
+    DWORD dmBitsPerPel;
+    DWORD dmPelsWidth;
+    DWORD dmPelsHeight;
+    DWORD dmDisplayFlags;
+    DWORD dmDisplayFrequency;
+    DWORD dmICMMethod;
+    DWORD dmICMIntent;
+    DWORD dmMediaType;
+    DWORD dmDitherType;
+    DWORD dmICCManufacturer;
+    DWORD dmICCModel;
+}
+
+alias DEVMODE* LPDEVMODE;
+alias DEVMODE _DEVICEMODE;
+alias DEVMODE DEVICEMODE;
+alias DEVMODE TDEVICEMODE;
+alias DEVMODE TDEVICEMODEA;
+alias DEVMODE TDEVMODE;
+alias DEVMODE* PDEVMODE;
+
+struct DEVNAMES
+{
+    ushort wDriverOffset;
+    ushort wDeviceOffset;
+    ushort wOutputOffset;
+    ushort wDefault;
+}
+
+alias DEVNAMES* LPDEVNAMES;
+alias DEVNAMES TAGDEVNAMES;
+alias DEVNAMES TDEVNAMES;
+alias DEVNAMES* PDEVNAMES;
+
+struct DIBSECTION
+{
+    BITMAP dsBm;
+    BITMAPINFOHEADER dsBmih;
+    DWORD[1 + 2] dsBitfields;
+    HANDLE dshSection;
+    DWORD dsOffset;
+}
+
+alias DIBSECTION TAGDIBSECTION;
+alias DIBSECTION TDIBSECTION;
+alias DIBSECTION* PDIBSECTION;
+
+union LARGE_INTEGER
+{
+    struct
+    {
+        DWORD LowPart;
+        LONG HighPart;
+    };
+    struct u
+    {
+        DWORD LowPart;
+        LONG HighPart;
+    };
+    LONGLONG QuadPart;
+}
+
+alias LARGE_INTEGER* PLARGE_INTEGER;
+alias LARGE_INTEGER _LARGE_INTEGER;
+alias LARGE_INTEGER TLARGEINTEGER;
+alias LARGE_INTEGER* PLARGEINTEGER;
+
+struct DISK_GEOMETRY
+{
+    LARGE_INTEGER Cylinders;
+    MEDIA_TYPE MediaType;
+    DWORD TracksPerCylinder;
+    DWORD SectorsPerTrack;
+    DWORD BytesPerSector;
+}
+
+alias DISK_GEOMETRY _DISK_GEOMETRY;
+alias DISK_GEOMETRY TDISKGEOMETRY;
+alias DISK_GEOMETRY* PDISKGEOMETRY;
+
+struct DISK_PERFORMANCE
+{
+    LARGE_INTEGER BytesRead;
+    LARGE_INTEGER BytesWritten;
+    LARGE_INTEGER ReadTime;
+    LARGE_INTEGER WriteTime;
+    LARGE_INTEGER IdleTime;
+    DWORD ReadCount;
+    DWORD WriteCount;
+    DWORD QueueDepth;
+    DWORD SplitCount;
+    LARGE_INTEGER QueryTime;
+    DWORD StorageDeviceNumber;
+    WCHAR StorageManagerName[8];
+}
+
+alias DISK_PERFORMANCE _DISK_PERFORMANCE;
+alias DISK_PERFORMANCE TDISKPERFORMANCE;
+alias DISK_PERFORMANCE* PDISKPERFORMANCE;
+
+align(1) struct DLGITEMTEMPLATE
+{
+    DWORD style;
+    DWORD dwExtendedStyle;
+    short x;
+    short y;
+    short cx;
+    short cy;
+    WORD id;
+}
+
+alias DLGITEMTEMPLATE* LPDLGITEMTEMPLATE;
+alias DLGITEMTEMPLATE TDLGITEMTEMPLATE;
+alias DLGITEMTEMPLATE* PDLGITEMTEMPLATE;
+
+align(1) struct DLGTEMPLATE
+{
+    DWORD style;
+    DWORD dwExtendedStyle;
+    WORD cdit;
+    short x;
+    short y;
+    short cx;
+    short cy;
+}
+
+alias DLGTEMPLATE* LPDLGTEMPLATE;
+alias DLGTEMPLATE* LPCDLGTEMPLATE;
+alias DLGTEMPLATE TDLGTEMPLATE;
+alias DLGTEMPLATE* PDLGTEMPLATE;
+
+struct DOC_INFO_1
+{
+    LPTSTR pDocName;
+    LPTSTR pOutputFile;
+    LPTSTR pDatatype;
+}
+
+alias DOC_INFO_1 _DOC_INFO_1;
+alias DOC_INFO_1 TDOCINFO1;
+alias DOC_INFO_1* PDOCINFO1;
+
+struct DOC_INFO_2
+{
+    LPTSTR pDocName;
+    LPTSTR pOutputFile;
+    LPTSTR pDatatype;
+    DWORD dwMode;
+    DWORD JobId;
+}
+
+alias DOC_INFO_2 _DOC_INFO_2;
+alias DOC_INFO_2 TDOCINFO2;
+alias DOC_INFO_2* PDOCINFO2;
+
+struct DOCINFOA
+{
+    int     cbSize;
+    LPCSTR   lpszDocName;
+    LPCSTR   lpszOutput;
+    LPCSTR   lpszDatatype;
+    DWORD    fwType;
+}
+alias DOCINFOA TDOCINFOA;
+
+struct DOCINFOW
+{
+    int     cbSize;
+    LPCWSTR  lpszDocName;
+    LPCWSTR  lpszOutput;
+    LPCWSTR  lpszDatatype;
+    DWORD    fwType;
+}
+alias DOCINFOW TDOCINFOW;
+
+version(Win32SansUnicode)
+{
+    alias DOCINFOA DOCINFO;
+}
+else
+{
+    alias DOCINFOW DOCINFO;
+}
+alias DOCINFO TDOCINFO;
+alias DOCINFO* LPDOCINFO;
+alias DOCINFO* PDOCINFO;
+
+
+struct DRAGLISTINFO
+{
+    UINT uNotification;
+    HWND hWnd;
+    POINT ptCursor;
+}
+
+alias DRAGLISTINFO* LPDRAGLISTINFO;
+alias DRAGLISTINFO TDRAGLISTINFO;
+alias DRAGLISTINFO* PDRAGLISTINFO;
+
+struct DRAWITEMSTRUCT
+{
+    UINT CtlType;
+    UINT CtlID;
+    UINT itemID;
+    UINT itemAction;
+    UINT itemState;
+    HWND hwndItem;
+    HDC hDC;
+    RECT rcItem;
+    DWORD itemData;
+}
+
+alias DRAWITEMSTRUCT* LPDRAWITEMSTRUCT;
+alias DRAWITEMSTRUCT TAGDRAWITEMSTRUCT;
+alias DRAWITEMSTRUCT TDRAWITEMSTRUCT;
+alias DRAWITEMSTRUCT* PDRAWITEMSTRUCT;
+
+struct DRAWTEXTPARAMS
+{
+    UINT cbSize;
+    int iTabLength;
+    int iLeftMargin;
+    int iRightMargin;
+    UINT uiLengthDrawn;
+}
+
+alias DRAWTEXTPARAMS* LPDRAWTEXTPARAMS;
+alias DRAWTEXTPARAMS TDRAWTEXTPARAMS;
+alias DRAWTEXTPARAMS* PDRAWTEXTPARAMS;
+
+struct PARTITION_INFORMATION
+{
+    ubyte PartitionType;
+    ubyte BootIndicator;
+    ubyte RecognizedPartition;
+    ubyte RewritePartition;
+    LARGE_INTEGER StartingOffset;
+    LARGE_INTEGER PartitionLength;
+    LARGE_INTEGER HiddenSectors;
+}
+
+alias PARTITION_INFORMATION _PARTITION_INFORMATION;
+alias PARTITION_INFORMATION TPARTITIONINFORMATION;
+alias PARTITION_INFORMATION* PPARTITIONINFORMATION;
+
+struct DRIVE_LAYOUT_INFORMATION
+{
+    DWORD PartitionCount;
+    DWORD Signature;
+    PARTITION_INFORMATION[1 + 0] PartitionEntry;
+}
+
+alias DRIVE_LAYOUT_INFORMATION _DRIVE_LAYOUT_INFORMATION;
+alias DRIVE_LAYOUT_INFORMATION TDRIVELAYOUTINFORMATION;
+alias DRIVE_LAYOUT_INFORMATION* PDRIVELAYOUTINFORMATION;
+
+struct DRIVER_INFO_1
+{
+    LPTSTR pName;
+}
+
+alias DRIVER_INFO_1 _DRIVER_INFO_1;
+alias DRIVER_INFO_1 TDRIVERINFO1;
+alias DRIVER_INFO_1* PDRIVERINFO1;
+
+struct DRIVER_INFO_2
+{
+    DWORD cVersion;
+    LPTSTR pName;
+    LPTSTR pEnvironment;
+    LPTSTR pDriverPath;
+    LPTSTR pDataFile;
+    LPTSTR pConfigFile;
+}
+
+alias DRIVER_INFO_2 _DRIVER_INFO_2;
+alias DRIVER_INFO_2 TDRIVERINFO2;
+alias DRIVER_INFO_2* PDRIVERINFO2;
+
+struct DRIVER_INFO_3
+{
+    DWORD cVersion;
+    LPTSTR pName;
+    LPTSTR pEnvironment;
+    LPTSTR pDriverPath;
+    LPTSTR pDataFile;
+    LPTSTR pConfigFile;
+    LPTSTR pHelpFile;
+    LPTSTR pDependentFiles;
+    LPTSTR pMonitorName;
+    LPTSTR pDefaultDataType;
+}
+
+alias DRIVER_INFO_3 _DRIVER_INFO_3;
+alias DRIVER_INFO_3 TDRIVERINFO3;
+alias DRIVER_INFO_3* PDRIVERINFO3;
+
+struct EDITSTREAM
+{
+    DWORD dwCookie;
+    DWORD dwError;
+    EDITSTREAMCALLBACK pfnCallback;
+}
+
+alias EDITSTREAM _EDITSTREAM;
+alias EDITSTREAM TEDITSTREAM;
+alias EDITSTREAM* PEDITSTREAM;
+
+struct EMR
+{
+    DWORD iType;
+    DWORD nSize;
+}
+
+alias EMR TAGEMR;
+alias EMR TEMR;
+alias EMR* PEMR;
+
+struct EMRANGLEARC
+{
+    EMR emr;
+    POINTL ptlCenter;
+    DWORD nRadius;
+    FLOAT eStartAngle;
+    FLOAT eSweepAngle;
+}
+
+alias EMRANGLEARC TAGEMRANGLEARC;
+alias EMRANGLEARC TEMRANGLEARC;
+alias EMRANGLEARC* PEMRANGLEARC;
+
+struct EMRARC
+{
+    EMR emr;
+    RECTL rclBox;
+    POINTL ptlStart;
+    POINTL ptlEnd;
+}
+
+alias EMRARC TAGEMRARC;
+alias EMRARC TEMRARC;
+alias EMRARC* PEMRARC;
+alias EMRARC EMRARCTO;
+alias EMRARC TEMRARCTO;
+alias EMRARC* PEMRARCTO;
+alias EMRARC EMRCHORD;
+alias EMRARC TEMRCHORD;
+alias EMRARC* PEMRCHORD;
+alias EMRARC EMRPIE;
+alias EMRARC TEMRPIE;
+alias EMRARC* PEMRPIE;
+
+struct XFORM
+{
+    FLOAT eM11;
+    FLOAT eM12;
+    FLOAT eM21;
+    FLOAT eM22;
+    FLOAT eDx;
+    FLOAT eDy;
+}
+
+alias XFORM* LPXFORM;
+alias XFORM _XFORM;
+alias XFORM TXFORM;
+alias XFORM* PXFORM;
+
+struct EMRBITBLT
+{
+    EMR emr;
+    RECTL rclBounds;
+    LONG xDest;
+    LONG yDest;
+    LONG cxDest;
+    LONG cyDest;
+    DWORD dwRop;
+    LONG xSrc;
+    LONG ySrc;
+    XFORM xformSrc;
+    COLORREF crBkColorSrc;
+    DWORD iUsageSrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+}
+
+alias EMRBITBLT TAGEMRBITBLT;
+alias EMRBITBLT TEMRBITBLT;
+alias EMRBITBLT* PEMRBITBLT;
+
+struct LOGBRUSH
+{
+    UINT lbStyle;
+    COLORREF lbColor;
+    LONG lbHatch;
+}
+
+alias LOGBRUSH TAGLOGBRUSH;
+alias LOGBRUSH TLOGBRUSH;
+alias LOGBRUSH* PLOGBRUSH;
+
+struct EMRCREATEBRUSHINDIRECT
+{
+    EMR emr;
+    DWORD ihBrush;
+    LOGBRUSH lb;
+}
+
+alias EMRCREATEBRUSHINDIRECT TAGEMRCREATEBRUSHINDIRECT;
+alias EMRCREATEBRUSHINDIRECT TEMRCREATEBRUSHINDIRECT;
+alias EMRCREATEBRUSHINDIRECT* PEMRCREATEBRUSHINDIRECT;
+alias LONG LCSCSTYPE;
+alias LONG LCSGAMUTMATCH;
+
+struct LOGCOLORSPACEA
+{
+    DWORD lcsSignature;
+    DWORD lcsVersion;
+    DWORD lcsSize;
+    LCSCSTYPE lcsCSType;
+    LCSGAMUTMATCH lcsIntent;
+    CIEXYZTRIPLE lcsEndpoints;
+    DWORD lcsGammaRed;
+    DWORD lcsGammaGreen;
+    DWORD lcsGammaBlue;
+    CHAR[1 + MAX_PATH-1] lcsFilename;
+}
+struct LOGCOLORSPACEW
+{
+    DWORD lcsSignature;
+    DWORD lcsVersion;
+    DWORD lcsSize;
+    LCSCSTYPE lcsCSType;
+    LCSGAMUTMATCH lcsIntent;
+    CIEXYZTRIPLE lcsEndpoints;
+    DWORD lcsGammaRed;
+    DWORD lcsGammaGreen;
+    DWORD lcsGammaBlue;
+    WCHAR[1 + MAX_PATH-1] lcsFilename;
+}
+version(Win32SansUnicode) {
+    alias LOGCOLORSPACEA LOGCOLORSPACE;
+}
+else {
+    alias LOGCOLORSPACEW LOGCOLORSPACE;
+}
+
+alias LOGCOLORSPACE* LPLOGCOLORSPACE;
+alias LOGCOLORSPACE TAGLOGCOLORSPACE;
+alias LOGCOLORSPACE TLOGCOLORSPACE;
+alias LOGCOLORSPACE TLOGCOLORSPACEA;
+alias LOGCOLORSPACE* PLOGCOLORSPACE;
+
+struct EMRCREATECOLORSPACE {
+    EMR            emr;
+    DWORD          ihCS;
+    LOGCOLORSPACEA lcs;
+}
+
+alias EMRCREATECOLORSPACE TAGEMRCREATECOLORSPACE;
+alias EMRCREATECOLORSPACE TEMRCREATECOLORSPACE;
+alias EMRCREATECOLORSPACE* PEMRCREATECOLORSPACE;
+
+struct EMRCREATEDIBPATTERNBRUSHPT
+{
+    EMR emr;
+    DWORD ihBrush;
+    DWORD iUsage;
+    DWORD offBmi;
+    DWORD cbBmi;
+    DWORD offBits;
+    DWORD cbBits;
+}
+
+alias EMRCREATEDIBPATTERNBRUSHPT TAGEMRCREATEDIBPATTERNBRUSHPT;
+alias EMRCREATEDIBPATTERNBRUSHPT TEMRCREATEDIBPATTERNBRUSHPT;
+alias EMRCREATEDIBPATTERNBRUSHPT PEMRCREATEDIBPATTERNBRUSHPT;
+
+struct EMRCREATEMONOBRUSH
+{
+    EMR emr;
+    DWORD ihBrush;
+    DWORD iUsage;
+    DWORD offBmi;
+    DWORD cbBmi;
+    DWORD offBits;
+    DWORD cbBits;
+}
+
+alias EMRCREATEMONOBRUSH TAGEMRCREATEMONOBRUSH;
+alias EMRCREATEMONOBRUSH TEMRCREATEMONOBRUSH;
+alias EMRCREATEMONOBRUSH* PEMRCREATEMONOBRUSH;
+
+struct PALETTEENTRY
+{
+    ubyte peRed;
+    ubyte peGreen;
+    ubyte peBlue;
+    ubyte peFlags;
+}
+
+alias PALETTEENTRY* LPPALETTEENTRY;
+alias PALETTEENTRY TAGPALETTEENTRY;
+alias PALETTEENTRY TPALETTEENTRY;
+alias PALETTEENTRY* PPALETTEENTRY;
+
+struct LOGPALETTE
+{
+    ushort palVersion;
+    ushort palNumEntries;
+    PALETTEENTRY[1 + 0] palPalEntry;
+}
+
+alias LOGPALETTE* LPLOGPALETTE;
+alias LOGPALETTE TAGLOGPALETTE;
+alias LOGPALETTE TLOGPALETTE;
+alias LOGPALETTE* PLOGPALETTE;
+
+struct EMRCREATEPALETTE
+{
+    EMR emr;
+    DWORD ihPal;
+    LOGPALETTE lgpl;
+}
+
+alias EMRCREATEPALETTE TAGEMRCREATEPALETTE;
+alias EMRCREATEPALETTE TEMRCREATEPALETTE;
+alias EMRCREATEPALETTE* PEMRCREATEPALETTE;
+
+struct LOGPEN
+{
+    UINT lopnStyle;
+    POINT lopnWidth;
+    COLORREF lopnColor;
+}
+
+alias LOGPEN TAGLOGPEN;
+alias LOGPEN TLOGPEN;
+alias LOGPEN* PLOGPEN;
+
+struct EMRCREATEPEN
+{
+    EMR emr;
+    DWORD ihPen;
+    LOGPEN lopn;
+}
+
+alias EMRCREATEPEN TAGEMRCREATEPEN;
+alias EMRCREATEPEN TEMRCREATEPEN;
+alias EMRCREATEPEN* PEMRCREATEPEN;
+
+struct EMRELLIPSE
+{
+    EMR emr;
+    RECTL rclBox;
+}
+
+alias EMRELLIPSE TAGEMRELLIPSE;
+alias EMRELLIPSE TEMRELLIPSE;
+alias EMRELLIPSE* PEMRELLIPSE;
+alias EMRELLIPSE EMRRECTANGLE;
+alias EMRELLIPSE TEMRRECTANGLE;
+alias EMRELLIPSE* PEMRRECTANGLE;
+
+struct EMREOF
+{
+    EMR emr;
+    DWORD nPalEntries;
+    DWORD offPalEntries;
+    DWORD nSizeLast;
+}
+
+alias EMREOF TAGEMREOF;
+alias EMREOF TEMREOF;
+alias EMREOF* PEMREOF;
+
+struct EMREXCLUDECLIPRECT
+{
+    EMR emr;
+    RECTL rclClip;
+}
+
+alias EMREXCLUDECLIPRECT TAGEMREXCLUDECLIPRECT;
+alias EMREXCLUDECLIPRECT TEMREXCLUDECLIPRECT;
+alias EMREXCLUDECLIPRECT* PEMREXCLUDECLIPRECT;
+alias EMREXCLUDECLIPRECT EMRINTERSECTCLIPRECT;
+alias EMREXCLUDECLIPRECT TEMRINTERSECTCLIPRECT;
+alias EMREXCLUDECLIPRECT* PEMRINTERSECTCLIPRECT;
+
+struct PANOSE
+{
+    ubyte bFamilyType;
+    ubyte bSerifStyle;
+    ubyte bWeight;
+    ubyte bProportion;
+    ubyte bContrast;
+    ubyte bStrokeVariation;
+    ubyte bArmStyle;
+    ubyte bLetterform;
+    ubyte bMidline;
+    ubyte bXHeight;
+}
+
+alias PANOSE TAGPANOSE;
+alias PANOSE TPANOSE;
+alias PANOSE* PPANOSE;
+
+struct EXTLOGFONT
+{
+    LOGFONT elfLogFont;
+    TCHAR[1 + LF_FULLFACESIZE-1] elfFullName = 0;
+    TCHAR[1 + LF_FACESIZE-1] elfStyle = 0;
+    DWORD elfVersion;
+    DWORD elfStyleSize;
+    DWORD elfMatch;
+    DWORD elfReserved;
+    ubyte[1 + ELF_VENDOR_SIZE-1] elfVendorId;
+    DWORD elfCulture;
+    PANOSE elfPanose;
+}
+
+alias EXTLOGFONT TAGEXTLOGFONT;
+alias EXTLOGFONT TEXTLOGFONT;
+alias EXTLOGFONT* PEXTLOGFONT;
+
+struct EMREXTCREATEFONTINDIRECTW
+{
+    EMR emr;
+    DWORD ihFont;
+    EXTLOGFONT elfw;
+}
+
+alias EMREXTCREATEFONTINDIRECTW TAGEMREXTCREATEFONTINDIRECTW;
+alias EMREXTCREATEFONTINDIRECTW TEMREXTCREATEFONTINDIRECTW;
+alias EMREXTCREATEFONTINDIRECTW* PEMREXTCREATEFONTINDIRECTW;
+
+struct EXTLOGPEN
+{
+    UINT elpPenStyle;
+    UINT elpWidth;
+    UINT elpBrushStyle;
+    COLORREF elpColor;
+    LONG elpHatch;
+    DWORD elpNumEntries;
+    DWORD[1 + 0] elpStyleEntry;
+}
+
+alias EXTLOGPEN TAGEXTLOGPEN;
+alias EXTLOGPEN TEXTLOGPEN;
+alias EXTLOGPEN* PEXTLOGPEN;
+
+struct EMREXTCREATEPEN
+{
+    EMR emr;
+    DWORD ihPen;
+    DWORD offBmi;
+    DWORD cbBmi;
+    DWORD offBits;
+    DWORD cbBits;
+    EXTLOGPEN elp;
+}
+
+alias EMREXTCREATEPEN TAGEMREXTCREATEPEN;
+alias EMREXTCREATEPEN TEMREXTCREATEPEN;
+alias EMREXTCREATEPEN* PEMREXTCREATEPEN;
+
+struct EMREXTFLOODFILL
+{
+    EMR emr;
+    POINTL ptlStart;
+    COLORREF crColor;
+    DWORD iMode;
+}
+
+alias EMREXTFLOODFILL TAGEMREXTFLOODFILL;
+alias EMREXTFLOODFILL TEMREXTFLOODFILL;
+alias EMREXTFLOODFILL* PEMREXTFLOODFILL;
+
+struct EMREXTSELECTCLIPRGN
+{
+    EMR emr;
+    DWORD cbRgnData;
+    DWORD iMode;
+    ubyte[1 + 0] RgnData;
+}
+
+alias EMREXTSELECTCLIPRGN TAGEMREXTSELECTCLIPRGN;
+alias EMREXTSELECTCLIPRGN TEMREXTSELECTCLIPRGN;
+alias EMREXTSELECTCLIPRGN* PEMREXTSELECTCLIPRGN;
+
+struct EMRTEXT
+{
+    POINTL ptlReference;
+    DWORD nChars;
+    DWORD offString;
+    DWORD fOptions;
+    RECTL rcl;
+    DWORD offDx;
+}
+
+alias EMRTEXT TAGEMRTEXT;
+alias EMRTEXT TEMRTEXT;
+alias EMRTEXT* PEMRTEXT;
+
+struct EMREXTTEXTOUTA
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD iGraphicsMode;
+    FLOAT exScale;
+    FLOAT eyScale;
+    EMRTEXT emrtext;
+}
+
+alias EMREXTTEXTOUTA TAGEMREXTTEXTOUTA;
+alias EMREXTTEXTOUTA TEMREXTTEXTOUTA;
+alias EMREXTTEXTOUTA* PEMREXTTEXTOUTA;
+alias EMREXTTEXTOUTA EMREXTTEXTOUTW;
+alias EMREXTTEXTOUTA TEMREXTTEXTOUTW;
+alias EMREXTTEXTOUTA* PEMREXTTEXTOUTW;
+
+struct EMRFILLPATH
+{
+    EMR emr;
+    RECTL rclBounds;
+}
+
+alias EMRFILLPATH TAGEMRFILLPATH;
+alias EMRFILLPATH TEMRFILLPATH;
+alias EMRFILLPATH* PEMRFILLPATH;
+alias EMRFILLPATH EMRSTROKEANDFILLPATH;
+alias EMRFILLPATH TEMRSTROKEANDFILLPATH;
+alias EMRFILLPATH* PEMRSTROKEANDFILLPATH;
+alias EMRFILLPATH EMRSTROKEPATH;
+alias EMRFILLPATH TEMRSTROKEPATH;
+alias EMRFILLPATH* PEMRSTROKEPATH;
+
+struct EMRFILLRGN
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cbRgnData;
+    DWORD ihBrush;
+    ubyte[1 + 0] RgnData;
+}
+
+alias EMRFILLRGN TAGEMRFILLRGN;
+alias EMRFILLRGN TEMRFILLRGN;
+alias EMRFILLRGN* PEMRFILLRGN;
+
+struct EMRFORMAT
+{
+    DWORD dSignature;
+    DWORD nVersion;
+    DWORD cbData;
+    DWORD offData;
+}
+
+alias EMRFORMAT TAGEMRFORMAT;
+alias EMRFORMAT TEMRFORMAT;
+alias EMRFORMAT* PEMRFORMAT;
+
+struct SIZE
+{
+    LONG cx;
+    LONG cy;
+}
+
+alias SIZE* LPSIZE;
+alias SIZE TAGSIZE;
+alias SIZE TSIZE;
+alias SIZE* PSIZE;
+alias SIZE SIZEL;
+alias SIZE TSIZEL;
+alias SIZE* PSIZEL;
+alias SIZE* LPSIZEL;
+
+struct EMRFRAMERGN
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cbRgnData;
+    DWORD ihBrush;
+    SIZEL szlStroke;
+    ubyte[1 + 0] RgnData;
+}
+
+alias EMRFRAMERGN TAGEMRFRAMERGN;
+alias EMRFRAMERGN TEMRFRAMERGN;
+alias EMRFRAMERGN* PEMRFRAMERGN;
+
+struct EMRGDICOMMENT
+{
+    EMR emr;
+    DWORD cbData;
+    ubyte[1 + 0] Data;
+}
+
+alias EMRGDICOMMENT TAGEMRGDICOMMENT;
+alias EMRGDICOMMENT TEMRGDICOMMENT;
+alias EMRGDICOMMENT* PEMRGDICOMMENT;
+
+struct EMRINVERTRGN
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cbRgnData;
+    ubyte[1 + 0] RgnData;
+}
+
+alias EMRINVERTRGN TAGEMRINVERTRGN;
+alias EMRINVERTRGN TEMRINVERTRGN;
+alias EMRINVERTRGN* PEMRINVERTRGN;
+alias EMRINVERTRGN EMRPAINTRGN;
+alias EMRINVERTRGN TEMRPAINTRGN;
+alias EMRINVERTRGN* PEMRPAINTRGN;
+
+struct EMRLINETO
+{
+    EMR emr;
+    POINTL ptl;
+}
+
+alias EMRLINETO TAGEMRLINETO;
+alias EMRLINETO TEMRLINETO;
+alias EMRLINETO* PEMRLINETO;
+alias EMRLINETO EMRMOVETOEX;
+alias EMRLINETO TEMRMOVETOEX;
+alias EMRLINETO* PEMRMOVETOEX;
+
+struct EMRMASKBLT
+{
+    EMR emr;
+    RECTL rclBounds;
+    LONG xDest;
+    LONG yDest;
+    LONG cxDest;
+    LONG cyDest;
+    DWORD dwRop;
+    LONG xSrc;
+    LONG ySrc;
+    XFORM xformSrc;
+    COLORREF crBkColorSrc;
+    DWORD iUsageSrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+    LONG xMask;
+    LONG yMask;
+    DWORD iUsageMask;
+    DWORD offBmiMask;
+    DWORD cbBmiMask;
+    DWORD offBitsMask;
+    DWORD cbBitsMask;
+}
+
+alias EMRMASKBLT TAGEMRMASKBLT;
+alias EMRMASKBLT TEMRMASKBLT;
+alias EMRMASKBLT* PEMRMASKBLT;
+
+struct EMRMODIFYWORLDTRANSFORM
+{
+    EMR emr;
+    XFORM xform;
+    DWORD iMode;
+}
+
+alias EMRMODIFYWORLDTRANSFORM TAGEMRMODIFYWORLDTRANSFORM;
+alias EMRMODIFYWORLDTRANSFORM TEMRMODIFYWORLDTRANSFORM;
+alias EMRMODIFYWORLDTRANSFORM PEMRMODIFYWORLDTRANSFORM;
+
+struct EMROFFSETCLIPRGN
+{
+    EMR emr;
+    POINTL ptlOffset;
+}
+
+alias EMROFFSETCLIPRGN TAGEMROFFSETCLIPRGN;
+alias EMROFFSETCLIPRGN TEMROFFSETCLIPRGN;
+alias EMROFFSETCLIPRGN* PEMROFFSETCLIPRGN;
+
+struct EMRPLGBLT
+{
+    EMR emr;
+    RECTL rclBounds;
+    POINTL[1 + 2] aptlDest;
+    LONG xSrc;
+    LONG ySrc;
+    LONG cxSrc;
+    LONG cySrc;
+    XFORM xformSrc;
+    COLORREF crBkColorSrc;
+    DWORD iUsageSrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+    LONG xMask;
+    LONG yMask;
+    DWORD iUsageMask;
+    DWORD offBmiMask;
+    DWORD cbBmiMask;
+    DWORD offBitsMask;
+    DWORD cbBitsMask;
+}
+
+alias EMRPLGBLT TAGEMRPLGBLT;
+alias EMRPLGBLT TEMRPLGBLT;
+alias EMRPLGBLT* PEMRPLGBLT;
+
+struct EMRPOLYDRAW
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cptl;
+    POINTL[1 + 0] aptl;
+    ubyte[1 + 0] abTypes;
+}
+
+alias EMRPOLYDRAW TAGEMRPOLYDRAW;
+alias EMRPOLYDRAW TEMRPOLYDRAW;
+alias EMRPOLYDRAW* PEMRPOLYDRAW;
+
+struct EMRPOLYDRAW16
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cpts;
+    POINTS[1 + 0] apts;
+    ubyte[1 + 0] abTypes;
+}
+
+alias EMRPOLYDRAW16 TAGEMRPOLYDRAW16;
+alias EMRPOLYDRAW16 TEMRPOLYDRAW16;
+alias EMRPOLYDRAW16* PEMRPOLYDRAW16;
+
+struct EMRPOLYLINE
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cptl;
+    POINTL[1 + 0] aptl;
+}
+
+alias EMRPOLYLINE TAGEMRPOLYLINE;
+alias EMRPOLYLINE TEMRPOLYLINE;
+alias EMRPOLYLINE* PEMRPOLYLINE;
+alias EMRPOLYLINE EMRPOLYBEZIER;
+alias EMRPOLYLINE TEMRPOLYBEZIER;
+alias EMRPOLYLINE* PEMRPOLYBEZIER;
+alias EMRPOLYLINE EMRPOLYGON;
+alias EMRPOLYLINE TEMRPOLYGON;
+alias EMRPOLYLINE* PEMRPOLYGON;
+alias EMRPOLYLINE EMRPOLYBEZIERTO;
+alias EMRPOLYLINE TEMRPOLYBEZIERTO;
+alias EMRPOLYLINE* PEMRPOLYBEZIERTO;
+alias EMRPOLYLINE EMRPOLYLINETO;
+alias EMRPOLYLINE TEMRPOLYLINETO;
+alias EMRPOLYLINE* PEMRPOLYLINETO;
+
+struct EMRPOLYLINE16
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD cpts;
+    POINTS[1 + 0] apts;
+}
+
+alias EMRPOLYLINE16 TAGEMRPOLYLINE16;
+alias EMRPOLYLINE16 TEMRPOLYLINE16;
+alias EMRPOLYLINE16* PEMRPOLYLINE16;
+alias EMRPOLYLINE16 EMRPOLYBEZIER16;
+alias EMRPOLYLINE16 TEMRPOLYBEZIER16;
+alias EMRPOLYLINE16* PEMRPOLYBEZIER16;
+alias EMRPOLYLINE16 EMRPOLYGON16;
+alias EMRPOLYLINE16 TEMRPOLYGON16;
+alias EMRPOLYLINE16* PEMRPOLYGON16;
+alias EMRPOLYLINE16 EMRPOLYBEZIERTO16;
+alias EMRPOLYLINE16 TEMRPOLYBEZIERTO16;
+alias EMRPOLYLINE16* PEMRPOLYBEZIERTO16;
+alias EMRPOLYLINE16 EMRPOLYLINETO16;
+alias EMRPOLYLINE16 TEMRPOLYLINETO16;
+alias EMRPOLYLINE16* PEMRPOLYLINETO16;
+
+struct EMRPOLYPOLYLINE
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD nPolys;
+    DWORD cptl;
+    DWORD[1 + 0] aPolyCounts;
+    POINTL[1 + 0] aptl;
+}
+
+alias EMRPOLYPOLYLINE TAGEMRPOLYPOLYLINE;
+alias EMRPOLYPOLYLINE TEMRPOLYPOLYLINE;
+alias EMRPOLYPOLYLINE* PEMRPOLYPOLYLINE;
+alias EMRPOLYPOLYLINE EMRPOLYPOLYGON;
+alias EMRPOLYPOLYLINE TEMRPOLYPOLYGON;
+alias EMRPOLYPOLYLINE* PEMRPOLYPOLYGON;
+
+struct EMRPOLYPOLYLINE16
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD nPolys;
+    DWORD cpts;
+    DWORD[1 + 0] aPolyCounts;
+    POINTS[1 + 0] apts;
+}
+
+alias EMRPOLYPOLYLINE16 TAGEMRPOLYPOLYLINE16;
+alias EMRPOLYPOLYLINE16 TEMRPOLYPOLYLINE16;
+alias EMRPOLYPOLYLINE16* PEMRPOLYPOLYLINE16;
+alias EMRPOLYPOLYLINE16 EMRPOLYPOLYGON16;
+alias EMRPOLYPOLYLINE16 TEMRPOLYPOLYGON16;
+alias EMRPOLYPOLYLINE16* PEMRPOLYPOLYGON16;
+
+struct EMRPOLYTEXTOUTA
+{
+    EMR emr;
+    RECTL rclBounds;
+    DWORD iGraphicsMode;
+    FLOAT exScale;
+    FLOAT eyScale;
+    LONG cStrings;
+    EMRTEXT[1 + 0] aemrtext;
+}
+
+alias EMRPOLYTEXTOUTA TAGEMRPOLYTEXTOUTA;
+alias EMRPOLYTEXTOUTA TEMRPOLYTEXTOUTA;
+alias EMRPOLYTEXTOUTA* PEMRPOLYTEXTOUTA;
+alias EMRPOLYTEXTOUTA EMRPOLYTEXTOUTW;
+alias EMRPOLYTEXTOUTA TEMRPOLYTEXTOUTW;
+alias EMRPOLYTEXTOUTA* PEMRPOLYTEXTOUTW;
+
+struct EMRRESIZEPALETTE
+{
+    EMR emr;
+    DWORD ihPal;
+    DWORD cEntries;
+}
+
+alias EMRRESIZEPALETTE TAGEMRRESIZEPALETTE;
+alias EMRRESIZEPALETTE TEMRRESIZEPALETTE;
+alias EMRRESIZEPALETTE* PEMRRESIZEPALETTE;
+
+struct EMRRESTOREDC
+{
+    EMR emr;
+    LONG iRelative;
+}
+
+alias EMRRESTOREDC TAGEMRRESTOREDC;
+alias EMRRESTOREDC TEMRRESTOREDC;
+alias EMRRESTOREDC* PEMRRESTOREDC;
+
+struct EMRROUNDRECT
+{
+    EMR emr;
+    RECTL rclBox;
+    SIZEL szlCorner;
+}
+
+alias EMRROUNDRECT TAGEMRROUNDRECT;
+alias EMRROUNDRECT TEMRROUNDRECT;
+alias EMRROUNDRECT* PEMRROUNDRECT;
+
+struct EMRSCALEVIEWPORTEXTEX
+{
+    EMR emr;
+    LONG xNum;
+    LONG xDenom;
+    LONG yNum;
+    LONG yDenom;
+}
+
+alias EMRSCALEVIEWPORTEXTEX TAGEMRSCALEVIEWPORTEXTEX;
+alias EMRSCALEVIEWPORTEXTEX TEMRSCALEVIEWPORTEXTEX;
+alias EMRSCALEVIEWPORTEXTEX* PEMRSCALEVIEWPORTEXTEX;
+alias EMRSCALEVIEWPORTEXTEX EMRSCALEWINDOWEXTEX;
+alias EMRSCALEVIEWPORTEXTEX TEMRSCALEWINDOWEXTEX;
+alias EMRSCALEVIEWPORTEXTEX* PEMRSCALEWINDOWEXTEX;
+
+struct EMRSELECTCOLORSPACE
+{
+    EMR emr;
+    DWORD ihCS;
+}
+
+alias EMRSELECTCOLORSPACE TAGEMRSELECTCOLORSPACE;
+alias EMRSELECTCOLORSPACE TEMRSELECTCOLORSPACE;
+alias EMRSELECTCOLORSPACE* PEMRSELECTCOLORSPACE;
+alias EMRSELECTCOLORSPACE EMRDELETECOLORSPACE;
+alias EMRSELECTCOLORSPACE TEMRDELETECOLORSPACE;
+alias EMRSELECTCOLORSPACE* PEMRDELETECOLORSPACE;
+
+struct EMRSELECTOBJECT
+{
+    EMR emr;
+    DWORD ihObject;
+}
+
+alias EMRSELECTOBJECT TAGEMRSELECTOBJECT;
+alias EMRSELECTOBJECT TEMRSELECTOBJECT;
+alias EMRSELECTOBJECT* PEMRSELECTOBJECT;
+alias EMRSELECTOBJECT EMRDELETEOBJECT;
+alias EMRSELECTOBJECT TEMRDELETEOBJECT;
+alias EMRSELECTOBJECT* PEMRDELETEOBJECT;
+
+struct EMRSELECTPALETTE
+{
+    EMR emr;
+    DWORD ihPal;
+}
+
+alias EMRSELECTPALETTE TAGEMRSELECTPALETTE;
+alias EMRSELECTPALETTE TEMRSELECTPALETTE;
+alias EMRSELECTPALETTE* PEMRSELECTPALETTE;
+
+struct EMRSETARCDIRECTION
+{
+    EMR emr;
+    DWORD iArcDirection;
+}
+
+alias EMRSETARCDIRECTION TAGEMRSETARCDIRECTION;
+alias EMRSETARCDIRECTION TEMRSETARCDIRECTION;
+alias EMRSETARCDIRECTION* PEMRSETARCDIRECTION;
+
+struct EMRSETBKCOLOR
+{
+    EMR emr;
+    COLORREF crColor;
+}
+
+alias EMRSETBKCOLOR TAGEMRSETTEXTCOLOR;
+alias EMRSETBKCOLOR TEMRSETBKCOLOR;
+alias EMRSETBKCOLOR* PEMRSETBKCOLOR;
+alias EMRSETBKCOLOR EMRSETTEXTCOLOR;
+alias EMRSETBKCOLOR TEMRSETTEXTCOLOR;
+alias EMRSETBKCOLOR* PEMRSETTEXTCOLOR;
+
+struct EMRSETCOLORADJUSTMENT
+{
+    EMR emr;
+    COLORADJUSTMENT ColorAdjustment;
+}
+
+alias EMRSETCOLORADJUSTMENT TAGEMRSETCOLORADJUSTMENT;
+alias EMRSETCOLORADJUSTMENT TEMRSETCOLORADJUSTMENT;
+alias EMRSETCOLORADJUSTMENT* PEMRSETCOLORADJUSTMENT;
+
+struct EMRSETDIBITSTODEVICE
+{
+    EMR emr;
+    RECTL rclBounds;
+    LONG xDest;
+    LONG yDest;
+    LONG xSrc;
+    LONG ySrc;
+    LONG cxSrc;
+    LONG cySrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+    DWORD iUsageSrc;
+    DWORD iStartScan;
+    DWORD cScans;
+}
+
+alias EMRSETDIBITSTODEVICE TAGEMRSETDIBITSTODEVICE;
+alias EMRSETDIBITSTODEVICE TEMRSETDIBITSTODEVICE;
+alias EMRSETDIBITSTODEVICE* PEMRSETDIBITSTODEVICE;
+
+struct EMRSETMAPPERFLAGS
+{
+    EMR emr;
+    DWORD dwFlags;
+}
+
+alias EMRSETMAPPERFLAGS TAGEMRSETMAPPERFLAGS;
+alias EMRSETMAPPERFLAGS TEMRSETMAPPERFLAGS;
+alias EMRSETMAPPERFLAGS* PEMRSETMAPPERFLAGS;
+
+struct EMRSETMITERLIMIT
+{
+    EMR emr;
+    FLOAT eMiterLimit;
+}
+
+alias EMRSETMITERLIMIT TAGEMRSETMITERLIMIT;
+alias EMRSETMITERLIMIT TEMRSETMITERLIMIT;
+alias EMRSETMITERLIMIT* PEMRSETMITERLIMIT;
+
+struct EMRSETPALETTEENTRIES
+{
+    EMR emr;
+    DWORD ihPal;
+    DWORD iStart;
+    DWORD cEntries;
+    PALETTEENTRY[1 + 0] aPalEntries;
+}
+
+alias EMRSETPALETTEENTRIES TAGEMRSETPALETTEENTRIES;
+alias EMRSETPALETTEENTRIES TEMRSETPALETTEENTRIES;
+alias EMRSETPALETTEENTRIES* PEMRSETPALETTEENTRIES;
+
+struct EMRSETPIXELV
+{
+    EMR emr;
+    POINTL ptlPixel;
+    COLORREF crColor;
+}
+
+alias EMRSETPIXELV TAGEMRSETPIXELV;
+alias EMRSETPIXELV TEMRSETPIXELV;
+alias EMRSETPIXELV* PEMRSETPIXELV;
+
+struct EMRSETVIEWPORTEXTEX
+{
+    EMR emr;
+    SIZEL szlExtent;
+}
+
+alias EMRSETVIEWPORTEXTEX TAGEMRSETVIEWPORTEXTEX;
+alias EMRSETVIEWPORTEXTEX TEMRSETVIEWPORTEXTEX;
+alias EMRSETVIEWPORTEXTEX* PEMRSETVIEWPORTEXTEX;
+alias EMRSETVIEWPORTEXTEX EMRSETWINDOWEXTEX;
+alias EMRSETVIEWPORTEXTEX TEMRSETWINDOWEXTEX;
+alias EMRSETVIEWPORTEXTEX* PEMRSETWINDOWEXTEX;
+
+struct EMRSETVIEWPORTORGEX
+{
+    EMR emr;
+    POINTL ptlOrigin;
+}
+
+alias EMRSETVIEWPORTORGEX TAGEMRSETVIEWPORTORGEX;
+alias EMRSETVIEWPORTORGEX TEMRSETVIEWPORTORGEX;
+alias EMRSETVIEWPORTORGEX* PEMRSETVIEWPORTORGEX;
+alias EMRSETVIEWPORTORGEX EMRSETWINDOWORGEX;
+alias EMRSETVIEWPORTORGEX TEMRSETWINDOWORGEX;
+alias EMRSETVIEWPORTORGEX* PEMRSETWINDOWORGEX;
+alias EMRSETVIEWPORTORGEX EMRSETBRUSHORGEX;
+alias EMRSETVIEWPORTORGEX TEMRSETBRUSHORGEX;
+alias EMRSETVIEWPORTORGEX* PEMRSETBRUSHORGEX;
+
+struct EMRSETWORLDTRANSFORM
+{
+    EMR emr;
+    XFORM xform;
+}
+
+alias EMRSETWORLDTRANSFORM TAGEMRSETWORLDTRANSFORM;
+alias EMRSETWORLDTRANSFORM TEMRSETWORLDTRANSFORM;
+alias EMRSETWORLDTRANSFORM* PEMRSETWORLDTRANSFORM;
+
+struct EMRSTRETCHBLT
+{
+    EMR emr;
+    RECTL rclBounds;
+    LONG xDest;
+    LONG yDest;
+    LONG cxDest;
+    LONG cyDest;
+    DWORD dwRop;
+    LONG xSrc;
+    LONG ySrc;
+    XFORM xformSrc;
+    COLORREF crBkColorSrc;
+    DWORD iUsageSrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+    LONG cxSrc;
+    LONG cySrc;
+}
+
+alias EMRSTRETCHBLT TAGEMRSTRETCHBLT;
+alias EMRSTRETCHBLT TEMRSTRETCHBLT;
+alias EMRSTRETCHBLT* PEMRSTRETCHBLT;
+
+struct EMRSTRETCHDIBITS
+{
+    EMR emr;
+    RECTL rclBounds;
+    LONG xDest;
+    LONG yDest;
+    LONG xSrc;
+    LONG ySrc;
+    LONG cxSrc;
+    LONG cySrc;
+    DWORD offBmiSrc;
+    DWORD cbBmiSrc;
+    DWORD offBitsSrc;
+    DWORD cbBitsSrc;
+    DWORD iUsageSrc;
+    DWORD dwRop;
+    LONG cxDest;
+    LONG cyDest;
+}
+
+alias EMRSTRETCHDIBITS TAGEMRSTRETCHDIBITS;
+alias EMRSTRETCHDIBITS TEMRSTRETCHDIBITS;
+alias EMRSTRETCHDIBITS* PEMRSTRETCHDIBITS;
+
+struct EMRABORTPATH
+{
+    EMR emr;
+}
+
+alias EMRABORTPATH TEMRABORTPATH;
+alias EMRABORTPATH* PEMRABORTPATH;
+alias EMRABORTPATH TAGABORTPATH;
+alias EMRABORTPATH TABORTPATH;
+alias EMRABORTPATH EMRBEGINPATH;
+alias EMRABORTPATH TEMRBEGINPATH;
+alias EMRABORTPATH* PEMRBEGINPATH;
+alias EMRABORTPATH EMRENDPATH;
+alias EMRABORTPATH TEMRENDPATH;
+alias EMRABORTPATH* PEMRENDPATH;
+alias EMRABORTPATH EMRCLOSEFIGURE;
+alias EMRABORTPATH TEMRCLOSEFIGURE;
+alias EMRABORTPATH* PEMRCLOSEFIGURE;
+alias EMRABORTPATH EMRFLATTENPATH;
+alias EMRABORTPATH TEMRFLATTENPATH;
+alias EMRABORTPATH* PEMRFLATTENPATH;
+alias EMRABORTPATH EMRWIDENPATH;
+alias EMRABORTPATH TEMRWIDENPATH;
+alias EMRABORTPATH* PEMRWIDENPATH;
+alias EMRABORTPATH EMRSETMETARGN;
+alias EMRABORTPATH TEMRSETMETARGN;
+alias EMRABORTPATH* PEMRSETMETARGN;
+alias EMRABORTPATH EMRSAVEDC;
+alias EMRABORTPATH TEMRSAVEDC;
+alias EMRABORTPATH* PEMRSAVEDC;
+alias EMRABORTPATH EMRREALIZEPALETTE;
+alias EMRABORTPATH TEMRREALIZEPALETTE;
+alias EMRABORTPATH* PEMRREALIZEPALETTE;
+
+struct EMRSELECTCLIPPATH
+{
+    EMR emr;
+    DWORD iMode;
+}
+
+alias EMRSELECTCLIPPATH TAGEMRSELECTCLIPPATH;
+alias EMRSELECTCLIPPATH TEMRSELECTCLIPPATH;
+alias EMRSELECTCLIPPATH* PEMRSELECTCLIPPATH;
+alias EMRSELECTCLIPPATH EMRSETBKMODE;
+alias EMRSELECTCLIPPATH TEMRSETBKMODE;
+alias EMRSELECTCLIPPATH* PEMRSETBKMODE;
+alias EMRSELECTCLIPPATH EMRSETMAPMODE;
+alias EMRSELECTCLIPPATH TEMRSETMAPMODE;
+alias EMRSELECTCLIPPATH* PEMRSETMAPMODE;
+alias EMRSELECTCLIPPATH EMRSETPOLYFILLMODE;
+alias EMRSELECTCLIPPATH TEMRSETPOLYFILLMODE;
+alias EMRSELECTCLIPPATH* PEMRSETPOLYFILLMODE;
+alias EMRSELECTCLIPPATH EMRSETROP2;
+alias EMRSELECTCLIPPATH TEMRSETROP2;
+alias EMRSELECTCLIPPATH* PEMRSETROP2;
+alias EMRSELECTCLIPPATH EMRSETSTRETCHBLTMODE;
+alias EMRSELECTCLIPPATH TEMRSETSTRETCHBLTMODE;
+alias EMRSELECTCLIPPATH* PEMRSETSTRETCHBLTMODE;
+alias EMRSELECTCLIPPATH EMRSETTEXTALIGN;
+alias EMRSELECTCLIPPATH TEMRSETTEXTALIGN;
+alias EMRSELECTCLIPPATH* PEMRSETTEXTALIGN;
+alias EMRSELECTCLIPPATH EMRENABLEICM;
+alias EMRSELECTCLIPPATH TEMRENABLEICM;
+alias EMRSELECTCLIPPATH* PEMRENABLEICM;
+
+struct NMHDR
+{
+    HWND hwndFrom;
+    UINT idFrom;
+    UINT code;
+}
+
+alias NMHDR TAGNMHDR;
+alias NMHDR TNMHDR;
+alias NMHDR* PNMHDR;
+
+struct ENCORRECTTEXT
+{
+    NMHDR nmhdr;
+    CHARRANGE chrg;
+    ushort seltyp;
+}
+
+alias ENCORRECTTEXT _ENCORRECTTEXT;
+alias ENCORRECTTEXT TENCORRECTTEXT;
+alias ENCORRECTTEXT* PENCORRECTTEXT;
+
+struct ENDROPFILES
+{
+    NMHDR nmhdr;
+    HANDLE hDrop;
+    LONG cp;
+    WINBOOL fProtected;
+}
+
+alias ENDROPFILES _ENDROPFILES;
+alias ENDROPFILES TENDROPFILES;
+alias ENDROPFILES* PENDROPFILES;
+
+struct ENSAVECLIPBOARD
+{
+    NMHDR nmhdr;
+    LONG cObjectCount;
+    LONG cch;
+}
+
+alias ENSAVECLIPBOARD TENSAVECLIPBOARD;
+alias ENSAVECLIPBOARD* PENSAVECLIPBOARD;
+
+struct ENOLEOPFAILED
+{
+    NMHDR nmhdr;
+    LONG iob;
+    LONG lOper;
+    HRESULT hr;
+}
+
+alias ENOLEOPFAILED TENOLEOPFAILED;
+alias ENOLEOPFAILED* PENOLEOPFAILED;
+
+align(2) struct ENHMETAHEADER
+{
+    DWORD iType;
+    DWORD nSize;
+    RECTL rclBounds;
+    RECTL rclFrame;
+    DWORD dSignature;
+    DWORD nVersion;
+    DWORD nBytes;
+    DWORD nRecords;
+    ushort nHandles;
+    ushort sReserved;
+    DWORD nDescription;
+    DWORD offDescription;
+    DWORD nPalEntries;
+    SIZEL szlDevice;
+    SIZEL szlMillimeters;
+//#if (WINVER >= 0x0400)
+    DWORD cbPixelFormat;
+    DWORD offPixelFormat;
+    DWORD bOpenGL;
+//#endif /* WINVER >= 0x0400 */
+//#if (WINVER >= 0x0500)
+    SIZEL szlMicrometers;
+//#endif /* WINVER >= 0x0500 */
+}
+
+alias ENHMETAHEADER* LPENHMETAHEADER;
+alias ENHMETAHEADER TAGENHMETAHEADER;
+alias ENHMETAHEADER TENHMETAHEADER;
+alias ENHMETAHEADER* PENHMETAHEADER;
+
+struct ENHMETARECORD
+{
+    DWORD iType;
+    DWORD nSize;
+    DWORD[1 + 0] dParm;
+}
+
+alias ENHMETARECORD* LPENHMETARECORD;
+alias ENHMETARECORD TAGENHMETARECORD;
+alias ENHMETARECORD TENHMETARECORD;
+alias ENHMETARECORD* PENHMETARECORD;
+
+struct ENPROTECTED
+{
+    NMHDR nmhdr;
+    UINT msg;
+    WPARAM wParam;
+    LPARAM lParam;
+    CHARRANGE chrg;
+}
+
+alias ENPROTECTED _ENPROTECTED;
+alias ENPROTECTED TENPROTECTED;
+alias ENPROTECTED* PENPROTECTED;
+
+struct SERVICE_STATUS
+{
+    DWORD dwServiceType;
+    DWORD dwCurrentState;
+    DWORD dwControlsAccepted;
+    DWORD dwWin32ExitCode;
+    DWORD dwServiceSpecificExitCode;
+    DWORD dwCheckPoint;
+    DWORD dwWaitHint;
+}
+
+alias SERVICE_STATUS* LPSERVICE_STATUS;
+alias SERVICE_STATUS _SERVICE_STATUS;
+alias SERVICE_STATUS TSERVICESTATUS;
+alias SERVICE_STATUS* PSERVICESTATUS;
+
+struct ENUM_SERVICE_STATUS
+{
+    LPTSTR lpServiceName;
+    LPTSTR lpDisplayName;
+    SERVICE_STATUS ServiceStatus;
+}
+
+alias ENUM_SERVICE_STATUS* LPENUM_SERVICE_STATUS;
+alias ENUM_SERVICE_STATUS _ENUM_SERVICE_STATUS;
+alias ENUM_SERVICE_STATUS TENUMSERVICESTATUS;
+alias ENUM_SERVICE_STATUS* PENUMSERVICESTATUS;
+
+struct ENUMLOGFONTA {
+  LOGFONTA elfLogFont;
+  BYTE     elfFullName[LF_FULLFACESIZE];
+  BYTE     elfStyle[LF_FACESIZE];
+}
+struct ENUMLOGFONTW {
+  LOGFONTW elfLogFont;
+  WCHAR    elfFullName[LF_FULLFACESIZE];
+  WCHAR    elfStyle[LF_FACESIZE];
+}
+struct ENUMLOGFONTEXA {
+    LOGFONTA  elfLogFont;
+    BYTE      elfFullName[LF_FULLFACESIZE];
+    BYTE      elfStyle[LF_FACESIZE];
+    BYTE      elfScript[LF_FACESIZE];
+}
+struct ENUMLOGFONTEXW {
+    LOGFONTW  elfLogFont;
+    WCHAR     elfFullName[LF_FULLFACESIZE];
+    WCHAR     elfStyle[LF_FACESIZE];
+    WCHAR     elfScript[LF_FACESIZE];
+}
+version(Win32SansUnicode){
+    alias ENUMLOGFONTA ENUMLOGFONT;
+    alias ENUMLOGFONTEXA ENUMLOGFONTEX;
+}else {
+    alias ENUMLOGFONTW ENUMLOGFONT;
+    alias ENUMLOGFONTEXW ENUMLOGFONTEX;
+}
+alias ENUMLOGFONT TAGENUMLOGFONT;
+alias ENUMLOGFONT TENUMLOGFONT;
+alias ENUMLOGFONT* PENUMLOGFONT;
+alias ENUMLOGFONTEX TAGENUMLOGFONTEX;
+alias ENUMLOGFONTEX TENUMLOGFONTEX;
+alias ENUMLOGFONTEX* PENUMLOGFONTEX;
+
+struct EVENTLOGRECORD
+{
+    DWORD Length;
+    DWORD Reserved;
+    DWORD RecordNumber;
+    DWORD TimeGenerated;
+    DWORD TimeWritten;
+    DWORD EventID;
+    ushort EventType;
+    ushort NumStrings;
+    ushort EventCategory;
+    ushort ReservedFlags;
+    DWORD ClosingRecordNumber;
+    DWORD StringOffset;
+    DWORD UserSidLength;
+    DWORD UserSidOffset;
+    DWORD DataLength;
+    DWORD DataOffset;
+}
+
+alias EVENTLOGRECORD _EVENTLOGRECORD;
+alias EVENTLOGRECORD TEVENTLOGRECORD;
+alias EVENTLOGRECORD* PEVENTLOGRECORD;
+
+struct EVENTMSG
+{
+    UINT message;
+    UINT paramL;
+    UINT paramH;
+    DWORD time;
+    HWND hwnd;
+}
+
+alias EVENTMSG TAGEVENTMSG;
+alias EVENTMSG TEVENTMSG;
+alias EVENTMSG* PEVENTMSG;
+
+struct EXCEPTION_POINTERS
+{
+    PEXCEPTION_RECORD ExceptionRecord;
+    PCONTEXT ContextRecord;
+}
+
+alias EXCEPTION_POINTERS* LPEXCEPTION_POINTERS;
+alias EXCEPTION_POINTERS* PEXCEPTION_POINTERS;
+alias EXCEPTION_POINTERS _EXCEPTION_POINTERS;
+alias EXCEPTION_POINTERS TEXCEPTIONPOINTERS;
+alias EXCEPTION_POINTERS* PEXCEPTIONPOINTERS;
+
+struct EXT_BUTTON
+{
+    ushort idCommand;
+    ushort idsHelp;
+    ushort fsStyle;
+}
+
+alias EXT_BUTTON* LPEXT_BUTTON;
+alias EXT_BUTTON _EXT_BUTTON;
+alias EXT_BUTTON TEXTBUTTON;
+alias EXT_BUTTON* PEXTBUTTON;
+
+struct FILTERKEYS
+{
+    UINT cbSize;
+    DWORD dwFlags;
+    DWORD iWaitMSec;
+    DWORD iDelayMSec;
+    DWORD iRepeatMSec;
+    DWORD iBounceMSec;
+}
+
+alias FILTERKEYS TAGFILTERKEYS;
+alias FILTERKEYS TFILTERKEYS;
+alias FILTERKEYS* PFILTERKEYS;
+
+struct FIND_NAME_BUFFER
+{
+    UCHAR length;
+    UCHAR access_control;
+    UCHAR frame_control;
+    UCHAR[1 + 5] destination_addr;
+    UCHAR[1 + 5] source_addr;
+    UCHAR[1 + 17] routing_info;
+}
+
+alias FIND_NAME_BUFFER _FIND_NAME_BUFFER;
+alias FIND_NAME_BUFFER TFINDNAMEBUFFER;
+alias FIND_NAME_BUFFER* PFINDNAMEBUFFER;
+
+struct FIND_NAME_HEADER
+{
+    ushort node_count;
+    UCHAR reserved;
+    UCHAR unique_group;
+}
+
+alias FIND_NAME_HEADER _FIND_NAME_HEADER;
+alias FIND_NAME_HEADER TFINDNAMEHEADER;
+alias FIND_NAME_HEADER* PFINDNAMEHEADER;
+
+struct FINDREPLACE
+{
+    DWORD lStructSize;
+    HWND hwndOwner;
+    HINST hInstance;
+    DWORD Flags;
+    LPTSTR lpstrFindWhat;
+    LPTSTR lpstrReplaceWith;
+    ushort wFindWhatLen;
+    ushort wReplaceWithLen;
+    LPARAM lCustData;
+    LPFRHOOKPROC lpfnHook;
+    LPCTSTR lpTemplateName;
+}
+
+alias FINDREPLACE* LPFINDREPLACE;
+alias FINDREPLACE TFINDREPLACE;
+alias FINDREPLACE* PFINDREPLACE;
+
+struct TFINDTEXT
+{
+    CHARRANGE chrg;
+    LPSTR lpstrText;
+}
+
+alias TFINDTEXT _FINDTEXT;
+alias TFINDTEXT FINDTEXT;
+alias TFINDTEXT* PFINDTEXT;
+
+struct FINDTEXTEX
+{
+    CHARRANGE chrg;
+    LPSTR lpstrText;
+    CHARRANGE chrgText;
+}
+
+alias FINDTEXTEX _FINDTEXTEX;
+alias FINDTEXTEX TFINDTEXTEX;
+alias FINDTEXTEX* PFINDTEXTEX;
+
+struct FMS_GETDRIVEINFO
+{
+    DWORD dwTotalSpace;
+    DWORD dwFreeSpace;
+    TCHAR[1 + 259] szPath;
+    TCHAR[1 + 13] szVolume;
+    TCHAR[1 + 127] szShare;
+}
+
+alias FMS_GETDRIVEINFO _FMS_GETDRIVEINFO;
+alias FMS_GETDRIVEINFO TFMSGETDRIVEINFO;
+alias FMS_GETDRIVEINFO* PFMSGETDRIVEINFO;
+
+struct FMS_GETFILESEL
+{
+    FILETIME ftTime;
+    DWORD dwSize;
+    ubyte bAttr;
+    TCHAR[1 + 259] szName;
+}
+
+alias FMS_GETFILESEL _FMS_GETFILESEL;
+alias FMS_GETFILESEL TFMSGETFILESEL;
+alias FMS_GETFILESEL* PFMSGETFILESEL;
+
+struct FMS_LOAD
+{
+    DWORD dwSize;
+    TCHAR[1 + MENU_TEXT_LEN-1] szMenuName;
+    HMENU hMenu;
+    UINT wMenuDelta;
+}
+
+alias FMS_LOAD _FMS_LOAD;
+alias FMS_LOAD TFMSLOAD;
+alias FMS_LOAD* PFMSLOAD;
+
+struct FMS_TOOLBARLOAD
+{
+    DWORD dwSize;
+    LPEXT_BUTTON lpButtons;
+    ushort cButtons;
+    ushort cBitmaps;
+    ushort idBitmap;
+    HBITMAP hBitmap;
+}
+
+alias FMS_TOOLBARLOAD _FMS_TOOLBARLOAD;
+alias FMS_TOOLBARLOAD TFMSTOOLBARLOAD;
+alias FMS_TOOLBARLOAD* PFMSTOOLBARLOAD;
+
+struct FOCUS_EVENT_RECORD
+{
+    WINBOOL bSetFocus;
+}
+
+alias FOCUS_EVENT_RECORD _FOCUS_EVENT_RECORD;
+alias FOCUS_EVENT_RECORD TFOCUSEVENTRECORD;
+alias FOCUS_EVENT_RECORD* PFOCUSEVENTRECORD;
+
+struct FORM_INFO_1
+{
+    DWORD Flags;
+    LPTSTR pName;
+    SIZEL Size;
+    RECTL ImageableArea;
+}
+
+alias FORM_INFO_1 _FORM_INFO_1;
+alias FORM_INFO_1 TFORMINFO1;
+alias FORM_INFO_1* PFORMINFO1;
+
+struct FORMAT_PARAMETERS
+{
+    MEDIA_TYPE MediaType;
+    DWORD StartCylinderNumber;
+    DWORD EndCylinderNumber;
+    DWORD StartHeadNumber;
+    DWORD EndHeadNumber;
+}
+
+alias FORMAT_PARAMETERS _FORMAT_PARAMETERS;
+alias FORMAT_PARAMETERS TFORMATPARAMETERS;
+alias FORMAT_PARAMETERS* PFORMATPARAMETERS;
+
+struct FORMATRANGE
+{
+    HDC _hdc;
+    HDC hdcTarget;
+    RECT rc;
+    RECT rcPage;
+    CHARRANGE chrg;
+}
+
+alias FORMATRANGE _FORMATRANGE;
+alias FORMATRANGE TFORMATRANGE;
+alias FORMATRANGE* PFORMATRANGE;
+
+struct GCP_RESULTSA
+{
+    DWORD   lStructSize;
+    LPSTR   lpOutString;
+    UINT  * lpOrder;
+    int   * lpDx;
+    int   * lpCaretPos;
+    LPSTR   lpClass;
+    LPWSTR  lpGlyphs;
+    UINT    nGlyphs;
+    int     nMaxFit;
+}
+
+struct GCP_RESULTSW
+{
+    DWORD   lStructSize;
+    LPWSTR  lpOutString;
+    UINT  * lpOrder;
+    int   * lpDx;
+    int   * lpCaretPos;
+    LPSTR   lpClass;
+    LPWSTR  lpGlyphs;
+    UINT    nGlyphs;
+    int     nMaxFit;
+}
+version(Win32SansUnicode)
+{
+    alias GCP_RESULTSA GCP_RESULTS;
+}
+else
+{
+    alias GCP_RESULTSW GCP_RESULTS;
+}
+alias GCP_RESULTS* LPGCP_RESULTS;
+alias GCP_RESULTS TAGGCP_RESULTS;
+alias GCP_RESULTS TGCPRESULTS;
+alias GCP_RESULTS* PGCPRESULTS;
+
+struct GENERIC_MAPPING
+{
+    ACCESS_MASK GenericRead;
+    ACCESS_MASK GenericWrite;
+    ACCESS_MASK GenericExecute;
+    ACCESS_MASK GenericAll;
+}
+
+alias GENERIC_MAPPING* PGENERIC_MAPPING;
+alias GENERIC_MAPPING _GENERIC_MAPPING;
+alias GENERIC_MAPPING TGENERICMAPPING;
+alias GENERIC_MAPPING* PGENERICMAPPING;
+
+struct GLYPHMETRICS
+{
+    UINT gmBlackBoxX;
+    UINT gmBlackBoxY;
+    POINT gmptGlyphOrigin;
+    short gmCellIncX;
+    short gmCellIncY;
+}
+
+alias GLYPHMETRICS* LPGLYPHMETRICS;
+alias GLYPHMETRICS _GLYPHMETRICS;
+alias GLYPHMETRICS TGLYPHMETRICS;
+alias GLYPHMETRICS* PGLYPHMETRICS;
+
+struct HANDLETABLE
+{
+    HGDIOBJ[1 + 0] objectHandle;
+}
+
+alias HANDLETABLE TAGHANDLETABLE;
+alias HANDLETABLE THANDLETABLE;
+alias HANDLETABLE* LPHANDLETABLE;
+
+struct HD_HITTESTINFO
+{
+    POINT pt;
+    UINT flags;
+    int iItem;
+}
+
+alias HD_HITTESTINFO _HD_HITTESTINFO;
+alias HD_HITTESTINFO THDHITTESTINFO;
+alias HD_HITTESTINFO  HDHITTESTINFO;
+alias HD_HITTESTINFO* PHDHITTESTINFO;
+
+struct HD_ITEM
+{
+    UINT mask;
+    int cxy;
+    LPTSTR pszText;
+    HBITMAP hbm;
+    int cchTextMax;
+    int fmt;
+    LPARAM lParam;
+    // _WIN32_IE >= 0x300
+    int iImage;
+    int iOrder;
+    // _WIN32_IE >= 0x500
+    UINT type;
+    void* pvFilter;
+    // _WIN32_WINNT >= 0x600
+    //UINT state;
+}
+
+alias HD_ITEM _HD_ITEM;
+alias HD_ITEM THDITEM;
+alias HD_ITEM* PHDITEM;
+
+struct WINDOWPOS
+{
+    HWND _hwnd;
+    HWND hwndInsertAfter;
+    int x;
+    int y;
+    int cx;
+    int cy;
+    UINT flags;
+}
+
+alias WINDOWPOS* LPWINDOWPOS;
+alias WINDOWPOS _WINDOWPOS;
+alias WINDOWPOS TWINDOWPOS;
+alias WINDOWPOS* PWINDOWPOS;
+
+struct HD_LAYOUT
+{
+    RECT* prc;
+    WINDOWPOS* pwpos;
+}
+
+alias HD_LAYOUT _HD_LAYOUT;
+alias HD_LAYOUT THDLAYOUT;
+alias HD_LAYOUT  HDLAYOUT;
+alias HD_LAYOUT* PHDLAYOUT;
+
+struct HD_NOTIFY
+{
+    NMHDR hdr;
+    int iItem;
+    int iButton;
+    HD_ITEM* pitem;
+}
+
+alias HD_NOTIFY _HD_NOTIFY;
+alias HD_NOTIFY THDNOTIFY;
+alias HD_NOTIFY* PHDNOTIFY;
+
+struct HELPINFO
+{
+    UINT cbSize;
+    int iContextType;
+    int iCtrlId;
+    HANDLE hItemHandle;
+    DWORD dwContextId;
+    POINT MousePos;
+}
+
+alias HELPINFO* LPHELPINFO;
+alias HELPINFO TAGHELPINFO;
+alias HELPINFO THELPINFO;
+alias HELPINFO* PHELPINFO;
+
+struct HELPWININFO
+{
+    int wStructSize;
+    int x;
+    int y;
+    int dx;
+    int dy;
+    int wMax;
+    TCHAR[1 + 1] rgchMember;
+}
+
+alias HELPWININFO THELPWININFO;
+alias HELPWININFO* PHELPWININFO;
+
+struct HIGHCONTRASTA
+{
+    UINT             cbSize;
+    DWORD            dwFlags;
+    LPSTR            lpszDefaultScheme;
+}
+struct HIGHCONTRASTW
+{
+    UINT             cbSize;
+    DWORD            dwFlags;
+    LPWSTR           lpszDefaultScheme;
+}
+version(Win32SansUnicode)
+{
+    alias HIGHCONTRASTA HIGHCONTRAST;
+}
+else
+{
+    alias HIGHCONTRASTW HIGHCONTRAST;
+}
+alias HIGHCONTRAST* LPHIGHCONTRAST;
+alias HIGHCONTRAST TAGHIGHCONTRAST;
+alias HIGHCONTRAST THIGHCONTRAST;
+alias HIGHCONTRAST* PHIGHCONTRAST;
+
+struct HSZPAIR
+{
+    HSZ hszSvc;
+    HSZ hszTopic;
+}
+
+alias HSZPAIR TAGHSZPAIR;
+alias HSZPAIR THSZPAIR;
+alias HSZPAIR* PHSZPAIR;
+
+struct ICONINFO
+{
+    WINBOOL fIcon;
+    DWORD xHotspot;
+    DWORD yHotspot;
+    HBITMAP hbmMask;
+    HBITMAP hbmColor;
+}
+
+alias ICONINFO _ICONINFO;
+alias ICONINFO TICONINFO;
+alias ICONINFO* PICONINFO;
+
+struct ICONMETRICS
+{
+    UINT cbSize;
+    int iHorzSpacing;
+    int iVertSpacing;
+    int iTitleWrap;
+    LOGFONT lfFont;
+}
+
+alias ICONMETRICS* LPICONMETRICS;
+alias ICONMETRICS TAGICONMETRICS;
+alias ICONMETRICS TICONMETRICS;
+alias ICONMETRICS* PICONMETRICS;
+
+struct IMAGEINFO
+{
+    HBITMAP hbmImage;
+    HBITMAP hbmMask;
+    int Unused1;
+    int Unused2;
+    RECT rcImage;
+}
+
+alias IMAGEINFO _IMAGEINFO;
+alias IMAGEINFO TIMAGEINFO;
+alias IMAGEINFO* PIMAGEINFO;
+
+align(1) struct KEY_EVENT_RECORD
+{
+    WINBOOL bKeyDown;
+    ushort wRepeatCount;
+    ushort wVirtualKeyCode;
+    ushort wVirtualScanCode;
+
+    union
+    {
+        struct
+        {
+            WCHAR UnicodeChar;
+            DWORD dwControlKeyState;
+        }
+        struct
+        {
+            char AsciiChar;
+        }
+    }
+}
+
+alias KEY_EVENT_RECORD _KEY_EVENT_RECORD;
+alias KEY_EVENT_RECORD TKEYEVENTRECORD;
+alias KEY_EVENT_RECORD* PKEYEVENTRECORD;
+
+struct MOUSE_EVENT_RECORD
+{
+    COORD dwMousePosition;
+    DWORD dwButtonState;
+    DWORD dwControlKeyState;
+    DWORD dwEventFlags;
+}
+
+alias MOUSE_EVENT_RECORD _MOUSE_EVENT_RECORD;
+alias MOUSE_EVENT_RECORD TMOUSEEVENTRECORD;
+alias MOUSE_EVENT_RECORD* PMOUSEEVENTRECORD;
+
+struct WINDOW_BUFFER_SIZE_RECORD
+{
+    COORD dwSize;
+}
+
+alias WINDOW_BUFFER_SIZE_RECORD _WINDOW_BUFFER_SIZE_RECORD;
+alias WINDOW_BUFFER_SIZE_RECORD TWINDOWBUFFERSIZERECORD;
+alias WINDOW_BUFFER_SIZE_RECORD* PWINDOWBUFFERSIZERECORD;
+
+struct MENU_EVENT_RECORD
+{
+    UINT dwCommandId;
+}
+
+alias MENU_EVENT_RECORD* PMENU_EVENT_RECORD;
+alias MENU_EVENT_RECORD _MENU_EVENT_RECORD;
+alias MENU_EVENT_RECORD TMENUEVENTRECORD;
+alias MENU_EVENT_RECORD* PMENUEVENTRECORD;
+
+struct INPUT_RECORD
+{
+    ushort EventType;
+
+    union
+    {
+        struct
+        {
+            KEY_EVENT_RECORD KeyEvent;
+        }
+        struct
+        {
+            MOUSE_EVENT_RECORD MouseEvent;
+        }
+        struct
+        {
+            WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+        }
+        struct
+        {
+            MENU_EVENT_RECORD MenuEvent;
+        }
+        struct
+        {
+            FOCUS_EVENT_RECORD FocusEvent;
+        }
+    }
+}
+
+alias INPUT_RECORD* PINPUT_RECORD;
+alias INPUT_RECORD _INPUT_RECORD;
+alias INPUT_RECORD TINPUTRECORD;
+alias INPUT_RECORD* PINPUTRECORD;
+
+struct SYSTEMTIME
+{
+    ushort wYear;
+    ushort wMonth;
+    ushort wDayOfWeek;
+    ushort wDay;
+    ushort wHour;
+    ushort wMinute;
+    ushort wSecond;
+    ushort wMilliseconds;
+}
+
+alias SYSTEMTIME* LPSYSTEMTIME;
+alias SYSTEMTIME _SYSTEMTIME;
+alias SYSTEMTIME TSYSTEMTIME;
+alias SYSTEMTIME* PSYSTEMTIME;
+
+struct JOB_INFO_1
+{
+    DWORD JobId;
+    LPTSTR pPrinterName;
+    LPTSTR pMachineName;
+    LPTSTR pUserName;
+    LPTSTR pDocument;
+    LPTSTR pDatatype;
+    LPTSTR pStatus;
+    DWORD Status;
+    DWORD Priority;
+    DWORD Position;
+    DWORD TotalPages;
+    DWORD PagesPrinted;
+    SYSTEMTIME Submitted;
+}
+
+alias JOB_INFO_1 _JOB_INFO_1;
+alias JOB_INFO_1 TJOBINFO1;
+alias JOB_INFO_1* PJOBINFO1;
+
+struct SID_IDENTIFIER_AUTHORITY
+{
+    ubyte[1 + 5] Value;
+}
+
+alias SID_IDENTIFIER_AUTHORITY* LPSID_IDENTIFIER_AUTHORITY;
+alias SID_IDENTIFIER_AUTHORITY* PSID_IDENTIFIER_AUTHORITY;
+alias SID_IDENTIFIER_AUTHORITY _SID_IDENTIFIER_AUTHORITY;
+alias SID_IDENTIFIER_AUTHORITY TSIDIDENTIFIERAUTHORITY;
+alias SID_IDENTIFIER_AUTHORITY* PSIDIDENTIFIERAUTHORITY;
+
+struct SID
+{
+    ubyte Revision;
+    ubyte SubAuthorityCount;
+    SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+    DWORD[1 + ANYSIZE_ARRAY-1] SubAuthority;
+}
+
+alias SID _SID;
+alias SID TSID;
+alias SID* PSID;
+alias ushort SECURITY_DESCRIPTOR_CONTROL;
+alias SECURITY_DESCRIPTOR_CONTROL* PSECURITY_DESCRIPTOR_CONTROL;
+alias SECURITY_DESCRIPTOR_CONTROL TSECURITYDESCRIPTORCONTROL;
+alias SECURITY_DESCRIPTOR_CONTROL* PSECURITYDESCRIPTORCONTROL;
+
+struct SECURITY_DESCRIPTOR
+{
+    ubyte Revision;
+    ubyte Sbz1;
+    SECURITY_DESCRIPTOR_CONTROL Control;
+    PSID Owner;
+    PSID Group;
+    PACL Sacl;
+    PACL Dacl;
+}
+
+alias SECURITY_DESCRIPTOR* PSECURITY_DESCRIPTOR;
+alias SECURITY_DESCRIPTOR _SECURITY_DESCRIPTOR;
+alias SECURITY_DESCRIPTOR TSECURITYDESCRIPTOR;
+alias SECURITY_DESCRIPTOR* PSECURITYDESCRIPTOR;
+
+struct JOB_INFO_2
+{
+    DWORD JobId;
+    LPTSTR pPrinterName;
+    LPTSTR pMachineName;
+    LPTSTR pUserName;
+    LPTSTR pDocument;
+    LPTSTR pNotifyName;
+    LPTSTR pDatatype;
+    LPTSTR pPrintProcessor;
+    LPTSTR pParameters;
+    LPTSTR pDriverName;
+    LPDEVMODE pDevMode;
+    LPTSTR pStatus;
+    PSECURITY_DESCRIPTOR pSecurityDescriptor;
+    DWORD Status;
+    DWORD Priority;
+    DWORD Position;
+    DWORD StartTime;
+    DWORD UntilTime;
+    DWORD TotalPages;
+    DWORD Size;
+    SYSTEMTIME Submitted;
+    DWORD Time;
+    DWORD PagesPrinted;
+}
+
+alias JOB_INFO_2 _JOB_INFO_2;
+alias JOB_INFO_2 TJOBINFO2;
+alias JOB_INFO_2* PJOBINFO2;
+
+struct KERNINGPAIR
+{
+    ushort wFirst;
+    ushort wSecond;
+    int iKernAmount;
+}
+
+alias KERNINGPAIR* LPKERNINGPAIR;
+alias KERNINGPAIR TAGKERNINGPAIR;
+alias KERNINGPAIR TKERNINGPAIR;
+alias KERNINGPAIR* PKERNINGPAIR;
+
+struct LANA_ENUM
+{
+    UCHAR length;
+    UCHAR[1 + MAX_LANA] lana;
+}
+
+alias LANA_ENUM _LANA_ENUM;
+alias LANA_ENUM TLANAENUM;
+alias LANA_ENUM* PLANAENUM;
+
+struct LDT_ENTRY
+{
+    ushort LimitLow;
+    ushort BaseLow;
+
+    union
+    {
+        struct
+        {
+            ubyte BaseMid;
+            ubyte Flags1;
+            ubyte Flags2;
+            ubyte BaseHi;
+        }
+        struct
+        {
+            int flag0;
+        }
+    }
+}
+
+alias LDT_ENTRY* LPLDT_ENTRY;
+alias LDT_ENTRY* PLDT_ENTRY;
+alias LDT_ENTRY _LDT_ENTRY;
+alias LDT_ENTRY TLDTENTRY;
+alias LDT_ENTRY* PLDTENTRY;
+enum : DWORD {
+    bm_LDT_ENTRY_BaseMid = (0xFF),
+    bp_LDT_ENTRY_BaseMid = (0),
+    bm_LDT_ENTRY_Type = (0x1F00),
+    bp_LDT_ENTRY_Type = (8),
+    bm_LDT_ENTRY_Dpl = (0x6000),
+    bp_LDT_ENTRY_Dpl = (13),
+    bm_LDT_ENTRY_Pres = (0x8000),
+    bp_LDT_ENTRY_Pres = (15),
+    bm_LDT_ENTRY_LimitHi = (0xF0000),
+    bp_LDT_ENTRY_LimitHi = (16),
+    bm_LDT_ENTRY_Sys = (0x100000),
+    bp_LDT_ENTRY_Sys = (20),
+    bm_LDT_ENTRY_Reserved_0 = (0x200000),
+    bp_LDT_ENTRY_Reserved_0 = (21),
+    bm_LDT_ENTRY_Default_Big = (0x400000),
+    bp_LDT_ENTRY_Default_Big = (22),
+    bm_LDT_ENTRY_Granularity = (0x800000),
+    bp_LDT_ENTRY_Granularity = (23),
+    bm_LDT_ENTRY_BaseHi = (0xFF000000),
+    bp_LDT_ENTRY_BaseHi = (24),
+}
+
+struct LOCALESIGNATURE
+{
+    DWORD[1 + 3] lsUsb;
+    DWORD[1 + 1] lsCsbDefault;
+    DWORD[1 + 1] lsCsbSupported;
+}
+
+alias LOCALESIGNATURE TAGLOCALESIGNATURE;
+alias LOCALESIGNATURE TLOCALESIGNATURE;
+alias LOCALESIGNATURE* PLOCALESIGNATURE;
+
+struct LOCALGROUP_MEMBERS_INFO_0
+{
+    PSID lgrmi0_sid;
+}
+
+alias LOCALGROUP_MEMBERS_INFO_0 _LOCALGROUP_MEMBERS_INFO_0;
+alias LOCALGROUP_MEMBERS_INFO_0 TLOCALGROUPMEMBERSINFO0;
+alias LOCALGROUP_MEMBERS_INFO_0* PLOCALGROUPMEMBERSINFO0;
+
+struct LOCALGROUP_MEMBERS_INFO_3
+{
+    LPWSTR lgrmi3_domainandname;
+}
+
+alias LOCALGROUP_MEMBERS_INFO_3 _LOCALGROUP_MEMBERS_INFO_3;
+alias LOCALGROUP_MEMBERS_INFO_3 TLOCALGROUPMEMBERSINFO3;
+alias LOCALGROUP_MEMBERS_INFO_3* PLOCALGROUPMEMBERSINFO3;
+alias int FXPT16DOT16;
+alias FXPT16DOT16* LPFXPT16DOT16;
+alias FXPT16DOT16 TFXPT16DOT16;
+alias FXPT16DOT16* PFXPT16DOT16;
+struct LUID {
+    DWORD LowPart;
+    LONG  HighPart;
+}
+alias LUID TLUID;
+alias LUID* PLUID;
+
+struct LUID_AND_ATTRIBUTES
+{
+    LUID Luid;
+    DWORD Attributes;
+}
+
+alias LUID_AND_ATTRIBUTES _LUID_AND_ATTRIBUTES;
+alias LUID_AND_ATTRIBUTES TLUIDANDATTRIBUTES;
+alias LUID_AND_ATTRIBUTES* PLUIDANDATTRIBUTES;
+alias LUID_AND_ATTRIBUTES[1 + ANYSIZE_ARRAY-1] LUID_AND_ATTRIBUTES_ARRAY;
+alias LUID_AND_ATTRIBUTES_ARRAY* PLUID_AND_ATTRIBUTES_ARRAY;
+alias LUID_AND_ATTRIBUTES_ARRAY TLUIDANDATTRIBUTESARRAY;
+alias LUID_AND_ATTRIBUTES_ARRAY* PLUIDANDATTRIBUTESARRAY;
+
+struct LVCOLUMNA {
+    UINT mask;
+    int fmt;
+    int cx;
+    LPSTR pszText;
+    int cchTextMax;
+    int iSubItem;
+    int iImage;
+    //if (_WIN32_IE >= 0x0300)
+    int iOrder;
+    //endif
+    //if (_WIN32_WINNT >= 0x0600)
+    //int cxMin;
+    //int cxDefault;
+    //int cxIdeal;
+    //endif
+}
+struct LVCOLUMNW {
+    UINT mask;
+    int fmt;
+    int cx;
+    LPWSTR pszText;
+    int cchTextMax;
+    int iSubItem;
+    int iImage;
+    //if (_WIN32_IE >= 0x0300)
+    int iOrder;
+    //endif
+    //if (_WIN32_WINNT >= 0x0600)
+    //int cxMin;
+    //int cxDefault;
+    //int cxIdeal;
+    //endif
+}
+version(Win32SansUnicode){
+    alias LVCOLUMNA LVCOLUMN;
+}else{
+    alias LVCOLUMNW LVCOLUMN;
+}
+alias LVCOLUMN* LPLVCOLUMN;
+alias LVCOLUMN LV_COLUMN;
+alias LV_COLUMN _LV_COLUMN;
+alias LV_COLUMN TLVCOLUMN;
+alias LV_COLUMN* PLVCOLUMN;
+
+struct LVITEMA {
+    UINT   mask;
+    int    iItem;
+    int    iSubItem;
+    UINT   state;
+    UINT   stateMask;
+    LPSTR  pszText;
+    int    cchTextMax;
+    int    iImage;
+    LPARAM lParam;
+//if (_WIN32_IE >= 0x0300)
+    int iIndent;
+//endif
+//if (_WIN32_WINNT >= 0x560)
+    int iGroupId;
+    UINT cColumns; // tile view columns
+    PUINT puColumns;
+//endif
+//if (_WIN32_WINNT >= 0x0600)
+//    int* piColFmt;
+//    int iGroup;
+//endif
+}
+struct LVITEMW {
+    UINT   mask;
+    int    iItem;
+    int    iSubItem;
+    UINT   state;
+    UINT   stateMask;
+    LPWSTR  pszText;
+    int    cchTextMax;
+    int    iImage;
+    LPARAM lParam;
+//if (_WIN32_IE >= 0x0300)
+    int iIndent;
+//endif
+//if (_WIN32_WINNT >= 0x560)
+    int iGroupId;
+    UINT cColumns; // tile view columns
+    PUINT puColumns;
+//endif
+//if (_WIN32_WINNT >= 0x0600)
+//    int* piColFmt;
+//    int iGroup;
+//endif
+}
+version(Win32SansUnicode){
+    alias LVITEMA LVITEM;
+}else{
+    alias LVITEMW LVITEM;
+}
+alias LVITEM* LPLVITEM;
+alias LVITEM LV_ITEM;
+
+alias LV_ITEM _LV_ITEM;
+alias LV_ITEM TLVITEM;
+alias LV_ITEM* PLVITEM;
+
+struct LV_DISPINFO
+{
+    NMHDR hdr;
+    LV_ITEM item;
+}
+
+alias LV_DISPINFO TAGLV_DISPINFO;
+alias LV_DISPINFO TLVDISPINFO;
+alias LV_DISPINFO* PLVDISPINFO;
+
+struct LV_FINDINFO
+{
+    UINT flags;
+    LPCTSTR psz;
+    LPARAM lParam;
+    POINT pt;
+    UINT vkDirection;
+}
+
+alias LV_FINDINFO _LV_FINDINFO;
+alias LV_FINDINFO TLVFINDINFO;
+alias LV_FINDINFO* PLVFINDINFO;
+
+struct LVHITTESTINFO
+{
+    POINT pt;
+    UINT flags;
+    int iItem;
+    int iSubItem;
+//#if _WIN32_WINNT >= 0x0600
+//    int iGroup;
+//#endif
+}
+
+alias LVHITTESTINFO LV_HITTESTINFO;
+
+alias LV_HITTESTINFO _LV_HITTESTINFO;
+alias LV_HITTESTINFO TLVHITTESTINFO;
+alias LV_HITTESTINFO* PLVHITTESTINFO;
+
+align(2) struct LV_KEYDOWN
+{
+    NMHDR hdr;
+    ushort wVKey;
+    UINT flags;
+}
+
+alias LV_KEYDOWN TAGLV_KEYDOWN;
+alias LV_KEYDOWN TLVKEYDOWN;
+alias LV_KEYDOWN* PLVKEYDOWN;
+
+struct MAT2
+{
+    FIXED eM11;
+    FIXED eM12;
+    FIXED eM21;
+    FIXED eM22;
+}
+
+alias MAT2 _MAT2;
+alias MAT2 TMAT2;
+alias MAT2* PMAT2;
+
+struct MDICREATESTRUCT
+{
+    LPCTSTR szClass;
+    LPCTSTR szTitle;
+    HANDLE hOwner;
+    int x;
+    int y;
+    int cx;
+    int cy;
+    DWORD style;
+    LPARAM lParam;
+}
+
+alias MDICREATESTRUCT* LPMDICREATESTRUCT;
+alias MDICREATESTRUCT TAGMDICREATESTRUCT;
+alias MDICREATESTRUCT TMDICREATESTRUCT;
+alias MDICREATESTRUCT* PMDICREATESTRUCT;
+
+struct MEASUREITEMSTRUCT
+{
+    UINT CtlType;
+    UINT CtlID;
+    UINT itemID;
+    UINT itemWidth;
+    UINT itemHeight;
+    DWORD itemData;
+}
+
+alias MEASUREITEMSTRUCT* LPMEASUREITEMSTRUCT;
+alias MEASUREITEMSTRUCT TAGMEASUREITEMSTRUCT;
+alias MEASUREITEMSTRUCT TMEASUREITEMSTRUCT;
+alias MEASUREITEMSTRUCT* PMEASUREITEMSTRUCT;
+
+struct MEMORY_BASIC_INFORMATION
+{
+    PVOID BaseAddress;
+    PVOID AllocationBase;
+    DWORD AllocationProtect;
+    DWORD RegionSize;
+    DWORD State;
+    DWORD Protect;
+    DWORD _Type;
+}
+
+alias MEMORY_BASIC_INFORMATION* PMEMORY_BASIC_INFORMATION;
+alias MEMORY_BASIC_INFORMATION _MEMORY_BASIC_INFORMATION;
+alias MEMORY_BASIC_INFORMATION TMEMORYBASICINFORMATION;
+alias MEMORY_BASIC_INFORMATION* PMEMORYBASICINFORMATION;
+
+struct MEMORYSTATUS
+{
+    DWORD dwLength;
+    DWORD dwMemoryLoad;
+    DWORD dwTotalPhys;
+    DWORD dwAvailPhys;
+    DWORD dwTotalPageFile;
+    DWORD dwAvailPageFile;
+    DWORD dwTotalVirtual;
+    DWORD dwAvailVirtual;
+}
+
+alias MEMORYSTATUS* LPMEMORYSTATUS;
+alias MEMORYSTATUS _MEMORYSTATUS;
+alias MEMORYSTATUS TMEMORYSTATUS;
+alias MEMORYSTATUS* PMEMORYSTATUS;
+
+struct MENUEX_TEMPLATE_HEADER
+{
+    ushort wVersion;
+    ushort wOffset;
+    DWORD dwHelpId;
+}
+
+alias MENUEX_TEMPLATE_HEADER TMENUXTEMPLATEHEADER;
+alias MENUEX_TEMPLATE_HEADER* PMENUXTEMPLATEHEADER;
+
+struct MENUEX_TEMPLATE_ITEM
+{
+    DWORD dwType;
+    DWORD dwState;
+    UINT uId;
+    ubyte bResInfo;
+    WCHAR[1 + 0] szText;
+    DWORD dwHelpId;
+}
+
+alias MENUEX_TEMPLATE_ITEM TMENUEXTEMPLATEITEM;
+alias MENUEX_TEMPLATE_ITEM* PMENUEXTEMPLATEITEM;
+
+/*
+* Feature in Windows.  The hbmpItem field requires Windows 4.10
+* or greater.  On Windows NT 4.0, passing in a larger struct size
+* in the cbSize field does nothing.  On Windows 95, the MENUITEMINFO
+* calls fail when the struct size is too large.  The fix is to ensure
+* that the correct struct size is used for the Windows platform.
+*/
+struct MENUITEMINFOA
+{
+    UINT    cbSize;
+    UINT    fMask;
+    UINT    fType;          // used if MIIM_TYPE
+    UINT    fState;         // used if MIIM_STATE
+    UINT    wID;            // used if MIIM_ID
+    HMENU   hSubMenu;       // used if MIIM_SUBMENU
+    HBITMAP hbmpChecked;    // used if MIIM_CHECKMARKS
+    HBITMAP hbmpUnchecked;  // used if MIIM_CHECKMARKS
+    DWORD   dwItemData;     // used if MIIM_DATA
+    LPSTR   dwTypeData;     // used if MIIM_TYPE
+    UINT    cch;            // used if MIIM_TYPE
+    HBITMAP hbmpItem;
+}
+alias MENUITEMINFOA* PMENUITEMINFOA, LPMENUITEMINFOA;
+struct MENUITEMINFOW
+{
+    UINT    cbSize;
+    UINT    fMask;
+    UINT    fType;          // used if MIIM_TYPE
+    UINT    fState;         // used if MIIM_STATE
+    UINT    wID;            // used if MIIM_ID
+    HMENU   hSubMenu;       // used if MIIM_SUBMENU
+    HBITMAP hbmpChecked;    // used if MIIM_CHECKMARKS
+    HBITMAP hbmpUnchecked;  // used if MIIM_CHECKMARKS
+    DWORD   dwItemData;     // used if MIIM_DATA
+    LPWSTR  dwTypeData;     // used if MIIM_TYPE
+    UINT    cch;            // used if MIIM_TYPE
+    HBITMAP hbmpItem;
+}   alias MENUITEMINFOW* PMENUITEMINFOW, LPMENUITEMINFOW;
+version(Win32SansUnicode)
+{
+    alias MENUITEMINFOA MENUITEMINFO;
+}
+else
+{
+    alias MENUITEMINFOW MENUITEMINFO;
+}
+alias MENUITEMINFO * LPMENUITEMINFO;
+alias MENUITEMINFO * LPCMENUITEMINFO;
+alias MENUITEMINFO TAGMENUITEMINFO;
+alias MENUITEMINFO TMENUITEMINFO;
+alias MENUITEMINFO TMENUITEMINFOA;
+alias MENUITEMINFO* PMENUITEMINFO;
+
+struct MENUITEMTEMPLATE
+{
+    ushort mtOption;
+    ushort mtID;
+    WCHAR[1 + 0] mtString;
+}
+
+alias MENUITEMTEMPLATE TMENUITEMTEMPLATE;
+alias MENUITEMTEMPLATE* PMENUITEMTEMPLATE;
+
+struct MENUITEMTEMPLATEHEADER
+{
+    ushort versionNumber;
+    ushort offset;
+}
+
+alias MENUITEMTEMPLATEHEADER TMENUITEMTEMPLATEHEADER;
+alias MENUITEMTEMPLATEHEADER* PMENUITEMTEMPLATEHEADER;
+
+struct MENUTEMPLATE
+{
+}
+
+alias MENUTEMPLATE* LPMENUTEMPLATE;
+alias MENUTEMPLATE TMENUTEMPLATE;
+alias MENUTEMPLATE* PMENUTEMPLATE;
+
+struct METAFILEPICT
+{
+    LONG mm;
+    LONG xExt;
+    LONG yExt;
+    HMETAFILE hMF;
+}
+
+alias METAFILEPICT* LPMETAFILEPICT;
+alias METAFILEPICT TAGMETAFILEPICT;
+alias METAFILEPICT TMETAFILEPICT;
+alias METAFILEPICT* PMETAFILEPICT;
+
+align(1) struct METAHEADER
+{
+    ushort mtType;
+    ushort mtHeaderSize;
+    ushort mtVersion;
+    DWORD mtSize;
+    ushort mtNoObjects;
+    DWORD mtMaxRecord;
+    ushort mtNoParameters;
+}
+
+alias METAHEADER TAGMETAHEADER;
+alias METAHEADER TMETAHEADER;
+alias METAHEADER* PMETAHEADER;
+
+struct METARECORD
+{
+    DWORD rdSize;
+    ushort rdFunction;
+    ushort[1 + 0] rdParm;
+}
+
+alias METARECORD* LPMETARECORD;
+alias METARECORD TAGMETARECORD;
+alias METARECORD TMETARECORD;
+alias METARECORD* PMETARECORD;
+
+struct MINIMIZEDMETRICS
+{
+    UINT cbSize;
+    int iWidth;
+    int iHorzGap;
+    int iVertGap;
+    int iArrange;
+}
+
+alias MINIMIZEDMETRICS* LPMINIMIZEDMETRICS;
+alias MINIMIZEDMETRICS TAGMINIMIZEDMETRICS;
+alias MINIMIZEDMETRICS TMINIMIZEDMETRICS;
+alias MINIMIZEDMETRICS* PMINIMIZEDMETRICS;
+
+struct MINMAXINFO
+{
+    POINT ptReserved;
+    POINT ptMaxSize;
+    POINT ptMaxPosition;
+    POINT ptMinTrackSize;
+    POINT ptMaxTrackSize;
+}
+
+alias MINMAXINFO TAGMINMAXINFO;
+alias MINMAXINFO TMINMAXINFO;
+alias MINMAXINFO* PMINMAXINFO;
+
+struct MODEMDEVCAPS
+{
+    DWORD dwActualSize;
+    DWORD dwRequiredSize;
+    DWORD dwDevSpecificOffset;
+    DWORD dwDevSpecificSize;
+    DWORD dwModemProviderVersion;
+    DWORD dwModemManufacturerOffset;
+    DWORD dwModemManufacturerSize;
+    DWORD dwModemModelOffset;
+    DWORD dwModemModelSize;
+    DWORD dwModemVersionOffset;
+    DWORD dwModemVersionSize;
+    DWORD dwDialOptions;
+    DWORD dwCallSetupFailTimer;
+    DWORD dwInactivityTimeout;
+    DWORD dwSpeakerVolume;
+    DWORD dwSpeakerMode;
+    DWORD dwModemOptions;
+    DWORD dwMaxDTERate;
+    DWORD dwMaxDCERate;
+    ubyte[1 + 0] abVariablePortion;
+}
+
+alias MODEMDEVCAPS* LPMODEMDEVCAPS;
+alias MODEMDEVCAPS TMODEMDEVCAPS;
+alias MODEMDEVCAPS* PMODEMDEVCAPS;
+alias MODEMDEVCAPS MODEMDEVCAPS_TAG;
+
+struct MODEMSETTINGS
+{
+    DWORD dwActualSize;
+    DWORD dwRequiredSize;
+    DWORD dwDevSpecificOffset;
+    DWORD dwDevSpecificSize;
+    DWORD dwCallSetupFailTimer;
+    DWORD dwInactivityTimeout;
+    DWORD dwSpeakerVolume;
+    DWORD dwSpeakerMode;
+    DWORD dwPreferredModemOptions;
+    DWORD dwNegotiatedModemOptions;
+    DWORD dwNegotiatedDCERate;
+    ubyte[1 + 0] abVariablePortion;
+}
+
+alias MODEMSETTINGS* LPMODEMSETTINGS;
+alias MODEMSETTINGS TMODEMSETTINGS;
+alias MODEMSETTINGS* PMODEMSETTINGS;
+alias MODEMSETTINGS MODEMSETTINGS_TAG;
+
+struct MONCBSTRUCT
+{
+    UINT cb;
+    DWORD dwTime;
+    HANDLE hTask;
+    DWORD dwRet;
+    UINT wType;
+    UINT wFmt;
+    HCONV hConv;
+    HSZ hsz1;
+    HSZ hsz2;
+    HDDEDATA hData;
+    DWORD dwData1;
+    DWORD dwData2;
+    CONVCONTEXT cc;
+    DWORD cbData;
+    DWORD[1 + 7] Data;
+}
+
+alias MONCBSTRUCT TAGMONCBSTRUCT;
+alias MONCBSTRUCT TMONCBSTRUCT;
+alias MONCBSTRUCT* PMONCBSTRUCT;
+
+struct MONCONVSTRUCT
+{
+    UINT cb;
+    WINBOOL fConnect;
+    DWORD dwTime;
+    HANDLE hTask;
+    HSZ hszSvc;
+    HSZ hszTopic;
+    HCONV hConvClient;
+    HCONV hConvServer;
+}
+
+alias MONCONVSTRUCT TAGMONCONVSTRUCT;
+alias MONCONVSTRUCT TMONCONVSTRUCT;
+alias MONCONVSTRUCT* PMONCONVSTRUCT;
+
+struct MONERRSTRUCT
+{
+    UINT cb;
+    UINT wLastError;
+    DWORD dwTime;
+    HANDLE hTask;
+}
+
+alias MONERRSTRUCT TAGMONERRSTRUCT;
+alias MONERRSTRUCT TMONERRSTRUCT;
+alias MONERRSTRUCT* PMONERRSTRUCT;
+
+struct MONHSZSTRUCT
+{
+    UINT cb;
+    WINBOOL fsAction;
+    DWORD dwTime;
+    HSZ hsz;
+    HANDLE hTask;
+    TCHAR[1 + 0] str;
+}
+
+alias MONHSZSTRUCT TAGMONHSZSTRUCT;
+alias MONHSZSTRUCT TMONHSZSTRUCT;
+alias MONHSZSTRUCT* PMONHSZSTRUCT;
+
+struct MONITOR_INFO_1
+{
+    LPTSTR pName;
+}
+
+alias MONITOR_INFO_1 _MONITOR_INFO_1;
+alias MONITOR_INFO_1 TMONITORINFO1;
+alias MONITOR_INFO_1* PMONITORINFO1;
+
+struct MONITOR_INFO_2
+{
+    LPTSTR pName;
+    LPTSTR pEnvironment;
+    LPTSTR pDLLName;
+}
+
+alias MONITOR_INFO_2 _MONITOR_INFO_2;
+alias MONITOR_INFO_2 TMONITORINFO2;
+alias MONITOR_INFO_2* PMONITORINFO2;
+
+struct MONLINKSTRUCT
+{
+    UINT cb;
+    DWORD dwTime;
+    HANDLE hTask;
+    WINBOOL fEstablished;
+    WINBOOL fNoData;
+    HSZ hszSvc;
+    HSZ hszTopic;
+    HSZ hszItem;
+    UINT wFmt;
+    WINBOOL fServer;
+    HCONV hConvServer;
+    HCONV hConvClient;
+}
+
+alias MONLINKSTRUCT TAGMONLINKSTRUCT;
+alias MONLINKSTRUCT TMONLINKSTRUCT;
+alias MONLINKSTRUCT* PMONLINKSTRUCT;
+
+struct MONMSGSTRUCT
+{
+    UINT cb;
+    HWND hwndTo;
+    DWORD dwTime;
+    HANDLE hTask;
+    UINT wMsg;
+    WPARAM wParam;
+    LPARAM lParam;
+    DDEML_MSG_HOOK_DATA dmhd;
+}
+
+alias MONMSGSTRUCT TAGMONMSGSTRUCT;
+alias MONMSGSTRUCT TMONMSGSTRUCT;
+alias MONMSGSTRUCT* PMONMSGSTRUCT;
+
+struct MOUSEHOOKSTRUCT
+{
+    POINT pt;
+    HWND hwnd;
+    UINT wHitTestCode;
+    DWORD dwExtraInfo;
+}
+
+alias MOUSEHOOKSTRUCT* LPMOUSEHOOKSTRUCT;
+alias MOUSEHOOKSTRUCT TAGMOUSEHOOKSTRUCT;
+alias MOUSEHOOKSTRUCT TMOUSEHOOKSTRUCT;
+alias MOUSEHOOKSTRUCT* PMOUSEHOOKSTRUCT;
+
+struct MOUSEKEYS
+{
+    DWORD cbSize;
+    DWORD dwFlags;
+    DWORD iMaxSpeed;
+    DWORD iTimeToMaxSpeed;
+    DWORD iCtrlSpeed;
+    DWORD dwReserved1;
+    DWORD dwReserved2;
+}
+
+alias MOUSEKEYS TMOUSEKEYS;
+alias MOUSEKEYS* PMOUSEKEYS;
+
+struct MSG
+{
+    HWND hwnd;
+    UINT message;
+    WPARAM wParam;
+    LPARAM lParam;
+    DWORD time;
+    POINT pt;
+}
+
+alias MSG* LPMSG;
+alias MSG TAGMSG;
+alias MSG TMSG;
+alias MSG* PMSG;
+extern(Windows){
+alias void (*MSGBOXCALLBACK)(LPHELPINFO);
+}
+alias MSGBOXCALLBACK TMSGBOXCALLBACK;
+
+struct MSGBOXPARAMS
+{
+    UINT cbSize;
+    HWND hwndOwner;
+    HINST hInstance;
+    LPCSTR lpszText;
+    LPCSTR lpszCaption;
+    DWORD dwStyle;
+    LPCSTR lpszIcon;
+    DWORD dwContextHelpId;
+    MSGBOXCALLBACK lpfnMsgBoxCallback;
+    DWORD dwLanguageId;
+}
+
+alias MSGBOXPARAMS* LPMSGBOXPARAMS;
+alias MSGBOXPARAMS TMSGBOXPARAMS;
+alias MSGBOXPARAMS TMSGBOXPARAMSA;
+alias MSGBOXPARAMS* PMSGBOXPARAMS;
+
+struct MSGFILTER
+{
+    NMHDR nmhdr;
+    UINT msg;
+    WPARAM wParam;
+    LPARAM lParam;
+}
+
+alias MSGFILTER _MSGFILTER;
+alias MSGFILTER TMSGFILTER;
+alias MSGFILTER* PMSGFILTER;
+
+struct MULTIKEYHELP
+{
+    DWORD mkSize;
+    TCHAR mkKeylist;
+    TCHAR[1 + 0] szKeyphrase;
+}
+
+alias MULTIKEYHELP TAGMULTIKEYHELP;
+alias MULTIKEYHELP TMULTIKEYHELP;
+alias MULTIKEYHELP* PMULTIKEYHELP;
+
+struct NAME_BUFFER
+{
+    UCHAR[1 + NCBNAMSZ-1] name;
+    UCHAR name_num;
+    UCHAR name_flags;
+}
+
+alias NAME_BUFFER _NAME_BUFFER;
+alias NAME_BUFFER TNAMEBUFFER;
+alias NAME_BUFFER* PNAMEBUFFER;
+alias _NCB* P_NCB;
+
+struct NCB
+{
+    UCHAR ncb_command;
+    UCHAR ncb_retcode;
+    UCHAR ncb_lsn;
+    UCHAR ncb_num;
+    PUCHAR ncb_buffer;
+    ushort ncb_length;
+    UCHAR[1 + NCBNAMSZ-1] ncb_callname;
+    UCHAR[1 + NCBNAMSZ-1] ncb_name;
+    UCHAR ncb_rto;
+    UCHAR ncb_sto;
+    POINTER ncb_post;
+    UCHAR ncb_lana_num;
+    UCHAR ncb_cmd_cplt;
+    UCHAR[1 + 9] ncb_reserve;
+    HANDLE ncb_event;
+}
+
+alias NCB _NCB;
+alias NCB TNCB;
+alias NCB* PNCB;
+
+struct NCCALCSIZE_PARAMS
+{
+    RECT[1 + 2] rgrc;
+    PWINDOWPOS lppos;
+}
+
+alias NCCALCSIZE_PARAMS _NCCALCSIZE_PARAMS;
+alias NCCALCSIZE_PARAMS TNCCALCSIZEPARAMS;
+alias NCCALCSIZE_PARAMS* PNCCALCSIZEPARAMS;
+
+struct NDDESHAREINFO
+{
+    LONG lRevision;
+    LPTSTR lpszShareName;
+    LONG lShareType;
+    LPTSTR lpszAppTopicList;
+    LONG fSharedFlag;
+    LONG fService;
+    LONG fStartAppFlag;
+    LONG nCmdShow;
+    LONG[1 + 1] qModifyId;
+    LONG cNumItems;
+    LPTSTR lpszItemList;
+}
+
+alias NDDESHAREINFO _NDDESHAREINFO;
+alias NDDESHAREINFO TNDDESHAREINFO;
+alias NDDESHAREINFO* PNDDESHAREINFO;
+
+struct NETRESOURCE
+{
+    DWORD dwScope;
+    DWORD dwType;
+    DWORD dwDisplayType;
+    DWORD dwUsage;
+    LPTSTR lpLocalName;
+    LPTSTR lpRemoteName;
+    LPTSTR lpComment;
+    LPTSTR lpProvider;
+}
+
+alias NETRESOURCE* LPNETRESOURCE;
+alias NETRESOURCE _NETRESOURCE;
+alias NETRESOURCE TNETRESOURCE;
+alias NETRESOURCE TNETRESOURCEA;
+alias NETRESOURCE* PNETRESOURCE;
+alias NETRESOURCE* PNETRESOURCEA;
+
+struct NEWCPLINFO
+{
+    DWORD dwSize;
+    DWORD dwFlags;
+    DWORD dwHelpContext;
+    LONG lData;
+    HICON hIcon;
+    TCHAR[1 + 31] szName;
+    TCHAR[1 + 63] szInfo;
+    TCHAR[1 + 127] szHelpFile;
+}
+
+alias NEWCPLINFO TAGNEWCPLINFO;
+alias NEWCPLINFO TNEWCPLINFO;
+alias NEWCPLINFO* PNEWCPLINFO;
+
+struct NEWTEXTMETRICA {
+    LONG   tmHeight;
+    LONG   tmAscent;
+    LONG   tmDescent;
+    LONG   tmInternalLeading;
+    LONG   tmExternalLeading;
+    LONG   tmAveCharWidth;
+    LONG   tmMaxCharWidth;
+    LONG   tmWeight;
+    LONG   tmOverhang;
+    LONG   tmDigitizedAspectX;
+    LONG   tmDigitizedAspectY;
+    BYTE  tmFirstChar;
+    BYTE  tmLastChar;
+    BYTE  tmDefaultChar;
+    BYTE  tmBreakChar;
+    BYTE   tmItalic;
+    BYTE   tmUnderlined;
+    BYTE   tmStruckOut;
+    BYTE   tmPitchAndFamily;
+    BYTE   tmCharSet;
+    DWORD  ntmFlags;
+    UINT   ntmSizeEM;
+    UINT   ntmCellHeight;
+    UINT   ntmAvgWidth;
+}
+struct NEWTEXTMETRICW {
+    LONG   tmHeight;
+    LONG   tmAscent;
+    LONG   tmDescent;
+    LONG   tmInternalLeading;
+    LONG   tmExternalLeading;
+    LONG   tmAveCharWidth;
+    LONG   tmMaxCharWidth;
+    LONG   tmWeight;
+    LONG   tmOverhang;
+    LONG   tmDigitizedAspectX;
+    LONG   tmDigitizedAspectY;
+    WCHAR  tmFirstChar;
+    WCHAR  tmLastChar;
+    WCHAR  tmDefaultChar;
+    WCHAR  tmBreakChar;
+    BYTE   tmItalic;
+    BYTE   tmUnderlined;
+    BYTE   tmStruckOut;
+    BYTE   tmPitchAndFamily;
+    BYTE   tmCharSet;
+    DWORD  ntmFlags;
+    UINT   ntmSizeEM;
+    UINT   ntmCellHeight;
+    UINT   ntmAvgWidth;
+}
+
+struct NEWTEXTMETRICEXA
+{
+    NEWTEXTMETRICA  ntmentm;
+    FONTSIGNATURE  ntmeFontSignature;
+}
+struct NEWTEXTMETRICEXW
+{
+    NEWTEXTMETRICW  ntmentm;
+    FONTSIGNATURE  ntmeFontSignature;
+}
+
+
+version(Win32SansUnicode)
+{
+    alias NEWTEXTMETRICA NEWTEXTMETRIC;
+    alias NEWTEXTMETRICEXA NEWTEXTMETRICEX;
+}
+else
+{
+    alias NEWTEXTMETRICW NEWTEXTMETRIC;
+    alias NEWTEXTMETRICEXW NEWTEXTMETRICEX;
+}
+
+alias NEWTEXTMETRIC TNEWTEXTMETRIC;
+alias NEWTEXTMETRIC* PNEWTEXTMETRIC;
+alias NEWTEXTMETRIC* LPNEWTEXTMETRIC;
+alias NEWTEXTMETRIC TAGNEWTEXTMETRIC;
+alias NEWTEXTMETRICEX TAGNEWTEXTMETRICEX;
+alias NEWTEXTMETRICEX TNEWTEXTMETRICEX;
+alias NEWTEXTMETRICEX* PNEWTEXTMETRICEX;
+
+struct NM_LISTVIEW
+{
+    NMHDR hdr;
+    int iItem;
+    int iSubItem;
+    UINT uNewState;
+    UINT uOldState;
+    UINT uChanged;
+    POINT ptAction;
+    LPARAM lParam;
+}
+
+alias NM_LISTVIEW TAGNM_LISTVIEW;
+alias NM_LISTVIEW TNMLISTVIEW;
+alias NM_LISTVIEW* PNMLISTVIEW;
+
+struct TVITEMA
+{
+    UINT      mask;
+    HTREEITEM hItem;
+    UINT      state;
+    UINT      stateMask;
+    LPSTR     pszText;
+    int       cchTextMax;
+    int       iImage;
+    int       iSelectedImage;
+    int       cChildren;
+    LPARAM    lParam;
+}
+struct TVITEMW
+{
+    UINT      mask;
+    HTREEITEM hItem;
+    UINT      state;
+    UINT      stateMask;
+    LPWSTR    pszText;
+    int       cchTextMax;
+    int       iImage;
+    int       iSelectedImage;
+    int       cChildren;
+    LPARAM    lParam;
+}
+version(Win32SansUnicode)
+{
+    alias TVITEMA TVITEM;
+}
+else
+{
+    alias TVITEMW TVITEM;
+}
+alias TVITEM* LPTVITEM;
+alias TVITEM* LPTV_ITEM;
+alias TVITEM _TV_ITEM;
+alias TVITEM TTVITEM;
+alias TVITEM TV_ITEM;
+alias TVITEM* PTVITEM;
+
+struct TVITEMEXA {
+    UINT      mask;
+    HTREEITEM hItem;
+    UINT      state;
+    UINT      stateMask;
+    LPSTR     pszText;
+    int       cchTextMax;
+    int       iImage;
+    int       iSelectedImage;
+    int       cChildren;
+    LPARAM    lParam;
+    int       iIntegral;
+//#if (_WIN32_IE >= 0x0600)
+//    UINT      uStateEx;
+//    HWND      hwnd;
+//    int       iExpandedImage;
+//#endif
+}
+struct TVITEMEXW {
+    UINT      mask;
+    HTREEITEM hItem;
+    UINT      state;
+    UINT      stateMask;
+    LPWSTR    pszText;
+    int       cchTextMax;
+    int       iImage;
+    int       iSelectedImage;
+    int       cChildren;
+    LPARAM    lParam;
+    int       iIntegral;
+//#if (_WIN32_IE >= 0x0600)
+//    UINT      uStateEx;
+//    HWND      hwnd;
+//    int       iExpandedImage;
+//#endif
+}
+version(Win32SansUnicode)
+{
+    alias TVITEMEXA TVITEMEX;
+}
+else
+{
+    alias TVITEMEXW TVITEMEX;
+}
+alias TVITEMEX * LPTVITEMEX;
+
+struct NMTREEVIEW
+{
+    NMHDR hdr;
+    UINT action;
+    TVITEM itemOld;
+    TVITEM itemNew;
+    POINT ptDrag;
+}
+alias NMTREEVIEW* PNMTREEVIEW;
+alias NMTREEVIEW* LPNMTREEVIEW;
+alias NMTREEVIEW  NM_TREEVIEW;
+alias NM_TREEVIEW* LPNM_TREEVIEW;
+alias NM_TREEVIEW _NM_TREEVIEW;
+alias NM_TREEVIEW TNMTREEVIEW;
+
+struct NM_UPDOWNW
+{
+    NMHDR hdr;
+    int iPos;
+    int iDelta;
+}
+
+alias NM_UPDOWNW _NM_UPDOWN;
+alias NM_UPDOWNW TNMUPDOWN;
+alias NM_UPDOWNW* PNMUPDOWN;
+alias NM_UPDOWNW NMUPDOWN;
+
+struct NONCLIENTMETRICSA {
+    int cbSize;
+    int iBorderWidth;
+    int iScrollWidth;
+    int iScrollHeight;
+    int iCaptionWidth;
+    int iCaptionHeight;
+    LOGFONTA lfCaptionFont;
+    int iSmCaptionWidth;
+    int iSmCaptionHeight;
+    LOGFONTA lfSmCaptionFont;
+    int iMenuWidth;
+    int iMenuHeight;
+    LOGFONTA lfMenuFont;
+    LOGFONTA lfStatusFont;
+    LOGFONTA lfMessageFont;
+//if (WINVER >= 0x0600)
+//  int iPaddedBorderWidth;
+//endif 
+
+}
+struct NONCLIENTMETRICSW {
+    int cbSize;
+    int iBorderWidth;
+    int iScrollWidth;
+    int iScrollHeight;
+    int iCaptionWidth;
+    int iCaptionHeight;
+    LOGFONTW lfCaptionFont;
+    int iSmCaptionWidth;
+    int iSmCaptionHeight;
+    LOGFONTW lfSmCaptionFont;
+    int iMenuWidth;
+    int iMenuHeight;
+    LOGFONTW lfMenuFont;
+    LOGFONTW lfStatusFont;
+    LOGFONTW lfMessageFont;
+//if (WINVER >= 0x0600)
+//  int iPaddedBorderWidth;
+//endif 
+}
+version(Win32SansUnicode)
+{
+    alias NONCLIENTMETRICSA NONCLIENTMETRICS;
+}
+else
+{
+    alias NONCLIENTMETRICSW NONCLIENTMETRICS;
+}
+alias NONCLIENTMETRICS* LPNONCLIENTMETRICS;
+alias NONCLIENTMETRICS TAGNONCLIENTMETRICS;
+alias NONCLIENTMETRICS TNONCLIENTMETRICS;
+alias NONCLIENTMETRICS* PNONCLIENTMETRICS;
+
+struct SERVICE_ADDRESS
+{
+    DWORD dwAddressType;
+    DWORD dwAddressFlags;
+    DWORD dwAddressLength;
+    DWORD dwPrincipalLength;
+    ubyte* lpAddress;
+    ubyte* lpPrincipal;
+}
+
+alias SERVICE_ADDRESS _SERVICE_ADDRESS;
+alias SERVICE_ADDRESS TSERVICEADDRESS;
+alias SERVICE_ADDRESS* PSERVICEADDRESS;
+
+struct SERVICE_ADDRESSES
+{
+    DWORD dwAddressCount;
+    SERVICE_ADDRESS[1 + 0] Addresses;
+}
+
+alias SERVICE_ADDRESSES* LPSERVICE_ADDRESSES;
+alias SERVICE_ADDRESSES _SERVICE_ADDRESSES;
+alias SERVICE_ADDRESSES TSERVICEADDRESSES;
+alias SERVICE_ADDRESSES* PSERVICEADDRESSES;
+
+align(1) struct __GUID
+{
+
+    union
+    {
+        struct
+        {
+            uint Data1;
+            ushort Data2;
+            ushort Data3;
+            ubyte[1 + 7] Data4;
+        }
+        struct
+        {
+            uint D1;
+            ushort D2;
+            ushort D3;
+            ubyte[1 + 7] D4;
+        }
+    }
+}
+
+alias __GUID* LPGUID;
+alias __GUID _GUID;
+alias __GUID GUID;
+alias __GUID TGUID;
+alias __GUID* PGUID;
+alias __GUID __CLSID;
+alias __CLSID* LPCLSID;
+alias __CLSID TCLSID;
+alias __CLSID* PCLSID;
+
+struct SERVICE_INFO
+{
+    LPGUID lpServiceType;
+    LPTSTR lpServiceName;
+    LPTSTR lpComment;
+    LPTSTR lpLocale;
+    DWORD dwDisplayHint;
+    DWORD dwVersion;
+    DWORD dwTime;
+    LPTSTR lpMachineName;
+    LPSERVICE_ADDRESSES lpServiceAddress;
+    BLOB ServiceSpecificInfo;
+}
+
+alias SERVICE_INFO _SERVICE_INFO;
+alias SERVICE_INFO TSERVICEINFO;
+alias SERVICE_INFO* PSERVICEINFO;
+
+struct NS_SERVICE_INFO
+{
+    DWORD dwNameSpace;
+    SERVICE_INFO ServiceInfo;
+}
+
+alias NS_SERVICE_INFO _NS_SERVICE_INFO;
+alias NS_SERVICE_INFO TNSSERVICEINFO;
+alias NS_SERVICE_INFO* PNSSERVICEINFO;
+
+struct NUMBERFMT
+{
+    UINT NumDigits;
+    UINT LeadingZero;
+    UINT Grouping;
+    LPTSTR lpDecimalSep;
+    LPTSTR lpThousandSep;
+    UINT NegativeOrder;
+}
+
+alias NUMBERFMT _NUMBERFMT;
+alias NUMBERFMT TNUMBERFMT;
+alias NUMBERFMT* PNUMBERFMT;
+
+struct OFSTRUCT
+{
+    ubyte cBytes;
+    ubyte fFixedDisk;
+    ushort nErrCode;
+    ushort Reserved1;
+    ushort Reserved2;
+    char[1 + OFS_MAXPATHNAME-1] szPathName;
+}
+
+alias OFSTRUCT* LPOFSTRUCT;
+alias OFSTRUCT _OFSTRUCT;
+alias OFSTRUCT TOFSTRUCT;
+alias OFSTRUCT* POFSTRUCT;
+
+struct OPENFILENAME
+{
+    DWORD lStructSize;
+    HWND hwndOwner;
+    HINST hInstance;
+    LPCTSTR lpstrFilter;
+    LPTSTR lpstrCustomFilter;
+    DWORD nMaxCustFilter;
+    DWORD nFilterIndex;
+    LPTSTR lpstrFile;
+    DWORD nMaxFile;
+    LPTSTR lpstrFileTitle;
+    DWORD nMaxFileTitle;
+    LPCTSTR lpstrInitialDir;
+    LPCTSTR lpstrTitle;
+    DWORD Flags;
+    ushort nFileOffset;
+    ushort nFileExtension;
+    LPCTSTR lpstrDefExt;
+    DWORD lCustData;
+    LPOFNHOOKPROC lpfnHook;
+    LPCTSTR lpTemplateName;
+//if (_WIN32_WINNT >= 0x0500)
+  void *        pvReserved;
+  DWORD         dwReserved;
+  DWORD         FlagsEx;
+//endif // (_WIN32_WINNT >= 0x0500)
+}
+
+alias OPENFILENAME* LPOPENFILENAME;
+alias OPENFILENAME TOPENFILENAME;
+alias OPENFILENAME* POPENFILENAME;
+alias OPENFILENAME TAGOFN;
+alias OPENFILENAME TOFN;
+alias OPENFILENAME* POFN;
+
+struct OFNOTIFY
+{
+    NMHDR hdr;
+    LPOPENFILENAME lpOFN;
+    LPTSTR pszFile;
+}
+
+alias OFNOTIFY* LPOFNOTIFY;
+alias OFNOTIFY _OFNOTIFY;
+alias OFNOTIFY TOFNOTIFY;
+alias OFNOTIFY* POFNOTIFY;
+
+struct OSVERSIONINFOA
+{
+    DWORD dwOSVersionInfoSize;
+    DWORD dwMajorVersion;
+    DWORD dwMinorVersion;
+    DWORD dwBuildNumber;
+    DWORD dwPlatformId;
+    CHAR szCSDVersion[ 128 ];
+}
+alias OSVERSIONINFOA* POSVERSIONINFOA, LPOSVERSIONINFOA;
+
+struct OSVERSIONINFOW
+{
+    DWORD dwOSVersionInfoSize;
+    DWORD dwMajorVersion;
+    DWORD dwMinorVersion;
+    DWORD dwBuildNumber;
+    DWORD dwPlatformId;
+    WCHAR szCSDVersion[ 128 ];
+}
+alias OSVERSIONINFOW* POSVERSIONINFOW, LPOSVERSIONINFOW;
+version(Win32SansUnicode)
+{
+    alias OSVERSIONINFOA OSVERSIONINFO;
+}
+else
+{
+    alias OSVERSIONINFOW OSVERSIONINFO;
+}
+alias OSVERSIONINFO* LPOSVERSIONINFO;
+alias OSVERSIONINFO _OSVERSIONINFO;
+alias OSVERSIONINFO TOSVERSIONINFO;
+alias OSVERSIONINFO* POSVERSIONINFO;
+
+struct TEXTMETRICA {
+    LONG tmHeight;
+    LONG tmAscent;
+    LONG tmDescent;
+    LONG tmInternalLeading;
+    LONG tmExternalLeading;
+    LONG tmAveCharWidth;
+    LONG tmMaxCharWidth;
+    LONG tmWeight;
+    LONG tmOverhang;
+    LONG tmDigitizedAspectX;
+    LONG tmDigitizedAspectY;
+
+    BYTE tmFirstChar;
+    BYTE tmLastChar;
+    BYTE tmDefaultChar;
+    BYTE tmBreakChar;
+
+    BYTE tmItalic;
+    BYTE tmUnderlined;
+    BYTE tmStruckOut;
+    BYTE tmPitchAndFamily;
+    BYTE tmCharSet;
+}
+struct TEXTMETRICW {
+    LONG tmHeight;
+    LONG tmAscent;
+    LONG tmDescent;
+    LONG tmInternalLeading;
+    LONG tmExternalLeading;
+    LONG tmAveCharWidth;
+    LONG tmMaxCharWidth;
+    LONG tmWeight;
+    LONG tmOverhang;
+    LONG tmDigitizedAspectX;
+    LONG tmDigitizedAspectY;
+
+    WCHAR tmFirstChar;
+    WCHAR tmLastChar;
+    WCHAR tmDefaultChar;
+    WCHAR tmBreakChar;
+
+    BYTE tmItalic;
+    BYTE tmUnderlined;
+    BYTE tmStruckOut;
+    BYTE tmPitchAndFamily;
+    BYTE tmCharSet;
+}
+version(Win32SansUnicode)
+{
+    alias TEXTMETRICA TEXTMETRIC;
+}
+else
+{
+    alias TEXTMETRICW TEXTMETRIC;
+}
+alias TEXTMETRIC* LPTEXTMETRIC;
+alias TEXTMETRIC TAGTEXTMETRIC;
+alias TEXTMETRIC TTEXTMETRIC;
+alias TEXTMETRIC* PTEXTMETRIC;
+
+struct OUTLINETEXTMETRICA
+{
+    UINT       otmSize;
+    TEXTMETRICA 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;
+}
+struct OUTLINETEXTMETRICW
+{
+    UINT       otmSize;
+    TEXTMETRICW 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(Win32SansUnicode)
+{
+    alias OUTLINETEXTMETRICA OUTLINETEXTMETRIC;
+    alias OUTLINETEXTMETRICA* LPOUTLINETEXTMETRICA;
+}
+else
+{
+    alias OUTLINETEXTMETRICW OUTLINETEXTMETRIC;
+    alias OUTLINETEXTMETRICW* LPOUTLINETEXTMETRICW;
+}
+
+struct OVERLAPPED
+{
+    DWORD Internal;
+    DWORD InternalHigh;
+    DWORD Offset;
+    DWORD OffsetHigh;
+    HANDLE hEvent;
+}
+
+alias OVERLAPPED* LPOVERLAPPED;
+alias OVERLAPPED _OVERLAPPED;
+alias OVERLAPPED TOVERLAPPED;
+alias OVERLAPPED* POVERLAPPED;
+
+struct TPAGESETUPDLG
+{
+    DWORD lStructSize;
+    HWND hwndOwner;
+    HGLOBAL hDevMode;
+    HGLOBAL hDevNames;
+    DWORD Flags;
+    POINT ptPaperSize;
+    RECT rtMinMargin;
+    RECT rtMargin;
+    HINST hInstance;
+    LPARAM lCustData;
+    LPPAGESETUPHOOK lpfnPageSetupHook;
+    LPPAGEPAINTHOOK lpfnPagePaintHook;
+    LPCTSTR lpPageSetupTemplateName;
+    HGLOBAL hPageSetupTemplate;
+}
+
+alias TPAGESETUPDLG PAGESETUPDLG;
+alias TPAGESETUPDLG* LPPAGESETUPDLG;
+alias TPAGESETUPDLG* PPAGESETUPDLG;
+alias TPAGESETUPDLG TAGPSD;
+alias TPAGESETUPDLG TPSD;
+alias TPAGESETUPDLG* PPSD;
+
+struct PAINTSTRUCT
+{
+    HDC hdc;
+    WINBOOL fErase;
+    RECT rcPaint;
+    WINBOOL fRestore;
+    WINBOOL fIncUpdate;
+    ubyte[1 + 31] rgbReserved;
+}
+
+alias PAINTSTRUCT* LPPAINTSTRUCT;
+alias PAINTSTRUCT TAGPAINTSTRUCT;
+alias PAINTSTRUCT TPAINTSTRUCT;
+alias PAINTSTRUCT* PPAINTSTRUCT;
+
+struct PARAFORMAT
+{
+    UINT cbSize;
+    DWORD dwMask;
+    ushort wNumbering;
+    ushort wReserved;
+    LONG dxStartIndent;
+    LONG dxRightIndent;
+    LONG dxOffset;
+    ushort wAlignment;
+    SHORT cTabCount;
+    LONG[1 + MAX_TAB_STOPS-1] rgxTabs;
+}
+
+alias PARAFORMAT _PARAFORMAT;
+alias PARAFORMAT TPARAFORMAT;
+alias PARAFORMAT* PPARAFORMAT;
+
+struct PERF_COUNTER_BLOCK
+{
+    DWORD ByteLength;
+}
+
+alias PERF_COUNTER_BLOCK _PERF_COUNTER_BLOCK;
+alias PERF_COUNTER_BLOCK TPERFCOUNTERBLOCK;
+alias PERF_COUNTER_BLOCK* PPERFCOUNTERBLOCK;
+
+struct PERF_COUNTER_DEFINITION
+{
+    DWORD ByteLength;
+    DWORD CounterNameTitleIndex;
+    LPWSTR CounterNameTitle;
+    DWORD CounterHelpTitleIndex;
+    LPWSTR CounterHelpTitle;
+    DWORD DefaultScale;
+    DWORD DetailLevel;
+    DWORD CounterType;
+    DWORD CounterSize;
+    DWORD CounterOffset;
+}
+
+alias PERF_COUNTER_DEFINITION _PERF_COUNTER_DEFINITION;
+alias PERF_COUNTER_DEFINITION TPERFCOUNTERDEFINITION;
+alias PERF_COUNTER_DEFINITION* PPERFCOUNTERDEFINITION;
+
+struct PERF_DATA_BLOCK
+{
+    WCHAR[1 + 3] Signature;
+    DWORD LittleEndian;
+    DWORD Version;
+    DWORD Revision;
+    DWORD TotalByteLength;
+    DWORD HeaderLength;
+    DWORD NumObjectTypes;
+    DWORD DefaultObject;
+    SYSTEMTIME SystemTime;
+    LARGE_INTEGER PerfTime;
+    LARGE_INTEGER PerfFreq;
+    LARGE_INTEGER PerfTime100nSec;
+    DWORD SystemNameLength;
+    DWORD SystemNameOffset;
+}
+
+alias PERF_DATA_BLOCK _PERF_DATA_BLOCK;
+alias PERF_DATA_BLOCK TPERFDATABLOCK;
+alias PERF_DATA_BLOCK* PPERFDATABLOCK;
+
+struct PERF_INSTANCE_DEFINITION
+{
+    DWORD ByteLength;
+    DWORD ParentObjectTitleIndex;
+    DWORD ParentObjectInstance;
+    DWORD UniqueID;
+    DWORD NameOffset;
+    DWORD NameLength;
+}
+
+alias PERF_INSTANCE_DEFINITION _PERF_INSTANCE_DEFINITION;
+alias PERF_INSTANCE_DEFINITION TPERFINSTANCEDEFINITION;
+alias PERF_INSTANCE_DEFINITION PPERFINSTANCEDEFINITION;
+
+struct PERF_OBJECT_TYPE
+{
+    DWORD TotalByteLength;
+    DWORD DefinitionLength;
+    DWORD HeaderLength;
+    DWORD ObjectNameTitleIndex;
+    LPWSTR ObjectNameTitle;
+    DWORD ObjectHelpTitleIndex;
+    LPWSTR ObjectHelpTitle;
+    DWORD DetailLevel;
+    DWORD NumCounters;
+    DWORD DefaultCounter;
+    DWORD NumInstances;
+    DWORD CodePage;
+    LARGE_INTEGER PerfTime;
+    LARGE_INTEGER PerfFreq;
+}
+
+alias PERF_OBJECT_TYPE _PERF_OBJECT_TYPE;
+alias PERF_OBJECT_TYPE TPERFOBJECTTYPE;
+alias PERF_OBJECT_TYPE* PPERFOBJECTTYPE;
+
+struct POLYTEXT
+{
+    int x;
+    int y;
+    UINT n;
+    LPCTSTR lpstr;
+    UINT uiFlags;
+    RECT rcl;
+    int* pdx;
+}
+
+alias POLYTEXT _POLYTEXT;
+alias POLYTEXT TPOLYTEXT;
+alias POLYTEXT* PPOLYTEXT;
+
+struct PORT_INFO_1
+{
+    LPTSTR pName;
+}
+
+alias PORT_INFO_1 _PORT_INFO_1;
+alias PORT_INFO_1 TPORTINFO1;
+alias PORT_INFO_1* PPORTINFO1;
+
+struct PORT_INFO_2
+{
+    LPSTR pPortName;
+    LPSTR pMonitorName;
+    LPSTR pDescription;
+    DWORD fPortType;
+    DWORD Reserved;
+}
+
+alias PORT_INFO_2 _PORT_INFO_2;
+alias PORT_INFO_2 TPORTINFO2;
+alias PORT_INFO_2* PPORTINFO2;
+
+struct PREVENT_MEDIA_REMOVAL
+{
+    ubyte PreventMediaRemoval;
+}
+
+alias PREVENT_MEDIA_REMOVAL _PREVENT_MEDIA_REMOVAL;
+alias PREVENT_MEDIA_REMOVAL TPREVENTMEDIAREMOVAL;
+alias PREVENT_MEDIA_REMOVAL* PPREVENTMEDIAREMOVAL;
+
+align(2) struct PRINTDLGA {  // pd
+    DWORD     lStructSize;
+    HWND      hwndOwner;
+    HANDLE    hDevMode;
+    HANDLE    hDevNames;
+    HDC       hDC;
+    DWORD     Flags;
+    WORD      nFromPage;
+    WORD      nToPage;
+    WORD      nMinPage;
+    WORD      nMaxPage;
+    WORD      nCopies;
+    HINSTANCE hInstance;
+    DWORD     lCustData;
+    LPPRINTHOOKPROC lpfnPrintHook;
+    LPSETUPHOOKPROC lpfnSetupHook;
+    LPCSTR    lpPrintTemplateName;
+    LPCSTR    lpSetupTemplateName;
+    HANDLE    hPrintTemplate;
+    HANDLE    hSetupTemplate;
+}
+alias PRINTDLGA* PPRINTDLGA;
+alias PRINTDLGA* LPPRINTDLGA;
+align(2) struct PRINTDLGW {  // pd
+    DWORD     lStructSize;
+    HWND      hwndOwner;
+    HANDLE    hDevMode;
+    HANDLE    hDevNames;
+    HDC       hDC;
+    DWORD     Flags;
+    WORD      nFromPage;
+    WORD      nToPage;
+    WORD      nMinPage;
+    WORD      nMaxPage;
+    WORD      nCopies;
+    HINSTANCE hInstance;
+    DWORD     lCustData;
+    LPPRINTHOOKPROC lpfnPrintHook;
+    LPSETUPHOOKPROC lpfnSetupHook;
+    LPCWSTR    lpPrintTemplateName;
+    LPCWSTR    lpSetupTemplateName;
+    HANDLE    hPrintTemplate;
+    HANDLE    hSetupTemplate;
+}
+alias PRINTDLGW* PPRINTDLGW;
+alias PRINTDLGW* LPPRINTDLGW;
+
+version(Win32SansUnicode){
+    alias PRINTDLGA PRINTDLG;
+}else{
+    alias PRINTDLGW PRINTDLG;
+}
+
+
+alias PRINTDLG* LPPRINTDLG;
+alias PRINTDLG* PPRINTDLG;
+alias PRINTDLG TAGPD;
+alias PRINTDLG TPD;
+alias PRINTDLG* PPD;
+
+struct PRINTER_DEFAULTS
+{
+    LPTSTR pDatatype;
+    LPDEVMODE pDevMode;
+    ACCESS_MASK DesiredAccess;
+}
+
+alias PRINTER_DEFAULTS _PRINTER_DEFAULTS;
+alias PRINTER_DEFAULTS TPRINTERDEFAULTS;
+alias PRINTER_DEFAULTS* PPRINTERDEFAULTS;
+
+struct PRINTER_INFO_1
+{
+    DWORD Flags;
+    LPTSTR pDescription;
+    LPTSTR pName;
+    LPTSTR pComment;
+}
+
+alias PRINTER_INFO_1* LPPRINTER_INFO_1;
+alias PRINTER_INFO_1* PPRINTER_INFO_1;
+alias PRINTER_INFO_1 _PRINTER_INFO_1;
+alias PRINTER_INFO_1 TPRINTERINFO1;
+alias PRINTER_INFO_1* PPRINTERINFO1;
+
+struct PRINTER_INFO_2
+{
+    LPTSTR pServerName;
+    LPTSTR pPrinterName;
+    LPTSTR pShareName;
+    LPTSTR pPortName;
+    LPTSTR pDriverName;
+    LPTSTR pComment;
+    LPTSTR pLocation;
+    LPDEVMODE pDevMode;
+    LPTSTR pSepFile;
+    LPTSTR pPrintProcessor;
+    LPTSTR pDatatype;
+    LPTSTR pParameters;
+    PSECURITY_DESCRIPTOR pSecurityDescriptor;
+    DWORD Attributes;
+    DWORD Priority;
+    DWORD DefaultPriority;
+    DWORD StartTime;
+    DWORD UntilTime;
+    DWORD Status;
+    DWORD cJobs;
+    DWORD AveragePPM;
+}
+
+alias PRINTER_INFO_2 _PRINTER_INFO_2;
+alias PRINTER_INFO_2 TPRINTERINFO2;
+alias PRINTER_INFO_2* PPRINTERINFO2;
+
+struct PRINTER_INFO_3
+{
+    PSECURITY_DESCRIPTOR pSecurityDescriptor;
+}
+
+alias PRINTER_INFO_3 _PRINTER_INFO_3;
+alias PRINTER_INFO_3 TPRINTERINFO3;
+alias PRINTER_INFO_3* PPRINTERINFO3;
+
+struct PRINTER_INFO_4
+{
+    LPTSTR pPrinterName;
+    LPTSTR pServerName;
+    DWORD Attributes;
+}
+
+alias PRINTER_INFO_4 _PRINTER_INFO_4;
+alias PRINTER_INFO_4 TPRINTERINFO4;
+alias PRINTER_INFO_4* PPRINTERINFO4;
+
+struct PRINTER_INFO_5
+{
+    LPTSTR pPrinterName;
+    LPTSTR pPortName;
+    DWORD Attributes;
+    DWORD DeviceNotSelectedTimeout;
+    DWORD TransmissionRetryTimeout;
+}
+
+alias PRINTER_INFO_5 _PRINTER_INFO_5;
+alias PRINTER_INFO_5 TPRINTERINFO5;
+alias PRINTER_INFO_5* PPRINTERINFO5;
+
+struct PRINTER_NOTIFY_INFO_DATA
+{
+    ushort _Type;
+    ushort Field;
+    DWORD Reserved;
+    DWORD Id;
+
+    union
+    {
+        struct
+        {
+            DWORD[1 + 1] adwData;
+        }
+        struct
+        {
+            DWORD cbBuf;
+            LPVOID pBuf;
+        }
+    }
+}
+
+alias PRINTER_NOTIFY_INFO_DATA _PRINTER_NOTIFY_INFO_DATA;
+alias PRINTER_NOTIFY_INFO_DATA TPRINTERNOTIFYINFODATA;
+alias PRINTER_NOTIFY_INFO_DATA* PPRINTERNOTIFYINFODATA;
+
+struct PRINTER_NOTIFY_INFO
+{
+    DWORD Version;
+    DWORD Flags;
+    DWORD Count;
+    PRINTER_NOTIFY_INFO_DATA[1 + 0] aData;
+}
+
+alias PRINTER_NOTIFY_INFO _PRINTER_NOTIFY_INFO;
+alias PRINTER_NOTIFY_INFO TPRINTERNOTIFYINFO;
+alias PRINTER_NOTIFY_INFO* PPRINTERNOTIFYINFO;
+
+struct PRINTER_NOTIFY_OPTIONS_TYPE
+{
+    ushort _Type;
+    ushort Reserved0;
+    DWORD Reserved1;
+    DWORD Reserved2;
+    DWORD Count;
+    PWORD pFields;
+}
+
+alias PRINTER_NOTIFY_OPTIONS_TYPE* PPRINTER_NOTIFY_OPTIONS_TYPE;
+alias PRINTER_NOTIFY_OPTIONS_TYPE _PRINTER_NOTIFY_OPTIONS_TYPE;
+alias PRINTER_NOTIFY_OPTIONS_TYPE TPRINTERNOTIFYOPTIONSTYPE;
+alias PRINTER_NOTIFY_OPTIONS_TYPE* PPRINTERNOTIFYOPTIONSTYPE;
+
+struct PRINTER_NOTIFY_OPTIONS
+{
+    DWORD Version;
+    DWORD Flags;
+    DWORD Count;
+    PPRINTER_NOTIFY_OPTIONS_TYPE pTypes;
+}
+
+alias PRINTER_NOTIFY_OPTIONS _PRINTER_NOTIFY_OPTIONS;
+alias PRINTER_NOTIFY_OPTIONS TPRINTERNOTIFYOPTIONS;
+alias PRINTER_NOTIFY_OPTIONS* PPRINTERNOTIFYOPTIONS;
+
+struct PRINTPROCESSOR_INFO_1
+{
+    LPTSTR pName;
+}
+
+alias PRINTPROCESSOR_INFO_1 _PRINTPROCESSOR_INFO_1;
+alias PRINTPROCESSOR_INFO_1 TPRINTPROCESSORINFO1;
+alias PRINTPROCESSOR_INFO_1* PPRINTPROCESSORINFO1;
+
+struct PRIVILEGE_SET
+{
+    DWORD PrivilegeCount;
+    DWORD Control;
+    LUID_AND_ATTRIBUTES[1 + ANYSIZE_ARRAY-1] Privilege;
+}
+
+alias PRIVILEGE_SET* LPPRIVILEGE_SET;
+alias PRIVILEGE_SET* PPRIVILEGE_SET;
+alias PRIVILEGE_SET _PRIVILEGE_SET;
+alias PRIVILEGE_SET TPRIVILEGESET;
+alias PRIVILEGE_SET* PPRIVILEGESET;
+
+struct PROCESS_HEAPENTRY
+{
+    PVOID lpData;
+    DWORD cbData;
+    ubyte cbOverhead;
+    ubyte iRegionIndex;
+    ushort wFlags;
+    DWORD dwCommittedSize;
+    DWORD dwUnCommittedSize;
+    LPVOID lpFirstBlock;
+    LPVOID lpLastBlock;
+    HANDLE hMem;
+}
+
+alias PROCESS_HEAPENTRY* LPPROCESS_HEAP_ENTRY;
+alias PROCESS_HEAPENTRY _PROCESS_HEAP_ENTRY;
+alias PROCESS_HEAPENTRY TPROCESSHEAPENTRY;
+alias PROCESS_HEAPENTRY* PPROCESSHEAPENTRY;
+
+struct PROCESS_INFORMATION
+{
+    HANDLE hProcess;
+    HANDLE hThread;
+    DWORD dwProcessId;
+    DWORD dwThreadId;
+}
+
+alias PROCESS_INFORMATION* LPPROCESS_INFORMATION;
+alias PROCESS_INFORMATION _PROCESS_INFORMATION;
+alias PROCESS_INFORMATION TPROCESSINFORMATION;
+alias PROCESS_INFORMATION* PPROCESSINFORMATION;
+extern(Windows){alias UINT (*LPFNPSPCALLBACK)(HWND, UINT, LPVOID);}
+alias LPFNPSPCALLBACK TFNPSPCALLBACK;
+
+
+struct PROPSHEETPAGE
+{
+    DWORD dwSize;
+    DWORD dwFlags;
+    HINST hInstance;
+    union {
+        LPCTSTR pszTemplate;
+        LPCDLGTEMPLATE pResource;
+    }
+    union {
+        HICON hIcon;
+        LPCTSTR pszIcon;
+    }
+    LPCTSTR pszTitle;
+    DLGPROC pfnDlgProc;
+    LPARAM lParam;
+    LPFNPSPCALLBACK pfnCallback;
+    UINT* pcRefParent;
+//if (_WIN32_IE >= 0x0500)
+    LPCTSTR pszHeaderTitle;
+    LPCTSTR pszHeaderSubTitle;
+//endif
+//if (_WIN32_WINNT >= 0x0501)
+    HANDLE hActCtx;
+//endif
+}
+
+alias PROPSHEETPAGE* LPPROPSHEETPAGE;
+alias PROPSHEETPAGE* LPCPROPSHEETPAGE;
+alias PROPSHEETPAGE _PROPSHEETPAGE;
+alias PROPSHEETPAGE TPROPSHEETPAGE;
+alias PROPSHEETPAGE* PPROPSHEETPAGE;
+
+struct EMPTYRECORD
+{
+}
+
+alias EMPTYRECORD* HPROPSHEETPAGE;
+
+struct PROPSHEETHEADER_U1
+{
+
+    union
+    {
+        struct
+        {
+            HICON hIcon;
+        }
+        struct
+        {
+            LPCTSTR pszIcon;
+        }
+    }
+}
+
+
+struct PROPSHEETHEADER_U2
+{
+
+    union
+    {
+        struct
+        {
+            UINT nStartPage;
+        }
+        struct
+        {
+            LPCTSTR pStartPage;
+        }
+    }
+}
+
+
+struct PROPSHEETHEADER_U3
+{
+
+    union
+    {
+        struct
+        {
+            LPCPROPSHEETPAGE ppsp;
+        }
+        struct
+        {
+            HPROPSHEETPAGE* phpage;
+        }
+    }
+}
+
+
+struct PROPSHEETHEADER
+{
+    DWORD dwSize;
+    DWORD dwFlags;
+    HWND hwndParent;
+    HINST hInstance;
+    PROPSHEETHEADER_U1 u1;
+    LPCTSTR pszCaption;
+    UINT nPages;
+    PROPSHEETHEADER_U2 u2;
+    PROPSHEETHEADER_U3 u3;
+    PFNPROPSHEETCALLBACK pfnCallback;
+//if (_WIN32_IE >= 0x0400)
+    union {
+        HBITMAP hbmWatermark;
+        LPCTSTR pszbmWatermark;
+    }
+    HPALETTE hplWatermark;
+    union {
+        HBITMAP hbmHeader; 
+        LPCSTR pszbmHeader;
+    }
+//endif
+}
+
+alias PROPSHEETHEADER* LPPROPSHEETHEADER;
+alias PROPSHEETHEADER* LPCPROPSHEETHEADER;
+alias PROPSHEETHEADER _PROPSHEETHEADER;
+alias PROPSHEETHEADER TPROPSHEETHEADER;
+alias PROPSHEETHEADER* PPROPSHEETHEADER;
+extern(Windows){
+alias WINBOOL (*LPFNADDPROPSHEETPAGE)(HPROPSHEETPAGE, LPARAM);
+alias WINBOOL (*LPFNADDPROPSHEETPAGES)(LPVOID, LPFNADDPROPSHEETPAGE, LPARAM);
+}
+alias LPFNADDPROPSHEETPAGE TFNADDPROPSHEETPAGE;
+alias LPFNADDPROPSHEETPAGES TFNADDPROPSHEETPAGES;
+
+struct PROTOCOL_INFO
+{
+    DWORD dwServiceFlags;
+    INT iAddressFamily;
+    INT iMaxSockAddr;
+    INT iMinSockAddr;
+    INT iSocketType;
+    INT iProtocol;
+    DWORD dwMessageSize;
+    LPTSTR lpProtocol;
+}
+
+alias PROTOCOL_INFO _PROTOCOL_INFO;
+alias PROTOCOL_INFO TPROTOCOLINFO;
+alias PROTOCOL_INFO* PPROTOCOLINFO;
+
+struct PROVIDOR_INFO_1
+{
+    LPTSTR pName;
+    LPTSTR pEnvironment;
+    LPTSTR pDLLName;
+}
+
+alias PROVIDOR_INFO_1 _PROVIDOR_INFO_1;
+alias PROVIDOR_INFO_1 TPROVIDORINFO1;
+alias PROVIDOR_INFO_1* PPROVIDORINFO1;
+
+struct PSHNOTIFY
+{
+    NMHDR hdr;
+    LPARAM lParam;
+}
+
+alias PSHNOTIFY* LPPSHNOTIFY;
+alias PSHNOTIFY _PSHNOTIFY;
+alias PSHNOTIFY TPSHNOTIFY;
+alias PSHNOTIFY* PPSHNOTIFY;
+
+struct PUNCTUATION
+{
+    UINT iSize;
+    LPSTR szPunctuation;
+}
+
+alias PUNCTUATION _PUNCTUATION;
+alias PUNCTUATION TPUNCTUATION;
+alias PUNCTUATION* PPUNCTUATION;
+
+struct QUERY_SERVICE_CONFIG
+{
+    DWORD dwServiceType;
+    DWORD dwStartType;
+    DWORD dwErrorControl;
+    LPTSTR lpBinaryPathName;
+    LPTSTR lpLoadOrderGroup;
+    DWORD dwTagId;
+    LPTSTR lpDependencies;
+    LPTSTR lpServiceStartName;
+    LPTSTR lpDisplayName;
+}
+
+alias QUERY_SERVICE_CONFIG* LPQUERY_SERVICE_CONFIG;
+alias QUERY_SERVICE_CONFIG _QUERY_SERVICE_CONFIG;
+alias QUERY_SERVICE_CONFIG TQUERYSERVICECONFIG;
+alias QUERY_SERVICE_CONFIG* PQUERYSERVICECONFIG;
+
+struct QUERY_SERVICE_LOCK_STATUS
+{
+    DWORD fIsLocked;
+    LPTSTR lpLockOwner;
+    DWORD dwLockDuration;
+}
+
+alias QUERY_SERVICE_LOCK_STATUS* LPQUERY_SERVICE_LOCK_STATUS;
+alias QUERY_SERVICE_LOCK_STATUS _QUERY_SERVICE_LOCK_STATUS;
+alias QUERY_SERVICE_LOCK_STATUS TQUERYSERVICELOCKSTATUS;
+alias QUERY_SERVICE_LOCK_STATUS* PQUERYSERVICELOCKSTATUS;
+
+struct RASAMB
+{
+    DWORD dwSize;
+    DWORD dwError;
+    TCHAR[1 + NETBIOS_NAME_LEN+1-1] szNetBiosError;
+    ubyte bLana;
+}
+
+alias RASAMB _RASAMB;
+alias RASAMB TRASAMB;
+alias RASAMB* PRASAMB;
+
+struct RASCONN
+{
+    DWORD dwSize;
+    HRASCONN hrasconn;
+    TCHAR[1 + RAS_MaxEntryName+1-1] szEntryName;
+    char[1 + RAS_MaxDeviceType+1-1] szDeviceType;
+    char[1 + RAS_MaxDeviceName+1-1] szDeviceName;
+}
+
+alias RASCONN _RASCONN;
+alias RASCONN TRASCONN;
+alias RASCONN* PRASCONN;
+
+struct RASCONNSTATUS
+{
+    DWORD dwSize;
+    RASCONNSTATE rasconnstate;
+    DWORD dwError;
+    TCHAR[1 + RAS_MaxDeviceType+1-1] szDeviceType;
+    TCHAR[1 + RAS_MaxDeviceName+1-1] szDeviceName;
+}
+
+alias RASCONNSTATUS _RASCONNSTATUS;
+alias RASCONNSTATUS TRASCONNSTATUS;
+alias RASCONNSTATUS* PRASCONNSTATUS;
+
+struct RASDIALEXTENSIONS
+{
+    DWORD dwSize;
+    DWORD dwfOptions;
+    HWND hwndParent;
+    DWORD reserved;
+}
+
+alias RASDIALEXTENSIONS _RASDIALEXTENSIONS;
+alias RASDIALEXTENSIONS TRASDIALEXTENSIONS;
+alias RASDIALEXTENSIONS* PRASDIALEXTENSIONS;
+
+struct RASDIALPARAMS
+{
+    DWORD dwSize;
+    TCHAR[1 + RAS_MaxEntryName+1-1] szEntryName;
+    TCHAR[1 + RAS_MaxPhoneNumber+1-1] szPhoneNumber;
+    TCHAR[1 + (RAS_MaxCallbackNumber+1)-1] szCallbackNumber;
+    TCHAR[1 + (UNLEN+1)-1] szUserName;
+    TCHAR[1 + (PWLEN+1)-1] szPassword;
+    TCHAR[1 + (DNLEN+1)-1] szDomain;
+}
+
+alias RASDIALPARAMS _RASDIALPARAMS;
+alias RASDIALPARAMS TRASDIALPARAMS;
+alias RASDIALPARAMS* PRASDIALPARAMS;
+
+struct RASENTRYNAME
+{
+    DWORD dwSize;
+    TCHAR[1 + (RAS_MaxEntryName+1)-1] szEntryName;
+}
+
+alias RASENTRYNAME _RASENTRYNAME;
+alias RASENTRYNAME TRASENTRYNAME;
+alias RASENTRYNAME* PRASENTRYNAME;
+
+struct RASPPPIP
+{
+    DWORD dwSize;
+    DWORD dwError;
+    TCHAR[RAS_MaxIpAddress+1] szIpAddress;
+}
+
+alias RASPPPIP _RASPPPIP;
+alias RASPPPIP TRASPPPIP;
+alias RASPPPIP* PRASPPPIP;
+
+struct RASPPPIPX
+{
+    DWORD dwSize;
+    DWORD dwError;
+    TCHAR[1 + (RAS_MaxIpxAddress+1)-1] szIpxAddress;
+}
+
+alias RASPPPIPX _RASPPPIPX;
+alias RASPPPIPX TRASPPPIPX;
+alias RASPPPIPX* PRASPPPIPX;
+
+struct RASPPPNBF
+{
+    DWORD dwSize;
+    DWORD dwError;
+    DWORD dwNetBiosError;
+    TCHAR[1 + (NETBIOS_NAME_LEN+1)-1] szNetBiosError;
+    TCHAR[1 + (NETBIOS_NAME_LEN+1)-1] szWorkstationName;
+    ubyte bLana;
+}
+
+alias RASPPPNBF _RASPPPNBF;
+alias RASPPPNBF TRASPPPNBF;
+alias RASPPPNBF* PRASPPPNBF;
+
+struct RASTERIZER_STATUS
+{
+    short nSize;
+    short wFlags;
+    short nLanguageID;
+}
+
+alias RASTERIZER_STATUS* LPRASTERIZER_STATUS;
+alias RASTERIZER_STATUS _RASTERIZER_STATUS;
+alias RASTERIZER_STATUS TRASTERIZERSTATUS;
+alias RASTERIZER_STATUS* PRASTERIZERSTATUS;
+
+struct REASSIGN_BLOCKS
+{
+    ushort Reserved;
+    ushort Count;
+    DWORD[1 + 0] BlockNumber;
+}
+
+alias REASSIGN_BLOCKS _REASSIGN_BLOCKS;
+alias REASSIGN_BLOCKS TREASSIGNBLOCKS;
+alias REASSIGN_BLOCKS* PREASSIGNBLOCKS;
+
+struct REMOTE_NAME_INFO
+{
+    LPTSTR lpUniversalName;
+    LPTSTR lpConnectionName;
+    LPTSTR lpRemainingPath;
+}
+
+alias REMOTE_NAME_INFO _REMOTE_NAME_INFO;
+alias REMOTE_NAME_INFO TREMOTENAMEINFO;
+alias REMOTE_NAME_INFO* PREMOTENAMEINFO;
+
+struct REPASTESPECIAL
+{
+    DWORD dwAspect;
+    DWORD dwParam;
+}
+
+alias REPASTESPECIAL _REPASTESPECIAL;
+alias REPASTESPECIAL TREPASTESPECIAL;
+alias REPASTESPECIAL* PREPASTESPECIAL;
+
+struct REQRESIZE
+{
+    NMHDR nmhdr;
+    RECT rc;
+}
+
+alias REQRESIZE _REQRESIZE;
+alias REQRESIZE TREQRESIZE;
+alias REQRESIZE* PREQRESIZE;
+
+struct RGNDATAHEADER
+{
+    DWORD dwSize;
+    DWORD iType;
+    DWORD nCount;
+    DWORD nRgnSize;
+    RECT rcBound;
+}
+
+alias RGNDATAHEADER _RGNDATAHEADER;
+alias RGNDATAHEADER TRGNDATAHEADER;
+alias RGNDATAHEADER* PRGNDATAHEADER;
+alias RGNDATAHEADER* LPRGNDATAHEADER;
+
+struct RGNDATA
+{
+    RGNDATAHEADER rdh;
+    char[1 + 0] Buffer;
+}
+
+alias RGNDATA* LPRGNDATA;
+alias RGNDATA _RGNDATA;
+alias RGNDATA TRGNDATA;
+alias RGNDATA* PRGNDATA;
+
+struct SCROLLINFO
+{
+    UINT cbSize;
+    UINT fMask;
+    int nMin;
+    int nMax;
+    UINT nPage;
+    int nPos;
+    int nTrackPos;
+}
+
+alias SCROLLINFO* LPSCROLLINFO;
+alias SCROLLINFO* LPCSCROLLINFO;
+alias SCROLLINFO TAGSCROLLINFO;
+alias SCROLLINFO TSCROLLINFO;
+alias SCROLLINFO* PSCROLLINFO;
+
+struct SECURITY_ATTRIBUTES
+{
+    DWORD nLength;
+    LPVOID lpSecurityDescriptor;
+    WINBOOL bInheritHandle;
+}
+
+alias SECURITY_ATTRIBUTES* LPSECURITY_ATTRIBUTES;
+alias SECURITY_ATTRIBUTES _SECURITY_ATTRIBUTES;
+alias SECURITY_ATTRIBUTES TSECURITYATTRIBUTES;
+alias SECURITY_ATTRIBUTES* PSECURITYATTRIBUTES;
+alias DWORD SECURITY_INFORMATION;
+alias SECURITY_INFORMATION* PSECURITY_INFORMATION;
+alias SECURITY_INFORMATION TSECURITYINFORMATION;
+alias SECURITY_INFORMATION* PSECURITYINFORMATION;
+
+struct SELCHANGE
+{
+    NMHDR nmhdr;
+    CHARRANGE chrg;
+    ushort seltyp;
+}
+
+alias SELCHANGE _SELCHANGE;
+alias SELCHANGE TSELCHANGE;
+alias SELCHANGE* PSELCHANGE;
+
+struct SERIALKEYS
+{
+    DWORD cbSize;
+    DWORD dwFlags;
+    LPSTR lpszActivePort;
+    LPSTR lpszPort;
+    DWORD iBaudRate;
+    DWORD iPortState;
+    UINT  iActive;
+}
+
+alias SERIALKEYS* LPSERIALKEYS;
+alias SERIALKEYS TAGSERIALKEYS;
+alias SERIALKEYS TSERIALKEYS;
+alias SERIALKEYS* PSERIALKEYS;
+
+struct SERVICE_TABLE_ENTRY
+{
+    LPTSTR lpServiceName;
+    LPSERVICE_MAIN_FUNCTION lpServiceProc;
+}
+
+alias SERVICE_TABLE_ENTRY* LPSERVICE_TABLE_ENTRY;
+alias SERVICE_TABLE_ENTRY _SERVICE_TABLE_ENTRY;
+alias SERVICE_TABLE_ENTRY TSERVICETABLEENTRY;
+alias SERVICE_TABLE_ENTRY* PSERVICETABLEENTRY;
+
+struct SERVICE_TYPE_VALUE_ABS
+{
+    DWORD dwNameSpace;
+    DWORD dwValueType;
+    DWORD dwValueSize;
+    LPTSTR lpValueName;
+    PVOID lpValue;
+}
+
+alias SERVICE_TYPE_VALUE_ABS _SERVICE_TYPE_VALUE_ABS;
+alias SERVICE_TYPE_VALUE_ABS TSERVICETYPEVALUEABS;
+alias SERVICE_TYPE_VALUE_ABS* PSERVICETYPEVALUEABS;
+
+struct SERVICE_TYPE_INFO_ABS
+{
+    LPTSTR lpTypeName;
+    DWORD dwValueCount;
+    SERVICE_TYPE_VALUE_ABS[1 + 0] Values;
+}
+
+alias SERVICE_TYPE_INFO_ABS _SERVICE_TYPE_INFO_ABS;
+alias SERVICE_TYPE_INFO_ABS TSERVICETYPEINFOABS;
+alias SERVICE_TYPE_INFO_ABS* PSERVICETYPEINFOABS;
+
+struct SESSION_BUFFER
+{
+    UCHAR lsn;
+    UCHAR state;
+    UCHAR[1 + NCBNAMSZ-1] local_name;
+    UCHAR[1 + NCBNAMSZ-1] remote_name;
+    UCHAR rcvs_outstanding;
+    UCHAR sends_outstanding;
+}
+
+alias SESSION_BUFFER _SESSION_BUFFER;
+alias SESSION_BUFFER TSESSIONBUFFER;
+alias SESSION_BUFFER* PSESSIONBUFFER;
+
+struct SESSION_HEADER
+{
+    UCHAR sess_name;
+    UCHAR num_sess;
+    UCHAR rcv_dg_outstanding;
+    UCHAR rcv_any_outstanding;
+}
+
+alias SESSION_HEADER _SESSION_HEADER;
+alias SESSION_HEADER TSESSIONHEADER;
+alias SESSION_HEADER* PSESSIONHEADER;
+
+struct SET_PARTITION_INFORMATION
+{
+    ubyte PartitionType;
+}
+
+alias SET_PARTITION_INFORMATION _SET_PARTITION_INFORMATION;
+alias SET_PARTITION_INFORMATION TSETPARTITIONINFORMATION;
+alias SET_PARTITION_INFORMATION* PSETPARTITIONINFORMATION;
+alias int SHCONTF;
+enum { SHCONTF_FOLDERS = 32, SHCONTF_NONFOLDERS = 64, SHCONTF_INCLUDEHIDDEN = 128,  };
+alias SHCONTF TAGSHCONTF;
+alias SHCONTF TSHCONTF;
+
+struct SHFILEINFOA
+{
+    HICON hIcon;
+    int iIcon;
+    DWORD dwAttributes;
+    CHAR[MAX_PATH] szDisplayName;
+    CHAR[80] szTypeName;
+}
+struct SHFILEINFOW
+{
+    HICON hIcon;
+    int iIcon;
+    DWORD dwAttributes;
+    WCHAR[MAX_PATH] szDisplayName;
+    WCHAR[80] szTypeName;
+}
+version(Win32SansUnicode)
+{
+    alias SHFILEINFOA SHFILEINFO;
+}
+else
+{
+    alias SHFILEINFOW SHFILEINFO;
+}
+
+alias SHFILEINFO _SHFILEINFO;
+alias SHFILEINFO TSHFILEINFO;
+alias SHFILEINFO* PSHFILEINFO;
+
+alias ushort FILEOP_FLAGS;
+alias FILEOP_FLAGS TFILEOPFLAGS;
+alias FILEOP_FLAGS* PFILEOPFLAGS;
+
+align(2) struct SHFILEOPSTRUCT
+{
+    HWND hwnd;
+    UINT wFunc;
+    LPCSTR pFrom;
+    LPCSTR pTo;
+    FILEOP_FLAGS fFlags;
+    WINBOOL fAnyOperationsAborted;
+    LPVOID hNameMappings;
+    LPCSTR lpszProgressTitle;
+}
+
+alias SHFILEOPSTRUCT* LPSHFILEOPSTRUCT;
+alias SHFILEOPSTRUCT _SHFILEOPSTRUCT;
+alias SHFILEOPSTRUCT TSHFILEOPSTRUCT;
+alias SHFILEOPSTRUCT* PSHFILEOPSTRUCT;
+alias int SHGNO;
+enum { SHGDN_NORMAL = 0, SHGDN_INFOLDER = 1, SHGDN_FORPARSING = 0x8000,  };
+alias SHGNO TAGSHGDN;
+alias SHGNO TSHGDN;
+
+struct SHNAMEMAPPING
+{
+    LPSTR pszOldPath;
+    LPSTR pszNewPath;
+    int cchOldPath;
+    int cchNewPath;
+}
+
+alias SHNAMEMAPPING* LPSHNAMEMAPPING;
+alias SHNAMEMAPPING _SHNAMEMAPPING;
+alias SHNAMEMAPPING TSHNAMEMAPPING;
+alias SHNAMEMAPPING* PSHNAMEMAPPING;
+
+struct SID_AND_ATTRIBUTES
+{
+    PSID Sid;
+    DWORD Attributes;
+}
+
+alias SID_AND_ATTRIBUTES _SID_AND_ATTRIBUTES;
+alias SID_AND_ATTRIBUTES TSIDANDATTRIBUTES;
+alias SID_AND_ATTRIBUTES* PSIDANDATTRIBUTES;
+alias SID_AND_ATTRIBUTES[1 + ANYSIZE_ARRAY-1] SID_AND_ATTRIBUTES_ARRAY;
+alias SID_AND_ATTRIBUTES_ARRAY* PSID_AND_ATTRIBUTES_ARRAY;
+alias SID_AND_ATTRIBUTES_ARRAY TSIDANDATTRIBUTESARRAY;
+alias SID_AND_ATTRIBUTES_ARRAY* PSIDANDATTRIBUTESARRAY;
+
+struct SINGLE_LIST_ENTRY
+{
+    _SINGLE_LIST_ENTRY* Next;
+}
+
+alias SINGLE_LIST_ENTRY _SINGLE_LIST_ENTRY;
+alias SINGLE_LIST_ENTRY TSINGLELISTENTRY;
+alias SINGLE_LIST_ENTRY* PSINGLELISTENTRY;
+
+struct SOUNDSENTRY
+{
+    UINT cbSize;
+    DWORD dwFlags;
+    DWORD iFSTextEffect;
+    DWORD iFSTextEffectMSec;
+    DWORD iFSTextEffectColorBits;
+    DWORD iFSGrafEffect;
+    DWORD iFSGrafEffectMSec;
+    DWORD iFSGrafEffectColor;
+    DWORD iWindowsEffect;
+    DWORD iWindowsEffectMSec;
+    LPTSTR lpszWindowsEffectDLL;
+    DWORD iWindowsEffectOrdinal;
+}
+
+alias SOUNDSENTRY* LPSOUNDSENTRY;
+alias SOUNDSENTRY TAGSOUNDSENTRY;
+alias SOUNDSENTRY TSOUNDSENTRY;
+alias SOUNDSENTRY* PSOUNDSENTRY;
+
+struct STARTUPINFO
+{
+    DWORD cb;
+    LPTSTR lpReserved;
+    LPTSTR lpDesktop;
+    LPTSTR lpTitle;
+    DWORD dwX;
+    DWORD dwY;
+    DWORD dwXSize;
+    DWORD dwYSize;
+    DWORD dwXCountChars;
+    DWORD dwYCountChars;
+    DWORD dwFillAttribute;
+    DWORD dwFlags;
+    ushort wShowWindow;
+    ushort cbReserved2;
+    LPBYTE lpReserved2;
+    HANDLE hStdInput;
+    HANDLE hStdOutput;
+    HANDLE hStdError;
+}
+
+alias STARTUPINFO* LPSTARTUPINFO;
+alias STARTUPINFO _STARTUPINFO;
+alias STARTUPINFO TSTARTUPINFO;
+alias STARTUPINFO* PSTARTUPINFO;
+
+struct STICKYKEYS
+{
+    DWORD cbSize;
+    DWORD dwFlags;
+}
+
+alias STICKYKEYS* LPSTICKYKEYS;
+alias STICKYKEYS TAGSTICKYKEYS;
+alias STICKYKEYS TSTICKYKEYS;
+alias STICKYKEYS* PSTICKYKEYS;
+
+struct STRRET
+{
+    UINT uType;
+
+    union
+    {
+        struct
+        {
+            LPWSTR pOleStr;
+        }
+        struct
+        {
+            UINT uOffset;
+        }
+        struct
+        {
+            char[1 + MAX_PATH-1] cStr;
+        }
+    }
+}
+
+alias STRRET* LPSTRRET;
+alias STRRET _STRRET;
+alias STRRET TSTRRET;
+alias STRRET* PSTRRET;
+
+struct STYLEBUF
+{
+    DWORD dwStyle;
+    TCHAR[1 + 31] szDescription;
+}
+
+alias STYLEBUF* LPSTYLEBUF;
+alias STYLEBUF _TAGSTYLEBUF;
+alias STYLEBUF TSTYLEBUF;
+alias STYLEBUF* PSTYLEBUF;
+
+struct STYLESTRUCT
+{
+    DWORD styleOld;
+    DWORD styleNew;
+}
+
+alias STYLESTRUCT* LPSTYLESTRUCT;
+alias STYLESTRUCT TAGSTYLESTRUCT;
+alias STYLESTRUCT TSTYLESTRUCT;
+alias STYLESTRUCT* PSTYLESTRUCT;
+
+struct SYSTEM_AUDIT_ACE
+{
+    ACE_HEADER Header;
+    ACCESS_MASK Mask;
+    DWORD SidStart;
+}
+
+alias SYSTEM_AUDIT_ACE _SYSTEM_AUDIT_ACE;
+alias SYSTEM_AUDIT_ACE TSYSTEMAUDITACE;
+alias SYSTEM_AUDIT_ACE* PSYSTEMAUDITACE;
+
+struct SYSTEM_INFO {
+    union {
+        DWORD dwOemId;
+        struct {
+            WORD wProcessorArchitecture;
+            WORD wReserved;
+        }
+    }
+    DWORD dwPageSize;
+    LPVOID lpMinimumApplicationAddress;
+    LPVOID lpMaximumApplicationAddress;
+    DWORD_PTR dwActiveProcessorMask;
+    DWORD dwNumberOfProcessors;
+    DWORD dwProcessorType;
+    DWORD dwAllocationGranularity;
+    WORD wProcessorLevel;
+    WORD wProcessorRevision;
+}
+
+alias SYSTEM_INFO* LPSYSTEM_INFO;
+alias SYSTEM_INFO _SYSTEM_INFO;
+alias SYSTEM_INFO TSYSTEMINFO;
+alias SYSTEM_INFO* PSYSTEMINFO;
+
+struct SYSTEM_POWER_STATUS
+{
+    ubyte ACLineStatus;
+    ubyte BatteryFlag;
+    ubyte BatteryLifePercent;
+    ubyte Reserved1;
+    DWORD BatteryLifeTime;
+    DWORD BatteryFullLifeTime;
+}
+
+alias SYSTEM_POWER_STATUS _SYSTEM_POWER_STATUS;
+alias SYSTEM_POWER_STATUS TSYSTEMPOWERSTATUS;
+alias SYSTEM_POWER_STATUS* PSYSTEMPOWERSTATUS;
+alias EMPTYRECORD* LPSYSTEM_POWER_STATUS;
+
+struct TAPE_ERASE
+{
+    DWORD Type;
+    BOOLEAN Immediate;
+}
+
+alias TAPE_ERASE _TAPE_ERASE;
+alias TAPE_ERASE TTAPEERASE;
+alias TAPE_ERASE* PTAPEERASE;
+
+struct TAPE_GET_DRIVE_PARAMETERS
+{
+    ubyte ECC;
+    ubyte Compression;
+    ubyte DataPadding;
+    ubyte ReportSetmarks;
+    ULONG DefaultBlockSize;
+    ULONG MaximumBlockSize;
+    ULONG MinimumBlockSize;
+    ULONG MaximumPartitionCount;
+    ULONG FeaturesLow;
+    ULONG FeaturesHigh;
+    ULONG EOTWarningZoneSize;
+}
+
+alias TAPE_GET_DRIVE_PARAMETERS _TAPE_GET_DRIVE_PARAMETERS;
+alias TAPE_GET_DRIVE_PARAMETERS TTAPEGETDRIVEPARAMETERS;
+alias TAPE_GET_DRIVE_PARAMETERS* PTAPEGETDRIVEPARAMETERS;
+
+struct TAPE_GET_MEDIA_PARAMETERS
+{
+    LARGE_INTEGER Capacity;
+    LARGE_INTEGER Remaining;
+    DWORD BlockSize;
+    DWORD PartitionCount;
+    ubyte WriteProtected;
+}
+
+alias TAPE_GET_MEDIA_PARAMETERS _TAPE_GET_MEDIA_PARAMETERS;
+alias TAPE_GET_MEDIA_PARAMETERS TTAPEGETMEDIAPARAMETERS;
+alias TAPE_GET_MEDIA_PARAMETERS* PTAPEGETMEDIAPARAMETERS;
+
+struct TAPE_GET_POSITION
+{
+    ULONG _Type;
+    ULONG Partition;
+    ULONG OffsetLow;
+    ULONG OffsetHigh;
+}
+
+alias TAPE_GET_POSITION _TAPE_GET_POSITION;
+alias TAPE_GET_POSITION TTAPEGETPOSITION;
+alias TAPE_GET_POSITION* PTAPEGETPOSITION;
+
+struct TAPE_PREPARE
+{
+    DWORD    Operation;
+    BOOLEAN  Immediate;
+}
+
+alias TAPE_PREPARE _TAPE_PREPARE;
+alias TAPE_PREPARE TTAPEPREPARE;
+alias TAPE_PREPARE* PTAPEPREPARE;
+
+struct TAPE_SET_DRIVE_PARAMETERS
+{
+    ubyte ECC;
+    ubyte Compression;
+    ubyte DataPadding;
+    ubyte ReportSetmarks;
+    ULONG EOTWarningZoneSize;
+}
+
+alias TAPE_SET_DRIVE_PARAMETERS _TAPE_SET_DRIVE_PARAMETERS;
+alias TAPE_SET_DRIVE_PARAMETERS TTAPESETDRIVEPARAMETERS;
+alias TAPE_SET_DRIVE_PARAMETERS* PTAPESETDRIVEPARAMETERS;
+
+struct TAPE_SET_MEDIA_PARAMETERS
+{
+    ULONG BlockSize;
+}
+
+alias TAPE_SET_MEDIA_PARAMETERS _TAPE_SET_MEDIA_PARAMETERS;
+alias TAPE_SET_MEDIA_PARAMETERS TTAPESETMEDIAPARAMETERS;
+alias TAPE_SET_MEDIA_PARAMETERS* PTAPESETMEDIAPARAMETERS;
+
+struct TAPE_SET_POSITION
+{
+    ULONG Method;
+    ULONG Partition;
+    LARGE_INTEGER Offset;
+    BOOLEAN Immediate;
+}
+
+alias TAPE_SET_POSITION _TAPE_SET_POSITION;
+alias TAPE_SET_POSITION TTAPESETPOSITION;
+alias TAPE_SET_POSITION* PTAPESETPOSITION;
+
+struct TAPE_WRITE_MARKS
+{
+    ULONG _Type;
+    ULONG Count;
+    BOOLEAN Immediate;
+}
+
+alias TAPE_WRITE_MARKS _TAPE_WRITE_MARKS;
+alias TAPE_WRITE_MARKS TTAPEWRITEMARKS;
+alias TAPE_WRITE_MARKS* PTAPEWRITEMARKS;
+
+struct TBADDBITMAP
+{
+    HINST hInst;
+    UINT nID;
+}
+
+alias TBADDBITMAP* LPTBADDBITMAP;
+alias TBADDBITMAP TTBADDBITMAP;
+alias TBADDBITMAP* PTBADDBITMAP;
+
+struct TBBUTTON {
+    align(2):
+    int     iBitmap;
+    int     idCommand;
+    BYTE    fsState;
+    BYTE    fsStyle;
+//#ifdef _WIN64
+//    BYTE     bReserved[6];     // padding for alignment
+//#elif defined(_WIN32)
+    BYTE     bReserved[2];     // padding for alignment
+//#endif
+    DWORD_PTR   dwData;
+    INT_PTR     iString;
+}
+
+alias TBBUTTON* LPTBBUTTON;
+alias TBBUTTON* LPCTBBUTTON;
+alias TBBUTTON _TBBUTTON;
+alias TBBUTTON TTBBUTTON;
+alias TBBUTTON* PTBBUTTON;
+
+struct NMTOOLBARA {
+    align(2):
+    NMHDR    hdr;
+    int      iItem;
+    TBBUTTON tbButton;
+    int      cchText;
+    LPSTR   pszText;
+    RECT     rcButton;
+}
+struct NMTOOLBARW {
+    align(2):
+    NMHDR    hdr;
+    int      iItem;
+    TBBUTTON tbButton;
+    int      cchText;
+    LPWSTR   pszText;
+    RECT     rcButton;
+}
+version(Win32SansUnicode){
+    alias NMTOOLBARA NMTOOLBAR;
+}else{
+    alias NMTOOLBARW NMTOOLBAR;
+}
+alias NMTOOLBAR* LPNMTOOLBAR;
+
+alias NMTOOLBAR TBNOTIFY;
+
+alias TBNOTIFY* LPTBNOTIFY;
+alias TBNOTIFY TTBNOTIFY;
+alias TBNOTIFY* PTBNOTIFY;
+
+struct TBSAVEPARAMS
+{
+    HKEY hkr;
+    LPCTSTR pszSubKey;
+    LPCTSTR pszValueName;
+}
+
+alias TBSAVEPARAMS TTBSAVEPARAMS;
+alias TBSAVEPARAMS* PTBSAVEPARAMS;
+
+struct TC_HITTESTINFO
+{
+    POINT pt;
+    UINT flags;
+}
+
+alias TC_HITTESTINFO TCHITTESTINFO;
+alias TC_HITTESTINFO _TC_HITTESTINFO;
+alias TC_HITTESTINFO TTCHITTESTINFO;
+alias TC_HITTESTINFO* PTCHITTESTINFO;
+
+struct TC_ITEM
+{
+    UINT mask;
+    UINT lpReserved1;
+    UINT lpReserved2;
+    LPTSTR pszText;
+    int cchTextMax;
+    int iImage;
+    LPARAM lParam;
+}
+
+alias TC_ITEM _TC_ITEM;
+alias TC_ITEM TTCITEM;
+alias TC_ITEM* PTCITEM;
+
+struct TC_ITEMHEADER
+{
+    UINT mask;
+    UINT lpReserved1;
+    UINT lpReserved2;
+    LPTSTR pszText;
+    int cchTextMax;
+    int iImage;
+}
+
+alias TC_ITEMHEADER _TC_ITEMHEADER;
+alias TC_ITEMHEADER TTCITEMHEADER;
+alias TC_ITEMHEADER* PTCITEMHEADER;
+
+align(1) struct NMTCKEYDOWN
+{
+    NMHDR hdr;
+    WORD wVKey;
+    UINT flags;
+}
+
+alias NMTCKEYDOWN TC_KEYDOWN;
+alias TC_KEYDOWN _TC_KEYDOWN;
+alias TC_KEYDOWN TTCKEYDOWN;
+alias TC_KEYDOWN* PTCKEYDOWN;
+
+struct TEXTRANGE
+{
+    CHARRANGE chrg;
+    LPSTR lpstrText;
+}
+
+alias TEXTRANGE _TEXTRANGE;
+alias TEXTRANGE TTEXTRANGE;
+alias TEXTRANGE* PTEXTRANGE;
+
+struct TIME_ZONE_INFORMATION
+{
+    LONG Bias;
+    WCHAR[1 + 31] StandardName;
+    SYSTEMTIME StandardDate;
+    LONG StandardBias;
+    WCHAR[1 + 31] DaylightName;
+    SYSTEMTIME DaylightDate;
+    LONG DaylightBias;
+}
+
+alias TIME_ZONE_INFORMATION* LPTIME_ZONE_INFORMATION;
+alias TIME_ZONE_INFORMATION _TIME_ZONE_INFORMATION;
+alias TIME_ZONE_INFORMATION TTIMEZONEINFORMATION;
+alias TIME_ZONE_INFORMATION* PTIMEZONEINFORMATION;
+
+struct TOGGLEKEYS
+{
+    DWORD cbSize;
+    DWORD dwFlags;
+}
+
+alias TOGGLEKEYS TAGTOGGLEKEYS;
+alias TOGGLEKEYS TTOGGLEKEYS;
+alias TOGGLEKEYS* PTOGGLEKEYS;
+
+struct TOKEN_SOURCE
+{
+    char[1 + 7] SourceName;
+    LUID SourceIdentifier;
+}
+
+alias TOKEN_SOURCE _TOKEN_SOURCE;
+alias TOKEN_SOURCE TTOKENSOURCE;
+alias TOKEN_SOURCE* PTOKENSOURCE;
+
+struct TOKEN_CONTROL
+{
+    LUID TokenId;
+    LUID AuthenticationId;
+    LUID ModifiedId;
+    TOKEN_SOURCE TokenSource;
+}
+
+alias TOKEN_CONTROL _TOKEN_CONTROL;
+alias TOKEN_CONTROL TTOKENCONTROL;
+alias TOKEN_CONTROL* PTOKENCONTROL;
+
+struct TOKEN_DEFAULT_DACL
+{
+    PACL DefaultDacl;
+}
+
+alias TOKEN_DEFAULT_DACL _TOKEN_DEFAULT_DACL;
+alias TOKEN_DEFAULT_DACL TTOKENDEFAULTDACL;
+alias TOKEN_DEFAULT_DACL* PTOKENDEFAULTDACL;
+
+struct TOKEN_GROUPS
+{
+    DWORD GroupCount;
+    SID_AND_ATTRIBUTES[1 + ANYSIZE_ARRAY-1] Groups;
+}
+
+alias TOKEN_GROUPS* PTOKEN_GROUPS;
+alias TOKEN_GROUPS* LPTOKEN_GROUPS;
+alias TOKEN_GROUPS _TOKEN_GROUPS;
+alias TOKEN_GROUPS TTOKENGROUPS;
+alias TOKEN_GROUPS* PTOKENGROUPS;
+
+struct TOKEN_OWNER
+{
+    PSID Owner;
+}
+
+alias TOKEN_OWNER _TOKEN_OWNER;
+alias TOKEN_OWNER TTOKENOWNER;
+alias TOKEN_OWNER* PTOKENOWNER;
+
+struct TOKEN_PRIMARY_GROUP
+{
+    PSID PrimaryGroup;
+}
+
+alias TOKEN_PRIMARY_GROUP _TOKEN_PRIMARY_GROUP;
+alias TOKEN_PRIMARY_GROUP TTOKENPRIMARYGROUP;
+alias TOKEN_PRIMARY_GROUP* PTOKENPRIMARYGROUP;
+
+struct TOKEN_PRIVILEGES
+{
+    DWORD PrivilegeCount;
+    LUID_AND_ATTRIBUTES[ANYSIZE_ARRAY] Privileges;
+}
+
+alias TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES;
+alias TOKEN_PRIVILEGES* LPTOKEN_PRIVILEGES;
+alias TOKEN_PRIVILEGES _TOKEN_PRIVILEGES;
+alias TOKEN_PRIVILEGES TTOKENPRIVILEGES;
+alias TOKEN_PRIVILEGES* PTOKENPRIVILEGES;
+
+struct TOKEN_STATISTICS
+{
+    LUID TokenId;
+    LUID AuthenticationId;
+    LARGE_INTEGER ExpirationTime;
+    TOKEN_TYPE TokenType;
+    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+    DWORD DynamicCharged;
+    DWORD DynamicAvailable;
+    DWORD GroupCount;
+    DWORD PrivilegeCount;
+    LUID ModifiedId;
+}
+
+alias TOKEN_STATISTICS _TOKEN_STATISTICS;
+alias TOKEN_STATISTICS TTOKENSTATISTICS;
+alias TOKEN_STATISTICS* PTOKENSTATISTICS;
+
+struct TOKEN_USER
+{
+    SID_AND_ATTRIBUTES User;
+}
+
+alias TOKEN_USER _TOKEN_USER;
+alias TOKEN_USER TTOKENUSER;
+alias TOKEN_USER* PTOKENUSER;
+
+struct TOOLINFOA
+{
+    UINT cbSize;
+    UINT uFlags;
+    HWND hwnd;
+    UINT uId;
+    RECT rect;
+    HINST hinst;
+    LPSTR lpszText;
+//if (_WIN32_IE >= 0x0300)
+    LPARAM lParam;
+//endif
+//if (_WIN32_WINNT >= 0x0501)
+    void *lpReserved;
+//endif
+}
+struct TOOLINFOW
+{
+    UINT cbSize;
+    UINT uFlags;
+    HWND hwnd;
+    UINT uId;
+    RECT rect;
+    HINST hinst;
+    LPWSTR lpszText;
+//if (_WIN32_IE >= 0x0300)
+    LPARAM lParam;
+//endif
+//if (_WIN32_WINNT >= 0x0501)
+    void *lpReserved;
+//endif
+
+}
+version(Win32SansUnicode)
+{
+    alias TOOLINFOA TOOLINFO;
+}
+else
+{
+    alias TOOLINFOW TOOLINFO;
+}
+alias TOOLINFO* LPTOOLINFO;
+alias TOOLINFO TTOOLINFO;
+alias TOOLINFO* PTOOLINFO;
+
+struct NMTTDISPINFOA {
+    NMHDR hdr;
+    LPSTR lpszText;
+    char szText[80];
+    HINSTANCE hinst;
+    UINT uFlags;
+    LPARAM lParam;
+}
+
+struct NMTTDISPINFOW {
+    NMHDR hdr;
+    LPWSTR lpszText;
+    WCHAR szText[80];
+    HINSTANCE hinst;
+    UINT uFlags;
+    LPARAM lParam;
+}
+version(Win32SansUnicode){
+    alias NMTTDISPINFOA NMTTDISPINFO;
+} else {
+    alias NMTTDISPINFOW NMTTDISPINFO;
+}
+
+
+alias NMTTDISPINFOA TOOLTIPTEXTA;
+alias NMTTDISPINFOW TOOLTIPTEXTW;
+version(Win32SansUnicode)
+{
+    alias TOOLTIPTEXTA TOOLTIPTEXT;
+}
+else
+{
+    alias TOOLTIPTEXTW TOOLTIPTEXT;
+}
+alias TOOLTIPTEXT* LPTOOLTIPTEXT;
+alias TOOLTIPTEXT TTOOLTIPTEXT;
+alias TOOLTIPTEXT* PTOOLTIPTEXT;
+
+struct TPMPARAMS
+{
+    UINT cbSize;
+    RECT rcExclude;
+}
+
+alias TPMPARAMS* LPTPMPARAMS;
+alias TPMPARAMS TAGTPMPARAMS;
+alias TPMPARAMS TTPMPARAMS;
+alias TPMPARAMS* PTPMPARAMS;
+
+struct TRANSMIT_FILE_BUFFERS
+{
+    PVOID Head;
+    DWORD HeadLength;
+    PVOID Tail;
+    DWORD TailLength;
+}
+
+alias TRANSMIT_FILE_BUFFERS _TRANSMIT_FILE_BUFFERS;
+alias TRANSMIT_FILE_BUFFERS TTRANSMITFILEBUFFERS;
+alias TRANSMIT_FILE_BUFFERS* PTRANSMITFILEBUFFERS;
+
+struct TTHITTESTINFO
+{
+    HWND hwnd;
+    POINT pt;
+    TOOLINFO ti;
+}
+
+alias TTHITTESTINFO* LPHITTESTINFO;
+alias TTHITTESTINFO _TT_HITTESTINFO;
+alias TTHITTESTINFO TTTHITTESTINFO;
+alias TTHITTESTINFO* PTTHITTESTINFO;
+
+struct TTPOLYCURVE
+{
+    ushort wType;
+    ushort cpfx;
+    POINTFX[1 + 0] apfx;
+}
+
+alias TTPOLYCURVE* LPTTPOLYCURVE;
+alias TTPOLYCURVE TAGTTPOLYCURVE;
+alias TTPOLYCURVE TTTPOLYCURVE;
+alias TTPOLYCURVE* PTTPOLYCURVE;
+
+struct TTPOLYGONHEADER
+{
+    DWORD cb;
+    DWORD dwType;
+    POINTFX pfxStart;
+}
+
+alias TTPOLYGONHEADER* LPTTPOLYGONHEADER;
+alias TTPOLYGONHEADER _TTPOLYGONHEADER;
+alias TTPOLYGONHEADER TTTPOLYGONHEADER;
+alias TTPOLYGONHEADER* PTTPOLYGONHEADER;
+
+struct TV_DISPINFO
+{
+    NMHDR hdr;
+    TV_ITEM item;
+}
+
+alias TV_DISPINFO _TV_DISPINFO;
+alias TV_DISPINFO TTVDISPINFO;
+alias TV_DISPINFO* PTVDISPINFO;
+
+struct TV_HITTESTINFO
+{
+    POINT pt;
+    UINT flags;
+    HTREEITEM hItem;
+}
+
+alias TV_HITTESTINFO* LPTV_HITTESTINFO;
+alias TV_HITTESTINFO _TVHITTESTINFO;
+alias TV_HITTESTINFO TTVHITTESTINFO;
+alias TV_HITTESTINFO* PTVHITTESTINFO;
+
+struct TVINSERTSTRUCTA
+{
+    HTREEITEM hParent;
+    HTREEITEM hInsertAfter;
+    union {
+        TVITEMEXA itemex;
+        TVITEMA item;
+    }
+}
+struct TVINSERTSTRUCTW
+{
+    HTREEITEM hParent;
+    HTREEITEM hInsertAfter;
+    union {
+        TVITEMEXW itemex;
+        TVITEMW item;
+    }
+}
+version(Win32SansUnicode)
+{
+    alias TVINSERTSTRUCTA TVINSERTSTRUCT;
+}
+else
+{
+    alias TVINSERTSTRUCTW TVINSERTSTRUCT;
+}
+
+alias TVINSERTSTRUCT  TV_INSERTSTRUCT;
+alias TVINSERTSTRUCT* LPTV_INSERTSTRUCT;
+alias TVINSERTSTRUCT _TV_INSERTSTRUCT;
+alias TVINSERTSTRUCT TTVINSERTSTRUCT;
+alias TVINSERTSTRUCT* PTVINSERTSTRUCT;
+
+align(2) struct TV_KEYDOWN
+{
+    NMHDR hdr;
+    ushort wVKey;
+    UINT flags;
+}
+
+alias TV_KEYDOWN _TV_KEYDOWN;
+alias TV_KEYDOWN TTVKEYDOWN;
+alias TV_KEYDOWN* PTVKEYDOWN;
+
+struct TV_SORTCB
+{
+    HTREEITEM hParent;
+    PFNTVCOMPARE lpfnCompare;
+    LPARAM lParam;
+}
+
+alias TV_SORTCB* LPTV_SORTCB;
+alias TV_SORTCB _TV_SORTCB;
+alias TV_SORTCB TTVSORTCB;
+alias TV_SORTCB* PTVSORTCB;
+
+struct UDACCEL
+{
+    UINT nSec;
+    UINT nInc;
+}
+
+alias UDACCEL TUDACCEL;
+alias UDACCEL* PUDACCEL;
+
+union ULARGE_INTEGER
+{
+    struct
+    {
+        DWORD LowPart;
+        DWORD HighPart;
+    };
+    struct u
+    {
+        DWORD LowPart;
+        DWORD HighPart;
+    };
+    DWORDLONG QuadPart;
+}
+alias ULARGE_INTEGER* PULARGE_INTEGER;
+alias ULARGE_INTEGER _ULARGE_INTEGER;
+alias ULARGE_INTEGER TULARGEINTEGER;
+alias ULARGE_INTEGER* PULARGEINTEGER;
+
+struct UNIVERSAL_NAME_INFO
+{
+    LPTSTR lpUniversalName;
+}
+
+alias UNIVERSAL_NAME_INFO _UNIVERSAL_NAME_INFO;
+alias UNIVERSAL_NAME_INFO TUNIVERSALNAMEINFO;
+alias UNIVERSAL_NAME_INFO* PUNIVERSALNAMEINFO;
+
+struct USEROBJECTFLAGS
+{
+    WINBOOL fInherit;
+    WINBOOL fReserved;
+    DWORD dwFlags;
+}
+
+alias USEROBJECTFLAGS TAGUSEROBJECTFLAGS;
+alias USEROBJECTFLAGS TUSEROBJECTFLAGS;
+alias USEROBJECTFLAGS* PUSEROBJECTFLAGS;
+
+struct VALENT
+{
+    LPTSTR ve_valuename;
+    DWORD ve_valuelen;
+    DWORD ve_valueptr;
+    DWORD ve_type;
+}
+
+alias VALENT TVALENT;
+alias VALENT* PVALENT;
+alias VALENT VALUE_ENT;
+alias VALENT TVALUE_ENT;
+alias VALENT* PVALUE_ENT;
+
+struct VERIFY_INFORMATION
+{
+    LARGE_INTEGER StartingOffset;
+    DWORD Length;
+}
+
+alias VERIFY_INFORMATION _VERIFY_INFORMATION;
+alias VERIFY_INFORMATION TVERIFYINFORMATION;
+alias VERIFY_INFORMATION* PVERIFYINFORMATION;
+
+struct VS_FIXEDFILEINFO
+{
+    DWORD dwSignature;
+    DWORD dwStrucVersion;
+    DWORD dwFileVersionMS;
+    DWORD dwFileVersionLS;
+    DWORD dwProductVersionMS;
+    DWORD dwProductVersionLS;
+    DWORD dwFileFlagsMask;
+    DWORD dwFileFlags;
+    DWORD dwFileOS;
+    DWORD dwFileType;
+    DWORD dwFileSubtype;
+    DWORD dwFileDateMS;
+    DWORD dwFileDateLS;
+}
+
+alias VS_FIXEDFILEINFO _VS_FIXEDFILEINFO;
+alias VS_FIXEDFILEINFO TVSFIXEDFILEINFO;
+alias VS_FIXEDFILEINFO* PVSFIXEDFILEINFO;
+
+struct WIN32_FIND_DATA
+{
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    TCHAR[1 + MAX_PATH-1] cFileName;
+    TCHAR[1 + 13] cAlternateFileName;
+}
+
+alias WIN32_FIND_DATA* LPWIN32_FIND_DATA;
+alias WIN32_FIND_DATA* PWIN32_FIND_DATA;
+alias WIN32_FIND_DATA _WIN32_FIND_DATA;
+alias WIN32_FIND_DATA TWIN32FINDDATA;
+alias WIN32_FIND_DATA TWIN32FINDDATAA;
+alias WIN32_FIND_DATA* PWIN32FINDDATA;
+
+struct WIN32_FIND_DATAW {
+    DWORD dwFileAttributes;
+    FILETIME ftCreationTime;
+    FILETIME ftLastAccessTime;
+    FILETIME ftLastWriteTime;
+    DWORD nFileSizeHigh;
+    DWORD nFileSizeLow;
+    DWORD dwReserved0;
+    DWORD dwReserved1;
+    WCHAR  cFileName[MAX_PATH];
+    WCHAR  cAlternateFileName[14];
+}
+
+alias WIN32_FIND_DATAW* LPWIN32_FIND_DATAW;
+alias WIN32_FIND_DATAW* PWIN32_FIND_DATAW;
+
+struct WIN32_FILE_ATTRIBUTE_DATA {
+  DWORD dwFileAttributes;
+  FILETIME ftCreationTime;
+  FILETIME ftLastAccessTime;
+  FILETIME ftLastWriteTime;
+  DWORD nFileSizeHigh;
+  DWORD nFileSizeLow;
+}
+
+enum {
+    GetFileInfoLevelStandard,
+    GetFileInfoLevelMax
+}
+
+struct WIN32_STREAM_ID
+{
+    DWORD dwStreamId;
+    DWORD dwStreamAttributes;
+    LARGE_INTEGER Size;
+    DWORD dwStreamNameSize;
+    WCHAR* cStreamName;
+}
+
+alias WIN32_STREAM_ID _WIN32_STREAM_ID;
+alias WIN32_STREAM_ID TWIN32STREAMID;
+alias WIN32_STREAM_ID* PWIN32STREAMID;
+
+struct WINDOWPLACEMENT
+{
+    UINT length;
+    UINT flags;
+    UINT showCmd;
+    POINT ptMinPosition;
+    POINT ptMaxPosition;
+    RECT rcNormalPosition;
+}
+
+alias WINDOWPLACEMENT _WINDOWPLACEMENT;
+alias WINDOWPLACEMENT TWINDOWPLACEMENT;
+alias WINDOWPLACEMENT* PWINDOWPLACEMENT;
+
+struct WNDCLASSA
+{
+    UINT style;
+    WNDPROC lpfnWndProc;
+    int cbClsExtra;
+    int cbWndExtra;
+    HANDLE hInstance;
+    HICON hIcon;
+    HCURSOR hCursor;
+    HBRUSH hbrBackground;
+    LPCSTR lpszMenuName;
+    LPCSTR lpszClassName;
+}
+
+alias WNDCLASSA* PWNDCLASSA, LPWNDCLASSA;
+
+struct WNDCLASSW
+{
+    UINT        style;
+    WNDPROC     lpfnWndProc;
+    int         cbClsExtra;
+    int         cbWndExtra;
+    HINSTANCE   hInstance;
+    HICON       hIcon;
+    HCURSOR     hCursor;
+    HBRUSH      hbrBackground;
+    LPCWSTR     lpszMenuName;
+    LPCWSTR     lpszClassName;
+}
+
+alias WNDCLASSW* PWNDCLASSW, LPWNDCLASSW;
+
+version(Win32SansUnicode)
+{
+    alias WNDCLASSA WNDCLASS;
+}
+else
+{
+    alias WNDCLASSW WNDCLASS;
+}
+alias WNDCLASS* LPWNDCLASS;
+alias WNDCLASS _WNDCLASS;
+alias WNDCLASS TWNDCLASS;
+alias WNDCLASS WNDCLASS_T;
+alias WNDCLASS* PWNDCLASS;
+
+struct WNDCLASSEX
+{
+    UINT cbSize;
+    UINT style;
+    WNDPROC lpfnWndProc;
+    int cbClsExtra;
+    int cbWndExtra;
+    HANDLE hInstance;
+    HICON hIcon;
+    HCURSOR hCursor;
+    HBRUSH hbrBackground;
+    LPCTSTR lpszMenuName;
+    LPCTSTR lpszClassName;
+    HANDLE hIconSm;
+}
+
+alias WNDCLASSEX* LPWNDCLASSEX;
+alias WNDCLASSEX _WNDCLASSEX;
+alias WNDCLASSEX TWNDCLASSEX;
+alias WNDCLASSEX TWNDCLASSEXA;
+alias WNDCLASSEX* PWNDCLASSEX;
+
+struct CONNECTDLGSTRUCT
+{
+    DWORD cbStructure;
+    HWND hwndOwner;
+    LPNETRESOURCE lpConnRes;
+    DWORD dwFlags;
+    DWORD dwDevNum;
+}
+
+alias CONNECTDLGSTRUCT* LPCONNECTDLGSTRUCT;
+alias CONNECTDLGSTRUCT _CONNECTDLGSTRUCT;
+alias CONNECTDLGSTRUCT TCONNECTDLGSTRUCT;
+alias CONNECTDLGSTRUCT* PCONNECTDLGSTRUCT;
+
+struct DISCDLGSTRUCT
+{
+    DWORD cbStructure;
+    HWND hwndOwner;
+    LPTSTR lpLocalName;
+    LPTSTR lpRemoteName;
+    DWORD dwFlags;
+}
+
+alias DISCDLGSTRUCT* LPDISCDLGSTRUCT;
+alias DISCDLGSTRUCT _DISCDLGSTRUCT;
+alias DISCDLGSTRUCT TDISCDLGSTRUCT;
+alias DISCDLGSTRUCT TDISCDLGSTRUCTA;
+alias DISCDLGSTRUCT* PDISCDLGSTRUCT;
+
+struct NETINFOSTRUCT
+{
+    DWORD cbStructure;
+    DWORD dwProviderVersion;
+    DWORD dwStatus;
+    DWORD dwCharacteristics;
+    DWORD dwHandle;
+    ushort wNetType;
+    DWORD dwPrinters;
+    DWORD dwDrives;
+}
+
+alias NETINFOSTRUCT* LPNETINFOSTRUCT;
+alias NETINFOSTRUCT _NETINFOSTRUCT;
+alias NETINFOSTRUCT TNETINFOSTRUCT;
+alias NETINFOSTRUCT* PNETINFOSTRUCT;
+
+struct NETCONNECTINFOSTRUCT
+{
+    DWORD cbStructure;
+    DWORD dwFlags;
+    DWORD dwSpeed;
+    DWORD dwDelay;
+    DWORD dwOptDataSize;
+}
+
+alias NETCONNECTINFOSTRUCT* LPNETCONNECTINFOSTRUCT;
+alias NETCONNECTINFOSTRUCT _NETCONNECTINFOSTRUCT;
+alias NETCONNECTINFOSTRUCT TNETCONNECTINFOSTRUCT;
+alias NETCONNECTINFOSTRUCT* PNETCONNECTINFOSTRUCT;
+extern(Windows){
+alias int (*ENUMMETAFILEPROC)(HDC, HANDLETABLE*, METARECORD*, int, LPARAM);
+alias int (*ENHMETAFILEPROC)(HDC, HANDLETABLE*, ENHMETARECORD*, int, LPARAM);
+alias int (*ENUMFONTSPROC)(LPLOGFONT, LPTEXTMETRIC, DWORD, LPARAM);
+alias int (*FONTENUMPROC)(ENUMLOGFONT*, NEWTEXTMETRIC*, int, LPARAM);
+alias int (*FONTENUMEXPROC)(ENUMLOGFONTEX*, NEWTEXTMETRICEX*, int, LPARAM);
+alias void (*LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD, DWORD);
+}
+
+struct POINTFLOAT
+{
+    FLOAT x;
+    FLOAT y;
+}
+
+alias POINTFLOAT _POINTFLOAT;
+alias POINTFLOAT TPOINTFLOAT;
+alias POINTFLOAT* PPOINTFLOAT;
+
+struct GLYPHMETRICSFLOAT
+{
+    FLOAT gmfBlackBoxX;
+    FLOAT gmfBlackBoxY;
+    POINTFLOAT gmfptGlyphOrigin;
+    FLOAT gmfCellIncX;
+    FLOAT gmfCellIncY;
+}
+
+alias GLYPHMETRICSFLOAT* LPGLYPHMETRICSFLOAT;
+alias GLYPHMETRICSFLOAT _GLYPHMETRICSFLOAT;
+alias GLYPHMETRICSFLOAT TGLYPHMETRICSFLOAT;
+alias GLYPHMETRICSFLOAT* PGLYPHMETRICSFLOAT;
+
+struct LAYERPLANEDESCRIPTOR
+{
+    ushort nSize;
+    ushort nVersion;
+    DWORD dwFlags;
+    ubyte iPixelType;
+    ubyte cColorBits;
+    ubyte cRedBits;
+    ubyte cRedShift;
+    ubyte cGreenBits;
+    ubyte cGreenShift;
+    ubyte cBlueBits;
+    ubyte cBlueShift;
+    ubyte cAlphaBits;
+    ubyte cAlphaShift;
+    ubyte cAccumBits;
+    ubyte cAccumRedBits;
+    ubyte cAccumGreenBits;
+    ubyte cAccumBlueBits;
+    ubyte cAccumAlphaBits;
+    ubyte cDepthBits;
+    ubyte cStencilBits;
+    ubyte cAuxBuffers;
+    ubyte iLayerPlane;
+    ubyte bReserved;
+    COLORREF crTransparent;
+}
+
+alias LAYERPLANEDESCRIPTOR* LPLAYERPLANEDESCRIPTOR;
+alias LAYERPLANEDESCRIPTOR TAGLAYERPLANEDESCRIPTOR;
+alias LAYERPLANEDESCRIPTOR TLAYERPLANEDESCRIPTOR;
+alias LAYERPLANEDESCRIPTOR* PLAYERPLANEDESCRIPTOR;
+
+struct PIXELFORMATDESCRIPTOR
+{
+    ushort nSize;
+    ushort nVersion;
+    DWORD dwFlags;
+    ubyte iPixelType;
+    ubyte cColorBits;
+    ubyte cRedBits;
+    ubyte cRedShift;
+    ubyte cGreenBits;
+    ubyte cGreenShift;
+    ubyte cBlueBits;
+    ubyte cBlueShift;
+    ubyte cAlphaBits;
+    ubyte cAlphaShift;
+    ubyte cAccumBits;
+    ubyte cAccumRedBits;
+    ubyte cAccumGreenBits;
+    ubyte cAccumBlueBits;
+    ubyte cAccumAlphaBits;
+    ubyte cDepthBits;
+    ubyte cStencilBits;
+    ubyte cAuxBuffers;
+    ubyte iLayerType;
+    ubyte bReserved;
+    DWORD dwLayerMask;
+    DWORD dwVisibleMask;
+    DWORD dwDamageMask;
+}
+
+alias PIXELFORMATDESCRIPTOR* LPPIXELFORMATDESCRIPTOR;
+alias PIXELFORMATDESCRIPTOR TAGPIXELFORMATDESCRIPTOR;
+alias PIXELFORMATDESCRIPTOR TPIXELFORMATDESCRIPTOR;
+alias PIXELFORMATDESCRIPTOR* PPIXELFORMATDESCRIPTOR;
+
+struct USER_INFO_2
+{
+    LPWSTR usri2_name;
+    LPWSTR usri2_password;
+    DWORD usri2_password_age;
+    DWORD usri2_priv;
+    LPWSTR usri2_home_dir;
+    LPWSTR usri2_comment;
+    DWORD usri2_flags;
+    LPWSTR usri2_script_path;
+    DWORD usri2_auth_flags;
+    LPWSTR usri2_full_name;
+    LPWSTR usri2_usr_comment;
+    LPWSTR usri2_parms;
+    LPWSTR usri2_workstations;
+    DWORD usri2_last_logon;
+    DWORD usri2_last_logoff;
+    DWORD usri2_acct_expires;
+    DWORD usri2_max_storage;
+    DWORD usri2_units_per_week;
+    PBYTE usri2_logon_hours;
+    DWORD usri2_bad_pw_count;
+    DWORD usri2_num_logons;
+    LPWSTR usri2_logon_server;
+    DWORD usri2_country_code;
+    DWORD usri2_code_page;
+}
+
+alias USER_INFO_2* PUSER_INFO_2;
+alias USER_INFO_2* LPUSER_INFO_2;
+alias USER_INFO_2 TUSERINFO2;
+alias USER_INFO_2* PUSERINFO2;
+
+struct USER_INFO_0
+{
+    LPWSTR usri0_name;
+}
+
+alias USER_INFO_0* PUSER_INFO_0;
+alias USER_INFO_0* LPUSER_INFO_0;
+alias USER_INFO_0 TUSERINFO0;
+alias USER_INFO_0* PUSERINFO0;
+
+struct USER_INFO_3
+{
+    LPWSTR usri3_name;
+    LPWSTR usri3_password;
+    DWORD usri3_password_age;
+    DWORD usri3_priv;
+    LPWSTR usri3_home_dir;
+    LPWSTR usri3_comment;
+    DWORD usri3_flags;
+    LPWSTR usri3_script_path;
+    DWORD usri3_auth_flags;
+    LPWSTR usri3_full_name;
+    LPWSTR usri3_usr_comment;
+    LPWSTR usri3_parms;
+    LPWSTR usri3_workstations;
+    DWORD usri3_last_logon;
+    DWORD usri3_last_logoff;
+    DWORD usri3_acct_expires;
+    DWORD usri3_max_storage;
+    DWORD usri3_units_per_week;
+    PBYTE usri3_logon_hours;
+    DWORD usri3_bad_pw_count;
+    DWORD usri3_num_logons;
+    LPWSTR usri3_logon_server;
+    DWORD usri3_country_code;
+    DWORD usri3_code_page;
+    DWORD usri3_user_id;
+    DWORD usri3_primary_group_id;
+    LPWSTR usri3_profile;
+    LPWSTR usri3_home_dir_drive;
+    DWORD usri3_password_expired;
+}
+
+alias USER_INFO_3* PUSER_INFO_3;
+alias USER_INFO_3* LPUSER_INFO_3;
+alias USER_INFO_3 TUSERINFO3;
+alias USER_INFO_3* PUSERINFO3;
+
+struct GROUP_INFO_2
+{
+    LPWSTR grpi2_name;
+    LPWSTR grpi2_comment;
+    DWORD grpi2_group_id;
+    DWORD grpi2_attributes;
+}
+
+alias GROUP_INFO_2* PGROUP_INFO_2;
+alias GROUP_INFO_2 TGROUPINFO2;
+alias GROUP_INFO_2* PGROUPINFO2;
+
+struct LOCALGROUP_INFO_0
+{
+    LPWSTR lgrpi0_name;
+}
+
+alias LOCALGROUP_INFO_0* PLOCALGROUP_INFO_0;
+alias LOCALGROUP_INFO_0* LPLOCALGROUP_INFO_0;
+alias LOCALGROUP_INFO_0 TLOCALGROUPINFO0;
+alias LOCALGROUP_INFO_0* PLOCALGROUPINFO0;
+
+struct IMAGE_DOS_HEADER
+{
+    ushort e_magic;
+    ushort e_cblp;
+    ushort e_cp;
+    ushort e_crlc;
+    ushort e_cparhdr;
+    ushort e_minalloc;
+    ushort e_maxalloc;
+    ushort e_ss;
+    ushort e_sp;
+    ushort e_csum;
+    ushort e_ip;
+    ushort e_cs;
+    ushort e_lfarlc;
+    ushort e_ovno;
+    ushort[1 + 3] e_res;
+    ushort e_oemid;
+    ushort e_oeminfo;
+    ushort[1 + 9] e_res2;
+    LONG e_lfanew;
+}
+
+alias IMAGE_DOS_HEADER* PIMAGE_DOS_HEADER;
+alias IMAGE_DOS_HEADER TIMAGEDOSHEADER;
+alias IMAGE_DOS_HEADER* PIMAGEDOSHEADER;
+alias ushort TVARTYPE;
+alias TVARIANT* PVARIANT;
+
+struct TVARIANT
+{
+    TVARTYPE vt;
+    ushort wReserved1;
+    ushort wReserved2;
+    ushort wReserved3;
+
+    union
+    {
+        struct
+        {
+            ubyte bVal;
+        }
+        struct
+        {
+            byte iVal;
+        }
+        struct
+        {
+            int lVal;
+        }
+        struct
+        {
+            float fltVal;
+        }
+        struct
+        {
+            double dblVal;
+        }
+        struct
+        {
+            ushort vbool;
+        }
+        struct
+        {
+            HRESULT scode;
+        }
+        struct
+        {
+            ubyte* pbVal;
+        }
+        struct
+        {
+            byte* piVal;
+        }
+        struct
+        {
+            int* plVal;
+        }
+        struct
+        {
+            float* pfltVal;
+        }
+        struct
+        {
+            double* pdblVal;
+        }
+        struct
+        {
+            ushort* pbool;
+        }
+        struct
+        {
+            HRESULT* pscode;
+        }
+        struct
+        {
+            POINTER byRef;
+        }
+    }
+}
+
+alias TVARIANT VARIANT;
+alias int MMRESULT;
+alias TWAVEFORMATEX* PWAVEFORMATEX;
+alias TWAVEFORMATEX WAVEFORMATEX;
+
+align(1) struct TWAVEFORMATEX
+{
+    ushort wFormatTag;
+    ushort nChannels;
+    DWORD nSamplesPerSec;
+    DWORD nAvgBytesPerSec;
+    ushort nBlockAlign;
+    ushort wBitsPerSample;
+    ushort cbSize;
+}
+
+alias CRITICAL_SECTION TRTLCRITICALSECTION;
+alias PCRITICAL_SECTION PRTLCRITICALSECTION;
+alias PGUID PIID;
+alias TGUID TIID;
+alias HANDLE THANDLE;
+alias TSMALLRECT* PSMALLRECT;
+alias SMALL_RECT TSMALLRECT;
+alias TCHARINFO* PCHARINFO;
+alias _CHAR_INFO TCHARINFO;
+alias POINTER TFARPROC;
+alias POINTER TFNDLGPROC;
+alias POINTER TFNTHREADSTARTROUTINE;
+
+struct _OBJECT_TYPE_LIST
+{
+    ushort Level;
+    ushort Sbz;
+    PGUID ObjectType;
+}
+
+alias _OBJECT_TYPE_LIST TOBJECTTYPELIST;
+alias TOBJECTTYPELIST* POBJECTTYPELIST;
+alias _OBJECT_TYPE_LIST OBJECT_TYPE_LIST;
+alias DWORD AUDIT_EVENT_TYPE;
+
+align(1) struct _BLENDFUNCTION
+{
+    ubyte BlendOp;
+    ubyte BlendFlags;
+    ubyte SourceConstantAlpha;
+    ubyte AlphaFormat;
+}
+
+alias _BLENDFUNCTION TBLENDFUNCTION;
+alias TBLENDFUNCTION* PBLENDFUNCTION;
+alias _BLENDFUNCTION BLENDFUNCTION;
+
+alias HANDLE HMONITOR;
+
+struct MONITORINFOEX
+{
+    DWORD  cbSize;
+    RECT   rcMonitor;
+    RECT   rcWork;
+    DWORD  dwFlags;
+    TCHAR  szDevice[CCHDEVICENAME];
+}
+alias MONITORINFOEX* LPMONITORINFOEX;
+
+struct MONITORINFO
+{
+    DWORD  cbSize;
+    RECT   rcMonitor;
+    RECT   rcWork;
+    DWORD  dwFlags;
+}
+alias MONITORINFO* LPMONITORINFO;
+
+struct WINDOWINFO
+{
+    DWORD cbSize;
+    RECT rcWindow;
+    RECT rcClient;
+    DWORD dwStyle;
+    DWORD dwExStyle;
+    DWORD dwWindowStatus;
+    UINT cxWindowBorders;
+    UINT cyWindowBorders;
+    ATOM atomWindowType;
+    short wCreatorVersion;
+};
+alias WINDOWINFO* PWINDOWINFO;
+alias WINDOWINFO* LPWINDOWINFO;
+
+enum : HRESULT
+{
+    S_OK            = 0x00000000,
+    S_FALSE         = 0x00000001,
+    E_UNEXPECTED    = 0x8000FFFF,
+    E_NOTIMPL       = 0x80004001,
+    E_OUTOFMEMORY   = 0x8007000E,
+    E_INVALIDARG    = 0x80070057,
+    E_NOINTERFACE   = 0x80004002,
+    E_POINTER       = 0x80004003,
+    E_HANDLE        = 0x80070006,
+    E_ABORT         = 0x80004004,
+    E_FAIL          = 0x80004005,
+    E_ACCESSDENIED  = 0x80070005,
+    E_PENDING       = 0x8000000A,
+}
+
+/*
+int CO_E_INIT_TLS = (DWORD)((0x80004006));
+int CO_E_INIT_MEMORY_ALLOCATOR = (DWORD)((0x80004008));
+int CO_E_INIT_CLASS_CACHE = (DWORD)((0x80004009));
+int CO_E_INIT_RPC_CHANNEL = (DWORD)((0x8000400A));
+int CO_E_INIT_TLS_SET_CHANNEL_CONTROL = (DWORD)((0x8000400B));
+int CO_E_INIT_TLS_CHANNEL_CONTROL = (DWORD)((0x8000400C));
+int CO_E_INIT_UNACCEPTED_USER_ALLOCATOR = (DWORD)((0x8000400D));
+int CO_E_INIT_SCM_MUTEX_EXISTS = (DWORD)((0x8000400E));
+int CO_E_INIT_SCM_FILE_MAPPING_EXISTS = (DWORD)((0x8000400F));
+int CO_E_INIT_SCM_MAP_VIEW_OF_FILE = (DWORD)((0x80004010));
+int CO_E_INIT_SCM_EXEC_FAILURE = (DWORD)((0x80004011));
+int CO_E_INIT_ONLY_SINGLE_THREADED = (DWORD)((0x80004012));
+int CO_E_CANT_REMOTE = (DWORD)((0x80004013));
+int CO_E_BAD_SERVER_NAME = (DWORD)((0x80004014));
+int CO_E_WRONG_SERVER_IDENTITY = (DWORD)((0x80004015));
+int CO_E_OLE1DDE_DISABLED = (DWORD)((0x80004016));
+int CO_E_RUNAS_SYNTAX = (DWORD)((0x80004017));
+int CO_E_CREATEPROCESS_FAILURE = (DWORD)((0x80004018));
+int CO_E_RUNAS_CREATEPROCESS_FAILURE = (DWORD)((0x80004019));
+int CO_E_RUNAS_LOGON_FAILURE = (DWORD)((0x8000401A));
+int CO_E_LAUNCH_PERMSSION_DENIED = (DWORD)((0x8000401B));
+int CO_E_START_SERVICE_FAILURE = (DWORD)((0x8000401C));
+int CO_E_REMOTE_COMMUNICATION_FAILURE = (DWORD)((0x8000401D));
+int CO_E_SERVER_START_TIMEOUT = (DWORD)((0x8000401E));
+int CO_E_CLSREG_INCONSISTENT = (DWORD)((0x8000401F));
+int CO_E_IIDREG_INCONSISTENT = (DWORD)((0x80004020));
+int CO_E_NOT_SUPPORTED = (DWORD)((0x80004021));
+int CO_E_FIRST = (DWORD)((0x800401F0));
+int CO_E_LAST = (DWORD)((0x800401FF));
+int CO_S_FIRST = (0x401F0);
+int CO_E_NOTINITIALIZED = (DWORD)((0x800401F0));
+int CO_E_ALREADYINITIALIZED = (DWORD)((0x800401F1));
+int CO_E_CANTDETERMINECLASS = (DWORD)((0x800401F2));
+int CO_E_CLASSSTRING = (DWORD)((0x800401F3));
+int CO_E_IIDSTRING = (DWORD)((0x800401F4));
+int CO_E_APPNOTFOUND = (DWORD)((0x800401F5));
+int CO_E_APPSINGLEUSE = (DWORD)((0x800401F6));
+int CO_E_ERRORINAPP = (DWORD)((0x800401F7));
+int CO_E_DLLNOTFOUND = (DWORD)((0x800401F8));
+int CO_E_ERRORINDLL = (DWORD)((0x800401F9));
+int CO_E_WRONGOSFORAPP = (DWORD)((0x800401FA));
+int CO_E_OBJNOTREG = (DWORD)((0x800401FB));
+int CO_E_OBJISREG = (DWORD)((0x800401FC));
+int CO_E_OBJNOTCONNECTED = (DWORD)((0x800401FD));
+int CO_E_APPDIDNTREG = (DWORD)((0x800401FE));
+int CO_E_RELEASED = (DWORD)((0x800401FF));
+*/
+
+} // !TANGOSVN
+
+///////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// missing in tango
+//alias TLOGFONTA* LPLOGFONTA;
+//alias TLOGFONTA LOGFONTA;
+//alias char CHAR;
+alias OPENFILENAME OPENFILENAMEW;
+alias OPENFILENAME OPENFILENAMEA;
+//alias WNDCLASS_T   WNDCLASS;
+
+//alias TCLSID *REFCLSID;
+
+//interface IUnknown{}
+//alias IUnknown LPUNKNOWN;
+
+
+struct SCRIPT_DIGITSUBSTITUTE {
+  ushort NationalDigitLanguage;
+  ushort TraditionalDigitLanguage;
+  DWORD DigitSubstitute;
+  DWORD dwReserved;
+}
+
+struct BUTTON_IMAGELIST {
+    HIMAGELIST himl;
+    RECT margin;
+    UINT uAlign;
+}
+
+alias HANDLE HTHEME;
+
+struct NMREBARCHILDSIZE {
+    NMHDR hdr;
+    UINT uBand;
+    UINT wID;
+    RECT rcChild;
+    RECT rcBand;
+}
+const int MAX_LINKID_TEXT = 48;
+const int L_MAX_URL_LENGTH = 2084;
+struct LITEM {
+    UINT mask;
+    int iLink;
+    UINT state;
+    UINT stateMask;
+    WCHAR szID[MAX_LINKID_TEXT];
+    WCHAR szUrl[L_MAX_URL_LENGTH];
+}
+struct NMLINK {
+    NMHDR hdr;
+    LITEM item;
+}
+struct NMLVODSTATECHANGE {
+  NMHDR hdr;
+  int iFrom;
+  int iTo;
+  UINT uNewState;
+  UINT uOldState;
+}
+struct NMTBHOTITEM {
+    NMHDR hdr;
+    int idOld;
+    int idNew;
+    DWORD dwFlags;
+}
+struct NMTVDISPINFO {
+    NMHDR hdr;
+    TVITEM item;
+}
+
+// only on Vista
+struct NMTVITEMCHANGE {
+    NMHDR hdr;
+    UINT uChanged;
+    HTREEITEM hItem;
+    UINT uStateNew;
+    UINT uStateOld;
+    LPARAM lParam;
+}
+
+struct ACTCTXA {
+  ULONG cbSize;
+  DWORD dwFlags;
+  LPCSTR lpSource;
+  USHORT wProcessorArchitecture;
+  LANGID wLangId;
+  LPCTSTR lpAssemblyDirectory;
+  LPCTSTR lpResourceName;
+  LPCTSTR lpApplicationName;
+  HMODULE hModule;
+}
+struct ACTCTXW {
+  ULONG cbSize;
+  DWORD dwFlags;
+  LPCWSTR lpSource;
+  USHORT wProcessorArchitecture;
+  LANGID wLangId;
+  LPCTSTR lpAssemblyDirectory;
+  LPCTSTR lpResourceName;
+  LPCTSTR lpApplicationName;
+  HMODULE hModule;
+}
+version(Win32SansUnicode) alias ACTCTXA ACTCTX;
+else          alias ACTCTXW ACTCTX;
+alias HANDLE HACTCTX;
+
+struct OSVERSIONINFOEX
+{
+  DWORD dwOSVersionInfoSize;
+  DWORD dwMajorVersion;
+  DWORD dwMinorVersion;
+  DWORD dwBuildNumber;
+  DWORD dwPlatformId;
+  TCHAR szCSDVersion[128];
+  WORD wServicePackMajor;
+  WORD wServicePackMinor;
+  WORD wSuiteMask;
+  BYTE wProductType;
+  BYTE wReserved;
+}
+
+
+
+// ....
+//--------------------------------------------------------------------------------
+
+// const int LF_FACESIZE = 32;
+// const int LF_FULLFACESIZE = 64;
+
+alias HANDLE HIMC;
+// alias HANDLE HTREEITEM;
+//alias HANDLE HDWP;
+//alias HANDLE HIMAGELIST;
+//alias HANDLE HMONITOR;
+//alias HANDLE HHOOK;
+//alias HANDLE HDROP;
+//alias HANDLE *LPHANDLE;
+
+alias HRESULT WINOLEAPI;
+// alias LPRECT LPCRECT;
+// alias LPRECT LPCRECTL;
+alias DWORD LGRPID;
+//alias LONG LONG_PTR;
+//alias ULONG ULONG_PTR;
+//alias DWORD DWORD_PTR;
+//alias int INT_PTR;
+//alias uint UINT_PTR;
+// alias DWORD LCID;
+// alias DWORD LCTYPE;
+alias USHORT COLOR16;
+
+//alias POINT POINTL;
+
+//alias long LONGLONG;
+//alias ulong DWORDLONG;
+
+//alias LONGLONG  *PLONGLONG;
+//alias DWORDLONG *PDWORDLONG;
+alias size_t    SIZE_T;
+//alias int       WPARAM_I;
+
+extern(Windows){
+
+/**
+ * Since Eclipse/SWT uses int as (msg, wparam, lparam) and some times check the value against (-1),
+ * but WNDPROC_I declared in windows header the (msg, wparam) is UINT which will never be -1 but 0xFFFF or
+ * something else. This made some SWT API failed. to fix the problem, it better to declare (msg, wparam)
+ * as int like Eclispe/SWT does. and we alias int to WPARAM_I.
+ */
+// alias LRESULT function(HWND, uint, uint, int) WNDPROC_I;
+// alias LRESULT function(int code, int wParam, LPARAM lParam) HOOKPROC_I;
+//
+// // Windows CALLBACK declaration here
+// alias WNDPROC_I BFFCALLBACK;        // browse for fold
+// alias WNDPROC_I LPCCHOOKPROC_I;     // choose color
+// alias WNDPROC_I LPCFHOOKPROC_I;     // choose font
+// alias WNDPROC_I LPPRINTHOOKPROC_I;  // print hook
+// alias WNDPROC_I LPSETUPHOOKPROC_I;  // print setup
+// alias WNDPROC_I TIMERPROC_I;        // timer
+
+alias LRESULT function (
+    int code,       // hook code
+    int wParam,  // undefined
+    int lParam   // address of structure with message data
+) MESSAGEPROC;
+
+
+//alias BOOL function (
+//  HMONITOR hMonitor,  // handle to display monitor
+//  HDC hdcMonitor,     // handle to monitor-appropriate device context
+//  LPRECT lprcMonitor, // pointer to monitor intersection rectangle
+//  LPARAM dwData       // data passed from EnumDisplayMonitors
+//) MONITORENUMPROC;
+
+//alias int function(
+//  ENUMLOGFONT *lpelf,    // logical-font data
+//  NEWTEXTMETRIC *lpntm,  // physical-font data
+//  DWORD FontType,        // type of font
+//  LPARAM lParam          // application-defined data
+//)FONTENUMPROC;
+
+//alias int function(
+//  ENUMLOGFONTEX *lpelfe,    // logical-font data
+//  NEWTEXTMETRICEX *lpntme,  // physical-font data
+//  DWORD FontType,           // type of font
+//  LPARAM lParam             // application-defined data
+//)FONTENUMEXPROC;
+
+alias BOOL function (
+  LGRPID LanguageGroup,             // language-group identifier
+  TCHAR* lpLanguageGroupString,     // language-group identifier string
+  TCHAR* lpLanguageGroupNameString, // language-group name string
+  DWORD dwFlags,                    // options
+  LONG_PTR  lParam                  // callback parameter
+)LANGUAGEGROUP_ENUMPROC;
+
+//alias BOOL function (
+//  TCHAR* lpLocaleString   // locale identifier string
+//)LOCALE_ENUMPROC;
+
+
+// end of Windows CALLBACK declaration
+
+
+
+//struct ABC {
+//    int     abcA;
+//    UINT    abcB;
+//    int     abcC;
+//}
+//alias ABC* PABC, LPABC;
+
+// declared in tango
+//struct ACCEL {
+//    align(1):
+//    BYTE   fVirt;
+//    WORD   key;
+//    WORD   cmd;
+//}
+//alias ACCEL* PACCEL, LPACCEL;
+
+// declared in phobos
+//struct BITMAP {
+//  int bmType;
+//  int bmWidth;
+//  int bmHeight;
+//  int bmWidthBytes;
+//  short bmPlanes;
+//  short bmBitsPixel;
+//  void* bmBits;
+//}
+
+//struct RGBQUAD { // rgbq
+//    byte    rgbBlue;
+//    byte    rgbGreen;
+//    byte    rgbRed;
+//    byte    rgbReserved;
+//}
+
+// declared in phobos
+//struct BITMAPINFO { // bmi
+//    BITMAPINFOHEADER bmiHeader;
+//    RGBQUAD          bmiColors[1];
+//}
+
+//struct BITMAPINFOHEADER {
+//  int biSize;
+//  int biWidth;
+//  int biHeight;
+//  short biPlanes;
+//  short biBitCount;
+//  int biCompression;
+//  int biSizeImage;
+//  int biXPelsPerMeter;
+//  int biYPelsPerMeter;
+//  int biClrUsed;
+//  int biClrImportant;
+//}
+
+
+
+//struct CHARSETINFO {
+//    UINT ciCharset;
+//    UINT ciACP;
+//    FONTSIGNATURE fs;
+//}alias CHARSETINFO* PCHARSETINFO, LPCHARSETINFO;
+
+
+
+
+struct COMBOBOXINFO {
+    DWORD cbSize;
+    RECT rcItem;
+    RECT rcButton;
+    DWORD stateButton;
+    HWND hwndCombo;
+    HWND hwndItem;
+    HWND hwndList;
+} alias COMBOBOXINFO* PCOMBOBOXINFO, LPCOMBOBOXINFO;
+
+//struct COMPOSITIONFORM {
+//    DWORD dwStyle;
+//    POINT ptCurrentPos;
+//    RECT rcArea;
+//}
+//alias COMPOSITIONFORM* LPCOMPOSITIONFORM;
+
+// const uint CCHDEVICENAME = 32;
+// const uint CCHFORMNAME = 32;
+
+struct DEVMODEA {    // dvmd
+    BYTE   dmDeviceName[CCHDEVICENAME];
+    WORD   dmSpecVersion;
+    WORD   dmDriverVersion;
+    WORD   dmSize;
+    WORD   dmDriverExtra;
+    DWORD  dmFields;
+//    union {
+//      struct {
+//        short dmOrientation;
+//        short dmPaperSize;
+//        short dmPaperLength;
+//        short dmPaperWidth;
+//      };
+//      POINTL dmPosition;
+//    };
+    POINT  dmPosition;
+    short  dmScale;
+    short  dmCopies;
+    short  dmDefaultSource;
+    short  dmPrintQuality;
+    short  dmColor;
+    short  dmDuplex;
+    short  dmYResolution;
+    short  dmTTOption;
+    short  dmCollate;
+    BYTE  dmFormName[CCHFORMNAME];
+    WORD  dmLogPixels;
+    DWORD  dmBitsPerPel;
+    DWORD  dmPelsWidth;
+    DWORD  dmPelsHeight;
+    DWORD  dmDisplayFlags;
+    DWORD  dmDisplayFrequency;
+//#if(WINVER >= 0x0400)
+    DWORD  dmICMMethod;
+    DWORD  dmICMIntent;
+    DWORD  dmMediaType;
+    DWORD  dmDitherType;
+    DWORD  dmReserved1;
+    DWORD  dmReserved2;
+//#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
+    DWORD  dmPanningWidth;
+    DWORD  dmPanningHeight;
+//#endif
+//#endif /* WINVER >= 0x0400 */
+}
+
+struct DEVMODEW {    // dvmd
+    WCHAR  dmDeviceName[CCHDEVICENAME];
+    WORD   dmSpecVersion;
+    WORD   dmDriverVersion;
+    WORD   dmSize;
+    WORD   dmDriverExtra;
+    DWORD  dmFields;
+//    union {
+//      struct {
+//        short dmOrientation;
+//        short dmPaperSize;
+//        short dmPaperLength;
+//        short dmPaperWidth;
+//      };
+      POINTL dmPosition;
+//    };
+    short  dmScale;
+    short  dmCopies;
+    short  dmDefaultSource;
+    short  dmPrintQuality;
+    short  dmColor;
+    short  dmDuplex;
+    short  dmYResolution;
+    short  dmTTOption;
+    short  dmCollate;
+    WCHAR dmFormName[CCHFORMNAME];
+    WORD  dmLogPixels;
+    DWORD  dmBitsPerPel;
+    DWORD  dmPelsWidth;
+    DWORD  dmPelsHeight;
+    DWORD  dmDisplayFlags;
+    DWORD  dmDisplayFrequency;
+//#if(WINVER >= 0x0400)
+    DWORD  dmICMMethod;
+    DWORD  dmICMIntent;
+    DWORD  dmMediaType;
+    DWORD  dmDitherType;
+    DWORD  dmReserved1;
+    DWORD  dmReserved2;
+//#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
+    DWORD  dmPanningWidth;
+    DWORD  dmPanningHeight;
+//#endif
+//#endif /* WINVER >= 0x0400 */
+}
+
+//PORTING_TODO: defined in tango
+//version(Win32SansUnicode){
+//    alias DEVMODEA DEVMODE;
+//}else{
+//    alias DEVMODEW DEVMODE;
+//}
+
+//struct DIBSECTION {
+//    // BITMAP
+//    int bmType;
+//    int bmWidth;
+//    int bmHeight;
+//    int bmWidthBytes;
+//    short bmPlanes;
+//    short bmBitsPixel;
+//    void* bmBits;
+//    // end BITMAP
+//    int biSize;
+//    int biWidth;
+//    int biHeight;
+//    short biPlanes;
+//    short biBitCount;
+//    int biCompression;
+//    int biSizeImage;
+//    int biXPelsPerMeter;
+//    int biYPelsPerMeter;
+//    int biClrUsed;
+//    int biClrImportant;
+//    int dsBitfields0;
+//    int dsBitfields1;
+//    int dsBitfields2;
+//    int dshSection;
+//    int dsOffset;
+//}
+
+struct DLLVERSIONINFO {
+    DWORD cbSize;
+    DWORD dwMajorVersion;
+    DWORD dwMinorVersion;
+    DWORD dwBuildNumber;
+    DWORD dwPlatformID;
+}
+
+
+
+struct DROPFILES {
+    DWORD  pFiles; // Offset of the file list from the beginning of this structure, in bytes.
+    POINT pt; // Drop point. The coordinates depend on fNC.
+    BOOL fNC;   // Nonclient area flag. If this member is TRUE, pt specifies the screen
+                      // coordinates of a point in a window's nonclient area. If it is FALSE,
+                      // pt specifies the client coordinates of a point in the client area.
+    BOOL fWide; // Value that indicates whether the file contains ANSI or Unicode
+                      // characters. If it is zero, it contains ANSI characters. Otherwise, it
+                      // contains Unicode characters.
+
+}
+
+
+// struct ENUMLOGFONTA {
+//   LOGFONTA elfLogFont;
+//   CHAR   elfFullName[LF_FULLFACESIZE];
+//   CHAR   elfStyle[LF_FACESIZE];
+// }
+// struct ENUMLOGFONTW {
+//   LOGFONTW elfLogFont;
+//   WCHAR   elfFullName[LF_FULLFACESIZE];
+//   WCHAR   elfStyle[LF_FACESIZE];
+// }
+// struct ENUMLOGFONTEXA {
+//     LOGFONTA  elfLogFont;
+//     BYTE  elfFullName[LF_FULLFACESIZE];
+//     BYTE  elfStyle[LF_FACESIZE];
+//     BYTE  elfScript[LF_FACESIZE];
+// }
+// struct ENUMLOGFONTEXW {
+//     LOGFONTW  elfLogFont;
+//     WCHAR  elfFullName[LF_FULLFACESIZE];
+//     WCHAR  elfStyle[LF_FACESIZE];
+//     WCHAR  elfScript[LF_FACESIZE];
+// }
+// version(Win32SansUnicode){
+//     alias ENUMLOGFONTA ENUMLOGFONT;
+//     alias ENUMLOGFONTEXA ENUMLOGFONTEX;
+// }else {
+//     alias ENUMLOGFONTW ENUMLOGFONT;
+//     alias ENUMLOGFONTEXW ENUMLOGFONTEX;
+// }
+
+// in phobos aready
+//struct FILETIME {
+//    DWORD dwLowDateTime;
+//    DWORD dwHighDateTime;
+//}
+
+
+
+struct GOFFSET {
+  LONG  du;
+  LONG  dv;
+}
+
+struct GRADIENT_RECT {
+  ULONG    UpperLeft;
+  ULONG    LowerRight;
+}
+
+struct GUITHREADINFO {
+    DWORD cbSize;
+    DWORD flags;
+    HWND hwndActive;
+    HWND hwndFocus;
+    HWND hwndCapture;
+    HWND hwndMenuOwner;
+    HWND hwndMoveSize;
+    HWND hwndCaret;
+    RECT rcCaret;
+}alias GUITHREADINFO* PGUITHREADINFO, LPGUITHREADINFO;
+
+struct HDITEMA {
+    UINT    mask;
+    int     cxy;
+    LPSTR  pszText;
+    HBITMAP hbm;
+    int     cchTextMax;
+    int     fmt;
+    LPARAM  lParam;
+//#if (_WIN32_IE >= 0x0300)
+    int     iImage;
+    int     iOrder;
+//#endif
+//#if (_WIN32_IE >= 0x0500)
+    UINT    type;
+    void    *pvFilter;
+//#endif
+//#if _WIN32_WINNT >= 0x0600
+//    UINT   state;
+//#endif
+}
+struct HDITEMW {
+    UINT    mask;
+    int     cxy;
+    LPWSTR  pszText;
+    HBITMAP hbm;
+    int     cchTextMax;
+    int     fmt;
+    LPARAM  lParam;
+//#if (_WIN32_IE >= 0x0300)
+    int     iImage;
+    int     iOrder;
+//#endif
+//#if (_WIN32_IE >= 0x0500)
+    UINT    type;
+    void    *pvFilter;
+//#endif
+//#if _WIN32_WINNT >= 0x0600
+//    UINT   state;
+//#endif
+}
+version(Win32SansUnicode){
+    alias HDITEMA HDITEM;
+}else{
+    alias HDITEMW HDITEM;
+}
+alias HDITEM* LPHDITEM;
+
+
+//struct ICONINFO {
+//   BOOL    fIcon;
+//   DWORD   xHotspot;
+//   DWORD   yHotspot;
+//   HBITMAP hbmMask;
+//   HBITMAP hbmColor;
+//}
+//alias ICONINFO*  PICONINFO, LPICONINFO;
+
+struct INITCOMMONCONTROLSEX {
+    DWORD dwSize;
+    DWORD dwICC;
+}alias INITCOMMONCONTROLSEX* PINITCOMMONCONTROLSEX, LPINITCOMMONCONTROLSEX;
+
+struct INPUT {
+    // Note: <Shawn> sizeof = 28
+    int type;
+  union {
+        MOUSEINPUT mi;
+        KEYBDINPUT ki;
+//        HARDWAREINPUT hi;
+    }
+}alias INPUT* PINPUT, LPINPUT;
+
+//struct ITEMIDLIST {
+//    SHITEMID mkid;
+//}
+//alias ITEMIDLIST* PITEMIDLIST, LPITEMIDLIST, LPCITEMIDLIST;
+
+struct KEYBDINPUT {
+    WORD wVk;
+    WORD wScan;
+    DWORD dwFlags;
+    DWORD time;
+    ULONG_PTR dwExtraInfo;
+}
+
+
+// struct LOGBRUSH {
+//   UINT     lbStyle;
+//   COLORREF lbColor;
+//   LONG     lbHatch;
+// }
+
+
+
+struct LVFINDINFOA {
+    UINT flags;
+    LPCSTR psz;
+    LPARAM lParam;
+    POINT pt;
+    UINT vkDirection;
+}
+alias LVFINDINFOA* LPFINDINFOA;
+struct LVFINDINFOW {
+    UINT flags;
+    LPCWSTR psz;
+    LPARAM lParam;
+    POINT pt;
+    UINT vkDirection;
+}
+alias LVFINDINFOW* LPFINDINFOW;
+
+version(Win32SansUnicode){
+    alias LVFINDINFOA LVFINDINFO;
+}else{
+    alias LVFINDINFOW LVFINDINFO;
+}
+
+
+struct MARGINS {
+    int cxLeftWidth;
+    int cxRightWidth;
+    int cyTopHeight;
+    int cyBottomHeight;
+}
+
+struct MENUBARINFO {
+  DWORD cbSize;
+  RECT  rcBar;
+  HMENU hMenu;
+  HWND  hwndMenu;
+  BOOL  flags;
+    //fBarFocused : 1;
+    //fFocused    : 1;
+}
+alias MENUBARINFO* PMENUBARINFO;
+alias MENUBARINFO* LPMENUBARINFO;
+
+struct MENUINFO {
+  DWORD   cbSize;
+  DWORD   fMask;
+  DWORD   dwStyle;
+  UINT    cyMax;
+  HBRUSH  hbrBack;
+  DWORD   dwContextHelpID;
+  ULONG_PTR  dwMenuData;
+}
+alias MENUINFO* PCMENUINFO, LPCMENUINFO, LPCCMENUINFO;
+
+/*
+* Feature in Windows.  The hbmpItem field requires Windows 4.10
+* or greater.  On Windows NT 4.0, passing in a larger struct size
+* in the cbSize field does nothing.  On Windows 95, the MENUITEMINFO
+* calls fail when the struct size is too large.  The fix is to ensure
+* that the correct struct size is used for the Windows platform.
+*/
+// struct MENUITEMINFOA
+// {
+//     UINT    cbSize;
+//     UINT    fMask;
+//     UINT    fType;          // used if MIIM_TYPE
+//     UINT    fState;         // used if MIIM_STATE
+//     UINT    wID;            // used if MIIM_ID
+//     HMENU   hSubMenu;       // used if MIIM_SUBMENU
+//     HBITMAP hbmpChecked;    // used if MIIM_CHECKMARKS
+//     HBITMAP hbmpUnchecked;  // used if MIIM_CHECKMARKS
+//     DWORD   dwItemData;     // used if MIIM_DATA
+//     LPSTR   dwTypeData;     // used if MIIM_TYPE
+//     UINT    cch;            // used if MIIM_TYPE
+//     HBITMAP hbmpItem;
+// }
+// alias MENUITEMINFOA* PMENUITEMINFOA, LPMENUITEMINFOA;
+// struct MENUITEMINFOW
+// {
+//     UINT    cbSize;
+//     UINT    fMask;
+//     UINT    fType;          // used if MIIM_TYPE
+//     UINT    fState;         // used if MIIM_STATE
+//     UINT    wID;            // used if MIIM_ID
+//     HMENU   hSubMenu;       // used if MIIM_SUBMENU
+//     HBITMAP hbmpChecked;    // used if MIIM_CHECKMARKS
+//     HBITMAP hbmpUnchecked;  // used if MIIM_CHECKMARKS
+//     DWORD   dwItemData;     // used if MIIM_DATA
+//     LPWSTR  dwTypeData;     // used if MIIM_TYPE
+//     UINT    cch;            // used if MIIM_TYPE
+//     HBITMAP hbmpItem;
+// }   alias MENUITEMINFOW* PMENUITEMINFOW, LPMENUITEMINFOW;
+//version(Win32SansUnicode){
+//    alias MENUITEMINFOA MENUITEMINFO;
+//}else{
+//    alias MENUITEMINFOW MENUITEMINFO;
+//}
+//alias MENUITEMINFO * LPMENUITEMINFO;
+
+
+//struct MONITORINFO {
+//    DWORD  cbSize;
+//    RECT   rcMonitor;
+//    RECT   rcWork;
+//    DWORD  dwFlags;
+//}
+//alias MONITORINFO* PMONITORINFO, LPMONITORINFO;
+
+struct MOUSEINPUT {
+    LONG      dx;
+    LONG      dy;
+    DWORD     mouseData;
+    DWORD     dwFlags;
+    DWORD     time;
+    ULONG_PTR dwExtraInfo;
+}
+
+//struct MSG {
+//  int hwnd;
+//  int message;
+//  int wParam;
+//  int lParam;
+//  int time;
+////    POINT pt;
+//  int x, y;
+//}
+/+
+struct NEWTEXTMETRICA { // ntm
+    LONG   tmHeight;
+    LONG   tmAscent;
+    LONG   tmDescent;
+    LONG   tmInternalLeading;
+    LONG   tmExternalLeading;
+    LONG   tmAveCharWidth;
+    LONG   tmMaxCharWidth;
+    LONG   tmWeight;
+    LONG   tmOverhang;
+    LONG   tmDigitizedAspectX;
+    LONG   tmDigitizedAspectY;
+    BYTE  tmFirstChar;
+    BYTE  tmLastChar;
+    BYTE  tmDefaultChar;
+    BYTE  tmBreakChar;
+    BYTE   tmItalic;
+    BYTE   tmUnderlined;
+    BYTE   tmStruckOut;
+    BYTE   tmPitchAndFamily;
+    BYTE   tmCharSet;
+    DWORD  ntmFlags;
+    UINT   ntmSizeEM;
+    UINT   ntmCellHeight;
+    UINT   ntmAvgWidth;
+}
+struct NEWTEXTMETRICW { // ntm
+    LONG   tmHeight;
+    LONG   tmAscent;
+    LONG   tmDescent;
+    LONG   tmInternalLeading;
+    LONG   tmExternalLeading;
+    LONG   tmAveCharWidth;
+    LONG   tmMaxCharWidth;
+    LONG   tmWeight;
+    LONG   tmOverhang;
+    LONG   tmDigitizedAspectX;
+    LONG   tmDigitizedAspectY;
+    WCHAR  tmFirstChar;
+    WCHAR  tmLastChar;
+    WCHAR  tmDefaultChar;
+    WCHAR  tmBreakChar;
+    BYTE   tmItalic;
+    BYTE   tmUnderlined;
+    BYTE   tmStruckOut;
+    BYTE   tmPitchAndFamily;
+    BYTE   tmCharSet;
+    DWORD  ntmFlags;
+    UINT   ntmSizeEM;
+    UINT   ntmCellHeight;
+    UINT   ntmAvgWidth;
+}
+struct NEWTEXTMETRICEXA {
+    NEWTEXTMETRICA  ntmentm;
+    FONTSIGNATURE  ntmeFontSignature;
+}
+struct NEWTEXTMETRICEXW {
+    NEWTEXTMETRICW  ntmentm;
+    FONTSIGNATURE  ntmeFontSignature;
+}
+version(Win32SansUnicode){
+    alias NEWTEXTMETRICA NEWTEXTMETRIC;
+    alias NEWTEXTMETRICEXA NEWTEXTMETRICEX;
+}else{
+    alias NEWTEXTMETRICW NEWTEXTMETRIC;
+    alias NEWTEXTMETRICEXW NEWTEXTMETRICEX;
+}
++/
+
+struct NMCUSTOMDRAW {
+    NMHDR  hdr;
+    DWORD  dwDrawStage;
+    HDC    hdc;
+    RECT   rc;
+    DWORD_PTR dwItemSpec;
+    UINT   uItemState;
+    LPARAM lItemlParam;
+}
+
+struct NMHEADER {
+    NMHDR    hdr;
+    int      iItem;
+    int      iButton;
+    HDITEM  *pitem;
+}
+
+struct NMLISTVIEW {
+    NMHDR   hdr;
+    int     iItem;
+    int     iSubItem;
+    UINT    uNewState;
+    UINT    uOldState;
+    UINT    uChanged;
+    POINT   ptAction;
+    LPARAM  lParam;
+}
+
+struct NMLVCUSTOMDRAW {
+    NMCUSTOMDRAW nmcd;
+    COLORREF clrText;
+    COLORREF clrTextBk;
+//#if (_WIN32_IE >= 0x0400)
+    int iSubItem;
+//#endif
+//if (_WIN32_IE >= 0x560)
+    DWORD dwItemType;
+    // Item Custom Draw	
+    COLORREF clrFace;
+    int iIconEffect;
+    int iIconPhase;
+    int iPartId;
+    int iStateId;
+    // Group Custom Draw
+    RECT rcText;
+    UINT uAlign;
+//endif
+}
+
+struct NMLVDISPINFOA {
+    NMHDR hdr;
+    LVITEMA item;
+}
+struct NMLVDISPINFOW {
+    NMHDR hdr;
+    LVITEMW item;
+}
+version(Win32SansUnicode){
+    alias NMLVDISPINFOA NMLVDISPINFO;
+}else{
+    alias NMLVDISPINFOW NMLVDISPINFO;
+}
+
+struct NMLVFINDITEMA {
+    NMHDR hdr;
+    int iStart;
+    LVFINDINFOA lvfi;
+}
+
+struct NMLVFINDITEMW {
+    NMHDR hdr;
+    int iStart;
+    LVFINDINFOW lvfi;
+}
+version(Win32SansUnicode){
+    alias NMLVFINDITEMA NMLVFINDITEM;
+}else{
+    alias NMLVFINDITEMW NMLVFINDITEM;
+}
+
+struct NMREBARCHEVRON {
+    NMHDR hdr;
+    UINT uBand;
+    UINT wID;
+    LPARAM lParam;
+    RECT rc;
+    LPARAM lParamNM;
+}
+
+struct NMRGINFO {
+    // NMHDR
+    HWND hwndFrom;
+    int idFrom;
+    int code;
+    // -end- NMHDR
+//  POINT ptAction;
+    int x;
+    int y;
+    int dwItemSpec;
+}
+
+
+struct NMTVCUSTOMDRAW {
+    NMCUSTOMDRAW nmcd;
+    COLORREF clrText;
+    COLORREF clrTextBk;
+//#if (_WIN32_IE &gt;= 0x0400)
+    int iLevel; // the iLevel field does not appear on WinCE
+//#endif
+}
+
+
+struct NOTIFYICONDATAA {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    char szTip[128] = '\0';
+    DWORD dwState;
+    DWORD dwStateMask;
+    char szInfo[256] = '\0';
+    union {
+        UINT uTimeout;
+        UINT uVersion;
+    };
+    char szInfoTitle[64] = '\0';
+    DWORD dwInfoFlags;
+    GUID guidItem;
+    HICON hBalloonIcon;
+} alias NOTIFYICONDATAA* PNOTIFYICONDATAA, LPNOTIFYICONDATAA;
+
+struct NOTIFYICONDATAW {
+    DWORD cbSize;
+    HWND hWnd;
+    UINT uID;
+    UINT uFlags;
+    UINT uCallbackMessage;
+    HICON hIcon;
+    WCHAR szTip[128] = '\0';
+    DWORD dwState;
+    DWORD dwStateMask;
+    WCHAR szInfo[256] = '\0';
+    union {
+        UINT uTimeout;
+        UINT uVersion;
+    }
+    WCHAR szInfoTitle[64] = '\0';
+    DWORD dwInfoFlags;
+    GUID guidItem;
+    HICON hBalloonIcon;
+}
+
+alias NOTIFYICONDATAW* PNOTIFYICONDATAW, LPNOTIFYICONDATAW;
+version(Win32SansUnicode){
+    alias NOTIFYICONDATAA NOTIFYICONDATA;
+}else{
+    alias NOTIFYICONDATAW NOTIFYICONDATA;
+}
+
+/* already in phobos now
+
+struct OPENFILENAMEA {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCSTR       lpstrFilter;
+   LPSTR        lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPSTR        lpstrFile;
+   DWORD        nMaxFile;
+   LPSTR        lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCSTR       lpstrInitialDir;
+   LPCSTR       lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCSTR       lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCSTR       lpTemplateName;
+}
+
+struct OPENFILENAMEW {
+   DWORD        lStructSize;
+   HWND         hwndOwner;
+   HINSTANCE    hInstance;
+   LPCWSTR      lpstrFilter;
+   LPWSTR       lpstrCustomFilter;
+   DWORD        nMaxCustFilter;
+   DWORD        nFilterIndex;
+   LPWSTR       lpstrFile;
+   DWORD        nMaxFile;
+   LPWSTR       lpstrFileTitle;
+   DWORD        nMaxFileTitle;
+   LPCWSTR      lpstrInitialDir;
+   LPCWSTR      lpstrTitle;
+   DWORD        Flags;
+   WORD         nFileOffset;
+   WORD         nFileExtension;
+   LPCWSTR      lpstrDefExt;
+   LPARAM       lCustData;
+   LPOFNHOOKPROC lpfnHook;
+   LPCWSTR      lpTemplateName;
+}
+*/
+
+//PORTING_TODO: is needed?
+//version(Win32SansUnicode){
+//    alias OPENFILENAMEA OPENFILENAME;
+//}else{
+//    alias OPENFILENAMEW OPENFILENAME;
+//}
+
+
+//struct PAINTSTRUCT {
+//  int hdc;
+//  int fErase;
+////    RECT rcPaint;
+//  public int left, top, right, bottom;
+//  int fRestore;
+//  int fIncUpdate;
+//  byte rgbReserved[32];
+//}
+//alias windows.PAINTSTRUCT PAINTSTRUCT;
+
+//struct POINT {
+//  LONG x, y;
+//}
+
+
+struct REBARBANDINFOA {
+    UINT        cbSize;
+    UINT        fMask;
+    UINT        fStyle;
+    COLORREF    clrFore;
+    COLORREF    clrBack;
+    LPSTR      lpText;
+    UINT        cch;
+    int         iImage;
+    HWND        hwndChild;
+    UINT        cxMinChild;
+    UINT        cyMinChild;
+    UINT        cx;
+    HBITMAP     hbmBack;
+    UINT        wID;
+//if (_WIN32_IE >= 0x0400)
+    UINT        cyChild;
+    UINT        cyMaxChild;
+    UINT        cyIntegral;
+    UINT        cxIdeal;
+    LPARAM      lParam;
+    UINT        cxHeader;
+    /* Note in WinCE.  The field cxHeader is not defined. */
+//endif
+//if (_WIN32_WINNT >= 0x0600)
+//    RECT        rcChevronLocation;  
+//    UINT        uChevronState; 
+//endif
+}
+struct REBARBANDINFOW {
+    UINT        cbSize;
+    UINT        fMask;
+    UINT        fStyle;
+    COLORREF    clrFore;
+    COLORREF    clrBack;
+    LPWSTR      lpText;
+    UINT        cch;
+    int         iImage;
+    HWND        hwndChild;
+    UINT        cxMinChild;
+    UINT        cyMinChild;
+    UINT        cx;
+    HBITMAP     hbmBack;
+    UINT        wID;
+//if (_WIN32_IE >= 0x0400)
+    UINT        cyChild;
+    UINT        cyMaxChild;
+    UINT        cyIntegral;
+    UINT        cxIdeal;
+    LPARAM      lParam;
+    UINT        cxHeader;
+    /* Note in WinCE.  The field cxHeader is not defined. */
+//endif
+//if (_WIN32_WINNT >= 0x0600)
+//    RECT        rcChevronLocation;  
+//    UINT        uChevronState; 
+//endif
+}
+version(Win32SansUnicode){
+    alias REBARBANDINFOA REBARBANDINFO;
+}else{
+    alias REBARBANDINFOW REBARBANDINFO;
+}
+
+//struct RECT {
+//  int left;
+//  int top;
+//  int right;
+//  int bottom;
+//}
+
+//struct RGNDATA {
+//    RGNDATAHEADER rdh;
+//    char          Buffer[1];
+//} alias RGNDATA* PRGNDATA, LPRGNDATA;
+
+
+
+template BITWISE(T)
+{
+    // bit value set
+    void btvs(T* pData, uint bitnum, uint val){
+        *pData &=  ~(0x01 << bitnum);
+        if(val) *pData |= (0x01 << bitnum);
+    }
+    // bit value get
+    T btvg(T* pData, uint bitnum){
+        return cast(T)((*pData >> bitnum) & 0x01);
+    }
+}
+alias BITWISE!(BYTE).btvs btvs;
+alias BITWISE!(WORD).btvs btvs;
+alias BITWISE!(DWORD).btvs btvs;
+alias BITWISE!(BYTE).btvg btvg;
+alias BITWISE!(WORD).btvg btvg;
+alias BITWISE!(DWORD).btvg btvg;
+
+
+struct SCRIPT_ANALYSIS {
+    WORD BITS;
+    SCRIPT_STATE s;
+
+    // getter
+    uint eScript()      { return BITS & 0x03FFU; }
+    uint fRTL()         { return btvg(&BITS, 10); }
+    uint fLayoutRTL()   { return btvg(&BITS, 11); }
+    uint fLinkBefore()  { return btvg(&BITS, 12); }
+    uint fLinkAfter()   { return btvg(&BITS, 13); }
+    uint fLogicalOrder(){ return btvg(&BITS, 14); }
+    uint fNoGlyphIndex(){ return btvg(&BITS, 15); }
+    // setter
+    void eScript(uint val)      { BITS &= 0xFC00; BITS |= (val & 0x03FF); }
+    void fRTL(uint val)         { btvs(&BITS, 10, val); }
+    void fLayoutRTL(uint val)   { btvs(&BITS, 11, val); }
+    void fLinkBefore(uint val)  { btvs(&BITS, 12, val); }
+    void fLinkAfter(uint val)   { btvs(&BITS, 13, val); }
+    void fLogicalOrder(uint val){ btvs(&BITS, 14, val); }
+    void fNoGlyphIndex(uint val){ btvs(&BITS, 15, val); }
+}
+
+alias void *SCRIPT_CACHE;
+
+struct SCRIPT_CONTROL {
+    align(1):
+    WORD uDefaultLanguage;
+    BYTE BITS;
+    BYTE fReserved;
+
+    // getter
+    uint fContextDigits()       { return btvg(&BITS, 0); }
+    uint fInvertPreBoundDir()   { return btvg(&BITS, 1); }
+    uint fInvertPostBoundDir()  { return btvg(&BITS, 2); }
+    uint fLinkStringBefore()    { return btvg(&BITS, 3); }
+    uint fLinkStringAfter()     { return btvg(&BITS, 4); }
+    uint fNeutralOverride()     { return btvg(&BITS, 5); }
+    uint fNumericOverride()     { return btvg(&BITS, 6); }
+    uint fLegacyBidiClass()     { return btvg(&BITS, 7); }
+
+    void fContextDigits(uint val)       { btvs(&BITS, 0, val); }
+    void fInvertPreBoundDir(uint val)   { btvs(&BITS, 1, val); }
+    void fInvertPostBoundDir(uint val)  { btvs(&BITS, 2, val); }
+    void fLinkStringBefore(uint val)    { btvs(&BITS, 3, val); }
+    void fLinkStringAfter(uint val)     { btvs(&BITS, 4, val); }
+    void fNeutralOverride(uint val)     { btvs(&BITS, 5, val); }
+    void fNumericOverride(uint val)     { btvs(&BITS, 6, val); }
+    void fLegacyBidiClass(uint val)     { btvs(&BITS, 7, val); }
+}
+
+struct SCRIPT_FONTPROPERTIES {
+  int   cBytes;
+  WORD  wgBlank;
+  WORD  wgDefault;
+  WORD  wgInvalid;
+  WORD  wgKashida;
+  int   iKashidaWidth;
+}
+
+struct SCRIPT_ITEM {
+    int iCharPos;
+    SCRIPT_ANALYSIS a;
+}
+
+struct SCRIPT_LOGATTR {
+    align(1):
+    BYTE BITS;
+
+    // gettter
+    uint fSoftBreak()   { return btvg(&BITS, 0); }
+    uint fWhiteSpace()  { return btvg(&BITS, 1); }
+    uint fCharStop()    { return btvg(&BITS, 2); }
+    uint fWordStop()    { return btvg(&BITS, 3); }
+    uint fInvalid()     { return btvg(&BITS, 4); }
+    uint fReserved()    { return cast(BYTE)(BITS>>5); }
+
+    void fSoftBreak(uint val)   { btvs(&BITS, 0, val); }
+    void fWhiteSpace(uint val)  { btvs(&BITS, 1, val); }
+    void fCharStop(uint val)    { btvs(&BITS, 2, val); }
+    void fWordStop(uint val)    { btvs(&BITS, 3, val); }
+    void fInvalid(uint val)     { btvs(&BITS, 4, val); }
+    void fReserved(uint val)    { BITS &= 0x1F; BITS |= (val & 0x07)<<5; }
+}
+
+
+struct SCRIPT_PROPERTIES {
+    DWORD   BITS1;
+    DWORD   BITS2;
+
+    uint langid()   { return BITS1 >> 16; }
+    uint fNumeric() { return btvg(&BITS1, 16); }
+    uint fComplex() { return btvg(&BITS1, 17); }
+    uint fNeedsWordBreaking()   { return btvg(&BITS1, 18); }
+    uint fNeedsCaretInfo()      { return btvg(&BITS1, 19); }
+    uint bCharSet()             { return (BITS1 >> 20) & 0xFF; }
+    uint fControl()             { return btvg(&BITS1, 28); }
+    uint fPrivateUseArea()      { return btvg(&BITS1, 29); }
+    uint fNeedsCharacterJustify(){ return btvg(&BITS1, 30); }
+    uint fInvalidGlyph()        { return btvg(&BITS1, 31); }
+    uint fInvalidLogAttr()      { return btvg(&BITS2, 0); }
+    uint fCDM()                 { return btvg(&BITS2, 1); }
+    uint fAmbiguousCharSet()    { return btvg(&BITS2, 2); }
+    uint fClusterSizeVaries()   { return btvg(&BITS2, 3); }
+    uint fRejectInvalid()       { return btvg(&BITS2, 4); }
+
+    void langid(uint val)       { BITS1 &= 0xFFFF0000; BITS1 |= (val & 0xFFFF); }
+    void fNumeric(uint val)             { btvs(&BITS1, 16, val); }
+    void fComplex(uint val)             { btvs(&BITS1, 17, val); }
+    void fNeedsWordBreaking(uint val)   { btvs(&BITS1, 18, val); }
+    void fNeedsCaretInfo(uint val)      { btvs(&BITS1, 19, val); }
+    void bCharSet(uint val)             { BITS1 &= 0xF00FFFFF; BITS1 |= (val & 0xFF)<<20; }
+    void fControl(uint val)             { btvs(&BITS1, 28, val); }
+    void fPrivateUseArea(uint val)      { btvs(&BITS1, 29, val); }
+    void fNeedsCharacterJustify(uint val){ btvs(&BITS1, 30, val); }
+    void fInvalidGlyph(uint val)        { btvs(&BITS1, 31, val); }
+    void fInvalidLogAttr(uint val)      { btvs(&BITS2, 0, val); }
+    void fCDM(uint val)                 { btvs(&BITS2, 1, val); }
+    void fAmbiguousCharSet(uint val)    { btvs(&BITS2, 2, val); }
+    void fClusterSizeVaries(uint val)   { btvs(&BITS2, 3, val); }
+    void fRejectInvalid(uint val)       { btvs(&BITS2, 4, val); }
+}
+
+
+struct SCRIPT_STATE {
+    WORD BITS;
+    // getter
+    uint uBidiLevel()           { return (BITS & 0x1F);}
+    uint fOverrideDirection()   { return btvg(&BITS, 5); }
+    uint fInhibitSymSwap()      { return btvg(&BITS, 6); }
+    uint fCharShape()           { return btvg(&BITS, 7); }
+    uint fDigitSubstitute()     { return btvg(&BITS, 8); }
+    uint fInhibitLigate()       { return btvg(&BITS, 9); }
+    uint fDisplayZWG()          { return btvg(&BITS, 10); }
+    uint fArabicNumContext()    { return btvg(&BITS, 11); }
+    uint fGcpClusters()         { return btvg(&BITS, 12); }
+    uint fReserved()            { return btvg(&BITS, 13); }
+    uint fEngineReserved()      { return (BITS >> 14) & 0x03;}
+    // setter
+    void uBidiLevel(uint val)           { BITS &= 0xFFE0; BITS |= (val & 0x1F); }
+    void fOverrideDirection(uint val)   { btvs(&BITS, 5, val); }
+    void fInhibitSymSwap(uint val)      { btvs(&BITS, 6, val); }
+    void fCharShape(uint val)           { btvs(&BITS, 7, val); }
+    void fDigitSubstitute(uint val)     { btvs(&BITS, 8, val); }
+    void fInhibitLigate(uint val)       { btvs(&BITS, 9, val); }
+    void fDisplayZWG(uint val)          { btvs(&BITS, 10, val); }
+    void fArabicNumContext(uint val)    { btvs(&BITS, 11, val); }
+    void fGcpClusters(uint val)         { btvs(&BITS, 12, val); }
+    void fReserved(uint val)            { btvs(&BITS, 13, val); }
+    void fEngineReserved(uint val)      { BITS &= 0x3FFF; BITS |= ((val & 0x03) << 14); }
+}
+
+
+struct SCRIPT_VISATTR {
+    align(1):
+    BYTE BITS;
+    BYTE fShapeReserved;
+
+    // getter
+    uint uJustification()   { return BITS & 0x0F; }
+    uint fClusterStart()    { return btvg(&BITS, 4); }
+    uint fDiacritic()       { return btvg(&BITS, 5); }
+    uint fZeroWidth()       { return btvg(&BITS, 6); }
+    uint fReserved()        { return btvg(&BITS, 7); }
+
+    // setter
+    void uJustification(uint val)   { BITS &= 0xF0; BITS |= (val & 0x0F); }
+    void fClusterStart(uint val)    { btvs(&BITS, 4, val); }
+    void fDiacritic(uint val)       { btvs(&BITS, 5, val); }
+    void fZeroWidth(uint val)       { btvs(&BITS, 6, val); }
+    void fReserved(uint val)        { btvs(&BITS, 7, val); }
+}
+
+//struct SCROLLINFO {
+//    UINT cbSize;
+//    UINT fMask;
+//    int  nMin;
+//    int  nMax;
+//    UINT nPage;
+//    int  nPos;
+//    int  nTrackPos;
+//}
+//alias SCROLLINFO* PSCROLLINFO, LPSCROLLINFO, LPCSCROLLINFO;
+
+version(WinCE)
+{
+struct SHACTIVATEINFO {
+    int cbSize;
+    HWND hwndLastFocus;
+    int fSipUp;
+    int fSipOnDeactivation;
+    int fActive;
+    int fReserved;
+}
+}
+
+struct SHELLEXECUTEINFOA {
+    DWORD cbSize;
+    ULONG fMask;
+    HWND hwnd;
+    LPCSTR lpVerb;
+    LPCSTR lpFile;
+    LPCSTR lpParameters;
+    LPCSTR lpDirectory;
+    int nShow;
+    HINSTANCE hInstApp;
+
+    // Optional members
+    LPVOID lpIDList;
+    LPCSTR lpClass;
+    HKEY hkeyClass;
+    DWORD dwHotKey;
+    HANDLE hIcon;
+    HANDLE hProcess;
+} alias SHELLEXECUTEINFOA* PSHELLEXECUTEINFOA, LPSHELLEXECUTEINFOA;
+struct SHELLEXECUTEINFOW {
+    DWORD cbSize;
+    ULONG fMask;
+    HWND hwnd;
+    LPCWSTR lpVerb;
+    LPCWSTR lpFile;
+    LPCWSTR lpParameters;
+    LPCWSTR lpDirectory;
+    int nShow;
+    HINSTANCE hInstApp;
+
+    // Optional members
+    LPVOID lpIDList;
+    LPCWSTR lpClass;
+    HKEY hkeyClass;
+    DWORD dwHotKey;
+    HANDLE hIcon;
+    HANDLE hProcess;
+} alias SHELLEXECUTEINFOW* PSHELLEXECUTEINFOW, LPSHELLEXECUTEINFOW;
+version(Win32SansUnicode){
+    alias SHELLEXECUTEINFOA SHELLEXECUTEINFO;
+}else{
+    alias SHELLEXECUTEINFOW SHELLEXECUTEINFO;
+}
+alias SHELLEXECUTEINFO* LPSHELLEXECUTEINFO;
+
+
+//version(WinCE)
+//{
+    struct SHMENUBARINFO {
+        int cbSize;
+        HWND hwndParent;
+        int dwFlags;
+        int nToolBarId;
+        HINSTANCE hInstRes;
+        int nBmpId;
+        int cBmpImages;
+        HWND hwndMB;
+    }
+
+    struct SHRGINFO {
+        DWORD cbSize;
+        HWND hwndClient;
+        POINT ptDown;
+        DWORD dwFlags;
+    }
+
+    struct SIPINFO {
+        DWORD cbSize;
+        DWORD fdwFlags;
+        RECT rcVisibleDesktop;
+        RECT rcSipRect;
+        DWORD dwImDataSize;
+        VOID *pvImData;
+    }
+//} // end of version WinCE
+
+//struct SIZE {
+//  LONG cx;
+//  LONG cy;
+//}
+//alias SIZE* LPSIZE, LPSIZEL;
+//alias SIZE SIZEL;
+
+
+struct TBBUTTONINFOA{
+    align(2):
+    UINT cbSize;
+    DWORD dwMask;
+    int idCommand;
+    int iImage;
+    BYTE fsState;
+    BYTE fsStyle;
+    WORD cx;
+    DWORD_PTR lParam;
+    LPSTR pszText;
+    int cchText;
+}
+struct TBBUTTONINFOW{
+    align(2):
+    UINT cbSize;
+    DWORD dwMask;
+    int idCommand;
+    int iImage;
+    BYTE fsState;
+    BYTE fsStyle;
+    WORD cx;
+    DWORD_PTR lParam;
+    LPWSTR pszText;
+    int cchText;
+}
+version(Win32SansUnicode){
+    alias TBBUTTONINFOA TBBUTTONINFO;
+}else{
+    alias TBBUTTONINFOW TBBUTTONINFO;
+}
+alias TBBUTTONINFO* LPTBBUTTONINFO;
+
+
+struct TCITEMA {
+    UINT mask;
+    DWORD dwState;
+    DWORD dwStateMask;
+    LPSTR pszText;
+    int cchTextMax;
+    int iImage;
+    LPARAM lParam;
+}
+struct TCITEMW {
+    UINT mask;
+    DWORD dwState;
+    DWORD dwStateMask;
+    LPWSTR pszText;
+    int cchTextMax;
+    int iImage;
+    LPARAM lParam;
+}
+version(Win32SansUnicode){
+    alias TCITEMA TCITEM;
+}else{
+    alias TCITEMW TCITEM;
+}
+
+
+// struct TOOLINFOA {
+//     UINT cbSize;
+//     UINT uFlags;
+//     HWND hwnd;
+//     UINT uId;
+//     RECT rect;
+//     HINSTANCE hinst;
+//     LPSTR lpszText;
+//     LPARAM lParam;
+// }
+// struct TOOLINFOW {
+//     UINT cbSize;
+//     UINT uFlags;
+//     HWND hwnd;
+//     UINT uId;
+//     RECT rect;
+//     HINSTANCE hinst;
+//     LPWSTR lpszText;
+//     LPARAM lParam;
+// }
+// version(Win32SansUnicode){
+//     alias TOOLINFOA TOOLINFO;
+// }else{
+//     alias TOOLINFOW TOOLINFO;
+// }
+
+struct TRACKMOUSEEVENT {
+    DWORD cbSize;
+    DWORD dwFlags;
+    HWND hwndTrack;
+    DWORD dwHoverTime;
+}
+alias TRACKMOUSEEVENT* PTRACKMOUSEEVENT, LPTRACKMOUSEEVENT;
+
+struct TRIVERTEX {
+  LONG        x;
+  LONG        y;
+  COLOR16     Red;
+  COLOR16     Green;
+  COLOR16     Blue;
+  COLOR16     Alpha;
+}
+alias TRIVERTEX* PTRIVERTEX, LPTRIVERTEX;
+
+
+struct TVHITTESTINFO {
+    POINT pt;
+    UINT flags;
+    HTREEITEM hItem;
+}
+
+
+
+
+
+
+//alias extern(Windows) int (*PFNTVCOMPARE)(LPARAM, LPARAM, LPARAM);
+struct TVSORTCB {
+    HTREEITEM hParent;
+    PFNTVCOMPARE lpfnCompare;
+    LPARAM lParam;
+}
+
+
+
+
+//struct WINDOWPLACEMENT {
+//    UINT length;
+//    UINT flags;
+//    UINT showCmd;
+//    POINT ptMinPosition;
+//    POINT ptMaxPosition;
+//    RECT rcNormalPosition;
+//}
+//
+// struct WINDOWPOS {
+//     HWND hwnd;
+//     HWND hwndInsertAfter;
+//     int x;
+//     int y;
+//     int cx;
+//     int cy;
+//     UINT flags;
+// }
+
+// WNDCLASSA is declared in phobos
+// struct WNDCLASSW {
+//     UINT        style;
+//     WNDPROC_I     lpfnWndProc;
+//     int         cbClsExtra;
+//     int         cbWndExtra;
+//     HINSTANCE   hInstance;
+//     HICON       hIcon;
+//     HCURSOR     hCursor;
+//     HBRUSH      hbrBackground;
+//     LPCWSTR     lpszMenuName;
+//     LPCWSTR     lpszClassName;
+// }alias WNDCLASSW* PWNDCLASSW, LPWNDCLASSW;
+//
+// // since phobos has alias WNDCLASSA to WNDCLASS, we have to alias it another name
+// version(Win32SansUnicode){
+//     alias WNDCLASSA WNDCLASS_T;
+// }else{
+//     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;
+
+}   // end of extern(Windows)
+
+
+
+
+
+// shlwapi.h
+enum {ASSOCF_INIT_BYEXENAME,
+    ASSOCF_OPEN_BYEXENAME,
+    ASSOCF_INIT_DEFAULTTOSTAR,
+    ASSOCF_INIT_DEFAULTTOFOLDER,
+    ASSOCF_NOUSERSETTINGS,
+    ASSOCF_NOTRUNCATE,
+    ASSOCF_VERIFY,
+    ASSOCF_REMAPRUNDLL,
+    ASSOCF_NOFIXUPS,
+    ASSOCF_IGNOREBASECLASS
+};
+
+alias DWORD ASSOCF;
+
+// usp10
+alias void* SCRIPT_STRING_ANALYSIS;
+struct SCRIPT_TABDEF {
+  int cTabStops;
+  int iScale;
+  int* pTabStops;
+  int iTabOrigin;
+}
+
+//struct SCRIPT_ANALYSIS {
+//    mixin(bitfields!(
+//        ushort, "eScript", 10,
+//        bool, "fRTL", 1,
+//        bool, "fLayoutRTL", 1,
+//        bool, "fLinkBefore", 1,
+//        bool, "fLinkAfter", 1,
+//        bool, "fLogicalOrder", 1,
+//        bool, "fNoGlyphIndex", 1));
+//    SCRIPT_STATE s ;
+//}
+//struct SCRIPT_STATE {
+//    mixin(bitfields!(
+//        ubyte, "uBidiLevel",  5,
+//        bool, "fOverrideDirection", 1,
+//        bool, "fInhibitSymSwap", 1,
+//        bool, "fCharShape", 1,
+//        bool, "fDigitSubstitute", 1,
+//        bool, "fInhibitLigate", 1,
+//        bool, "fDisplayZWG", 1,
+//        bool, "fArabicNumContext", 1,
+//        bool, "fGcpClusters", 1,
+//        bool, "fReserved", 1,
+//        ubyte, "fEngineReserved", 2));
+//}
+//
+//struct SCRIPT_CONTROL {
+//    mixin(bitfields!(
+//        ushort, "uDefaultLanguage", 16,
+//        bool, "fContextDigits", 1,
+//        bool, "fInvertPreBoundDir", 1,
+//        bool, "fInvertPostBoundDir", 1,
+//        bool, "fLinkStringBefore", 1,
+//        bool, "fLinkStringAfter", 1,
+//        bool, "fNeutralOverride", 1,
+//        bool, "fNumericOverride", 1,
+//        bool, "fLegacyBidiClass", 1,
+//        ubyte, "fReserved", 8));
+//}
+//
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FillData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.FillData;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+
+class FillData {
+
+    int defaultWidth = -1, defaultHeight = -1;
+    int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+Point computeSize (Control control, int wHint, int hHint, bool flushCache_) {
+    if (flushCache_) flushCache();
+    if (wHint is SWT.DEFAULT && hHint is SWT.DEFAULT) {
+        if (defaultWidth is -1 || defaultHeight is -1) {
+            Point size = control.computeSize (wHint, hHint, flushCache_);
+            defaultWidth = size.x;
+            defaultHeight = size.y;
+        }
+        return new Point(defaultWidth, defaultHeight);
+    }
+    if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
+        Point size = control.computeSize (wHint, hHint, flushCache_);
+        currentWhint = wHint;
+        currentHhint = hHint;
+        currentWidth = size.x;
+        currentHeight = size.y;
+    }
+    return new Point(currentWidth, currentHeight);
+}
+void flushCache () {
+    defaultWidth = defaultHeight = -1;
+    currentWidth = currentHeight = -1;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FillLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.FillLayout;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.layout.FillData;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * <code>FillLayout</code> is the simplest layout class. It lays out
+ * controls in a single row or column, forcing them to be the same size.
+ * <p>
+ * Initially, the controls will all be as tall as the tallest control,
+ * and as wide as the widest. <code>FillLayout</code> does not wrap,
+ * but you can specify margins and spacing. You might use it to
+ * lay out buttons in a task bar or tool bar, or to stack checkboxes
+ * in a <code>Group</code>. <code>FillLayout</code> can also be used
+ * when a <code>Composite</code> only has one child. For example,
+ * if a <code>Shell</code> has a single <code>Group</code> child,
+ * <code>FillLayout</code> will cause the <code>Group</code> to
+ * completely fill the <code>Shell</code> (if margins are 0).
+ * </p>
+ * <p>
+ * Example code: first a <code>FillLayout</code> is created and
+ * its type field is set, and then the layout is set into the
+ * <code>Composite</code>. Note that in a <code>FillLayout</code>,
+ * children are always the same size, and they fill all available space.
+ * <pre>
+ *      FillLayout fillLayout = new FillLayout();
+ *      fillLayout.type = SWT.VERTICAL;
+ *      shell.setLayout(fillLayout);
+ * </pre>
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class FillLayout : Layout {
+    /**
+     * type specifies how controls will be positioned
+     * within the layout.
+     *
+     * The default value is HORIZONTAL.
+     *
+     * Possible values are: <ul>
+     *    <li>HORIZONTAL: Position the controls horizontally from left to right</li>
+     *    <li>VERTICAL: Position the controls vertically from top to bottom</li>
+     * </ul>
+     */
+    public int type = SWT.HORIZONTAL;
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int marginWidth = 0;
+
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int marginHeight = 0;
+
+    /**
+     * spacing specifies the number of pixels between the edge of one cell
+     * and the edge of its neighbouring cell.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int spacing = 0;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of fill layout
+ *
+ * @since 2.0
+ */
+public this (int type) {
+    this.type = type;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) {
+    Control [] children = composite.getChildren ();
+    int count = children.length;
+    int maxWidth = 0, maxHeight = 0;
+    for (int i=0; i<count; i++) {
+        Control child = children [i];
+        int w = wHint, h = hHint;
+        if (count > 0) {
+            if (type is SWT.HORIZONTAL && wHint !is SWT.DEFAULT) {
+                w = Math.max (0, (wHint - (count - 1) * spacing) / count);
+            }
+            if (type is SWT.VERTICAL && hHint !is SWT.DEFAULT) {
+                h = Math.max (0, (hHint - (count - 1) * spacing) / count);
+            }
+        }
+        Point size = computeChildSize (child, w, h, flushCache);
+        maxWidth = Math.max (maxWidth, size.x);
+        maxHeight = Math.max (maxHeight, size.y);
+    }
+    int width = 0, height = 0;
+    if (type is SWT.HORIZONTAL) {
+        width = count * maxWidth;
+        if (count !is 0) width += (count - 1) * spacing;
+        height = maxHeight;
+    } else {
+        width = maxWidth;
+        height = count * maxHeight;
+        if (count !is 0) height += (count - 1) * spacing;
+    }
+    width += marginWidth * 2;
+    height += marginHeight * 2;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    return new Point (width, height);
+}
+
+Point computeChildSize (Control control, int wHint, int hHint, bool flushCache) {
+    FillData data = cast(FillData)control.getLayoutData ();
+    if (data is null) {
+        data = new FillData ();
+        control.setLayoutData (data);
+    }
+    Point size = null;
+    if (wHint is SWT.DEFAULT && hHint is SWT.DEFAULT) {
+        size = data.computeSize (control, wHint, hHint, flushCache);
+    } else {
+        // TEMPORARY CODE
+        int trimX, trimY;
+        if ( auto sa = cast(Scrollable)control ) {
+            Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+            trimX = rect.width;
+            trimY = rect.height;
+        } else {
+            trimX = trimY = control.getBorderWidth () * 2;
+        }
+        int w = wHint is SWT.DEFAULT ? wHint : Math.max (0, wHint - trimX);
+        int h = hHint is SWT.DEFAULT ? hHint : Math.max (0, hHint - trimY);
+        size = data.computeSize (control, w, h, flushCache);
+    }
+    return size;
+}
+
+override protected bool flushCache (Control control) {
+    Object data = control.getLayoutData();
+    if (data !is null) (cast(FillData)data).flushCache();
+    return true;
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf( '.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+override protected void layout (Composite composite, bool flushCache) {
+    Rectangle rect = composite.getClientArea ();
+    Control [] children = composite.getChildren ();
+    int count = children.length;
+    if (count is 0) return;
+    int width = rect.width - marginWidth * 2;
+    int height = rect.height - marginHeight * 2;
+    if (type is SWT.HORIZONTAL) {
+        width -= (count - 1) * spacing;
+        int x = rect.x + marginWidth, extra = width % count;
+        int y = rect.y + marginHeight, cellWidth = width / count;
+        for (int i=0; i<count; i++) {
+            Control child = children [i];
+            int childWidth = cellWidth;
+            if (i is 0) {
+                childWidth += extra / 2;
+            } else {
+                if (i is count - 1) childWidth += (extra + 1) / 2;
+            }
+            child.setBounds (x, y, childWidth, height);
+            x += childWidth + spacing;
+        }
+    } else {
+        height -= (count - 1) * spacing;
+        int x = rect.x + marginWidth, cellHeight = height / count;
+        int y = rect.y + marginHeight, extra = height % count;
+        for (int i=0; i<count; i++) {
+            Control child = children [i];
+            int childHeight = cellHeight;
+            if (i is 0) {
+                childHeight += extra / 2;
+            } else {
+                if (i is count - 1) childHeight += (extra + 1) / 2;
+            }
+            child.setBounds (x, y, width, childHeight);
+            y += childHeight + spacing;
+        }
+    }
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+override public String toString () {
+    String string = getName () ~ " {";
+    string ~= "type="~((type is SWT.VERTICAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")~" ";
+    if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+    if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+    if (spacing !is 0) string ~= "spacing="~to!(String)(spacing)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormAttachment.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.FormAttachment;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.FormData;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are used to define the edges of a control
+ * within a <code>FormLayout</code>.
+ * <p>
+ * <code>FormAttachments</code> are set into the top, bottom, left,
+ * and right fields of the <code>FormData</code> for a control.
+ * For example:
+ * <pre>
+ *      FormData data = new FormData();
+ *      data.top = new FormAttachment(0,5);
+ *      data.bottom = new FormAttachment(100,-5);
+ *      data.left = new FormAttachment(0,5);
+ *      data.right = new FormAttachment(100,-5);
+ *      button.setLayoutData(data);
+ * </pre>
+ * </p>
+ * <p>
+ * A <code>FormAttachment</code> defines where to attach the side of
+ * a control by using the equation, y = ax + b. The "a" term represents
+ * a fraction of the parent composite's width (from the left) or height
+ * (from the top). It can be defined using a numerator and denominator,
+ * or just a percentage value. If a percentage is used, the denominator
+ * is set to 100. The "b" term in the equation represents an offset, in
+ * pixels, from the attachment position. For example:
+ * <pre>
+ *      FormAttachment attach = new FormAttachment (20, -5);
+ * </pre>
+ * specifies that the side to which the <code>FormAttachment</code>
+ * object belongs will lie at 20% of the parent composite, minus 5 pixels.
+ * </p>
+ * <p>
+ * Control sides can also be attached to another control.
+ * For example:
+ * <pre>
+ *      FormAttachment attach = new FormAttachment (button, 10);
+ * </pre>
+ * specifies that the side to which the <code>FormAttachment</code>
+ * object belongs will lie in the same position as the adjacent side of
+ * the <code>button</code> control, plus 10 pixels. The control side can
+ * also be attached to the opposite side of the specified control.
+ * For example:
+ * <pre>
+ *      FormData data = new FormData ();
+ *      data.left = new FormAttachment (button, 0, SWT.LEFT);
+ * </pre>
+ * specifies that the left side of the control will lie in the same position
+ * as the left side of the <code>button</code> control. The control can also
+ * be attached in a position that will center the control on the specified
+ * control. For example:
+ * <pre>
+ *      data.left = new FormAttachment (button, 0, SWT.CENTER);
+ * </pre>
+ * specifies that the left side of the control will be positioned so that it is
+ * centered between the left and right sides of the <code>button</code> control.
+ * If the alignment is not specified, the default is to attach to the adjacent side.
+ * </p>
+ *
+ * @see FormLayout
+ * @see FormData
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public final class FormAttachment {
+    /**
+     * numerator specifies the numerator of the "a" term in the
+     * equation, y = ax + b, which defines the attachment.
+     */
+    public int numerator;
+
+    /**
+     * denominator specifies the denominator of the "a" term in the
+     * equation, y = ax + b, which defines the attachment.
+     *
+     * The default value is 100.
+     */
+    public int denominator = 100;
+
+    /**
+     * offset specifies the offset, in pixels, of the control side
+     * from the attachment position.
+     * If the offset is positive, then the control side is offset
+     * to the right of or below the attachment position. If it is
+     * negative, then the control side is offset to the left of or
+     * above the attachment position.
+     *
+     * This is equivalent to the "b" term in the equation y = ax + b.
+     * The default value is 0.
+     */
+    public int offset;
+
+    /**
+     * control specifies the control to which the control side is
+     * attached.
+     */
+    public Control control;
+
+    /**
+     * alignment specifies the alignment of the control side that is
+     * attached to a control.
+     * <p>
+     * For top and bottom attachments, TOP, BOTTOM and CENTER are used. For left
+     * and right attachments, LEFT, RIGHT and CENTER are used. If any other case
+     * occurs, the default will be used instead.
+     * </p>
+     *
+     * <br>Possible values are: <ul>
+     *    <li>{@link SWT#TOP}: Attach the side to the top side of the specified control.</li>
+     *    <li>{@link SWT#BOTTOM}: Attach the side to the bottom side of the specified control.</li>
+     *    <li>{@link SWT#LEFT}: Attach the side to the left side of the specified control.</li>
+     *    <li>{@link SWT#RIGHT}: Attach the side to the right side of the specified control.</li>
+     *    <li>{@link SWT#CENTER}: Attach the side at a position which will center the control on the specified control.</li>
+     *    <li>{@link SWT#DEFAULT}: Attach the side to the adjacent side of the specified control.</li>
+     * </ul>
+     */
+    public int alignment;
+
+/**
+ * Constructs a new instance of this class.
+ * Since no numerator, denominator or offset is specified,
+ * the attachment is treated as a percentage of the form.
+ * The numerator is zero, the denominator is 100 and the
+ * offset is zero.
+ *
+ * @since 3.2
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of this class given a numerator
+ * Since no denominator or offset is specified, the default
+ * is to treat the numerator as a percentage of the form, with a
+ * denominator of 100. The offset is zero.
+ *
+ * @param numerator the percentage of the position
+ *
+ * @since 3.0
+ */
+public this (int numerator) {
+    this (numerator, 100, 0);
+}
+
+/**
+ * Constructs a new instance of this class given a numerator
+ * and an offset. Since no denominator is specified, the default
+ * is to treat the numerator as a percentage of the form, with a
+ * denominator of 100.
+ *
+ * @param numerator the percentage of the position
+ * @param offset the offset of the side from the position
+ */
+public this (int numerator, int offset) {
+    this (numerator, 100, offset);
+}
+
+/**
+ * Constructs a new instance of this class given a numerator
+ * and denominator and an offset. The position of the side is
+ * given by the fraction of the form defined by the numerator
+ * and denominator.
+ *
+ * @param numerator the numerator of the position
+ * @param denominator the denominator of the position
+ * @param offset the offset of the side from the position
+ */
+public this (int numerator, int denominator, int offset) {
+    if (denominator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
+    this.numerator = numerator;
+    this.denominator = denominator;
+    this.offset = offset;
+}
+
+/**
+ * Constructs a new instance of this class given a control.
+ * Since no alignment is specified, the default alignment is
+ * to attach the side to the adjacent side of the specified
+ * control. Since no offset is specified, an offset of 0 is
+ * used.
+ *
+ * @param control the control the side is attached to
+ */
+public this (Control control) {
+    this (control, 0, SWT.DEFAULT);
+}
+
+/**
+ * Constructs a new instance of this class given a control
+ * and an offset. Since no alignment is specified, the default
+ * alignment is to attach the side to the adjacent side of the
+ * specified control.
+ *
+ * @param control the control the side is attached to
+ * @param offset the offset of the side from the control
+ */
+public this (Control control, int offset) {
+    this (control, offset, SWT.DEFAULT);
+}
+
+/**
+ * Constructs a new instance of this class given a control,
+ * an offset and an alignment.  The possible alignment values are:
+ * <dl>
+ * <dt><b>{@link SWT#TOP}</b></dt>
+ * <dd>the side will be attached to the top side of the specified control</dd>
+ * <dt><b>{@link SWT#BOTTOM}</b></dt>
+ * <dd>the side will be attached to the bottom side of the specified control</dd>
+ * <dt><b>{@link SWT#LEFT}</b></dt>
+ * <dd>the side will be attached to the left side of the specified control</dd>
+ * <dt><b>{@link SWT#RIGHT}</b></dt>
+ * <dd>the side will be attached to the right side of the specified control</dd>
+ * <dt><b>{@link SWT#CENTER}</b></dt>
+ * <dd>the side will be centered on the same side of the specified control</dd>
+ * <dt><b>{@link SWT#DEFAULT}</b></dt>
+ * <dd>the side will be attached to the adjacent side of the specified control</dd>
+ * </dl>
+ *
+ * @param control the control the side is attached to
+ * @param offset the offset of the side from the control
+ * @param alignment the alignment of the side to the control it is attached to,
+ *      one of TOP, BOTTOM, LEFT, RIGHT, CENTER, or DEFAULT
+ */
+public this (Control control, int offset, int alignment) {
+    this.control = control;
+    this.offset = offset;
+    this.alignment = alignment;
+}
+
+FormAttachment divide (int value) {
+    return new FormAttachment (numerator, denominator * value, offset / value);
+}
+
+int gcd (int m, int n) {
+    int temp;
+    m = Math.abs (m);
+    n = Math.abs (n);
+    if (m < n) {
+        temp = m;
+        m = n;
+        n = temp;
+    }
+    while (n !is 0){
+        temp = m;
+        m = n;
+        n = temp % n;
+    }
+    return m;
+}
+
+FormAttachment minus (FormAttachment attachment) {
+    FormAttachment solution = new FormAttachment ();
+    solution.numerator = numerator * attachment.denominator - denominator * attachment.numerator;
+    solution.denominator = denominator * attachment.denominator;
+    int gcd = gcd (solution.denominator, solution.numerator);
+    solution.numerator = solution.numerator / gcd;
+    solution.denominator = solution.denominator / gcd;
+    solution.offset = offset - attachment.offset;
+    return solution;
+}
+
+FormAttachment minus (int value) {
+    return new FormAttachment (numerator, denominator, offset - value);
+}
+
+FormAttachment plus (FormAttachment attachment) {
+    FormAttachment solution = new FormAttachment ();
+    solution.numerator = numerator * attachment.denominator + denominator * attachment.numerator;
+    solution.denominator = denominator * attachment.denominator;
+    int gcd = gcd (solution.denominator, solution.numerator);
+    solution.numerator = solution.numerator / gcd;
+    solution.denominator = solution.denominator / gcd;
+    solution.offset = offset + attachment.offset;
+    return solution;
+}
+
+FormAttachment plus (int value) {
+    return new FormAttachment (numerator, denominator, offset + value);
+}
+
+int solveX (int value) {
+    if (denominator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
+    return ((numerator * value) / denominator) + offset;
+}
+
+int solveY (int value) {
+    if (numerator is 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
+    return (value - offset) * denominator / numerator;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the FormAttachment
+ */
+public override String toString () {
+    String string = control !is null ? control.toString () : Format( "{}/{}", numerator, denominator );
+    return Format("{{y = ({})x + {}}", string, ( offset >= 0 ? Format(")x + {}", offset ) : Format( ")x - {}", -offset)));
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.FormData;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.layout.FormAttachment;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * Instances of this class are used to define the attachments
+ * of a control in a <code>FormLayout</code>.
+ * <p>
+ * To set a <code>FormData</code> object into a control, you use the
+ * <code>setLayoutData ()</code> method. To define attachments for the
+ * <code>FormData</code>, set the fields directly, like this:
+ * <pre>
+ *      FormData data = new FormData();
+ *      data.left = new FormAttachment(0,5);
+ *      data.right = new FormAttachment(100,-5);
+ *      button.setLayoutData(formData);
+ * </pre>
+ * </p>
+ * <p>
+ * <code>FormData</code> contains the <code>FormAttachments</code> for
+ * each edge of the control that the <code>FormLayout</code> uses to
+ * determine the size and position of the control. <code>FormData</code>
+ * objects also allow you to set the width and height of controls within
+ * a <code>FormLayout</code>.
+ * </p>
+ *
+ * @see FormLayout
+ * @see FormAttachment
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 2.0
+ */
+public final class FormData {
+    /**
+     * width specifies the preferred width in pixels. This value
+     * is the wHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see Control#computeSize(int, int, bool)
+     */
+    public int width = SWT.DEFAULT;
+    /**
+     * height specifies the preferred height in pixels. This value
+     * is the hHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see Control#computeSize(int, int, bool)
+     */
+    public int height = SWT.DEFAULT;
+    /**
+     * left specifies the attachment of the left side of
+     * the control.
+     */
+    public FormAttachment left;
+    /**
+     * right specifies the attachment of the right side of
+     * the control.
+     */
+    public FormAttachment right;
+    /**
+     * top specifies the attachment of the top of the control.
+     */
+    public FormAttachment top;
+    /**
+     * bottom specifies the attachment of the bottom of the
+     * control.
+     */
+    public FormAttachment bottom;
+
+    int cacheWidth = -1, cacheHeight = -1;
+    int defaultWhint, defaultHhint, defaultWidth = -1, defaultHeight = -1;
+    int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+    FormAttachment cacheLeft, cacheRight, cacheTop, cacheBottom;
+    bool isVisited, needed;
+
+/**
+ * Constructs a new instance of FormData using
+ * default values.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of FormData according to the parameters.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param width a minimum width for the control
+ * @param height a minimum height for the control
+ */
+public this (int width, int height) {
+    this.width = width;
+    this.height = height;
+}
+
+void computeSize (Control control, int wHint, int hHint, bool flushCache_) {
+    if (cacheWidth !is -1 && cacheHeight !is -1) return;
+    if (wHint is this.width && hHint is this.height) {
+        if (defaultWidth is -1 || defaultHeight is -1 || wHint !is defaultWhint || hHint !is defaultHhint) {
+            Point size =  control.computeSize (wHint, hHint, flushCache_);
+            defaultWhint = wHint;
+            defaultHhint = hHint;
+            defaultWidth = size.x;
+            defaultHeight = size.y;
+        }
+        cacheWidth = defaultWidth;
+        cacheHeight = defaultHeight;
+        return;
+    }
+    if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
+        Point size =  control.computeSize (wHint, hHint, flushCache_);
+        currentWhint = wHint;
+        currentHhint = hHint;
+        currentWidth = size.x;
+        currentHeight = size.y;
+    }
+    cacheWidth = currentWidth;
+    cacheHeight = currentHeight;
+}
+
+void flushCache () {
+    cacheWidth = cacheHeight = -1;
+    defaultHeight = defaultWidth = -1;
+    currentHeight = currentWidth = -1;
+}
+
+int getWidth (Control control, bool flushCache) {
+    needed = true;
+    computeSize (control, width, height, flushCache);
+    return cacheWidth;
+}
+
+int getHeight (Control control, bool flushCache) {
+    computeSize (control, width, height, flushCache);
+    return cacheHeight;
+}
+
+FormAttachment getBottomAttachment (Control control, int spacing, bool flushCache) {
+    if (cacheBottom !is null) return cacheBottom;
+    if (isVisited) return cacheBottom = new FormAttachment (0, getHeight (control, flushCache));
+    if (bottom is null) {
+        if (top is null) return cacheBottom = new FormAttachment (0, getHeight (control, flushCache));
+        return cacheBottom = getTopAttachment (control, spacing, flushCache).plus (getHeight (control, flushCache));
+    }
+    Control bottomControl = bottom.control;
+    if (bottomControl !is null) {
+        if (bottomControl.isDisposed ()) {
+            bottom.control = bottomControl = null;
+        } else {
+            if (bottomControl.getParent () !is control.getParent ()) {
+                bottomControl = null;
+            }
+        }
+    }
+    if (bottomControl is null) return cacheBottom = bottom;
+    isVisited = true;
+    FormData bottomData = cast(FormData) bottomControl.getLayoutData ();
+    FormAttachment bottomAttachment = bottomData.getBottomAttachment (bottomControl, spacing, flushCache);
+    switch (bottom.alignment) {
+        case SWT.BOTTOM:
+            cacheBottom = bottomAttachment.plus (bottom.offset);
+            break;
+        case SWT.CENTER: {
+            FormAttachment topAttachment = bottomData.getTopAttachment (bottomControl, spacing, flushCache);
+            FormAttachment bottomHeight = bottomAttachment.minus (topAttachment);
+            cacheBottom = bottomAttachment.minus (bottomHeight.minus (getHeight (control, flushCache)).divide (2));
+            break;
+        }
+        default: {
+            FormAttachment topAttachment = bottomData.getTopAttachment (bottomControl, spacing, flushCache);
+            cacheBottom = topAttachment.plus (bottom.offset - spacing);
+            break;
+        }
+    }
+    isVisited = false;
+    return cacheBottom;
+}
+
+FormAttachment getLeftAttachment (Control control, int spacing, bool flushCache) {
+    if (cacheLeft !is null) return cacheLeft;
+    if (isVisited) return cacheLeft = new FormAttachment (0, 0);
+    if (left is null) {
+        if (right is null) return cacheLeft = new FormAttachment (0, 0);
+        return cacheLeft = getRightAttachment (control, spacing, flushCache).minus (getWidth (control, flushCache));
+    }
+    Control leftControl = left.control;
+    if (leftControl !is null) {
+        if (leftControl.isDisposed ()) {
+            left.control = leftControl = null;
+        } else {
+            if (leftControl.getParent () !is control.getParent ()) {
+                leftControl = null;
+            }
+        }
+    }
+    if (leftControl is null) return cacheLeft = left;
+    isVisited = true;
+    FormData leftData = cast(FormData) leftControl.getLayoutData ();
+    FormAttachment leftAttachment = leftData.getLeftAttachment (leftControl, spacing, flushCache);
+    switch (left.alignment) {
+        case SWT.LEFT:
+            cacheLeft = leftAttachment.plus (left.offset);
+            break;
+        case SWT.CENTER: {
+            FormAttachment rightAttachment = leftData.getRightAttachment (leftControl, spacing, flushCache);
+            FormAttachment leftWidth = rightAttachment.minus (leftAttachment);
+            cacheLeft = leftAttachment.plus (leftWidth.minus (getWidth (control, flushCache)).divide (2));
+            break;
+        }
+        default: {
+            FormAttachment rightAttachment = leftData.getRightAttachment (leftControl, spacing, flushCache);
+            cacheLeft = rightAttachment.plus (left.offset + spacing);
+        }
+    }
+    isVisited = false;
+    return cacheLeft;
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf( '.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+FormAttachment getRightAttachment (Control control, int spacing, bool flushCache) {
+    if (cacheRight !is null) return cacheRight;
+    if (isVisited) return cacheRight = new FormAttachment (0, getWidth (control, flushCache));
+    if (right is null) {
+        if (left is null) return cacheRight = new FormAttachment (0, getWidth (control, flushCache));
+        return cacheRight = getLeftAttachment (control, spacing, flushCache).plus (getWidth (control, flushCache));
+    }
+    Control rightControl = right.control;
+    if (rightControl !is null) {
+        if (rightControl.isDisposed ()) {
+            right.control = rightControl = null;
+        } else {
+            if (rightControl.getParent () !is control.getParent ()) {
+                rightControl = null;
+            }
+        }
+    }
+    if (rightControl is null) return cacheRight = right;
+    isVisited = true;
+    FormData rightData = cast(FormData) rightControl.getLayoutData ();
+    FormAttachment rightAttachment = rightData.getRightAttachment (rightControl, spacing, flushCache);
+    switch (right.alignment) {
+        case SWT.RIGHT:
+            cacheRight = rightAttachment.plus (right.offset);
+            break;
+        case SWT.CENTER: {
+            FormAttachment leftAttachment = rightData.getLeftAttachment (rightControl, spacing, flushCache);
+            FormAttachment rightWidth = rightAttachment.minus (leftAttachment);
+            cacheRight = rightAttachment.minus (rightWidth.minus (getWidth (control, flushCache)).divide (2));
+            break;
+        }
+        default: {
+            FormAttachment leftAttachment = rightData.getLeftAttachment (rightControl, spacing, flushCache);
+            cacheRight = leftAttachment.plus (right.offset - spacing);
+            break;
+        }
+    }
+    isVisited = false;
+    return cacheRight;
+}
+
+FormAttachment getTopAttachment (Control control, int spacing, bool flushCache) {
+    if (cacheTop !is null) return cacheTop;
+    if (isVisited) return cacheTop = new FormAttachment (0, 0);
+    if (top is null) {
+        if (bottom is null) return cacheTop = new FormAttachment (0, 0);
+        return cacheTop = getBottomAttachment (control, spacing, flushCache).minus (getHeight (control, flushCache));
+    }
+    Control topControl = top.control;
+    if (topControl !is null) {
+        if (topControl.isDisposed ()) {
+            top.control = topControl = null;
+        } else {
+            if (topControl.getParent () !is control.getParent ()) {
+                topControl = null;
+            }
+        }
+    }
+    if (topControl is null) return cacheTop = top;
+    isVisited = true;
+    FormData topData = cast(FormData) topControl.getLayoutData ();
+    FormAttachment topAttachment = topData.getTopAttachment (topControl, spacing, flushCache);
+    switch (top.alignment) {
+        case SWT.TOP:
+            cacheTop = topAttachment.plus (top.offset);
+            break;
+        case SWT.CENTER: {
+            FormAttachment bottomAttachment = topData.getBottomAttachment (topControl, spacing, flushCache);
+            FormAttachment topHeight = bottomAttachment.minus (topAttachment);
+            cacheTop = topAttachment.plus (topHeight.minus (getHeight (control, flushCache)).divide (2));
+            break;
+        }
+        default: {
+            FormAttachment bottomAttachment = topData.getBottomAttachment (topControl, spacing, flushCache);
+            cacheTop = bottomAttachment.plus (top.offset + spacing);
+            break;
+        }
+    }
+    isVisited = false;
+    return cacheTop;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the FormData object
+ */
+override public String toString () {
+    String string = getName()~" {";
+    if (width !is SWT.DEFAULT) string ~= "width="~to!(String)(width)~" ";
+    if (height !is SWT.DEFAULT) string ~= "height="~to!(String)(height)~" ";
+    if (left !is null) string ~= "left="~to!(String)(left)~" ";
+    if (right !is null) string ~= "right="~to!(String)(right)~" ";
+    if (top !is null) string ~= "top="~to!(String)(top)~" ";
+    if (bottom !is null) string ~= "bottom="~to!(String)(bottom)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/FormLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.FormLayout;
+
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Scrollable;
+
+import tango.util.Convert;
+import Math = tango.math.Math;
+import java.lang.all;
+
+/**
+ * Instances of this class control the position and size of the
+ * children of a composite control by using <code>FormAttachments</code>
+ * to optionally configure the left, top, right and bottom edges of
+ * each child.
+ * <p>
+ * The following example code creates a <code>FormLayout</code> and then sets
+ * it into a <code>Shell</code>:
+ * <pre>
+ *      Display display = new Display ();
+ *      Shell shell = new Shell(display);
+ *      FormLayout layout = new FormLayout();
+ *      layout.marginWidth = 3;
+ *      layout.marginHeight = 3;
+ *      shell.setLayout(layout);
+ * </pre>
+ * </p>
+ * <p>
+ * To use a <code>FormLayout</code>, create a <code>FormData</code> with
+ * <code>FormAttachment</code> for each child of <code>Composite</code>.
+ * The following example code attaches <code>button1</code> to the top
+ * and left edge of the composite and <code>button2</code> to the right
+ * edge of <code>button1</code> and the top and right edges of the
+ * composite:
+ * <pre>
+ *      FormData data1 = new FormData();
+ *      data1.left = new FormAttachment(0, 0);
+ *      data1.top = new FormAttachment(0, 0);
+ *      button1.setLayoutData(data1);
+ *      FormData data2 = new FormData();
+ *      data2.left = new FormAttachment(button1);
+ *      data2.top = new FormAttachment(0, 0);
+ *      data2.right = new FormAttachment(100, 0);
+ *      button2.setLayoutData(data2);
+ * </pre>
+ * </p>
+ * <p>
+ * Each side of a child control can be attached to a position in the parent
+ * composite, or to other controls within the <code>Composite</code> by
+ * creating instances of <code>FormAttachment</code> and setting them into
+ * the top, bottom, left, and right fields of the child's <code>FormData</code>.
+ * </p>
+ * <p>
+ * If a side is not given an attachment, it is defined as not being attached
+ * to anything, causing the child to remain at its preferred size.  If a child
+ * is given no attachment on either the left or the right or top or bottom, it is
+ * automatically attached to the left and top of the composite respectively.
+ * The following code positions <code>button1</code> and <code>button2</code>
+ * but relies on default attachments:
+ * <pre>
+ *      FormData data2 = new FormData();
+ *      data2.left = new FormAttachment(button1);
+ *      data2.right = new FormAttachment(100, 0);
+ *      button2.setLayoutData(data2);
+ * </pre>
+ * </p>
+ * <p>
+ * IMPORTANT: Do not define circular attachments.  For example, do not attach
+ * the right edge of <code>button1</code> to the left edge of <code>button2</code>
+ * and then attach the left edge of <code>button2</code> to the right edge of
+ * <code>button1</code>.  This will over constrain the layout, causing undefined
+ * behavior.  The algorithm will terminate, but the results are undefined.
+ * </p>
+ *
+ * @see FormData
+ * @see FormAttachment
+ * @see <a href="http://www.eclipse.org/swt/snippets/#formlayout">FormLayout snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 
+ *
+ * @since 2.0
+ */
+public final class FormLayout : Layout {
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the layout.
+     *
+     * The default value is 0.
+     */
+    public int marginWidth = 0;
+
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the layout.
+     *
+     * The default value is 0.
+     */
+    public int marginHeight = 0;
+
+
+    /**
+     * marginLeft specifies the number of pixels of horizontal margin
+     * that will be placed along the left edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginLeft = 0;
+
+    /**
+     * marginTop specifies the number of pixels of vertical margin
+     * that will be placed along the top edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginTop = 0;
+
+    /**
+     * marginRight specifies the number of pixels of horizontal margin
+     * that will be placed along the right edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginRight = 0;
+
+    /**
+     * marginBottom specifies the number of pixels of vertical margin
+     * that will be placed along the bottom edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginBottom = 0;
+
+    /**
+     * spacing specifies the number of pixels between the edge of one control
+     * and the edge of its neighbouring control.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int spacing = 0;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {
+}
+
+/*
+ * Computes the preferred height of the form with
+ * respect to the preferred height of the control.
+ *
+ * Given that the equations for top (T) and bottom (B)
+ * of the control in terms of the height of the form (X)
+ * are:
+ *      T = AX + B
+ *      B = CX + D
+ *
+ * The equation for the height of the control (H)
+ * is bottom (B) minus top (T) or (H = B - T) or:
+ *
+ *      H = (CX + D) - (AX + B)
+ *
+ * Solving for (X), the height of the form, we get:
+ *
+ *      X = (H + B - D) / (C - A)
+ *
+ * When (A = C), (C - A = 0) and the equation has no
+ * solution for X.  This is a special case meaning that
+ * the control does not constrain the height of the
+ * form.  In this case, we need to arbitrarily define
+ * the height of the form (X):
+ *
+ * Case 1: A = C, A = 0, C = 0
+ *
+ *      Let X = D, the distance from the top of the form
+ *      to the bottom edge of the control.  In this case,
+ *      the control was attached to the top of the form
+ *      and the form needs to be large enough to show the
+ *      bottom edge of the control.
+ *
+ * Case 2: A = C, A = 1, C = 1
+ *
+ *      Let X = -B, the distance from the bottom of the
+ *      form to the top edge of the control.  In this case,
+ *      the control was attached to the bottom of the form
+ *      and the only way that the control would be visible
+ *      is if the offset is negative.  If the offset is
+ *      positive, there is no possible height for the form
+ *      that will show the control as it will always be
+ *      below the bottom edge of the form.
+ *
+ * Case 3: A = C, A !is 0, C !is 0 and A !is 1, C !is 0
+ *
+ *      Let X = D / (1 - C), the distance from the top of the
+ *      form to the bottom edge of the control.  In this case,
+ *      since C is not 0 or 1, it must be a fraction, U / V.
+ *      The offset D is the distance from CX to the bottom edge
+ *      of the control.  This represents a fraction of the form
+ *      (1 - C)X. Since the height of a fraction of the form is
+ *      known, the height of the entire form can be found by setting
+ *      (1 - C)X = D.  We solve this equation for X in terms of U
+ *      and V, giving us X = (U * D) / (U - V). Similarly, if the
+ *      offset D is negative, the control is positioned above CX.
+ *      The offset -B is the distance from the top edge of the control
+ *      to CX. We can find the height of the entire form by setting
+ *      CX = -B. Solving in terms of U and V gives us X = (-B * V) / U.
+ */
+int computeHeight (Control control, FormData data, bool flushCache) {
+    FormAttachment top = data.getTopAttachment (control, spacing, flushCache);
+    FormAttachment bottom = data.getBottomAttachment (control, spacing, flushCache);
+    FormAttachment height = bottom.minus (top);
+    if (height.numerator is 0) {
+        if (bottom.numerator is 0) return bottom.offset;
+        if (bottom.numerator is bottom.denominator) return -top.offset;
+        if (bottom.offset <= 0) {
+            return -top.offset * top.denominator / bottom.numerator;
+        }
+        int divider = bottom.denominator - bottom.numerator;
+        return bottom.denominator * bottom.offset / divider;
+    }
+    return height.solveY (data.getHeight (control, flushCache));
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache) {
+    Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache);
+    if (wHint !is SWT.DEFAULT) size.x = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+    return size;
+}
+
+override protected bool flushCache (Control control) {
+    Object data = control.getLayoutData ();
+    if (data !is null) (cast(FormData) data).flushCache ();
+    return true;
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf('.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+/*
+ * Computes the preferred height of the form with
+ * respect to the preferred height of the control.
+ */
+int computeWidth (Control control, FormData data, bool flushCache) {
+    FormAttachment left = data.getLeftAttachment (control, spacing, flushCache);
+    FormAttachment right = data.getRightAttachment (control, spacing, flushCache);
+    FormAttachment width = right.minus (left);
+    if (width.numerator is 0) {
+        if (right.numerator is 0) return right.offset;
+        if (right.numerator is right.denominator) return -left.offset;
+        if (right.offset <= 0) {
+            return -left.offset * left.denominator / left.numerator;
+        }
+        int divider = right.denominator - right.numerator;
+        return right.denominator * right.offset / divider;
+    }
+    return width.solveY (data.getWidth (control, flushCache));
+}
+
+override protected void layout (Composite composite, bool flushCache) {
+    Rectangle rect = composite.getClientArea ();
+    int x = rect.x + marginLeft + marginWidth;
+    int y = rect.y + marginTop + marginHeight;
+    int width = Math.max (0, rect.width - marginLeft - 2 * marginWidth - marginRight);
+    int height = Math.max (0, rect.height - marginTop - 2 * marginHeight - marginBottom);
+    layout (composite, true, x, y, width, height, flushCache);
+}
+
+Point layout (Composite composite, bool move, int x, int y, int width, int height, bool flushCache) {
+    Control [] children = composite.getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        FormData data = cast(FormData) child.getLayoutData ();
+        if (data is null) child.setLayoutData (data = new FormData ());
+        if (flushCache) data.flushCache ();
+        data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
+    }
+    bool [] flush = null;
+    Rectangle [] bounds = null;
+    int w = 0, h = 0;
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        FormData data = cast(FormData) child.getLayoutData ();
+        if (width !is SWT.DEFAULT) {
+            data.needed = false;
+            FormAttachment left = data.getLeftAttachment (child, spacing, flushCache);
+            FormAttachment right = data.getRightAttachment (child, spacing, flushCache);
+            int x1 = left.solveX (width), x2 = right.solveX (width);
+            if (data.height is SWT.DEFAULT && !data.needed) {
+                int trim = 0;
+                //TEMPORARY CODE
+                if ( auto sa = cast(Scrollable)child) {
+                    Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+                    trim = rect.width;
+                } else {
+                    trim = child.getBorderWidth () * 2;
+                }
+                data.cacheWidth = data.cacheHeight = -1;
+                int currentWidth = Math.max (0, x2 - x1 - trim);
+                data.computeSize (child, currentWidth, data.height, flushCache);
+                if (flush is null) flush = new bool [children.length];
+                flush [i] = true;
+            }
+            w = Math.max (x2, w);
+            if (move) {
+                if (bounds is null) bounds = new Rectangle [children.length];
+                bounds [i] = new Rectangle (0, 0, 0, 0);
+                bounds [i].x = x + x1;
+                bounds [i].width = x2 - x1;
+            }
+        } else {
+            w = Math.max (computeWidth (child, data, flushCache), w);
+        }
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        FormData data = cast(FormData) child.getLayoutData ();
+        if (height !is SWT.DEFAULT) {
+            int y1 = data.getTopAttachment (child, spacing, flushCache).solveX (height);
+            int y2 = data.getBottomAttachment (child, spacing, flushCache).solveX (height);
+            h = Math.max (y2, h);
+            if (move) {
+                bounds [i].y = y + y1;
+                bounds [i].height = y2 - y1;
+            }
+        } else {
+            h = Math.max (computeHeight (child, data, flushCache), h);
+        }
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        FormData data = cast(FormData) child.getLayoutData ();
+        if (flush !is null && flush [i]) data.cacheWidth = data.cacheHeight = -1;
+        data.cacheLeft = data.cacheRight = data.cacheTop = data.cacheBottom = null;
+    }
+    if (move) {
+        for (int i=0; i<children.length; i++) {
+            children [i].setBounds (bounds [i]);
+        }
+    }
+    w += marginLeft + marginWidth * 2 + marginRight;
+    h += marginTop + marginHeight * 2 + marginBottom;
+    return new Point (w, h);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+override public String toString () {
+    String string =  getName ()~" {";
+    if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+    if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+    if (marginLeft !is 0) string ~= "marginLeft="~to!(String)(marginLeft)~" ";
+    if (marginRight !is 0) string ~= "marginRight="~to!(String)(marginRight)~" ";
+    if (marginTop !is 0) string ~= "marginTop="~to!(String)(marginTop)~" ";
+    if (marginBottom !is 0) string ~= "marginBottom="~to!(String)(marginBottom)~" ";
+    if (spacing !is 0) string ~= "spacing="~to!(String)(spacing)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,567 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.GridData;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * <code>GridData</code> is the layout data object associated with
+ * <code>GridLayout</code>. To set a <code>GridData</code> object into a
+ * control, you use the <code>Control.setLayoutData(Object)</code> method.
+ * <p>
+ * There are two ways to create a <code>GridData</code> object with certain
+ * fields set. The first is to set the fields directly, like this:
+ * <pre>
+ *      GridData gridData = new GridData();
+ *      gridData.horizontalAlignment = GridData.FILL;
+ *      gridData.grabExcessHorizontalSpace = true;
+ *      button1.setLayoutData(gridData);
+ * </pre>
+ * The second is to take advantage of convenience style bits defined
+ * by <code>GridData</code>:
+ * <pre>
+ *      button1.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
+ * </pre>
+ * </p>
+ * <p>
+ * NOTE: Do not reuse <code>GridData</code> objects. Every control in a
+ * <code>Composite</code> that is managed by a <code>GridLayout</code>
+ * must have a unique <code>GridData</code> object. If the layout data
+ * for a control in a <code>GridLayout</code> is null at layout time,
+ * a unique <code>GridData</code> object is created for it.
+ * </p>
+ *
+ * @see GridLayout
+ * @see Control#setLayoutData
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class GridData {
+    /**
+     * verticalAlignment specifies how controls will be positioned
+     * vertically within a cell.
+     *
+     * The default value is CENTER.
+     *
+     * Possible values are: <ul>
+     *    <li>SWT.BEGINNING (or SWT.TOP): Position the control at the top of the cell</li>
+     *    <li>SWT.CENTER: Position the control in the vertical center of the cell</li>
+     *    <li>SWT.END (or SWT.BOTTOM): Position the control at the bottom of the cell</li>
+     *    <li>SWT.FILL: Resize the control to fill the cell vertically</li>
+     * </ul>
+     */
+    public int verticalAlignment = CENTER;
+
+    /**
+     * horizontalAlignment specifies how controls will be positioned
+     * horizontally within a cell.
+     *
+     * The default value is BEGINNING.
+     *
+     * Possible values are: <ul>
+     *    <li>SWT.BEGINNING (or SWT.LEFT): Position the control at the left of the cell</li>
+     *    <li>SWT.CENTER: Position the control in the horizontal center of the cell</li>
+     *    <li>SWT.END (or SWT.RIGHT): Position the control at the right of the cell</li>
+     *    <li>SWT.FILL: Resize the control to fill the cell horizontally</li>
+     * </ul>
+     */
+    public int horizontalAlignment = BEGINNING;
+
+    /**
+     * widthHint specifies the preferred width in pixels. This value
+     * is the wHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see Control#computeSize(int, int, bool)
+     */
+    public int widthHint = SWT.DEFAULT;
+
+    /**
+     * heightHint specifies the preferred height in pixels. This value
+     * is the hHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see Control#computeSize(int, int, bool)
+     */
+    public int heightHint = SWT.DEFAULT;
+
+    /**
+     * horizontalIndent specifies the number of pixels of indentation
+     * that will be placed along the left side of the cell.
+     *
+     * The default value is 0.
+     */
+    public int horizontalIndent = 0;
+
+    /**
+     * verticalIndent specifies the number of pixels of indentation
+     * that will be placed along the top side of the cell.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int verticalIndent = 0;
+
+    /**
+     * horizontalSpan specifies the number of column cells that the control
+     * will take up.
+     *
+     * The default value is 1.
+     */
+    public int horizontalSpan = 1;
+
+    /**
+     * verticalSpan specifies the number of row cells that the control
+     * will take up.
+     *
+     * The default value is 1.
+     */
+    public int verticalSpan = 1;
+
+    /**
+     * <p>grabExcessHorizontalSpace specifies whether the width of the cell
+     * changes depending on the size of the parent Composite.  If
+     * grabExcessHorizontalSpace is <code>true</code>, the following rules
+     * apply to the width of the cell:</p>
+     * <ul>
+     * <li>If extra horizontal space is available in the parent, the cell will
+     * grow to be wider than its preferred width.  The new width
+     * will be "preferred width + delta" where delta is the extra
+     * horizontal space divided by the number of grabbing columns.</li>
+     * <li>If there is not enough horizontal space available in the parent, the
+     * cell will shrink until it reaches its minimum width as specified by
+     * GridData.minimumWidth. The new width will be the maximum of
+     * "minimumWidth" and "preferred width - delta", where delta is
+     * the amount of space missing divided by the number of grabbing columns.</li>
+     * <li>If the parent is packed, the cell will be its preferred width
+     * as specified by GridData.widthHint.</li>
+     * <li>If the control spans multiple columns and there are no other grabbing
+     * controls in any of the spanned columns, the last column in the span will
+     * grab the extra space.  If there is at least one other grabbing control
+     * in the span, the grabbing will be spread over the columns already
+     * marked as grabExcessHorizontalSpace.</li>
+     * </ul>
+     *
+     * <p>The default value is false.</p>
+     *
+     * @see GridData#minimumWidth
+     * @see GridData#widthHint
+     */
+    public bool grabExcessHorizontalSpace = false;
+
+    /**
+     * <p>grabExcessVerticalSpace specifies whether the height of the cell
+     * changes depending on the size of the parent Composite.  If
+     * grabExcessVerticalSpace is <code>true</code>, the following rules
+     * apply to the height of the cell:</p>
+     * <ul>
+     * <li>If extra vertical space is available in the parent, the cell will
+     * grow to be taller than its preferred height.  The new height
+     * will be "preferred height + delta" where delta is the extra
+     * vertical space divided by the number of grabbing rows.</li>
+     * <li>If there is not enough vertical space available in the parent, the
+     * cell will shrink until it reaches its minimum height as specified by
+     * GridData.minimumHeight. The new height will be the maximum of
+     * "minimumHeight" and "preferred height - delta", where delta is
+     * the amount of space missing divided by the number of grabbing rows.</li>
+     * <li>If the parent is packed, the cell will be its preferred height
+     * as specified by GridData.heightHint.</li>
+     * <li>If the control spans multiple rows and there are no other grabbing
+     * controls in any of the spanned rows, the last row in the span will
+     * grab the extra space.  If there is at least one other grabbing control
+     * in the span, the grabbing will be spread over the rows already
+     * marked as grabExcessVerticalSpace.</li>
+     * </ul>
+     *
+     * <p>The default value is false.</p>
+     *
+     * @see GridData#minimumHeight
+     * @see GridData#heightHint
+     */
+    public bool grabExcessVerticalSpace = false;
+
+    /**
+     * minimumWidth specifies the minimum width in pixels.  This value
+     * applies only if grabExcessHorizontalSpace is true. A value of
+     * SWT.DEFAULT means that the minimum width will be the result
+     * of Control.computeSize(int, int, bool) where wHint is
+     * determined by GridData.widthHint.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     * @see Control#computeSize(int, int, bool)
+     * @see GridData#widthHint
+     */
+    public int minimumWidth = 0;
+
+    /**
+     * minimumHeight specifies the minimum height in pixels.  This value
+     * applies only if grabExcessVerticalSpace is true.  A value of
+     * SWT.DEFAULT means that the minimum height will be the result
+     * of Control.computeSize(int, int, bool) where hHint is
+     * determined by GridData.heightHint.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     * @see Control#computeSize(int, int, bool)
+     * @see GridData#heightHint
+     */
+    public int minimumHeight = 0;
+
+    /**
+     * exclude informs the layout to ignore this control when sizing
+     * and positioning controls.  If this value is <code>true</code>,
+     * the size and position of the control will not be managed by the
+     * layout.  If this value is <code>false</code>, the size and
+     * position of the control will be computed and assigned.
+     *
+     * The default value is <code>false</code>.
+     *
+     * @since 3.1
+     */
+    public bool exclude = false;
+
+    /**
+     * Value for horizontalAlignment or verticalAlignment.
+     * Position the control at the top or left of the cell.
+     * Not recommended. Use SWT.BEGINNING, SWT.TOP or SWT.LEFT instead.
+     */
+    public static const int BEGINNING = SWT.BEGINNING;
+
+    /**
+     * Value for horizontalAlignment or verticalAlignment.
+     * Position the control in the vertical or horizontal center of the cell
+     * Not recommended. Use SWT.CENTER instead.
+     */
+    public static const int CENTER = 2;
+
+    /**
+     * Value for horizontalAlignment or verticalAlignment.
+     * Position the control at the bottom or right of the cell
+     * Not recommended. Use SWT.END, SWT.BOTTOM or SWT.RIGHT instead.
+     */
+    public static const int END = 3;
+
+    /**
+     * Value for horizontalAlignment or verticalAlignment.
+     * Resize the control to fill the cell horizontally or vertically.
+     * Not recommended. Use SWT.FILL instead.
+     */
+    public static const int FILL = SWT.FILL;
+
+    /**
+     * Style bit for <code>new GridData(int)</code>.
+     * Position the control at the top of the cell.
+     * Not recommended. Use
+     * <code>new GridData(int, SWT.BEGINNING, bool, bool)</code>
+     * instead.
+     */
+    public static const int VERTICAL_ALIGN_BEGINNING =  1 << 1;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to position the
+     * control in the vertical center of the cell.
+     * Not recommended. Use
+     * <code>new GridData(int, SWT.CENTER, bool, bool)</code>
+     * instead.
+     */
+    public static const int VERTICAL_ALIGN_CENTER = 1 << 2;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to position the
+     * control at the bottom of the cell.
+     * Not recommended. Use
+     * <code>new GridData(int, SWT.END, bool, bool)</code>
+     * instead.
+     */
+    public static const int VERTICAL_ALIGN_END = 1 << 3;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fill the cell vertically.
+     * Not recommended. Use
+     * <code>new GridData(int, SWT.FILL, bool, bool)</code>
+     * instead
+     */
+    public static const int VERTICAL_ALIGN_FILL = 1 << 4;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to position the
+     * control at the left of the cell.
+     * Not recommended. Use
+     * <code>new GridData(SWT.BEGINNING, int, bool, bool)</code>
+     * instead.
+     */
+    public static const int HORIZONTAL_ALIGN_BEGINNING =  1 << 5;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to position the
+     * control in the horizontal center of the cell.
+     * Not recommended. Use
+     * <code>new GridData(SWT.CENTER, int, bool, bool)</code>
+     * instead.
+     */
+    public static const int HORIZONTAL_ALIGN_CENTER = 1 << 6;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to position the
+     * control at the right of the cell.
+     * Not recommended. Use
+     * <code>new GridData(SWT.END, int, bool, bool)</code>
+     * instead.
+     */
+    public static const int HORIZONTAL_ALIGN_END = 1 << 7;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fill the cell horizontally.
+     * Not recommended. Use
+     * <code>new GridData(SWT.FILL, int, bool, bool)</code>
+     * instead.
+     */
+    public static const int HORIZONTAL_ALIGN_FILL = 1 << 8;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fit the remaining horizontal space.
+     * Not recommended. Use
+     * <code>new GridData(int, int, true, bool)</code>
+     * instead.
+     */
+    public static const int GRAB_HORIZONTAL = 1 << 9;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fit the remaining vertical space.
+     * Not recommended. Use
+     * <code>new GridData(int, int, bool, true)</code>
+     * instead.
+     */
+    public static const int GRAB_VERTICAL = 1 << 10;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fill the cell vertically and to fit the remaining
+     * vertical space.
+     * FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL
+     * Not recommended. Use
+     * <code>new GridData(int, SWT.FILL, bool, true)</code>
+     * instead.
+     */
+    public static const int FILL_VERTICAL = VERTICAL_ALIGN_FILL | GRAB_VERTICAL;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fill the cell horizontally and to fit the remaining
+     * horizontal space.
+     * FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL
+     * Not recommended. Use
+     * <code>new GridData(SWT.FILL, int, true, bool)</code>
+     * instead.
+     */
+    public static const int FILL_HORIZONTAL = HORIZONTAL_ALIGN_FILL | GRAB_HORIZONTAL;
+
+    /**
+     * Style bit for <code>new GridData(int)</code> to resize the
+     * control to fill the cell horizontally and vertically and
+     * to fit the remaining horizontal and vertical space.
+     * FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL
+     * Not recommended. Use
+     * <code>new GridData(SWT.FILL, SWT.FILL, true, true)</code>
+     * instead.
+     */
+    public static const int FILL_BOTH = FILL_VERTICAL | FILL_HORIZONTAL;
+
+    int cacheWidth = -1, cacheHeight = -1;
+    int defaultWhint, defaultHhint, defaultWidth = -1, defaultHeight = -1;
+    int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;
+
+/**
+ * Constructs a new instance of GridData using
+ * default values.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance based on the GridData style.
+ * This constructor is not recommended.
+ *
+ * @param style the GridData style
+ */
+public this (int style) {
+    if ((style & VERTICAL_ALIGN_BEGINNING) !is 0) verticalAlignment = BEGINNING;
+    if ((style & VERTICAL_ALIGN_CENTER) !is 0) verticalAlignment = CENTER;
+    if ((style & VERTICAL_ALIGN_FILL) !is 0) verticalAlignment = FILL;
+    if ((style & VERTICAL_ALIGN_END) !is 0) verticalAlignment = END;
+    if ((style & HORIZONTAL_ALIGN_BEGINNING) !is 0) horizontalAlignment = BEGINNING;
+    if ((style & HORIZONTAL_ALIGN_CENTER) !is 0) horizontalAlignment = CENTER;
+    if ((style & HORIZONTAL_ALIGN_FILL) !is 0) horizontalAlignment = FILL;
+    if ((style & HORIZONTAL_ALIGN_END) !is 0) horizontalAlignment = END;
+    grabExcessHorizontalSpace = (style & GRAB_HORIZONTAL) !is 0;
+    grabExcessVerticalSpace = (style & GRAB_VERTICAL) !is 0;
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ *
+ * @param horizontalAlignment how control will be positioned horizontally within a cell,
+ *      one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
+ * @param verticalAlignment how control will be positioned vertically within a cell,
+ *      one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
+ * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
+ * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
+ *
+ * @since 3.0
+ */
+public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace) {
+    this (horizontalAlignment, verticalAlignment, grabExcessHorizontalSpace, grabExcessVerticalSpace, 1, 1);
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ *
+ * @param horizontalAlignment how control will be positioned horizontally within a cell,
+ *      one of: SWT.BEGINNING (or SWT.LEFT), SWT.CENTER, SWT.END (or SWT.RIGHT), or SWT.FILL
+ * @param verticalAlignment how control will be positioned vertically within a cell,
+ *      one of: SWT.BEGINNING (or SWT.TOP), SWT.CENTER, SWT.END (or SWT.BOTTOM), or SWT.FILL
+ * @param grabExcessHorizontalSpace whether cell will be made wide enough to fit the remaining horizontal space
+ * @param grabExcessVerticalSpace whether cell will be made high enough to fit the remaining vertical space
+ * @param horizontalSpan the number of column cells that the control will take up
+ * @param verticalSpan the number of row cells that the control will take up
+ *
+ * @since 3.0
+ */
+public this (int horizontalAlignment, int verticalAlignment, bool grabExcessHorizontalSpace, bool grabExcessVerticalSpace, int horizontalSpan, int verticalSpan) {
+    this.horizontalAlignment = horizontalAlignment;
+    this.verticalAlignment = verticalAlignment;
+    this.grabExcessHorizontalSpace = grabExcessHorizontalSpace;
+    this.grabExcessVerticalSpace = grabExcessVerticalSpace;
+    this.horizontalSpan = horizontalSpan;
+    this.verticalSpan = verticalSpan;
+}
+
+/**
+ * Constructs a new instance of GridData according to the parameters.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param width a minimum width for the column
+ * @param height a minimum height for the row
+ *
+ * @since 3.0
+ */
+public this (int width, int height) {
+    this.widthHint = width;
+    this.heightHint = height;
+}
+
+void computeSize (Control control, int wHint, int hHint, bool flushCache) {
+    if (cacheWidth !is -1 && cacheHeight !is -1) return;
+    if (wHint is this.widthHint && hHint is this.heightHint) {
+        if (defaultWidth is -1 || defaultHeight is -1 || wHint !is defaultWhint || hHint !is defaultHhint) {
+            Point size = control.computeSize (wHint, hHint, flushCache);
+            defaultWhint = wHint;
+            defaultHhint = hHint;
+            defaultWidth = size.x;
+            defaultHeight = size.y;
+        }
+        cacheWidth = defaultWidth;
+        cacheHeight = defaultHeight;
+        return;
+    }
+    if (currentWidth is -1 || currentHeight is -1 || wHint !is currentWhint || hHint !is currentHhint) {
+        Point size = control.computeSize (wHint, hHint, flushCache);
+        currentWhint = wHint;
+        currentHhint = hHint;
+        currentWidth = size.x;
+        currentHeight = size.y;
+    }
+    cacheWidth = currentWidth;
+    cacheHeight = currentHeight;
+}
+
+void flushCache () {
+    cacheWidth = cacheHeight = -1;
+    defaultWidth = defaultHeight = -1;
+    currentWidth = currentHeight = -1;
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf('.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the GridData object
+ */
+override public String toString () {
+    String hAlign = "";
+    switch (horizontalAlignment) {
+        case SWT.FILL: hAlign = "SWT.FILL"; break;
+        case SWT.BEGINNING: hAlign = "SWT.BEGINNING"; break;
+        case SWT.LEFT: hAlign = "SWT.LEFT"; break;
+        case SWT.END: hAlign = "SWT.END"; break;
+        case END: hAlign = "GridData.END"; break;
+        case SWT.RIGHT: hAlign = "SWT.RIGHT"; break;
+        case SWT.CENTER: hAlign = "SWT.CENTER"; break;
+        case CENTER: hAlign = "GridData.CENTER"; break;
+        default: hAlign = "Undefined "~to!(String)(horizontalAlignment); break;
+    }
+    String vAlign = "";
+    switch (verticalAlignment) {
+        case SWT.FILL: vAlign = "SWT.FILL"; break;
+        case SWT.BEGINNING: vAlign = "SWT.BEGINNING"; break;
+        case SWT.TOP: vAlign = "SWT.TOP"; break;
+        case SWT.END: vAlign = "SWT.END"; break;
+        case END: vAlign = "GridData.END"; break;
+        case SWT.BOTTOM: vAlign = "SWT.BOTTOM"; break;
+        case SWT.CENTER: vAlign = "SWT.CENTER"; break;
+        case CENTER: vAlign = "GridData.CENTER"; break;
+        default: vAlign = "Undefined "~to!(String)(verticalAlignment); break;
+    }
+    String string = getName()~" {";
+    string ~= "horizontalAlignment="~to!(String)(hAlign)~" ";
+    if (horizontalIndent !is 0) string ~= "horizontalIndent="~to!(String)(horizontalIndent)~" ";
+    if (horizontalSpan !is 1) string ~= "horizontalSpan="~to!(String)(horizontalSpan)~" ";
+    if (grabExcessHorizontalSpace) string ~= "grabExcessHorizontalSpace="~to!(String)(grabExcessHorizontalSpace)~" ";
+    if (widthHint !is SWT.DEFAULT) string ~= "widthHint="~to!(String)(widthHint)~" ";
+    if (minimumWidth !is 0) string ~= "minimumWidth="~to!(String)(minimumWidth)~" ";
+    string ~= "verticalAlignment="~vAlign~" ";
+    if (verticalIndent !is 0) string ~= "verticalIndent="~to!(String)(verticalIndent)~" ";
+    if (verticalSpan !is 1) string ~= "verticalSpan="~to!(String)(verticalSpan)~" ";
+    if (grabExcessVerticalSpace) string ~= "grabExcessVerticalSpace="~to!(String)(grabExcessVerticalSpace)~" ";
+    if (heightHint !is SWT.DEFAULT) string ~= "heightHint="~to!(String)(heightHint)~" ";
+    if (minimumHeight !is 0) string ~= "minimumHeight="~to!(String)(minimumHeight)~" ";
+    if (exclude) string ~= "exclude="~to!(String)(exclude)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/GridLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,761 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.GridLayout;
+
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Scrollable;
+
+import java.lang.System;
+
+import tango.util.Convert;
+import Math = tango.math.Math;
+import java.lang.all;
+
+
+/**
+ * Instances of this class lay out the control children of a
+ * <code>Composite</code> in a grid.
+ * <p>
+ * <code>GridLayout</code> has a number of configuration fields, and the
+ * controls it lays out can have an associated layout data object, called
+ * <code>GridData</code>. The power of <code>GridLayout</code> lies in the
+ * ability to configure <code>GridData</code> for each control in the layout.
+ * </p>
+ * <p>
+ * The following code creates a shell managed by a <code>GridLayout</code>
+ * with 3 columns:
+ * <pre>
+ *      Display display = new Display();
+ *      Shell shell = new Shell(display);
+ *      GridLayout gridLayout = new GridLayout();
+ *      gridLayout.numColumns = 3;
+ *      shell.setLayout(gridLayout);
+ * </pre>
+ * The <code>numColumns</code> field is the most important field in a
+ * <code>GridLayout</code>. Widgets are laid out in columns from left
+ * to right, and a new row is created when <code>numColumns</code> + 1
+ * controls are added to the <code>Composite<code>.
+ * </p>
+ *
+ * @see GridData
+ * @see <a href="http://www.eclipse.org/swt/snippets/#gridlayout">GridLayout snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class GridLayout : Layout {
+
+    /**
+     * numColumns specifies the number of cell columns in the layout.
+     * If numColumns has a value less than 1, the layout will not
+     * set the size and position of any controls.
+     *
+     * The default value is 1.
+     */
+    public int numColumns = 1;
+
+    /**
+     * makeColumnsEqualWidth specifies whether all columns in the layout
+     * will be forced to have the same width.
+     *
+     * The default value is false.
+     */
+    public bool makeColumnsEqualWidth = false;
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the layout.
+     *
+     * The default value is 5.
+     */
+    public int marginWidth = 5;
+
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the layout.
+     *
+     * The default value is 5.
+     */
+    public int marginHeight = 5;
+
+    /**
+     * marginLeft specifies the number of pixels of horizontal margin
+     * that will be placed along the left edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginLeft = 0;
+
+    /**
+     * marginTop specifies the number of pixels of vertical margin
+     * that will be placed along the top edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginTop = 0;
+
+    /**
+     * marginRight specifies the number of pixels of horizontal margin
+     * that will be placed along the right edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginRight = 0;
+
+    /**
+     * marginBottom specifies the number of pixels of vertical margin
+     * that will be placed along the bottom edge of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.1
+     */
+    public int marginBottom = 0;
+
+    /**
+     * horizontalSpacing specifies the number of pixels between the right
+     * edge of one cell and the left edge of its neighbouring cell to
+     * the right.
+     *
+     * The default value is 5.
+     */
+    public int horizontalSpacing = 5;
+
+    /**
+     * verticalSpacing specifies the number of pixels between the bottom
+     * edge of one cell and the top edge of its neighbouring cell underneath.
+     *
+     * The default value is 5.
+     */
+    public int verticalSpacing = 5;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {}
+
+/**
+ * Constructs a new instance of this class given the
+ * number of columns, and whether or not the columns
+ * should be forced to have the same width.
+ * If numColumns has a value less than 1, the layout will not
+ * set the size and position of any controls.
+ *
+ * @param numColumns the number of columns in the grid
+ * @param makeColumnsEqualWidth whether or not the columns will have equal width
+ *
+ * @since 2.0
+ */
+public this (int numColumns, bool makeColumnsEqualWidth) {
+    this.numColumns = numColumns;
+    this.makeColumnsEqualWidth = makeColumnsEqualWidth;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache_) {
+    Point size = layout (composite, false, 0, 0, wHint, hHint, flushCache_);
+    if (wHint !is SWT.DEFAULT) size.x = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+    return size;
+}
+
+override protected bool flushCache (Control control) {
+    Object data = control.getLayoutData ();
+    if (data !is null) (cast(GridData) data).flushCache ();
+    return true;
+}
+
+GridData getData (Control [][] grid, int row, int column, int rowCount, int columnCount, bool first) {
+    Control control = grid [row] [column];
+    if (control !is null) {
+        GridData data = cast(GridData) control.getLayoutData ();
+        int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+        int vSpan = Math.max (1, data.verticalSpan);
+        int i = first ? row + vSpan - 1 : row - vSpan + 1;
+        int j = first ? column + hSpan - 1 : column - hSpan + 1;
+        if (0 <= i && i < rowCount) {
+            if (0 <= j && j < columnCount) {
+                if (control is grid [i][j]) return data;
+            }
+        }
+    }
+    return null;
+}
+
+override protected void layout (Composite composite, bool flushCache_) {
+    Rectangle rect = composite.getClientArea ();
+    layout (composite, true, rect.x, rect.y, rect.width, rect.height, flushCache_);
+}
+
+Point layout (Composite composite, bool move, int x, int y, int width, int height, bool flushCache_) {
+    if (numColumns < 1) {
+        return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+    }
+    Control [] children = composite.getChildren ();
+    int count = 0;
+    for (int i=0; i<children.length; i++) {
+        Control control = children [i];
+        GridData data = cast(GridData) control.getLayoutData ();
+        if (data is null || !data.exclude) {
+            children [count++] = children [i];
+        }
+    }
+    if (count is 0) {
+        return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+    }
+    for (int i=0; i<count; i++) {
+        Control child = children [i];
+        GridData data = cast(GridData) child.getLayoutData ();
+        if (data is null) child.setLayoutData (data = new GridData ());
+        if (flushCache_) data.flushCache ();
+        data.computeSize (child, data.widthHint, data.heightHint, flushCache_);
+        if (data.grabExcessHorizontalSpace && data.minimumWidth > 0) {
+            if (data.cacheWidth < data.minimumWidth) {
+                int trim = 0;
+                //TEMPORARY CODE
+                if ( auto sa = cast(Scrollable)child ) {
+                    Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+                    trim = rect.width;
+                } else {
+                    trim = child.getBorderWidth () * 2;
+                }
+                data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+                data.computeSize (child, Math.max (0, data.minimumWidth - trim), data.heightHint, false);
+            }
+        }
+        if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+            data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+        }
+    }
+
+    /* Build the grid */
+    int row = 0, column = 0, rowCount = 0, columnCount = numColumns;
+    Control [][] grid = new Control [][]( 4, columnCount );
+    for (int i=0; i<count; i++) {
+        Control child = children [i];
+        GridData data = cast(GridData) child.getLayoutData ();
+        int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+        int vSpan = Math.max (1, data.verticalSpan);
+        while (true) {
+            int lastRow = row + vSpan;
+            if (lastRow >= grid.length) {
+                Control [][] newGrid = new Control[][]( lastRow + 4, columnCount );
+                SimpleType!(Control[]).arraycopy (grid, 0, newGrid, 0, grid.length);
+                grid = newGrid;
+            }
+            if (grid [row] is null) {
+                grid [row] = new Control [columnCount];
+            }
+            while (column < columnCount && grid [row] [column] !is null) {
+                column++;
+            }
+            int endCount = column + hSpan;
+            if (endCount <= columnCount) {
+                int index = column;
+                while (index < endCount && grid [row] [index] is null) {
+                    index++;
+                }
+                if (index is endCount) break;
+                column = index;
+            }
+            if (column + hSpan >= columnCount) {
+                column = 0;
+                row++;
+            }
+        }
+        for (int j=0; j<vSpan; j++) {
+            if (grid [row + j] is null) {
+                grid [row + j] = new Control [columnCount];
+            }
+            for (int k=0; k<hSpan; k++) {
+                grid [row + j] [column + k] = child;
+            }
+        }
+        rowCount = Math.max (rowCount, row + vSpan);
+        column += hSpan;
+    }
+
+    /* Column widths */
+    int availableWidth = width - horizontalSpacing * (columnCount - 1) - (marginLeft + marginWidth * 2 + marginRight);
+    int expandCount = 0;
+    int [] widths = new int [columnCount];
+    int [] minWidths = new int [columnCount];
+    bool [] expandColumn = new bool [columnCount];
+    for (int j=0; j<columnCount; j++) {
+        for (int i=0; i<rowCount; i++) {
+            GridData data = getData (grid, i, j, rowCount, columnCount, true);
+            if (data !is null) {
+                int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                if (hSpan is 1) {
+                    int w = data.cacheWidth + data.horizontalIndent;
+                    widths [j] = Math.max (widths [j], w);
+                    if (data.grabExcessHorizontalSpace) {
+                        if (!expandColumn [j]) expandCount++;
+                        expandColumn [j] = true;
+                    }
+                    if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) {
+                        w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+                        w += data.horizontalIndent;
+                        minWidths [j] = Math.max (minWidths [j], w);
+                    }
+                }
+            }
+        }
+        for (int i=0; i<rowCount; i++) {
+            GridData data = getData (grid, i, j, rowCount, columnCount, false);
+            if (data !is null) {
+                int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                if (hSpan > 1) {
+                    int spanWidth = 0, spanMinWidth = 0, spanExpandCount = 0;
+                    for (int k=0; k<hSpan; k++) {
+                        spanWidth += widths [j-k];
+                        spanMinWidth += minWidths [j-k];
+                        if (expandColumn [j-k]) spanExpandCount++;
+                    }
+                    if (data.grabExcessHorizontalSpace && spanExpandCount is 0) {
+                        expandCount++;
+                        expandColumn [j] = true;
+                    }
+                    int w = data.cacheWidth + data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing;
+                    if (w > 0) {
+                        if (makeColumnsEqualWidth) {
+                            int equalWidth = (w + spanWidth) / hSpan;
+                            int remainder = (w + spanWidth) % hSpan, last = -1;
+                            for (int k = 0; k < hSpan; k++) {
+                                widths [last=j-k] = Math.max (equalWidth, widths [j-k]);
+                            }
+                            if (last > -1) widths [last] += remainder;
+                        } else {
+                            if (spanExpandCount is 0) {
+                                widths [j] += w;
+                            } else {
+                                int delta = w / spanExpandCount;
+                                int remainder = w % spanExpandCount, last = -1;
+                                for (int k = 0; k < hSpan; k++) {
+                                    if (expandColumn [j-k]) {
+                                        widths [last=j-k] += delta;
+                                    }
+                                }
+                                if (last > -1) widths [last] += remainder;
+                            }
+                        }
+                    }
+                    if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) {
+                        w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+                        w += data.horizontalIndent - spanMinWidth - (hSpan - 1) * horizontalSpacing;
+                        if (w > 0) {
+                            if (spanExpandCount is 0) {
+                                minWidths [j] += w;
+                            } else {
+                                int delta = w / spanExpandCount;
+                                int remainder = w % spanExpandCount, last = -1;
+                                for (int k = 0; k < hSpan; k++) {
+                                    if (expandColumn [j-k]) {
+                                        minWidths [last=j-k] += delta;
+                                    }
+                                }
+                                if (last > -1) minWidths [last] += remainder;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (makeColumnsEqualWidth) {
+        int minColumnWidth = 0;
+        int columnWidth = 0;
+        for (int i=0; i<columnCount; i++) {
+            minColumnWidth = Math.max (minColumnWidth, minWidths [i]);
+            columnWidth = Math.max (columnWidth, widths [i]);
+        }
+        columnWidth = width is SWT.DEFAULT || expandCount is 0 ? columnWidth : Math.max (minColumnWidth, availableWidth / columnCount);
+        for (int i=0; i<columnCount; i++) {
+            expandColumn [i] = expandCount > 0;
+            widths [i] = columnWidth;
+        }
+    } else {
+        if (width !is SWT.DEFAULT && expandCount > 0) {
+            int totalWidth = 0;
+            for (int i=0; i<columnCount; i++) {
+                totalWidth += widths [i];
+            }
+            int c = expandCount;
+            int delta = (availableWidth - totalWidth) / c;
+            int remainder = (availableWidth - totalWidth) % c;
+            int last = -1;
+            while (totalWidth !is availableWidth) {
+                for (int j=0; j<columnCount; j++) {
+                    if (expandColumn [j]) {
+                        if (widths [j] + delta > minWidths [j]) {
+                            widths [last = j] = widths [j] + delta;
+                        } else {
+                            widths [j] = minWidths [j];
+                            expandColumn [j] = false;
+                            c--;
+                        }
+                    }
+                }
+                if (last > -1) widths [last] += remainder;
+
+                for (int j=0; j<columnCount; j++) {
+                    for (int i=0; i<rowCount; i++) {
+                        GridData data = getData (grid, i, j, rowCount, columnCount, false);
+                        if (data !is null) {
+                            int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                            if (hSpan > 1) {
+                                if (!data.grabExcessHorizontalSpace || data.minimumWidth !is 0) {
+                                    int spanWidth = 0, spanExpandCount = 0;
+                                    for (int k=0; k<hSpan; k++) {
+                                        spanWidth += widths [j-k];
+                                        if (expandColumn [j-k]) spanExpandCount++;
+                                    }
+                                    int w = !data.grabExcessHorizontalSpace || data.minimumWidth is SWT.DEFAULT ? data.cacheWidth : data.minimumWidth;
+                                    w += data.horizontalIndent - spanWidth - (hSpan - 1) * horizontalSpacing;
+                                    if (w > 0) {
+                                        if (spanExpandCount is 0) {
+                                            widths [j] += w;
+                                        } else {
+                                            int delta2 = w / spanExpandCount;
+                                            int remainder2 = w % spanExpandCount, last2 = -1;
+                                            for (int k = 0; k < hSpan; k++) {
+                                                if (expandColumn [j-k]) {
+                                                    widths [last2=j-k] += delta2;
+                                                }
+                                            }
+                                            if (last2 > -1) widths [last2] += remainder2;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                if (c is 0) break;
+                totalWidth = 0;
+                for (int i=0; i<columnCount; i++) {
+                    totalWidth += widths [i];
+                }
+                delta = (availableWidth - totalWidth) / c;
+                remainder = (availableWidth - totalWidth) % c;
+                last = -1;
+            }
+        }
+    }
+
+    /* Wrapping */
+    GridData [] flush = null;
+    int flushLength = 0;
+    if (width !is SWT.DEFAULT) {
+        for (int j=0; j<columnCount; j++) {
+            for (int i=0; i<rowCount; i++) {
+                GridData data = getData (grid, i, j, rowCount, columnCount, false);
+                if (data !is null) {
+                    if (data.heightHint is SWT.DEFAULT) {
+                        Control child = grid [i][j];
+                        //TEMPORARY CODE
+                        int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                        int currentWidth = 0;
+                        for (int k=0; k<hSpan; k++) {
+                            currentWidth += widths [j-k];
+                        }
+                        currentWidth += (hSpan - 1) * horizontalSpacing - data.horizontalIndent;
+                        if ((currentWidth !is data.cacheWidth && data.horizontalAlignment is SWT.FILL) || (data.cacheWidth > currentWidth)) {
+                            int trim = 0;
+                            if ( auto sa = cast(Scrollable)child ) {
+                                Rectangle rect = sa.computeTrim (0, 0, 0, 0);
+                                trim = rect.width;
+                            } else {
+                                trim = child.getBorderWidth () * 2;
+                            }
+                            data.cacheWidth = data.cacheHeight = SWT.DEFAULT;
+                            data.computeSize (child, Math.max (0, currentWidth - trim), data.heightHint, false);
+                            if (data.grabExcessVerticalSpace && data.minimumHeight > 0) {
+                                data.cacheHeight = Math.max (data.cacheHeight, data.minimumHeight);
+                            }
+                            if (flush is null) flush = new GridData [count];
+                            flush [flushLength++] = data;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /* Row heights */
+    int availableHeight = height - verticalSpacing * (rowCount - 1) - (marginTop + marginHeight * 2 + marginBottom);
+    expandCount = 0;
+    int [] heights = new int [rowCount];
+    int [] minHeights = new int [rowCount];
+    bool [] expandRow = new bool [rowCount];
+    for (int i=0; i<rowCount; i++) {
+        for (int j=0; j<columnCount; j++) {
+            GridData data = getData (grid, i, j, rowCount, columnCount, true);
+            if (data !is null) {
+                int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount));
+                if (vSpan is 1) {
+                    int h = data.cacheHeight + data.verticalIndent;
+                    heights [i] = Math.max (heights [i], h);
+                    if (data.grabExcessVerticalSpace) {
+                        if (!expandRow [i]) expandCount++;
+                        expandRow [i] = true;
+                    }
+                    if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) {
+                        h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+                        h += data.verticalIndent;
+                        minHeights [i] = Math.max (minHeights [i], h);
+                    }
+                }
+            }
+        }
+        for (int j=0; j<columnCount; j++) {
+            GridData data = getData (grid, i, j, rowCount, columnCount, false);
+            if (data !is null) {
+                int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount));
+                if (vSpan > 1) {
+                    int spanHeight = 0, spanMinHeight = 0, spanExpandCount = 0;
+                    for (int k=0; k<vSpan; k++) {
+                        spanHeight += heights [i-k];
+                        spanMinHeight += minHeights [i-k];
+                        if (expandRow [i-k]) spanExpandCount++;
+                    }
+                    if (data.grabExcessVerticalSpace && spanExpandCount is 0) {
+                        expandCount++;
+                        expandRow [i] = true;
+                    }
+                    int h = data.cacheHeight + data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing;
+                    if (h > 0) {
+                        if (spanExpandCount is 0) {
+                            heights [i] += h;
+                        } else {
+                            int delta = h / spanExpandCount;
+                            int remainder = h % spanExpandCount, last = -1;
+                            for (int k = 0; k < vSpan; k++) {
+                                if (expandRow [i-k]) {
+                                    heights [last=i-k] += delta;
+                                }
+                            }
+                            if (last > -1) heights [last] += remainder;
+                        }
+                    }
+                    if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) {
+                        h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+                        h += data.verticalIndent - spanMinHeight - (vSpan - 1) * verticalSpacing;
+                        if (h > 0) {
+                            if (spanExpandCount is 0) {
+                                minHeights [i] += h;
+                            } else {
+                                int delta = h / spanExpandCount;
+                                int remainder = h % spanExpandCount, last = -1;
+                                for (int k = 0; k < vSpan; k++) {
+                                    if (expandRow [i-k]) {
+                                        minHeights [last=i-k] += delta;
+                                    }
+                                }
+                                if (last > -1) minHeights [last] += remainder;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (height !is SWT.DEFAULT && expandCount > 0) {
+        int totalHeight = 0;
+        for (int i=0; i<rowCount; i++) {
+            totalHeight += heights [i];
+        }
+        int c = expandCount;
+        int delta = (availableHeight - totalHeight) / c;
+        int remainder = (availableHeight - totalHeight) % c;
+        int last = -1;
+        while (totalHeight !is availableHeight) {
+            for (int i=0; i<rowCount; i++) {
+                if (expandRow [i]) {
+                    if (heights [i] + delta > minHeights [i]) {
+                        heights [last = i] = heights [i] + delta;
+                    } else {
+                        heights [i] = minHeights [i];
+                        expandRow [i] = false;
+                        c--;
+                    }
+                }
+            }
+            if (last > -1) heights [last] += remainder;
+
+            for (int i=0; i<rowCount; i++) {
+                for (int j=0; j<columnCount; j++) {
+                    GridData data = getData (grid, i, j, rowCount, columnCount, false);
+                    if (data !is null) {
+                        int vSpan = Math.max (1, Math.min (data.verticalSpan, rowCount));
+                        if (vSpan > 1) {
+                            if (!data.grabExcessVerticalSpace || data.minimumHeight !is 0) {
+                                int spanHeight = 0, spanExpandCount = 0;
+                                for (int k=0; k<vSpan; k++) {
+                                    spanHeight += heights [i-k];
+                                    if (expandRow [i-k]) spanExpandCount++;
+                                }
+                                int h = !data.grabExcessVerticalSpace || data.minimumHeight is SWT.DEFAULT ? data.cacheHeight : data.minimumHeight;
+                                h += data.verticalIndent - spanHeight - (vSpan - 1) * verticalSpacing;
+                                if (h > 0) {
+                                    if (spanExpandCount is 0) {
+                                        heights [i] += h;
+                                    } else {
+                                        int delta2 = h / spanExpandCount;
+                                        int remainder2 = h % spanExpandCount, last2 = -1;
+                                        for (int k = 0; k < vSpan; k++) {
+                                            if (expandRow [i-k]) {
+                                                heights [last2=i-k] += delta2;
+                                            }
+                                        }
+                                        if (last2 > -1) heights [last2] += remainder2;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (c is 0) break;
+            totalHeight = 0;
+            for (int i=0; i<rowCount; i++) {
+                totalHeight += heights [i];
+            }
+            delta = (availableHeight - totalHeight) / c;
+            remainder = (availableHeight - totalHeight) % c;
+            last = -1;
+        }
+    }
+
+    /* Position the controls */
+    if (move) {
+        int gridY = y + marginTop + marginHeight;
+        for (int i=0; i<rowCount; i++) {
+            int gridX = x + marginLeft + marginWidth;
+            for (int j=0; j<columnCount; j++) {
+                GridData data = getData (grid, i, j, rowCount, columnCount, true);
+                if (data !is null) {
+                    int hSpan = Math.max (1, Math.min (data.horizontalSpan, columnCount));
+                    int vSpan = Math.max (1, data.verticalSpan);
+                    int cellWidth = 0, cellHeight = 0;
+                    for (int k=0; k<hSpan; k++) {
+                        cellWidth += widths [j+k];
+                    }
+                    for (int k=0; k<vSpan; k++) {
+                        cellHeight += heights [i+k];
+                    }
+                    cellWidth += horizontalSpacing * (hSpan - 1);
+                    int childX = gridX + data.horizontalIndent;
+                    int childWidth = Math.min (data.cacheWidth, cellWidth);
+                    switch (data.horizontalAlignment) {
+                        case SWT.CENTER:
+                        case GridData.CENTER:
+                            childX += Math.max (0, (cellWidth - data.horizontalIndent - childWidth) / 2);
+                            break;
+                        case SWT.RIGHT:
+                        case SWT.END:
+                        case GridData.END:
+                            childX += Math.max (0, cellWidth - data.horizontalIndent - childWidth);
+                            break;
+                        case SWT.FILL:
+                            childWidth = cellWidth - data.horizontalIndent;
+                            break;
+                        default:
+                    }
+                    cellHeight += verticalSpacing * (vSpan - 1);
+                    int childY = gridY + data.verticalIndent;
+                    int childHeight = Math.min (data.cacheHeight, cellHeight);
+                    switch (data.verticalAlignment) {
+                        case SWT.CENTER:
+                        case GridData.CENTER:
+                            childY += Math.max (0, (cellHeight - data.verticalIndent - childHeight) / 2);
+                            break;
+                        case SWT.BOTTOM:
+                        case SWT.END:
+                        case GridData.END:
+                            childY += Math.max (0, cellHeight - data.verticalIndent - childHeight);
+                            break;
+                        case SWT.FILL:
+                            childHeight = cellHeight - data.verticalIndent;
+                            break;
+                        default:
+                    }
+                    Control child = grid [i][j];
+                    if (child !is null) {
+                        child.setBounds (childX, childY, childWidth, childHeight);
+                    }
+                }
+                gridX += widths [j] + horizontalSpacing;
+            }
+            gridY += heights [i] + verticalSpacing;
+        }
+    }
+
+    // clean up cache
+    for (int i = 0; i < flushLength; i++) {
+        flush [i].cacheWidth = flush [i].cacheHeight = -1;
+    }
+
+    int totalDefaultWidth = 0;
+    int totalDefaultHeight = 0;
+    for (int i=0; i<columnCount; i++) {
+        totalDefaultWidth += widths [i];
+    }
+    for (int i=0; i<rowCount; i++) {
+        totalDefaultHeight += heights [i];
+    }
+    totalDefaultWidth += horizontalSpacing * (columnCount - 1) + marginLeft + marginWidth * 2 + marginRight;
+    totalDefaultHeight += verticalSpacing * (rowCount - 1) + marginTop + marginHeight * 2 + marginBottom;
+    return new Point (totalDefaultWidth, totalDefaultHeight);
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf('.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+override public String toString () {
+    String string = getName ()~" {";
+    if (numColumns !is 1) string ~= "numColumns="~to!(String)(numColumns)~" ";
+    if (makeColumnsEqualWidth) string ~= "makeColumnsEqualWidth="~to!(String)(makeColumnsEqualWidth)~" ";
+    if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+    if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+    if (marginLeft !is 0) string ~= "marginLeft="~to!(String)(marginLeft)~" ";
+    if (marginRight !is 0) string ~= "marginRight="~to!(String)(marginRight)~" ";
+    if (marginTop !is 0) string ~= "marginTop="~to!(String)(marginTop)~" ";
+    if (marginBottom !is 0) string ~= "marginBottom="~to!(String)(marginBottom)~" ";
+    if (horizontalSpacing !is 0) string ~= "horizontalSpacing="~to!(String)(horizontalSpacing)~" ";
+    if (verticalSpacing !is 0) string ~= "verticalSpacing="~to!(String)(verticalSpacing)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.RowData;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * Each control controlled by a <code>RowLayout</code> can have its initial
+ * width and height specified by setting a <code>RowData</code> object
+ * into the control.
+ * <p>
+ * The following code uses a <code>RowData</code> object to change the initial
+ * size of a <code>Button</code> in a <code>Shell</code>:
+ * <pre>
+ *      Display display = new Display();
+ *      Shell shell = new Shell(display);
+ *      shell.setLayout(new RowLayout());
+ *      Button button1 = new Button(shell, SWT.PUSH);
+ *      button1.setText("Button 1");
+ *      button1.setLayoutData(new RowData(50, 40));
+ * </pre>
+ * </p>
+ *
+ * @see RowLayout
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class RowData {
+    /**
+     * width specifies the desired width in pixels. This value
+     * is the wHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see org.eclipse.swt.widgets.Control#computeSize(int, int, bool)
+     */
+    public int width = SWT.DEFAULT;
+    /**
+     * height specifies the preferred height in pixels. This value
+     * is the hHint passed into Control.computeSize(int, int, bool)
+     * to determine the preferred size of the control.
+     *
+     * The default value is SWT.DEFAULT.
+     *
+     * @see org.eclipse.swt.widgets.Control#computeSize(int, int, bool)
+     */
+    public int height = SWT.DEFAULT;
+
+    /**
+     * exclude informs the layout to ignore this control when sizing
+     * and positioning controls.  If this value is <code>true</code>,
+     * the size and position of the control will not be managed by the
+     * layout.  If this value is <code>false</code>, the size and
+     * position of the control will be computed and assigned.
+     *
+     * The default value is <code>false</code>.
+     *
+     * @since 3.1
+     */
+    public bool exclude = false;
+
+/**
+ * Constructs a new instance of RowData using
+ * default values.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of RowData according to the parameters.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param width a minimum width for the control
+ * @param height a minimum height for the control
+ */
+public this (int width, int height) {
+    this.width = width;
+    this.height = height;
+}
+
+/**
+ * Constructs a new instance of RowData according to the parameter.
+ * A value of SWT.DEFAULT indicates that no minimum width or
+ * no minimum height is specified.
+ *
+ * @param point a point whose x coordinate specifies a minimum width for the control
+ * and y coordinate specifies a minimum height for the control
+ */
+public this (Point point) {
+    this (point.x, point.y);
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf('.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the RowData object
+ */
+override public String toString () {
+    String string = getName ()~" {";
+    if (width !is SWT.DEFAULT) string ~= "width="~to!(String)(width)~" ";
+    if (height !is SWT.DEFAULT) string ~= "height="~to!(String)(height)~" ";
+    if (exclude) string ~= "exclude="~to!(String)(exclude)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/RowLayout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,516 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.layout.RowLayout;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.layout.RowData;
+import tango.util.Convert;
+import Math = tango.math.Math;
+import java.lang.all;
+
+
+/**
+ * Instances of this class determine the size and position of the
+ * children of a <code>Composite</code> by placing them either in
+ * horizontal rows or vertical columns within the parent <code>Composite</code>.
+ * <p>
+ * <code>RowLayout</code> aligns all controls in one row if the
+ * <code>type</code> is set to horizontal, and one column if it is
+ * set to vertical. It has the ability to wrap, and provides configurable
+ * margins and spacing. <code>RowLayout</code> has a number of configuration
+ * fields. In addition, the height and width of each control in a
+ * <code>RowLayout</code> can be specified by setting a <code>RowData</code>
+ * object into the control using <code>setLayoutData ()</code>.
+ * </p>
+ * <p>
+ * The following example code creates a <code>RowLayout</code>, sets all
+ * of its fields to non-default values, and then sets it into a
+ * <code>Shell</code>.
+ * <pre>
+ *      RowLayout rowLayout = new RowLayout();
+ *      rowLayout.wrap = false;
+ *      rowLayout.pack = false;
+ *      rowLayout.justify = true;
+ *      rowLayout.type = SWT.VERTICAL;
+ *      rowLayout.marginLeft = 5;
+ *      rowLayout.marginTop = 5;
+ *      rowLayout.marginRight = 5;
+ *      rowLayout.marginBottom = 5;
+ *      rowLayout.spacing = 0;
+ *      shell.setLayout(rowLayout);
+ * </pre>
+ * If you are using the default field values, you only need one line of code:
+ * <pre>
+ *      shell.setLayout(new RowLayout());
+ * </pre>
+ * </p>
+ *
+ * @see RowData
+ * @see <a href="http://www.eclipse.org/swt/snippets/#rowlayout">RowLayout snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: LayoutExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class RowLayout : Layout {
+
+    /**
+     * type specifies whether the layout places controls in rows or
+     * columns.
+     *
+     * The default value is HORIZONTAL.
+     *
+     * Possible values are: <ul>
+     *    <li>HORIZONTAL: Position the controls horizontally from left to right</li>
+     *    <li>VERTICAL: Position the controls vertically from top to bottom</li>
+     * </ul>
+     *
+     * @since 2.0
+     */
+    public int type = SWT.HORIZONTAL;
+
+    /**
+     * marginWidth specifies the number of pixels of horizontal margin
+     * that will be placed along the left and right edges of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int marginWidth = 0;
+
+    /**
+     * marginHeight specifies the number of pixels of vertical margin
+     * that will be placed along the top and bottom edges of the layout.
+     *
+     * The default value is 0.
+     *
+     * @since 3.0
+     */
+    public int marginHeight = 0;
+
+    /**
+     * spacing specifies the number of pixels between the edge of one cell
+     * and the edge of its neighbouring cell.
+     *
+     * The default value is 3.
+     */
+    public int spacing = 3;
+
+    /**
+     * wrap specifies whether a control will be wrapped to the next
+     * row if there is insufficient space on the current row.
+     *
+     * The default value is true.
+     */
+    public bool wrap = true;
+
+    /**
+     * pack specifies whether all controls in the layout take
+     * their preferred size.  If pack is false, all controls will
+     * have the same size which is the size required to accommodate the
+     * largest preferred height and the largest preferred width of all
+     * the controls in the layout.
+     *
+     * The default value is true.
+     */
+    public bool pack = true;
+
+    /**
+     * fill specifies whether the controls in a row should be
+     * all the same height for horizontal layouts, or the same
+     * width for vertical layouts.
+     *
+     * The default value is false.
+     *
+     * @since 3.0
+     */
+    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.
+     *
+     * The default value is false.
+     */
+    public bool justify = false;
+
+    /**
+     * marginLeft specifies the number of pixels of horizontal margin
+     * that will be placed along the left edge of the layout.
+     *
+     * The default value is 3.
+     */
+    public int marginLeft = 3;
+
+    /**
+     * marginTop specifies the number of pixels of vertical margin
+     * that will be placed along the top edge of the layout.
+     *
+     * The default value is 3.
+     */
+    public int marginTop = 3;
+
+    /**
+     * marginRight specifies the number of pixels of horizontal margin
+     * that will be placed along the right edge of the layout.
+     *
+     * The default value is 3.
+     */
+    public int marginRight = 3;
+
+    /**
+     * marginBottom specifies the number of pixels of vertical margin
+     * that will be placed along the bottom edge of the layout.
+     *
+     * The default value is 3.
+     */
+    public int marginBottom = 3;
+
+/**
+ * Constructs a new instance of this class.
+ */
+public this () {
+}
+
+/**
+ * Constructs a new instance of this class given the type.
+ *
+ * @param type the type of row layout
+ *
+ * @since 2.0
+ */
+public this (int type) {
+    this.type = type;
+}
+
+override protected Point computeSize (Composite composite, int wHint, int hHint, bool flushCache_) {
+    Point extent;
+    if (type is SWT.HORIZONTAL) {
+        extent = layoutHorizontal (composite, false, (wHint !is SWT.DEFAULT) && wrap, wHint, flushCache_);
+    } else {
+        extent = layoutVertical (composite, false, (hHint !is SWT.DEFAULT) && wrap, hHint, flushCache_);
+    }
+    if (wHint !is SWT.DEFAULT) extent.x = wHint;
+    if (hHint !is SWT.DEFAULT) extent.y = hHint;
+    return extent;
+}
+
+Point computeSize (Control control, bool flushCache_) {
+    int wHint = SWT.DEFAULT, hHint = SWT.DEFAULT;
+    RowData data = cast(RowData) control.getLayoutData ();
+    if (data !is null) {
+        wHint = data.width;
+        hHint = data.height;
+    }
+    return control.computeSize (wHint, hHint, flushCache_);
+}
+
+override protected bool flushCache (Control control) {
+    return true;
+}
+
+String getName () {
+    String string = this.classinfo.name;
+    int index = string.lastIndexOf('.');
+    if (index is -1 ) return string;
+    return string[ index + 1 .. string.length ];
+}
+
+override protected void layout (Composite composite, bool flushCache_) {
+    Rectangle clientArea = composite.getClientArea ();
+    if (type is SWT.HORIZONTAL) {
+        layoutHorizontal (composite, true, wrap, clientArea.width, flushCache_);
+    } else {
+        layoutVertical (composite, true, wrap, clientArea.height, flushCache_);
+    }
+}
+
+Point layoutHorizontal (Composite composite, bool move, bool wrap, int width, bool flushCache_) {
+    Control [] children = composite.getChildren ();
+    int count = 0;
+    for (int i=0; i<children.length; i++) {
+        Control control = children [i];
+        RowData data = cast(RowData) control.getLayoutData ();
+        if (data is null || !data.exclude) {
+            children [count++] = children [i];
+        }
+    }
+    if (count is 0) {
+        return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+    }
+    int childWidth = 0, childHeight = 0, maxHeight = 0;
+    if (!pack) {
+        for (int i=0; i<count; i++) {
+            Control child = children [i];
+            Point size = computeSize (child, flushCache_);
+            childWidth = Math.max (childWidth, size.x);
+            childHeight = Math.max (childHeight, size.y);
+        }
+        maxHeight = childHeight;
+    }
+    int clientX = 0, clientY = 0;
+    if (move) {
+        Rectangle rect = composite.getClientArea ();
+        clientX = rect.x;
+        clientY = rect.y;
+    }
+    int [] wraps = null;
+    bool wrapped = false;
+    Rectangle [] bounds = null;
+    if (move && (justify || fill || center)) {
+        bounds = new Rectangle [count];
+        wraps = new int [count];
+    }
+    int maxX = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
+    for (int i=0; i<count; i++) {
+        Control child = children [i];
+        if (pack) {
+            Point size = computeSize (child, flushCache_);
+            childWidth = size.x;
+            childHeight = size.y;
+        }
+        if (wrap && (i !is 0) && (x + childWidth > width)) {
+            wrapped = true;
+            if (move && (justify || fill || center)) wraps [i - 1] = maxHeight;
+            x = marginLeft + marginWidth;
+            y += spacing + maxHeight;
+            if (pack) maxHeight = 0;
+        }
+        if (pack || fill || center) {
+            maxHeight = Math.max (maxHeight, childHeight);
+        }
+        if (move) {
+            int childX = x + clientX, childY = y + clientY;
+            if (justify || fill || center) {
+                bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
+            } else {
+                child.setBounds (childX, childY, childWidth, childHeight);
+            }
+        }
+        x += spacing + childWidth;
+        maxX = Math.max (maxX, x);
+    }
+    maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing);
+    if (!wrapped) maxX += marginRight + marginWidth;
+    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 || center) {
+                int last = 0;
+                if (count > 0) wraps [count - 1] = maxHeight;
+                for (int i=0; i<count; i++) {
+                    if (wraps [i] !is 0) {
+                        int wrapCount = i - last + 1;
+                        if (justify) {
+                            int wrapX = 0;
+                            for (int j=last; j<=i; j++) {
+                                wrapX += bounds [j].width + spacing;
+                            }
+                            space = Math.max (0, (width - wrapX) / (wrapCount + 1));
+                            margin = Math.max (0, ((width - wrapX) % (wrapCount + 1)) / 2);
+                        }
+                        for (int j=last; j<=i; j++) {
+                            if (justify) bounds [j].x += (space * (j - last + 1)) + margin;
+                            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;
+                    }
+                }
+            }
+        }
+        for (int i=0; i<count; i++) {
+            if (!wrapped) {
+                if (justify) bounds [i].x += (space * (i + 1)) + margin;
+                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]);
+        }
+    }
+    return new Point (maxX, y + maxHeight + marginBottom + marginHeight);
+}
+
+Point layoutVertical (Composite composite, bool move, bool wrap, int height, bool flushCache_) {
+    Control [] children = composite.getChildren ();
+    int count = 0;
+    for (int i=0; i<children.length; i++) {
+        Control control = children [i];
+        RowData data = cast(RowData) control.getLayoutData ();
+        if (data is null || !data.exclude) {
+            children [count++] = children [i];
+        }
+    }
+    if (count is 0) {
+        return new Point (marginLeft + marginWidth * 2 + marginRight, marginTop + marginHeight * 2 + marginBottom);
+    }
+    int childWidth = 0, childHeight = 0, maxWidth = 0;
+    if (!pack) {
+        for (int i=0; i<count; i++) {
+            Control child = children [i];
+            Point size = computeSize (child, flushCache_);
+            childWidth = Math.max (childWidth, size.x);
+            childHeight = Math.max (childHeight, size.y);
+        }
+        maxWidth = childWidth;
+    }
+    int clientX = 0, clientY = 0;
+    if (move) {
+        Rectangle rect = composite.getClientArea ();
+        clientX = rect.x;
+        clientY = rect.y;
+    }
+    int [] wraps = null;
+    bool wrapped = false;
+    Rectangle [] bounds = null;
+    if (move && (justify || fill || center)) {
+        bounds = new Rectangle [count];
+        wraps = new int [count];
+    }
+    int maxY = 0, x = marginLeft + marginWidth, y = marginTop + marginHeight;
+    for (int i=0; i<count; i++) {
+        Control child = children [i];
+        if (pack) {
+            Point size = computeSize (child, flushCache_);
+            childWidth = size.x;
+            childHeight = size.y;
+        }
+        if (wrap && (i !is 0) && (y + childHeight > height)) {
+            wrapped = true;
+            if (move && (justify || fill || center)) wraps [i - 1] = maxWidth;
+            x += spacing + maxWidth;
+            y = marginTop + marginHeight;
+            if (pack) maxWidth = 0;
+        }
+        if (pack || fill || center) {
+            maxWidth = Math.max (maxWidth, childWidth);
+        }
+        if (move) {
+            int childX = x + clientX, childY = y + clientY;
+            if (justify || fill || center) {
+                bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
+            } else {
+                child.setBounds (childX, childY, childWidth, childHeight);
+            }
+        }
+        y += spacing + childHeight;
+        maxY = Math.max (maxY, y);
+    }
+    maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing);
+    if (!wrapped) maxY += marginBottom + marginHeight;
+    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 || center) {
+                int last = 0;
+                if (count > 0) wraps [count - 1] = maxWidth;
+                for (int i=0; i<count; i++) {
+                    if (wraps [i] !is 0) {
+                        int wrapCount = i - last + 1;
+                        if (justify) {
+                            int wrapY = 0;
+                            for (int j=last; j<=i; j++) {
+                                wrapY += bounds [j].height + spacing;
+                            }
+                            space = Math.max (0, (height - wrapY) / (wrapCount + 1));
+                            margin = Math.max (0, ((height - wrapY) % (wrapCount + 1)) / 2);
+                        }
+                        for (int j=last; j<=i; j++) {
+                            if (justify) bounds [j].y += (space * (j - last + 1)) + margin;
+                            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;
+                    }
+                }
+            }
+        }
+        for (int i=0; i<count; i++) {
+            if (!wrapped) {
+                if (justify) bounds [i].y += (space * (i + 1)) + margin;
+                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]);
+        }
+    }
+    return new Point (x + maxWidth + marginRight + marginWidth, maxY);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the layout
+ */
+override public String toString () {
+    String string = getName ()~" {";
+    string ~= "type="~((type !is SWT.HORIZONTAL) ? "SWT.VERTICAL" : "SWT.HORIZONTAL")~" ";
+    if (marginWidth !is 0) string ~= "marginWidth="~to!(String)(marginWidth)~" ";
+    if (marginHeight !is 0) string ~= "marginHeight="~to!(String)(marginHeight)~" ";
+    if (marginLeft !is 0) string ~= "marginLeft="~to!(String)(marginLeft)~" ";
+    if (marginTop !is 0) string ~= "marginTop="~to!(String)(marginTop)~" ";
+    if (marginRight !is 0) string ~= "marginRight="~to!(String)(marginRight)~" ";
+    if (marginBottom !is 0) string ~= "marginBottom="~to!(String)(marginBottom)~" ";
+    if (spacing !is 0) string ~= "spacing="~to!(String)(spacing)~" ";
+    string ~= "wrap="~to!(String)(wrap)~" ";
+    string ~= "pack="~to!(String)(pack)~" ";
+    string ~= "fill="~to!(String)(fill)~" ";
+    string ~= "justify="~to!(String)(justify)~" ";
+    string = string.trim();
+    string ~= "}";
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/layout/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,13 @@
+module org.eclipse.swt.layout.all;
+
+public import org.eclipse.swt.layout.FillData;
+public import org.eclipse.swt.layout.FillLayout;
+public import org.eclipse.swt.layout.FormAttachment;
+public import org.eclipse.swt.layout.FormData;
+public import org.eclipse.swt.layout.FormLayout;
+public import org.eclipse.swt.layout.GridData;
+public import org.eclipse.swt.layout.GridLayout;
+public import org.eclipse.swt.layout.RowData;
+public import org.eclipse.swt.layout.RowLayout;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,18 @@
+module org.eclipse.swt.ole.all;
+
+public import org.eclipse.swt.ole.win32.OLE;
+public import org.eclipse.swt.ole.win32.OleAutomation;
+public import org.eclipse.swt.ole.win32.OleClientSite;
+public import org.eclipse.swt.ole.win32.OleControlSite;
+public import org.eclipse.swt.ole.win32.OleEvent;
+public import org.eclipse.swt.ole.win32.OleEventSink;
+public import org.eclipse.swt.ole.win32.OleEventTable;
+public import org.eclipse.swt.ole.win32.OleFrame;
+public import org.eclipse.swt.ole.win32.OleFunctionDescription;
+public import org.eclipse.swt.ole.win32.OleListener;
+public import org.eclipse.swt.ole.win32.OleParameterDescription;
+public import org.eclipse.swt.ole.win32.OlePropertyChangeSink;
+public import org.eclipse.swt.ole.win32.OlePropertyDescription;
+public import org.eclipse.swt.ole.win32.Variant;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OLE.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OLE;
+
+import java.io.File;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+import tango.util.Convert;
+/**
+ *
+ * OLE contains all the constants used to create an ActiveX Control or an OLE Document.
+ *
+ * <p>Definitions for these constants can be found in MSDN.
+ *
+ */
+public class OLE : SWT {
+
+    public static const int S_FALSE = 1; // Used for functions that semantically return a bool FALSE result to indicate that the function succeeded.
+    public static const int S_OK    = 0; // Function succeeded.
+    public static const int E_FAIL = -2147467259;  // Unspecified failure.
+    public static const int E_INVALIDARG = -2147024809; // Invalid argument
+    public static const int E_NOINTERFACE = -2147467262;  // QueryInterface did not recognize the requested interface.
+    public static const int E_NOTIMPL = -2147467263; // Not implemented
+
+    public static const String IID_IUNKNOWN = "{00000000-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+    public static const String IID_IDISPATCH = "{00020400-0000-0000-C000-000000000046}"; //$NON-NLS-1$
+
+    // Verbs that can be invoked on this client
+    public static const int OLEIVERB_DISCARDUNDOSTATE = -6; // close the OLE object and discard the undo state
+    public static const int OLEIVERB_HIDE             = -3; // hide the OLE object
+    public static const int OLEIVERB_INPLACEACTIVATE  = -5; // open the OLE for editing in-place
+    public static const int OLEIVERB_OPEN             = -2; // open the OLE object for editing in a separate window
+    public static const int OLEIVERB_PRIMARY          =  0; // opens the OLE object for editing
+    public static const int OLEIVERB_PROPERTIES       = -7; // request the OLE object properties dialog
+    public static const int OLEIVERB_SHOW             = -1; // show the OLE object
+    public static const int OLEIVERB_UIACTIVATE       = -4; // activate the UI for the OLE object
+
+    public static const int PROPERTY_CHANGING = 0;
+    public static const int PROPERTY_CHANGED = 1;
+
+    /**
+     * Error code for OleError - No specific error information available
+     */
+    public static const int HRESULT_UNSPECIFIED       = 0;
+    /**
+     * Error code for OleError - Failed to create file
+     */
+    public static const int ERROR_CANNOT_CREATE_FILE = 1000;
+    /**
+     * Error code for OleError - Failed to create Ole Client
+     */
+    public static const int ERROR_CANNOT_CREATE_OBJECT = 1001;
+    /**
+     * Error code for OleError - File does not exist, is not accessible to user or does not have the correct format
+     */
+    public static const int ERROR_CANNOT_OPEN_FILE = 1002;
+    /**
+     * Error code for OleError - Failed to find requested interface on OLE Object
+     */
+    public static const int ERROR_INTERFACE_NOT_FOUND = 1003;
+    /**
+     * Error code for OleError - Class ID not found in registry
+     */
+    public static const int ERROR_INVALID_CLASSID = 1004;
+    /**
+     * Error code for OleError - Failed to get the class factory for the specified classID
+     */
+    public static const int ERROR_CANNOT_ACCESS_CLASSFACTORY = 1005;
+    /**
+     * Error code for OleError - Failed to create Licensed instance
+     */
+    public static const int ERROR_CANNOT_CREATE_LICENSED_OBJECT = 1006;
+    /**
+     * Error code for OleError - Out of Memory
+     */
+    public static const int ERROR_OUT_OF_MEMORY = 1007;
+    /**
+     * Error code for OleError - Failed to change Variant type
+     */
+    public static const int ERROR_CANNOT_CHANGE_VARIANT_TYPE = 1010;
+    /**
+     * Error code for OleError - Invalid address received for Ole Interface
+     */
+    public static const int ERROR_INVALID_INTERFACE_ADDRESS = 1011;
+    /**
+     * Error code for OleError - Unable to find Application
+     */
+    public static const int ERROR_APPLICATION_NOT_FOUND = 1013;
+    /**
+     * Error code for OleError - Action can not be performed
+     */
+    public static const int ERROR_ACTION_NOT_PERFORMED = 1014;
+
+    public static const int OLECMDF_SUPPORTED    = 1;
+    public static const int OLECMDF_ENABLED      = 2;
+    public static const int OLECMDF_LATCHED      = 4;
+    public static const int OLECMDF_NINCHED      = 8;
+
+    public static const int OLECMDTEXTF_NONE      = 0;
+    public static const int OLECMDTEXTF_NAME      = 1;
+    public static const int OLECMDTEXTF_STATUS    = 2;
+
+    public static const int OLECMDEXECOPT_DODEFAULT        = 0;
+    public static const int OLECMDEXECOPT_PROMPTUSER       = 1;
+    public static const int OLECMDEXECOPT_DONTPROMPTUSER   = 2;
+    public static const int OLECMDEXECOPT_SHOWHELP         = 3;
+
+    public static const int OLECMDID_OPEN              = 1;
+    public static const int OLECMDID_NEW               = 2;
+    public static const int OLECMDID_SAVE              = 3;
+    public static const int OLECMDID_SAVEAS            = 4;
+    public static const int OLECMDID_SAVECOPYAS        = 5;
+    public static const int OLECMDID_PRINT             = 6;
+    public static const int OLECMDID_PRINTPREVIEW      = 7;
+    public static const int OLECMDID_PAGESETUP         = 8;
+    public static const int OLECMDID_SPELL             = 9;
+    public static const int OLECMDID_PROPERTIES        = 10;
+    public static const int OLECMDID_CUT               = 11;
+    public static const int OLECMDID_COPY              = 12;
+    public static const int OLECMDID_PASTE             = 13;
+    public static const int OLECMDID_PASTESPECIAL      = 14;
+    public static const int OLECMDID_UNDO              = 15;
+    public static const int OLECMDID_REDO              = 16;
+    public static const int OLECMDID_SELECTALL         = 17;
+    public static const int OLECMDID_CLEARSELECTION    = 18;
+    public static const int OLECMDID_ZOOM              = 19;
+    public static const int OLECMDID_GETZOOMRANGE      = 20;
+    public static const int OLECMDID_UPDATECOMMANDS    = 21;
+    public static const int OLECMDID_REFRESH           = 22;
+    public static const int OLECMDID_STOP              = 23;
+    public static const int OLECMDID_HIDETOOLBARS      = 24;
+    public static const int OLECMDID_SETPROGRESSMAX    = 25;
+    public static const int OLECMDID_SETPROGRESSPOS    = 26;
+    public static const int OLECMDID_SETPROGRESSTEXT   = 27;
+    public static const int OLECMDID_SETTITLE          = 28;
+    public static const int OLECMDID_SETDOWNLOADSTATE  = 29;
+    public static const int OLECMDID_STOPDOWNLOAD      = 30;
+
+    /* Ole Property Description flags */
+    public static int VARFLAG_FREADONLY = 0x1;
+    public static int VARFLAG_FSOURCE = 0x2;
+    public static int VARFLAG_FBINDABLE = 0x4;
+    public static int VARFLAG_FREQUESTEDIT = 0x8;
+    public static int VARFLAG_FDISPLAYBIND = 0x10;
+    public static int VARFLAG_FDEFAULTBIND = 0x20;
+    public static int VARFLAG_FHIDDEN = 0x40;
+    public static int VARFLAG_FRESTRICTED = 0x80;
+    public static int VARFLAG_FDEFAULTCOLLELEM = 0x100;
+    public static int VARFLAG_FUIDEFAULT = 0x200;
+    public static int VARFLAG_FNONBROWSABLE = 0x400;
+    public static int VARFLAG_FREPLACEABLE = 0x800;
+    public static int VARFLAG_FIMMEDIATEBIND = 0x1000;
+
+    /* Ole Property Description kind */
+    public static int VAR_PERINSTANCE = 0;
+    public static int VAR_STATIC = 1;
+    public static int VAR_CONST = 2;
+    public static int VAR_DISPATCH = 3;
+
+    /* Ole Parameter Description flags */
+    public static short IDLFLAG_NONE = 0;
+    public static short IDLFLAG_FIN = 1;
+    public static short IDLFLAG_FOUT = 2;
+    public static short IDLFLAG_FLCID = 4;
+    public static short IDLFLAG_FRETVAL = 8;
+
+    /* Ole Description types */
+    public static const short VT_BOOL = 11;     // bool; True=-1, False=0.
+    public static const short VT_BSTR = 8;      // Binary String.
+    public static const short VT_BYREF = 16384; // By reference - must be combined with one of the other VT values
+    public static const short VT_CY = 6;        // Currency.
+    public static const short VT_DATE = 7;      // Date.
+    public static const short VT_DISPATCH = 9;  // IDispatch
+    public static const short VT_EMPTY = 0;     // Not specified.
+    public static const short VT_ERROR = 10;    // Scodes.
+    public static const short VT_I2 = 2;        // 2-byte signed int.
+    public static const short VT_I4 = 3;        // 4-byte signed int.
+    public static const short VT_NULL = 1;      // Null.
+    public static const short VT_R4 = 4;        // 4-byte real.
+    public static const short VT_R8 = 5;        // 8-byte real.
+    public static const short VT_UI1 = 17;      // Unsigned char.
+    public static const short VT_UI4 = 19;      // Unsigned int.
+    public static const short VT_UNKNOWN = 13;  // IUnknown FAR*.
+    public static const short VT_VARIANT = 12;  // VARIANT FAR*.
+    public static const short VT_PTR = 26;
+    public static const short VT_USERDEFINED = 29;
+    public static const short VT_HRESULT = 25;
+    public static const short VT_DECIMAL = 14;
+    public static const short VT_I1 = 16;
+    public static const short VT_UI2 = 18;
+    public static const short VT_I8 = 20;
+    public static const short VT_UI8 = 21;
+    public static const short VT_INT = 22;
+    public static const short VT_UINT = 23;
+    public static const short VT_VOID = 24;
+    public static const short VT_SAFEARRAY = 27;
+    public static const short VT_CARRAY = 28;
+    public static const short VT_LPSTR = 30;
+    public static const short VT_LPWSTR = 31;
+    public static const short VT_RECORD = 36;
+    public static const short VT_FILETIME = 64;
+    public static const short VT_BLOB = 65;
+    public static const short VT_STREAM = 66;
+    public static const short VT_STORAGE = 67;
+    public static const short VT_STREAMED_OBJECT = 68;
+    public static const short VT_STORED_OBJECT = 69;
+    public static const short VT_BLOB_OBJECT = 70;
+    public static const short VT_CF = 71;
+    public static const short VT_CLSID = 72;
+    public static const short VT_VERSIONED_STREAM = 73;
+    public static const short VT_BSTR_BLOB = 0xfff;
+    public static const short VT_VECTOR = 0x1000;
+    public static const short VT_ARRAY = 0x2000;
+
+    /* Ole Function Description Invoke Kind values */
+    public static const int INVOKE_FUNC = 1;
+    public static const int INVOKE_PROPERTYGET = 2;
+    public static const int INVOKE_PROPERTYPUT = 4;
+    public static const int INVOKE_PROPERTYPUTREF = 8;
+
+    /* Ole Function Description function kind */
+    public static const int FUNC_VIRTUAL = 0;
+    public static const int FUNC_PUREVIRTUAL = 1;
+    public static const int FUNC_NONVIRTUAL = 2;
+    public static const int FUNC_STATIC = 3;
+    public static const int FUNC_DISPATCH = 4;
+
+    /* Ole Function Description function flags */
+    public static const short FUNCFLAG_FRESTRICTED = 1;
+    public static const short FUNCFLAG_FSOURCE = 0x2;
+    public static const short FUNCFLAG_FBINDABLE = 0x4;
+    public static const short FUNCFLAG_FREQUESTEDIT = 0x8;
+    public static const short FUNCFLAG_FDISPLAYBIND = 0x10;
+    public static const short FUNCFLAG_FDEFAULTBIND = 0x20;
+    public static const short FUNCFLAG_FHIDDEN = 0x40;
+    public static const short FUNCFLAG_FUSESGETLASTERROR = 0x80;
+    public static const short FUNCFLAG_FDEFAULTCOLLELEM = 0x100;
+    public static const short FUNCFLAG_FUIDEFAULT = 0x200;
+    public static const short FUNCFLAG_FNONBROWSABLE = 0x400;
+    public static const short FUNCFLAG_FREPLACEABLE = 0x800;
+    public static const short FUNCFLAG_FIMMEDIATEBIND = 0x1000;
+
+    /* Ole Function Description calling convention */
+    public static const int CC_FASTCALL = 0;
+    public static const int CC_CDECL = 1;
+    public static const int CC_MSCPASCAL = 2;
+    public static const int CC_PASCAL = 2;
+    public static const int CC_MACPASCAL = 3;
+    public static const int CC_STDCALL = 4;
+    public static const int CC_FPFASTCALL = 5;
+    public static const int CC_SYSCALL = 6;
+    public static const int CC_MPWCDECL = 7;
+    public static const int CC_MPWPASCAL = 8;
+    public static const int CC_MAX = 9;
+
+    static const String ERROR_NOT_IMPLEMENTED_MSG = "Required functionality not currently supported.";//$NON-NLS-1$
+    static const String ERROR_CANNOT_CREATE_FILE_MSG = "Failed to create file.";//$NON-NLS-1$
+    static const String ERROR_CANNOT_CREATE_OBJECT_MSG = "Failed to create Ole Client.";//$NON-NLS-1$
+    static const String ERROR_CANNOT_OPEN_FILE_MSG = "File does not exist, is not accessible to user or does not have the correct format.";//$NON-NLS-1$
+    static const String ERROR_INTERFACE_NOT_FOUND_MSG = "Failed to find requested interface on OLE Object.";//$NON-NLS-1$
+    static const String ERROR_INVALID_CLASSID_MSG = "Class ID not found in registry";//$NON-NLS-1$
+    static const String ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG = "Failed to get the class factory for the specified classID";//$NON-NLS-1$
+    static const String ERROR_CANNOT_CREATE_LICENSED_OBJECT_MSG = "Failed to create Licensed instance";//$NON-NLS-1$
+    static const String ERROR_OUT_OF_MEMORY_MSG = "Out of Memory";//$NON-NLS-1$
+    static const String ERROR_CANNOT_CHANGE_VARIANT_TYPE_MSG = "Failed to change Variant type";//$NON-NLS-1$
+    static const String ERROR_INVALID_INTERFACE_ADDRESS_MSG = "Invalid address received for Ole Interface.";//$NON-NLS-1$
+    static const String ERROR_APPLICATION_NOT_FOUND_MSG = "Unable to find Application.";//$NON-NLS-1$
+    static const String ERROR_ACTION_NOT_PERFORMED_MSG = "Action can not be performed.";//$NON-NLS-1$
+
+
+public static void error (String file, long line, int code) {
+    error (code, 0);
+}
+public static void error (int code) {
+    error (code, 0);
+}
+public static void error (String file, long line, int code, int hresult) {
+    error (code, hresult);
+}
+public static void error (int code, int hresult) {
+
+    switch (code) {
+        /* Illegal Arguments (non-fatal) */
+        case ERROR_INVALID_INTERFACE_ADDRESS :{
+            throw new IllegalArgumentException (ERROR_INVALID_INTERFACE_ADDRESS_MSG);
+        }
+
+        /* SWT Errors (non-fatal) */
+        case ERROR_CANNOT_CREATE_FILE : {
+            String msg = ERROR_CANNOT_CREATE_FILE_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_CANNOT_CREATE_OBJECT : {
+            String msg = ERROR_CANNOT_CREATE_OBJECT_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);//$NON-NLS-1$
+        }
+        case ERROR_CANNOT_OPEN_FILE : {
+            String msg = ERROR_CANNOT_OPEN_FILE_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_INTERFACE_NOT_FOUND : {
+            String msg = ERROR_INTERFACE_NOT_FOUND_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_INVALID_CLASSID : {
+            String msg = ERROR_INVALID_CLASSID_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_CANNOT_ACCESS_CLASSFACTORY : {
+            String msg = ERROR_CANNOT_ACCESS_CLASSFACTORY_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_CANNOT_CREATE_LICENSED_OBJECT : {
+            String msg = ERROR_CANNOT_CREATE_LICENSED_OBJECT_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_CANNOT_CHANGE_VARIANT_TYPE : {
+            String msg = ERROR_CANNOT_CHANGE_VARIANT_TYPE_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_APPLICATION_NOT_FOUND : {
+            String msg = ERROR_APPLICATION_NOT_FOUND_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+        case ERROR_ACTION_NOT_PERFORMED : {
+            String msg = ERROR_ACTION_NOT_PERFORMED_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult);//$NON-NLS-1$
+            throw new SWTException (code, msg);
+        }
+
+        /* OS Failure/Limit (fatal, may occur only on some platforms) */
+        case ERROR_OUT_OF_MEMORY : {
+            String msg = ERROR_ACTION_NOT_PERFORMED_MSG;
+            if (hresult !is 0) msg ~= " result = "~to!(String)(hresult); //$NON-NLS-1$
+            throw new SWTError (code, msg);
+        }
+        default:
+    }
+
+    /* Unknown/Undefined Error */
+    SWT.error(code);
+}
+
+/*
+ * Finds the OLE program id that is associated with an extension.
+ * The extension may or may not begin with a '.'.  On platforms
+ * that do not support OLE, an empty string is returned.
+ *
+ * @param extension the program extension
+ * @return a string that is the OLE program id or an empty string
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when extension is null</li>
+ *  </ul>
+ */
+public static String findProgramID (String extension) {
+    if (extension is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (extension.length is 0) return ""; //$NON-NLS-1$
+
+    if (extension.charAt (0) !is '.') extension = "." ~ extension; //$NON-NLS-1$
+
+    /* Use the character encoding for the default locale */
+    TCHAR[] extensionKey = StrToTCHARs(0, extension, true);
+    String result = getKeyValue(extensionKey);
+    if (result !is null) {
+        // look for "<programID>\NotInsertable"
+        TCHAR[] notInsertableKey = StrToTCHARs(0, result~"\\NotInsertable", true); //$NON-NLS-1$
+        if (getKeyExists(notInsertableKey)) return ""; //$NON-NLS-1$
+        // look for "<programID>\Insertable"
+        TCHAR[] insertableKey = StrToTCHARs(0, result~"\\Insertable", true); //$NON-NLS-1$
+        if (getKeyExists(insertableKey)) return result;
+        // look for "<programID>\protocol\StdFileEditing\server"
+        TCHAR[] serverKey = StrToTCHARs(0, result~"\\protocol\\StdFileEditing\\server", true); //$NON-NLS-1$
+        if (getKeyExists(serverKey)) return result;
+    }
+
+    return ""; //$NON-NLS-1$
+}
+static String getKeyValue (TCHAR[] key) {
+    void* [1] phkResult;
+    if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+        return null;
+    }
+    String result = null;
+    uint [1] lpcbData;
+    if (OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr) is 0) {
+        int length_ = lpcbData [0] / TCHAR.sizeof;
+        if (length_ is 0) {
+            result = "";
+        } else {
+            /* Use the character encoding for the default locale */
+            TCHAR[] lpData = NewTCHARs (0, length_);
+            if (OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr) is 0) {
+                length_ = Math.max(0, lpData.length - 1);
+                result = TCHARsToStr( lpData[ 0 .. length_ ] );
+            }
+        }
+    }
+    if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+    return result;
+}
+private static bool getKeyExists (TCHAR[] key) {
+    void* [1] phkResult;
+    if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+        return false;
+    }
+    if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+    return true;
+}
+/**
+ * Returns true if the specified file has an OLE Storage format.
+ *
+ * Note all empty files (regardless of extension) will return false.
+ *
+ * @param file the file to be checked
+ *
+ * @return true if this file has an OLE Storage format
+ */
+public static bool isOleFile(File file) {
+    if (file is null || !file.exists() || file.isDirectory())
+        return false;
+
+    return (COM.StgIsStorageFile( StrToTCHARz(file.getAbsolutePath()~"\0")) is COM.S_OK);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleAutomation.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,704 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleAutomation;
+
+
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+// import org.eclipse.swt.internal.ole.win32.DISPPARAMS;
+// import org.eclipse.swt.internal.ole.win32.EXCEPINFO;
+// import org.eclipse.swt.internal.ole.win32.FUNCDESC;
+// import org.eclipse.swt.internal.ole.win32.GUID;
+// import org.eclipse.swt.internal.ole.win32.IDispatch;
+// import org.eclipse.swt.internal.ole.win32.ITypeInfo;
+// import org.eclipse.swt.internal.ole.win32.TYPEATTR;
+// import org.eclipse.swt.internal.ole.win32.VARDESC;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OlePropertyDescription;
+import org.eclipse.swt.ole.win32.OleFunctionDescription;
+import org.eclipse.swt.ole.win32.OleParameterDescription;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+
+/**
+ * OleAutomation provides a generic mechanism for accessing functionality that is
+ * specific to a particular ActiveX Control or OLE Document.
+ *
+ * <p>The OLE Document or ActiveX Control must support the IDispatch interface in order to provide
+ * OleAutomation support. The additional functionality provided by the OLE Object is specified in
+ * its IDL file.  The additional methods can either be to get property values (<code>getProperty</code>),
+ * to set property values (<code>setProperty</code>) or to invoke a method (<code>invoke</code> or
+ * <code>invokeNoReply</code>).  Arguments are passed around in the form of <code>Variant</code>
+ * objects.
+ *
+ * <p>Here is a sample IDL fragment:
+ *
+ * <pre>
+ *  interface IMyControl : IDispatch
+ *  {
+ *      [propget, id(0)] HRESULT maxFileCount([retval, out] int *c);
+ *      [propput, id(0)] HRESULT maxFileCount([in] int c);
+ *      [id(1)] HRESULT AddFile([in] BSTR fileName);
+ *  };
+ * </pre>
+ *
+ * <p>An example of how to interact with this extended functionality is shown below:
+ *
+ * <code><pre>
+ *  OleAutomation automation = new OleAutomation(myControlSite);
+ *
+ *  // Look up the ID of the maxFileCount parameter
+ *  int[] rgdispid = automation.getIDsOfNames(new String[]{"maxFileCount"});
+ *  int maxFileCountID = rgdispid[0];
+ *
+ *  // Set the property maxFileCount to 100:
+ *  if (automation.setProperty(maxFileCountID, new Variant(100))) {
+ *      System.out.println("Max File Count was successfully set.");
+ *  }
+ *
+ *  // Get the new value of the maxFileCount parameter:
+ *  Variant pVarResult = automation.getProperty(maxFileCountID);
+ *  if (pVarResult !is null) {
+ *      System.out.println("Max File Count is "+pVarResult.getInt());
+ *  }
+ *
+ *  // Invoke the AddFile method
+ *  // Look up the IDs of the AddFile method and its parameter
+ *  rgdispid = automation.getIDsOfNames(new String[]{"AddFile", "fileName"});
+ *  int dispIdMember = rgdispid[0];
+ *  int[] rgdispidNamedArgs = new int[] {rgdispid[1]};
+ *
+ *  // Convert arguments to Variant objects
+ *  Variant[] rgvarg = new Variant[1];
+ *  String fileName = "C:\\testfile";
+ *  rgvarg[0] = new Variant(fileName);
+ *
+ *  // Call the method
+ *  Variant pVarResult = automation.invoke(dispIdMember, rgvarg, rgdispidNamedArgs);
+ *
+ *  // Check the return value
+ *  if (pVarResult is null || pVarResult.getInt() !is OLE.S_OK){
+ *      System.out.println("Failed to add file "+fileName);
+ *  }
+ *
+ *  automation.dispose();
+ *
+ * </pre></code>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
+ */
+public final class OleAutomation {
+    private IDispatch objIDispatch;
+    private String exceptionDescription;
+    private ITypeInfo objITypeInfo;
+
+this(IDispatch idispatch) {
+    if (idispatch is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+    objIDispatch = idispatch;
+    objIDispatch.AddRef();
+
+    int result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo);
+    if (result is OLE.S_OK) {
+        objITypeInfo.AddRef();
+    }
+}
+/**
+ * Creates an OleAutomation object for the specified client.
+ *
+ * @param clientSite the site for the OLE Document or ActiveX Control whose additional functionality
+ *        you need to access
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_INVALID_INTERFACE_ADDRESS when called with an invalid client site
+ *  </ul>
+ */
+ public this(OleClientSite clientSite) {
+    if (clientSite is null) OLE.error(OLE.ERROR_INVALID_INTERFACE_ADDRESS);
+    objIDispatch = clientSite.getAutomationObject();
+
+    auto result = objIDispatch.GetTypeInfo(0, COM.LOCALE_USER_DEFAULT, &objITypeInfo);
+    if (result is OLE.S_OK) {
+        objITypeInfo.AddRef();
+    }
+ }
+/**
+ * Disposes the automation object.
+ * <p>
+ * This method releases the IDispatch interface on the OLE Document or ActiveX Control.
+ * Do not use the OleAutomation object after it has been disposed.
+ */
+public void dispose() {
+
+    if (objIDispatch !is null){
+        objIDispatch.Release();
+    }
+    objIDispatch = null;
+
+    if (objITypeInfo !is null){
+        objITypeInfo.Release();
+    }
+    objITypeInfo = null;
+
+}
+IDispatch getAddress() {
+    return objIDispatch;
+}
+/**
+ * Returns the fully qualified name of the Help file for the given member ID.
+ * 
+ * @param dispId the member ID whose Help file is being retrieved.
+ * @return a string representing the fully qualified name of a Help 
+ * file or null.
+ */
+public String getHelpFile(int dispId) {
+    if (objITypeInfo is null) return null;
+    BSTR file;
+    HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, null, null, &file );
+    if (rc is OLE.S_OK) {
+        String str = WCHARzToStr( file, -1 );
+        COM.SysFreeString(file);
+        return str;
+    }
+    return null;
+}
+/**
+ * Returns the documentation string for the given member ID.
+ * 
+ * @param dispId the member ID in which the documentation is being retrieved.
+ * @return the documentation string if it exists; otherwise return null.
+ */
+public String getDocumentation(int dispId) {
+    if (objITypeInfo is null) return null;
+    BSTR doc;
+    HRESULT rc = objITypeInfo.GetDocumentation(dispId, null, &doc, null, null );
+    if (rc == OLE.S_OK) {
+        String s = WCHARzToStr(doc, -1);
+        COM.SysFreeString(doc);
+        return s;
+    }
+    return null;
+}
+/**
+ * Returns the property description of a variable at the given index.
+ * 
+ * @param index the index of a variable whose property is being retrieved.
+ * @return an OlePropertyDescription for a variable at the given index.
+ */
+public OlePropertyDescription getPropertyDescription(int index) {
+    if (objITypeInfo is null) return null;
+    VARDESC* vardesc;
+    HRESULT rc = objITypeInfo.GetVarDesc(index, &vardesc);
+    if (rc != OLE.S_OK) return null;
+//  VARDESC* vardesc = new VARDESC();
+//  COM.MoveMemory(vardesc, ppVarDesc[0], VARDESC.sizeof);
+
+    OlePropertyDescription data = new OlePropertyDescription();
+    data.id = vardesc.memid;
+    data.name = getName(vardesc.memid);
+    data.type = vardesc.elemdescVar.tdesc.vt;
+    if (data.type == OLE.VT_PTR) {
+//      short[] vt = new short[1];
+//      COM.MoveMemory(vt, vardesc.elemdescVar.tdesc_union + 4, 2);
+        // TODO:
+        data.type = vardesc.elemdescVar.tdesc.vt;
+    }
+    data.flags = vardesc.wVarFlags;
+    data.kind = vardesc.varkind;
+    data.description = getDocumentation(vardesc.memid);
+    data.helpFile = getHelpFile(vardesc.memid);
+
+    objITypeInfo.ReleaseVarDesc(vardesc);
+    return data;
+}
+/**
+ * Returns the description of a function at the given index.
+ * 
+ * @param index the index of a function whose property is being retrieved.
+ * @return an OleFunctionDescription for a function at the given index.
+ */
+public OleFunctionDescription getFunctionDescription(int index) {
+    if (objITypeInfo is null) return null;
+    FUNCDESC* funcdesc;
+    HRESULT rc = objITypeInfo.GetFuncDesc(index, &funcdesc);
+    if (rc != OLE.S_OK) return null;
+
+    OleFunctionDescription data = new OleFunctionDescription();
+
+    data.id = funcdesc.memid;
+    data.optionalArgCount = funcdesc.cParamsOpt;
+    data.invokeKind = funcdesc.invkind;
+    data.funcKind = funcdesc.funckind;
+    data.flags = funcdesc.wFuncFlags;
+    data.callingConvention = funcdesc.callconv;
+    data.documentation = getDocumentation(funcdesc.memid);
+    data.helpFile = getHelpFile(funcdesc.memid);
+
+    String[] names = getNames(funcdesc.memid, funcdesc.cParams + 1);
+    if (names.length > 0) {
+        data.name = names[0];
+    }
+    data.args = new OleParameterDescription[funcdesc.cParams];
+    for (int i = 0; i < data.args.length; i++) {
+        data.args[i] = new OleParameterDescription();
+        if (names.length > i + 1) {
+            data.args[i].name = names[i + 1];
+        }
+        short[1] vt;
+        COM.MoveMemory(vt.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 4, 2);
+        if (vt[0] is OLE.VT_PTR) {
+            int[1] pTypedesc;
+            COM.MoveMemory(pTypedesc.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16, 4);
+            short[1] vt2;
+            COM.MoveMemory(vt2.ptr, pTypedesc[0] + 4, 2);
+            vt[0] = cast(short)(vt2[0] | COM.VT_BYREF);
+        }
+        data.args[i].type = vt[0];
+        short[1] wParamFlags;
+        COM.MoveMemory(wParamFlags.ptr, (cast(void*)funcdesc.lprgelemdescParam) + i * 16 + 12, 2);
+        data.args[i].flags = wParamFlags[0];
+    }
+
+    data.returnType = funcdesc.elemdescFunc.tdesc.vt;
+    if (data.returnType is OLE.VT_PTR) {
+        ushort[1] vt;
+        COM.MoveMemory(vt.ptr, funcdesc.elemdescFunc.tdesc.u.lpadesc, 2);
+        data.returnType = vt[0];
+    }
+
+    objITypeInfo.ReleaseFuncDesc(funcdesc);
+    return data;
+}
+/**
+ * Returns the type info of the current object referenced by the automation.
+ * The type info contains information about the object such as the function descriptions,
+ * the member descriptions and attributes of the type.
+ * 
+ * @return the type info of the receiver
+ */
+public TYPEATTR* getTypeInfoAttributes() {
+    if (objITypeInfo is null) return null;
+    TYPEATTR* ppTypeAttr;
+    HRESULT rc = objITypeInfo.GetTypeAttr(&ppTypeAttr);
+    if (rc !is OLE.S_OK) return null;
+    TYPEATTR* typeattr = new TYPEATTR();
+    COM.MoveMemory(typeattr, ppTypeAttr, TYPEATTR.sizeof);
+    objITypeInfo.ReleaseTypeAttr(ppTypeAttr);
+    return typeattr;
+}
+/**
+ * Returns the name of the given member ID.
+ * 
+ * @param dispId the member ID in which the name is being retrieved.
+ * @return the name if it exists; otherwise return null.
+ */
+public String getName(int dispId) {
+    if (objITypeInfo is null) return null;
+    BSTR name;
+    HRESULT rc = objITypeInfo.GetDocumentation(dispId, &name, null, null, null );
+    if (rc == OLE.S_OK) {
+        String s = WCHARzToStr(name, -1);
+        COM.SysFreeString(name);
+        return s;
+    }
+    return null;
+}
+/**
+ * Returns the name of a function and parameter names for the specified function ID.
+ * 
+ * @param dispId the function ID in which the name and parameters are being retrieved.
+ * @param maxSize the maximum number of names to retrieve.
+ * @return an array of name containing the function name and the parameter names
+ */
+public String[] getNames(int dispId, int maxSize) {
+    if (objITypeInfo is null) return new String[0];
+    BSTR[] names = new BSTR[maxSize];
+    uint count;
+    HRESULT rc = objITypeInfo.GetNames(dispId, names.ptr, maxSize, &count);
+    if (rc == OLE.S_OK) {
+        String[] newNames = new String[count];
+        for(int i=0; i<count; ++i){
+            newNames[i] = WCHARzToStr(names[i], -1);
+            COM.SysFreeString(names[i]);
+        }
+        return newNames;
+    }
+    return null;
+}
+/**
+ * Returns the positive integer values (IDs) that are associated with the specified names by the
+ * IDispatch implementor.  If you are trying to get the names of the parameters in a method, the first
+ * String in the names array must be the name of the method followed by the names of the parameters.
+ *
+ * @param names an array of names for which you require the identifiers
+ *
+ * @return positive integer values that are associated with the specified names in the same
+ *         order as the names where provided; or null if the names are unknown
+ */
+public int[] getIDsOfNames(String[] names) {
+
+    int count = names.length;
+    wchar*[] wcNames = new wchar*[count];
+    for(int i=0; i<count; ++i){
+        wcNames[i] = StrToWCHARz(names[i]);
+    }
+    int[] rgdispid = new int[count];
+    // TODO: NULL GUID ??
+    GUID id;
+    HRESULT result = objIDispatch.GetIDsOfNames(&id, wcNames.ptr, count, COM.LOCALE_USER_DEFAULT, rgdispid.ptr);
+    if (result != COM.S_OK) return null;
+
+    return rgdispid;
+}
+/**
+ * Returns a description of the last error encountered.
+ *
+ * @return a description of the last error encountered
+ */
+public String getLastError() {
+
+    return exceptionDescription;
+
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ */
+public Variant getProperty(int dispIdMember) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, null, null, pVarResult);
+    return (result is OLE.S_OK) ? pVarResult : null;
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ *
+ * @since 2.0
+ */
+public Variant getProperty(int dispIdMember, Variant[] rgvarg) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, null, pVarResult);
+    return (result is OLE.S_OK) ? pVarResult : null;
+
+}
+/**
+ * Returns the value of the property specified by the dispIdMember.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @return the value of the property specified by the dispIdMember or null
+ *
+ * @since 2.0
+ */
+public Variant getProperty(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_PROPERTYGET, rgvarg, rgdispidNamedArgs, pVarResult);
+    return (result is OLE.S_OK) ? pVarResult : null;
+}
+
+/**
+ * Invokes a method on the OLE Object; the method has no parameters.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, pVarResult);
+    return (result is COM.S_OK) ? pVarResult : null;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no optional parameters.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember, Variant[] rgvarg) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, pVarResult);
+    return (result is COM.S_OK) ? pVarResult : null;
+}
+/**
+ * Invokes a method on the OLE Object; the method has optional parameters.  It is not
+ * necessary to specify all the optional parameters, only include the parameters for which
+ * you are providing values.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @return the result of the method or null if the method failed to give result information
+ */
+public Variant invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, pVarResult);
+    return (result is COM.S_OK) ? pVarResult : null;
+}
+private int invoke(int dispIdMember, ushort wFlags, Variant[] rgvarg, int[] rgdispidNamedArgs, Variant pVarResult) {
+    assert(objIDispatch);
+
+    // get the IDispatch interface for the control
+    if (objIDispatch is null) return COM.E_FAIL;
+
+    // create a DISPPARAMS structure for the input parameters
+    DISPPARAMS pDispParams;
+
+    // store arguments in rgvarg
+    if (rgvarg !is null && rgvarg.length > 0) {
+        VARIANT[] tempArgs = new VARIANT[rgvarg.length];
+        for (int i = 0; i < rgvarg.length ; ++i) {
+            rgvarg[i].getData(&tempArgs[i]);
+        }
+        // the reverse sequency
+        tempArgs.reverse;
+        pDispParams.cArgs = tempArgs.length;
+        pDispParams.rgvarg = tempArgs.ptr;
+    }
+
+    // if arguments have ids, store the ids in rgdispidNamedArgs
+    if (rgdispidNamedArgs !is null && rgdispidNamedArgs.length > 0) {
+        DISPID[] tempArgs = rgdispidNamedArgs.dup;
+        // the reverse sequency
+        tempArgs.reverse;
+        pDispParams.cNamedArgs = tempArgs.length;
+        pDispParams.rgdispidNamedArgs = tempArgs.ptr;
+    }
+
+    // invoke the method
+    EXCEPINFO excepInfo;
+    uint pArgErr;
+    VARIANT* pVarResultAddress = null;
+    if (pVarResult !is null)
+        pVarResultAddress = new VARIANT();
+
+    GUID id;    // IID_NULL
+    /*
+         HRESULT Invoke(
+                [in] DISPID dispIdMember,
+                [in] REFIID riid,
+                [in] LCID lcid,
+                [in] WORD wFlags,
+                [in, out] DISPPARAMS * pDispParams,
+                [out] VARIANT * pVarResult,
+                [out] EXCEPINFO * pExcepInfo,
+                [out] UINT * puArgErr
+            );
+     */
+    HRESULT result = objIDispatch.Invoke(dispIdMember, &id, COM.LOCALE_USER_DEFAULT, wFlags, &pDispParams, pVarResultAddress, &excepInfo, &pArgErr);
+
+    if (pVarResultAddress !is null){
+        pVarResult.setData(pVarResultAddress);
+        COM.VariantClear(pVarResultAddress);
+    }
+
+    // free the Dispparams resources
+    if (pDispParams.rgvarg !is null) {
+        for (int i = 0, length = rgvarg.length; i < length; i++){
+            COM.VariantClear(&pDispParams.rgvarg[i]);
+        }
+        pDispParams.rgvarg = null;
+    }
+    pDispParams.rgdispidNamedArgs = null;
+
+    // save error string and cleanup EXCEPINFO
+    manageExcepinfo(result, &excepInfo);
+
+    return result;
+}
+/**
+ * Invokes a method on the OLE Object; the method has no parameters.  In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value.  For these applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *      <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *  </ul>
+ */
+public void invokeNoReply(int dispIdMember) {
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, null, null, null);
+    if (result !is COM.S_OK)
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has no optional parameters.  In the early days of OLE,
+ * the IDispatch interface was not well defined and some applications (mainly Word) did not support
+ * a return value.  For these applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember, Variant[] rgvarg)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *      <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *  </ul>
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg) {
+    int result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, null, null);
+    if (result !is COM.S_OK)
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+/**
+ * Invokes a method on the OLE Object; the method has optional parameters.  It is not
+ * necessary to specify all the optional parameters, only include the parameters for which
+ * you are providing values.  In the early days of OLE, the IDispatch interface was not well
+ * defined and some applications (mainly Word) did not support a return value.  For these
+ * applications, call this method instead of calling
+ * <code>public void invoke(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs)</code>.
+ *
+ * @param dispIdMember the ID of the method as specified by the IDL of the ActiveX Control; the
+ *        value for the ID can be obtained using OleAutomation.getIDsOfNames
+ *
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *        read only unless the Variant is a By Reference Variant type.
+ *
+ * @param rgdispidNamedArgs an array of identifiers for the arguments specified in rgvarg; the
+ *        parameter IDs must be in the same order as their corresponding values;
+ *        all arguments must have an identifier - identifiers can be obtained using
+ *        OleAutomation.getIDsOfNames
+ *
+ * @exception org.eclipse.swt.SWTException <ul>
+ *      <li>ERROR_ACTION_NOT_PERFORMED when method invocation fails
+ *  </ul>
+ */
+public void invokeNoReply(int dispIdMember, Variant[] rgvarg, int[] rgdispidNamedArgs) {
+    HRESULT result = invoke(dispIdMember, COM.DISPATCH_METHOD, rgvarg, rgdispidNamedArgs, null);
+    if (result !is COM.S_OK)
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_ACTION_NOT_PERFORMED, result);
+}
+private void manageExcepinfo(int hResult, EXCEPINFO* excepInfo) {
+
+    if (hResult is COM.S_OK){
+        exceptionDescription = "No Error"; //$NON-NLS-1$
+        return;
+    }
+
+    // extract exception info
+    if (hResult is COM.DISP_E_EXCEPTION) {
+        if (excepInfo.bstrDescription !is null){
+            exceptionDescription = WCHARzToStr(excepInfo.bstrDescription);
+        } else {
+            exceptionDescription = ("OLE Automation Error Exception "); //$NON-NLS-1$
+            if (excepInfo.wCode != 0){
+                exceptionDescription ~= "code = ";
+                exceptionDescription ~= cast(int)(excepInfo.wCode); //$NON-NLS-1$
+            } else if (excepInfo.scode != 0){
+                exceptionDescription ~= "code = ";
+                exceptionDescription ~= (excepInfo.scode); //$NON-NLS-1$
+            }
+        }
+    } else {
+        exceptionDescription = ("OLE Automation Error HResult : ") ~ toHex(hResult); //$NON-NLS-1$
+    }
+
+    // cleanup EXCEPINFO struct
+    if (excepInfo.bstrDescription !is null)
+        COM.SysFreeString(excepInfo.bstrDescription);
+    if (excepInfo.bstrHelpFile !is null)
+        COM.SysFreeString(excepInfo.bstrHelpFile);
+    if (excepInfo.bstrSource !is null)
+        COM.SysFreeString(excepInfo.bstrSource);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *                     value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg the new value of the property
+ *
+ * @return true if the operation was successful
+ */
+public bool setProperty(int dispIdMember, Variant rgvarg) {
+
+    Variant[] rgvarg2 = new Variant[1];
+    rgvarg2[0] = rgvarg;
+    int[] rgdispidNamedArgs;
+    rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT;
+    ushort dwFlags = COM.DISPATCH_PROPERTYPUT;
+    if ((rgvarg.getType() & COM.VT_BYREF) == COM.VT_BYREF)
+        dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, dwFlags, rgvarg2, rgdispidNamedArgs, pVarResult);
+    return (result == COM.S_OK);
+}
+/**
+ * Sets the property specified by the dispIdMember to a new value.
+ *
+ * @param dispIdMember the ID of the property as specified by the IDL of the ActiveX Control; the
+ *                     value for the ID can be obtained using OleAutomation.getIDsOfNames
+ * @param rgvarg an array of arguments for the method.  All arguments are considered to be
+ *                     read only unless the Variant is a By Reference Variant type.
+ *
+ * @return true if the operation was successful
+ *
+ * @since 2.0
+ */
+public bool setProperty(int dispIdMember, Variant[] rgvarg) {
+    int[] rgdispidNamedArgs;
+    rgdispidNamedArgs ~= COM.DISPID_PROPERTYPUT;
+    ushort dwFlags = COM.DISPATCH_PROPERTYPUT;
+    for (int i = 0; i < rgvarg.length; i++) {
+        if ((rgvarg[i].getType() & COM.VT_BYREF) == COM.VT_BYREF)
+        dwFlags = COM.DISPATCH_PROPERTYPUTREF;
+    }
+    Variant pVarResult = new Variant();
+    HRESULT result = invoke(dispIdMember, dwFlags, rgvarg, rgdispidNamedArgs, pVarResult);
+    return (result == COM.S_OK);
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleClientSite.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1447 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleClientSite;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.lang.all;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.Compatibility;
+// import org.eclipse.swt.internal.ole.win32.CAUUID;
+// import org.eclipse.swt.internal.ole.win32.COM;
+// import org.eclipse.swt.internal.ole.win32.COMObject;
+// import org.eclipse.swt.internal.ole.win32.GUID;
+// import org.eclipse.swt.internal.ole.win32.IDispatch;
+// import org.eclipse.swt.internal.ole.win32.IMoniker;
+// import org.eclipse.swt.internal.ole.win32.IOleCommandTarget;
+// import org.eclipse.swt.internal.ole.win32.IOleDocument;
+// import org.eclipse.swt.internal.ole.win32.IOleDocumentView;
+// import org.eclipse.swt.internal.ole.win32.IOleInPlaceObject;
+// import org.eclipse.swt.internal.ole.win32.IOleLink;
+// import org.eclipse.swt.internal.ole.win32.IOleObject;
+// import org.eclipse.swt.internal.ole.win32.IPersist;
+// import org.eclipse.swt.internal.ole.win32.IPersistStorage;
+// import org.eclipse.swt.internal.ole.win32.ISpecifyPropertyPages;
+// import org.eclipse.swt.internal.ole.win32.IStorage;
+// import org.eclipse.swt.internal.ole.win32.IStream;
+// import org.eclipse.swt.internal.ole.win32.IUnknown;
+// import org.eclipse.swt.internal.ole.win32.IViewObject2;
+// import org.eclipse.swt.internal.ole.win32.OLECMD;
+// import org.eclipse.swt.internal.ole.win32.OLEINPLACEFRAMEINFO;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.ole.win32.DOCOBJ;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.swt.ole.win32.OleFrame;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+
+/**
+ * OleClientSite provides a site to manage an embedded OLE Document within a container.
+ *
+ * <p>The OleClientSite provides the following capabilities:
+ * <ul>
+ *  <li>creates the in-place editor for a blank document or opening an existing OLE Document
+ *  <li>lays the editor out
+ *  <li>provides a mechanism for activating and deactivating the Document
+ *  <li>provides a mechanism for saving changes made to the document
+ * </ul>
+ *
+ * <p>This object implements the OLE Interfaces IUnknown, IOleClientSite, IAdviseSink,
+ * IOleInPlaceSite
+ *
+ * <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.
+ * </p><p>
+ * <dl>
+ *  <dt><b>Styles</b> <dd>BORDER
+ *  <dt><b>Events</b> <dd>Dispose, Move, Resize
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
+ */
+public class OleClientSite : Composite {
+
+    // Interfaces for this Ole Client Container
+    private _IUnknownImpl          iUnknown;
+    private _IOleClientSiteImpl    iOleClientSite;
+    private _IAdviseSinkImpl       iAdviseSink;
+    private _IOleInPlaceSiteImpl   iOleInPlaceSite;
+    private _IOleDocumentSiteImpl  iOleDocumentSite;
+
+    protected GUID* appClsid;
+    private GUID* objClsid;
+    private int  refCount;
+
+    // References to the associated Frame.
+    package OleFrame frame;
+
+    // Access to the embedded/linked Ole Object
+    protected IUnknown              objIUnknown;
+    protected IOleObject            objIOleObject;
+    protected IViewObject2          objIViewObject2;
+    protected IOleInPlaceObject     objIOleInPlaceObject;
+    protected IOleCommandTarget     objIOleCommandTarget;
+    protected IOleDocumentView      objDocumentView;
+
+    // Related storage information
+    protected IStorage tempStorage;     // IStorage interface of the receiver
+
+    // Internal state and style information
+    private int     aspect;    // the display aspect of the embedded object, e.g., DvaspectContent or DvaspectIcon
+    private int     type;      // Indicates the type of client that can be supported inside this container
+    private bool isStatic;  // Indicates item's display is static, i.e., a bitmap, metafile, etc.
+
+    private RECT borderWidths;
+    private RECT indent;
+    private bool inUpdate = false;
+    private bool inInit = true;
+    private bool inDispose = false;
+
+    private static const String WORDPROGID = "Word.Document"; //$NON-NLS-1$
+
+    private Listener listener;
+
+    enum{
+        STATE_NONE = 0,
+        STATE_RUNNING = 1,
+        STATE_INPLACEACTIVE = 2,
+        STATE_UIACTIVE = 3,
+        STATE_ACTIVE = 4,
+    }
+    int state = STATE_NONE;
+
+protected this(Composite parent, int style) {
+    /*
+     * NOTE: this constructor should never be used by itself because it does
+     * not create an Ole Object
+     */
+    super(parent, style);
+
+    createCOMInterfaces();
+
+    // install the Ole Frame for this Client Site
+    while (parent !is null) {
+        if ( auto aframe = cast(OleFrame)parent){
+            frame = aframe;
+            break;
+        }
+        parent = parent.getParent();
+    }
+    if (frame is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_INVALID_ARGUMENT);
+    frame.AddRef();
+
+    aspect   = COM.DVASPECT_CONTENT;
+    type     = COM.OLEEMBEDDED;
+    isStatic = false;
+
+    listener = new class() Listener {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+            case SWT.Resize :
+            case SWT.Move :    onResize(e); break;
+            case SWT.Dispose : onDispose(e); break;
+            case SWT.FocusIn:  onFocusIn(e); break;
+            case SWT.FocusOut:  onFocusOut(e); break;
+            case SWT.Paint:    onPaint(e); break;
+            case SWT.Traverse: onTraverse(e); break;
+            case SWT.KeyDown: /* required for traversal */ break;
+            default :
+                OLE.error (__FILE__, __LINE__, SWT.ERROR_NOT_IMPLEMENTED);
+            }
+        }
+    };
+
+    frame.addListener(SWT.Resize, listener);
+    frame.addListener(SWT.Move, listener);
+    addListener(SWT.Dispose, listener);
+    addListener(SWT.FocusIn, listener);
+    addListener(SWT.FocusOut, listener);
+    addListener(SWT.Paint, listener);
+    addListener(SWT.Traverse, listener);
+    addListener(SWT.KeyDown, listener);
+}
+/**
+ * Create an OleClientSite child widget using the OLE Document type associated with the
+ * specified file.  The OLE Document type is determined either through header information in the file
+ * or through a Registry entry for the file extension. Use style bits to select a particular look
+ * or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param file the file that is to be opened in this OLE Document
+ *
+ * @exception IllegalArgumentException
+ * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
+ *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
+ * @exception SWTException
+ * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *     <li>ERROR_CANNOT_OPEN_FILE when failed to open file
+ *     <li>ERROR_INTERFACE_NOT_FOUND when unable to create callbacks for OLE Interfaces
+ *     <li>ERROR_INVALID_CLASSID
+ * </ul>
+ */
+public this(Composite parent, int style, File file) {
+    this(parent, style);
+    try {
+
+        if (file is null || file.isDirectory() || !file.exists())
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT);
+
+        // Is there an associated CLSID?
+        appClsid = new GUID();
+        TCHAR* fileName = StrToTCHARz( 0, file.getAbsolutePath() );
+        int result = COM.GetClassFile(fileName, appClsid);
+        if (result !is COM.S_OK)
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result);
+        // associated CLSID may not be installed on this machine
+        if (getProgramID() is null)
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID, result);
+
+        // Open a temporary storage object
+        tempStorage = createTempStorage();
+
+        // Create ole object with storage object
+        result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+        if (result !is COM.S_OK)
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+        // Init sinks
+        addObjectReferences();
+
+        if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+    } catch (SWTException e) {
+        dispose();
+        disposeCOMInterfaces();
+        throw e;
+    }
+}
+/**
+ * Create an OleClientSite child widget to edit a blank document using the specified OLE Document
+ * application.  Use style bits to select a particular look or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier of am OLE Document application;
+ *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ *               in the registry for the desired OLE Document (for example, the VersionIndependentProgID
+ *               for Word is Word.Document)
+ *
+ * @exception IllegalArgumentException
+ *<ul>
+ *     <li>ERROR_NULL_ARGUMENT when the parent is null
+ *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame
+ *</ul>
+ * @exception SWTException
+ * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ * </ul>
+ */
+public this(Composite parent, int style, String progId) {
+    this(parent, style);
+    try {
+        appClsid = getClassID(progId);
+        if (appClsid is null)
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+        // Open a temporary storage object
+        tempStorage = createTempStorage();
+
+        // Create ole object with storage object
+        HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+        if (result !is COM.S_OK)
+            OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+        // Init sinks
+        addObjectReferences();
+
+        if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+
+    } catch (SWTException e) {
+        dispose();
+        disposeCOMInterfaces();
+        throw e;
+    }
+}
+/**
+ * Create an OleClientSite child widget to edit the specified file using the specified OLE Document
+ * application.  Use style bits to select a particular look or set of properties.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>OleClientSite</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier of am OLE Document application;
+ *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ *               in the registry for the desired OLE Document (for example, the VersionIndependentProgID
+ *               for Word is Word.Document)
+ * @param file the file that is to be opened in this OLE Document
+ *
+ * @exception IllegalArgumentException
+ * <ul><li>ERROR_NULL_ARGUMENT when the parent is null
+ *     <li>ERROR_INVALID_ARGUMENT when the parent is not an OleFrame</ul>
+ * @exception SWTException
+ * <ul><li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *     <li>ERROR_CANNOT_OPEN_FILE when failed to open file
+ * </ul>
+ */
+public this(Composite parent, int style, String progId, File file) {
+    this(parent, style);
+    try {
+        if (file is null || file.isDirectory() || !file.exists()) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_ARGUMENT);
+        appClsid = getClassID(progId);
+        if (appClsid is null) OLE.error (__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+        // Are we opening this file with the preferred OLE object?
+        wchar* fileName = StrToWCHARz(file.getAbsolutePath());
+        GUID* fileClsid = new GUID();
+        COM.GetClassFile(fileName, fileClsid);
+
+        if (COM.IsEqualGUID(appClsid, fileClsid)){
+            // Using the same application that created file, therefore, use default mechanism.
+            tempStorage = createTempStorage();
+            // Create ole object with storage object
+            HRESULT result = COM.OleCreateFromFile(appClsid, fileName, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+            if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+        } else {
+            // Not using the same application that created file, therefore, copy from original file to a new storage file
+            IStorage storage = null;
+            if (COM.StgIsStorageFile(fileName) is COM.S_OK) {
+                int mode = COM.STGM_READ | COM.STGM_TRANSACTED | COM.STGM_SHARE_EXCLUSIVE;
+                HRESULT result = COM.StgOpenStorage(fileName, null, mode, null, 0, &storage); //Does an AddRef if successful
+                if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+            } else {
+                // Original file is not a Storage file so copy contents to a stream in a new storage file
+                int mode = COM.STGM_READWRITE | COM.STGM_DIRECT | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+                HRESULT result = COM.StgCreateDocfile(null, mode | COM.STGM_DELETEONRELEASE, 0, &storage); // Increments ref count if successful
+                if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+                // Create a stream on the storage object.
+                // Word does not follow the standard and does not use "CONTENTS" as the name of
+                // its primary stream
+                wchar* streamName = StrToWCHARz("CONTENTS"); //$NON-NLS-1$
+                GUID* wordGUID = getClassID(WORDPROGID);
+                if (wordGUID !is null && COM.IsEqualGUID(appClsid, wordGUID)) streamName = "WordDocument"; //$NON-NLS-1$
+                IStream stream;
+                result = storage.CreateStream(streamName, mode, 0, 0, &stream); // Increments ref count if successful
+                if (result !is COM.S_OK) {
+                    storage.Release();
+                    OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+                }
+                try {
+                    // Copy over data in file to named stream
+                    FileInputStream fileInput = new FileInputStream(file);
+                    int increment = 1024*4;
+                    byte[] buffer = new byte[increment];
+                    int count = 0;
+                    while((count = fileInput.read(buffer)) > 0){
+                        auto pv = COM.CoTaskMemAlloc(count);
+                        OS.MoveMemory(pv, buffer.ptr, count);
+                        result = stream.Write(pv, count, null) ;
+                        COM.CoTaskMemFree(pv);
+                        if (result !is COM.S_OK) {
+                            fileInput.close();
+                            stream.Release();
+                            storage.Release();
+                            OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+                        }
+                    }
+                    fileInput.close();
+                    stream.Commit(COM.STGC_DEFAULT);
+                    stream.Release();
+                } catch (IOException err) {
+                    stream.Release();
+                    storage.Release();
+                    OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE);
+                }
+            }
+
+            // Open a temporary storage object
+            tempStorage = createTempStorage();
+            // Copy over contents of file
+            HRESULT result = storage.CopyTo(0, null, null, tempStorage);
+            storage.Release();
+            if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_OPEN_FILE, result);
+
+            // create ole client
+            result = COM.CoCreateInstance(appClsid, null, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, &COM.IIDIUnknown, cast(void**)&objIUnknown);
+            if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+            // get the persistent storage of the ole client
+            IPersistStorage iPersistStorage;
+            result = objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage);
+            if (result !is COM.S_OK) OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+            // load the contents of the file into the ole client site
+            result = iPersistStorage.Load(tempStorage);
+            iPersistStorage.Release();
+            if (result !is COM.S_OK)OLE.error (__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+        }
+
+        // Init sinks
+        addObjectReferences();
+
+        if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+
+    } catch (SWTException e) {
+        dispose();
+        disposeCOMInterfaces();
+        throw e;
+    }
+}
+protected void addObjectReferences() {
+    //
+    IPersist objIPersist;
+    if (objIUnknown.QueryInterface(&COM.IIDIPersist, cast(void**)&objIPersist) is COM.S_OK) {
+        GUID* tempid = new GUID();
+        if (objIPersist.GetClassID(tempid) is COM.S_OK)
+            objClsid = tempid;
+        objIPersist.Release();
+    }
+
+    //
+    HRESULT result = objIUnknown.QueryInterface(&COM.IIDIViewObject2, cast(void**)&objIViewObject2);
+    if (result !is COM.S_OK)
+        OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result);
+    objIViewObject2.SetAdvise(aspect, 0, iAdviseSink);
+
+    //
+    result = objIUnknown.QueryInterface(&COM.IIDIOleObject, cast(void**)&objIOleObject);
+    if (result !is COM.S_OK)
+        OLE.error (__FILE__, __LINE__, OLE.ERROR_INTERFACE_NOT_FOUND, result);
+    objIOleObject.SetClientSite(iOleClientSite);
+    uint pdwConnection;
+    objIOleObject.Advise(iAdviseSink, &pdwConnection);
+    objIOleObject.SetHostNames("main", "main");  //$NON-NLS-1$ //$NON-NLS-2$
+
+    // Notify the control object that it is embedded in an OLE container
+    COM.OleSetContainedObject(objIUnknown, true);
+
+    // Is OLE object linked or embedded?
+    IOleLink objIOleLink;
+    if (objIUnknown.QueryInterface(&COM.IIDIOleLink, cast(void**)&objIOleLink) is COM.S_OK) {
+        IMoniker objIMoniker;
+        if (objIOleLink.GetSourceMoniker(&objIMoniker) is COM.S_OK) {
+            objIMoniker.Release();
+            type = COM.OLELINKED;
+            objIOleLink.BindIfRunning();
+        } else {
+            isStatic = true;
+        }
+        objIOleLink.Release();
+    }
+}
+protected int AddRef() {
+    refCount++;
+    return refCount;
+}
+private int CanInPlaceActivate() {
+    if (aspect is COM.DVASPECT_CONTENT && type is COM.OLEEMBEDDED)
+        return COM.S_OK;
+
+    return COM.S_FALSE;
+}
+private int ContextSensitiveHelp(int fEnterMode) {
+    return COM.S_OK;
+}
+protected void createCOMInterfaces() {
+    iUnknown = new _IUnknownImpl(this);
+    iOleClientSite = new _IOleClientSiteImpl(this);
+    iAdviseSink = new _IAdviseSinkImpl(this);
+    iOleInPlaceSite = new _IOleInPlaceSiteImpl(this);
+    iOleDocumentSite = new _IOleDocumentSiteImpl(this);
+}
+protected IStorage createTempStorage() {
+    IStorage tmpStorage;
+    int grfMode = COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_DELETEONRELEASE;
+    HRESULT result = COM.StgCreateDocfile(null, grfMode, 0, &tmpStorage);
+    if (result !is COM.S_OK) OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_FILE, result);
+    return (tmpStorage);
+}
+/**
+ * Deactivates an active in-place object and discards the object's undo state.
+ */
+public void deactivateInPlaceClient() {
+    if (objIOleInPlaceObject !is null) {
+        objIOleInPlaceObject.InPlaceDeactivate();
+    }
+}
+private void deleteTempStorage() {
+    //Destroy this item's contents in the temp root IStorage.
+    if (tempStorage !is null){
+        tempStorage.Release();
+    }
+    tempStorage = null;
+}
+protected void disposeCOMInterfaces() {
+    iUnknown = null;
+    iOleClientSite = null;
+    iAdviseSink = null;
+    iOleInPlaceSite = null;
+    iOleDocumentSite = null;
+}
+/**
+ * Requests that the OLE Document or ActiveX Control perform an action; actions are almost always
+ * changes to the activation state.
+ *
+ * @param verb the operation that is requested.  This is one of the OLE.OLEIVERB_ values
+ *
+ * @return an HRESULT value indicating the success of the operation request; OLE.S_OK indicates
+ *         success
+ */
+public int doVerb(int verb) {
+    // Not all OLE clients (for example PowerPoint) can be set into the running state in the constructor.
+    // The fix is to ensure that the client is in the running state before invoking any verb on it.
+    if (state is STATE_NONE) {
+        if (COM.OleRun(objIUnknown) is OLE.S_OK) state = STATE_RUNNING;
+    }
+    if (state is STATE_NONE || isStatic)
+        return COM.E_FAIL;
+
+    // See PR: 1FV9RZW
+    RECT rect;
+    OS.GetClientRect(handle, &rect);
+    int result = objIOleObject.DoVerb(verb, null, iOleClientSite, 0, handle, &rect);
+
+    if (state !is STATE_RUNNING && inInit) {
+        updateStorage();
+        inInit = false;
+    }
+    return result;
+}
+/**
+ * Asks the OLE Document or ActiveX Control to execute a command from a standard
+ * list of commands. The OLE Document or ActiveX Control must support the IOleCommandTarget
+ * interface.  The OLE Document or ActiveX Control does not have to support all the commands
+ * in the standard list.  To check if a command is supported, you can call queryStatus with
+ * the cmdID.
+ *
+ * @param cmdID the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
+ *              commands
+ * @param options the optional flags; these are the OLE.OLECMDEXECOPT_ values
+ * @param in the argument for the command
+ * @param out the return value of the command
+ *
+ * @return an HRESULT value; OLE.S_OK is returned if successful
+ *
+ */
+public int exec(int cmdID, int options, Variant pvaIn, Variant pvaOut) {
+
+    if (objIOleCommandTarget is null) {
+        if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK)
+            return OLE.ERROR_INTERFACE_NOT_FOUND;
+    }
+
+    VARIANT* pIn = null;
+    VARIANT* pOut = null;
+
+    if(pvaIn){
+        pIn = new VARIANT();
+        pvaIn.getData(pIn);
+    }
+    if(pvaOut){
+        pOut = new VARIANT();
+        pvaOut.getData(pOut);
+    }
+
+    HRESULT result = objIOleCommandTarget.Exec(null, cmdID, options, pIn, pOut);
+
+    if(pIn) {
+        COM.VariantClear(pIn);
+    }
+
+    if(pOut) {
+        pvaOut.setData(pOut);
+        COM.VariantClear(pOut);
+    }
+
+    return result;
+}
+IDispatch getAutomationObject() {
+    IDispatch ppvObject;
+    if (objIUnknown.QueryInterface(&COM.IIDIDispatch, cast(void**)&ppvObject) !is COM.S_OK)
+        return null;
+    return ppvObject;
+}
+protected GUID* getClassID(String clientName) {
+    // create a GUID struct to hold the result
+    GUID* guid = new GUID();
+
+    // create a null terminated array of char
+    wchar* buffer = null;
+    if (clientName !is null) {
+        buffer = StrToWCHARz(clientName);;
+    }
+    if (COM.CLSIDFromProgID(buffer, guid) !is COM.S_OK){
+        HRESULT result = COM.CLSIDFromString(buffer, guid);
+        if (result !is COM.S_OK) return null;
+    }
+    return guid;
+}
+
+private HRESULT GetContainer(IOleContainer* ppContainer) {
+    /* Simple containers that do not support links to their embedded
+     * objects probably do not need to implement this method. Instead,
+     * they can return E_NOINTERFACE and set ppContainer to NULL.
+     */
+    if (ppContainer !is null)
+        *ppContainer = null;
+    return COM.E_NOINTERFACE;
+}
+
+private SIZE* getExtent() {
+    SIZE* sizel = new SIZE();
+    // get the current size of the embedded OLENatives object
+    if (objIOleObject !is null) {
+        if ( objIViewObject2 !is null && !COM.OleIsRunning(objIOleObject)) {
+            objIViewObject2.GetExtent(aspect, -1, null, sizel);
+        } else {
+            objIOleObject.GetExtent(aspect, sizel);
+        }
+    }
+    return xFormHimetricToPixels(sizel);
+}
+/**
+ * Returns the indent value that would be used to compute the clipping area
+ * of the active X object.
+ * 
+ * NOTE: The indent value is no longer being used by the client site.
+ * 
+ * @return the rectangle representing the indent
+ */
+public Rectangle getIndent() {
+    return new Rectangle(indent.left, indent.right, indent.top, indent.bottom);
+}
+/**
+ * Returns the program ID of the OLE Document or ActiveX Control.
+ *
+ * @return the program ID of the OLE Document or ActiveX Control
+ */
+public String getProgramID(){
+    if (appClsid !is null){
+        wchar* hMem;
+        if (COM.ProgIDFromCLSID(appClsid, &hMem) is COM.S_OK) {
+            int length = OS.GlobalSize(hMem);
+            auto ptr = OS.GlobalLock(hMem);
+            wchar[] buffer = new wchar[length];
+            COM.MoveMemory(buffer.ptr, ptr, length);
+            OS.GlobalUnlock(hMem);
+            OS.GlobalFree(hMem);
+
+            String result = WCHARzToStr(buffer.ptr);
+            // remove null terminator
+            //int index = result.indexOf("\0");
+            return result;//.substring(0, index);
+        }
+    }
+    return null;
+}
+int ActivateMe(IOleDocumentView pViewToActivate) {
+    if (pViewToActivate is null) {
+        void* ppvObject;
+        if (objIUnknown.QueryInterface(&COM.IIDIOleDocument, &ppvObject) !is COM.S_OK) return COM.E_FAIL;
+        IOleDocument objOleDocument = cast(IOleDocument)ppvObject;
+        if (objOleDocument.CreateView(iOleInPlaceSite, null, 0, &objDocumentView) !is COM.S_OK) return COM.E_FAIL;
+        objOleDocument.Release();
+    } else {
+        objDocumentView = pViewToActivate;
+        objDocumentView.AddRef();
+        objDocumentView.SetInPlaceSite(iOleInPlaceSite);
+    }
+    objDocumentView.UIActivate(1);//TRUE
+    RECT* rect = getRect();
+    objDocumentView.SetRect(rect);
+    objDocumentView.Show(1);//TRUE
+    return COM.S_OK;
+}
+protected int GetWindow(HWND* phwnd) {
+    if (phwnd is null)
+        return COM.E_INVALIDARG;
+    if (frame is null) {
+        *phwnd = null;
+        return COM.E_NOTIMPL;
+    }
+
+    // Copy the Window's handle into the memory passed in
+    *phwnd = frame.handle;
+    return COM.S_OK;
+}
+RECT* getRect() {
+    Point location = this.getLocation();
+    Rectangle area = frame.getClientArea();
+    RECT* rect = new RECT();
+    rect.left   = location.x;
+    rect.top    = location.y;
+    rect.right  = location.x + area.width - borderWidths.left - borderWidths.right;
+    rect.bottom = location.y + area.height - borderWidths.top - borderWidths.bottom;
+    return rect;
+}
+
+private int GetWindowContext(IOleInPlaceFrame* ppFrame, IOleInPlaceUIWindow* ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) {
+    if (frame is null || ppFrame is null)
+        return COM.E_NOTIMPL;
+
+    // fill in frame handle
+    auto iOleInPlaceFrame = frame.getIOleInPlaceFrame();
+    *ppFrame = iOleInPlaceFrame;
+    frame.AddRef();
+
+    // null out document handle
+    if (ppDoc !is null) *ppDoc = null;
+
+    // fill in position and clipping info
+    RECT* rect = getRect();
+    if (lprcPosRect !is null) OS.MoveMemory(lprcPosRect, rect, RECT.sizeof);
+    if (lprcClipRect !is null) OS.MoveMemory(lprcClipRect, rect, RECT.sizeof);
+
+    // get frame info
+    OLEINPLACEFRAMEINFO* frameInfo = new OLEINPLACEFRAMEINFO();
+    frameInfo.cb = OLEINPLACEFRAMEINFO.sizeof;
+    frameInfo.fMDIApp = 0;
+    frameInfo.hwndFrame = frame.handle;
+    Shell shell = getShell();
+    Menu menubar = shell.getMenuBar();
+    if (menubar !is null && !menubar.isDisposed()) {
+        auto hwnd = shell.handle;
+        auto cAccel = OS.SendMessage(hwnd, OS.WM_APP, 0, 0);
+        if (cAccel !is 0) {
+            auto hAccel = cast(HACCEL) OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+            if (hAccel !is null) {
+                frameInfo.cAccelEntries = cAccel;
+                frameInfo.haccel = hAccel;
+            }
+        }
+    }
+    COM.MoveMemory(lpFrameInfo, frameInfo, OLEINPLACEFRAMEINFO.sizeof);
+
+    return COM.S_OK;
+}
+/**
+ * Returns whether ole document is dirty by checking whether the content 
+ * of the file representing the document is dirty.
+ * 
+ * @return <code>true</code> if the document has been modified,
+ *         <code>false</code> otherwise.
+ * @since 3.1
+ */
+public bool isDirty() {
+    /*
+     *  Note: this method must return true unless it is absolutely clear that the
+     * contents of the Ole Document do not differ from the contents in the file
+     * on the file system.
+     */
+
+    // Get access to the persistent storage mechanism
+    IPersistStorage permStorage;
+    if (objIOleObject.QueryInterface(&COM.IIDIPersistFile, cast(void**)&permStorage) !is COM.S_OK)
+        return true;
+    // Are the contents of the permanent storage different from the file?
+    auto result = permStorage.IsDirty();
+    permStorage.Release();
+    if (result is COM.S_FALSE) return false;
+    return true;
+}
+public bool isFocusControl () {
+    checkWidget ();
+    auto focusHwnd = OS.GetFocus();
+    if (objIOleInPlaceObject is null) return (handle is focusHwnd);
+    HWND phwnd;
+    objIOleInPlaceObject.GetWindow(&phwnd);
+    while (focusHwnd !is null) {
+        if (phwnd is focusHwnd) return true;
+        focusHwnd = OS.GetParent(focusHwnd);
+    }
+    return false;
+}
+private int OnClose() {
+    return COM.S_OK;
+}
+private int OnDataChange(int pFormatetc, int pStgmed) {
+    return COM.S_OK;
+}
+private void onDispose(Event e) {
+    inDispose = true;
+    if (state !is STATE_NONE)
+        doVerb(OLE.OLEIVERB_DISCARDUNDOSTATE);
+    deactivateInPlaceClient();
+    releaseObjectInterfaces(); // Note, must release object interfaces before releasing frame
+    deleteTempStorage();
+
+    // remove listeners
+    removeListener(SWT.Dispose, listener);
+    removeListener(SWT.FocusIn, listener);
+    removeListener(SWT.Paint, listener);
+    removeListener(SWT.Traverse, listener);
+    removeListener(SWT.KeyDown, listener);
+    frame.removeListener(SWT.Resize, listener);
+    frame.removeListener(SWT.Move, listener);
+
+    frame.Release();
+    frame = null;
+}
+void onFocusIn(Event e) {
+    if (inDispose) return;
+    if (state !is STATE_UIACTIVE) doVerb(OLE.OLEIVERB_SHOW);
+    if (objIOleInPlaceObject is null) return;
+    if (isFocusControl()) return;
+    HWND phwnd;
+    objIOleInPlaceObject.GetWindow(&phwnd);
+    if (phwnd is null) return;
+    OS.SetFocus(phwnd);
+}
+void onFocusOut(Event e) {
+}
+private int OnInPlaceActivate() {
+    state = STATE_INPLACEACTIVE;
+    frame.setCurrentDocument(this);
+    if (objIOleObject is null)
+        return COM.S_OK;
+    int[] ppvObject = new int[1];
+    if (objIOleObject.QueryInterface(&COM.IIDIOleInPlaceObject, cast(void**)&objIOleInPlaceObject) is COM.S_OK) {
+        //objIOleInPlaceObject = new IOleInPlaceObject(ppvObject[0]);
+    }
+    return COM.S_OK;
+}
+private int OnInPlaceDeactivate() {
+    if (objIOleInPlaceObject !is null) objIOleInPlaceObject.Release();
+    objIOleInPlaceObject = null;
+    state = STATE_RUNNING;
+    redraw();
+    Shell shell = getShell();
+    if (isFocusControl() || frame.isFocusControl()) {
+        shell.traverse(SWT.TRAVERSE_TAB_NEXT);
+    }
+    return COM.S_OK;
+}
+private int OnPosRectChange(LPRECT lprcPosRect) {
+    Point size = getSize();
+    setExtent(size.x, size.y);
+    return COM.S_OK;
+}
+private void onPaint(Event e) {
+    if (state is STATE_RUNNING || state is STATE_INPLACEACTIVE) {
+        SIZE* size = getExtent();
+        Rectangle area = getClientArea();
+        RECT* rect = new RECT();
+        if (getProgramID().startsWith("Excel.Sheet")) { //$NON-NLS-1$
+            rect.left = area.x; rect.right = area.x + (area.height * size.cx / size.cy);
+            rect.top = area.y; rect.bottom = area.y + area.height;
+        } else {
+            rect.left = area.x; rect.right = area.x + size.cx;
+            rect.top = area.y; rect.bottom = area.y + size.cy;
+        }
+
+        auto pArea = cast(RECT*)OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, RECT.sizeof);
+        OS.MoveMemory(pArea, rect, RECT.sizeof);
+        COM.OleDraw(objIUnknown, aspect, e.gc.handle, pArea);
+        OS.GlobalFree(pArea);
+    }
+}
+private void onResize(Event e) {
+    Rectangle area = frame.getClientArea();
+    setBounds(borderWidths.left,
+              borderWidths.top,
+              area.width - borderWidths.left - borderWidths.right,
+              area.height - borderWidths.top - borderWidths.bottom);
+
+    setObjectRects();
+}
+private void OnSave() {
+}
+private int OnShowWindow(int fShow) {
+    return COM.S_OK;
+}
+private int OnUIActivate() {
+    if (objIOleInPlaceObject is null) return COM.E_FAIL;
+    state = STATE_UIACTIVE;
+    HWND phwnd;
+    if (objIOleInPlaceObject.GetWindow(&phwnd) is COM.S_OK) {
+        OS.SetWindowPos(phwnd, cast(HWND)OS.HWND_TOP, 0, 0, 0, 0, OS.SWP_NOSIZE | OS.SWP_NOMOVE);
+    }
+    return COM.S_OK;
+}
+private int OnUIDeactivate(int fUndoable) {
+    // currently, we are ignoring the fUndoable flag
+    if (frame is null || frame.isDisposed()) return COM.S_OK;
+    state = STATE_INPLACEACTIVE;
+    frame.SetActiveObject(null, null);
+    redraw();
+    Shell shell = getShell();
+    if (isFocusControl() || frame.isFocusControl()) {
+        shell.traverse(SWT.TRAVERSE_TAB_NEXT);
+    }
+    Menu menubar = shell.getMenuBar();
+    if (menubar is null || menubar.isDisposed())
+        return COM.S_OK;
+
+    auto shellHandle = shell.handle;
+    OS.SetMenu(shellHandle, menubar.handle);
+    return COM.OleSetMenuDescriptor(null, shellHandle, null, null, null);
+}
+private void onTraverse(Event event) {
+    switch (event.detail) {
+        case SWT.TRAVERSE_ESCAPE:
+        case SWT.TRAVERSE_RETURN:
+        case SWT.TRAVERSE_TAB_NEXT:
+        case SWT.TRAVERSE_TAB_PREVIOUS:
+        case SWT.TRAVERSE_PAGE_NEXT:
+        case SWT.TRAVERSE_PAGE_PREVIOUS:
+        case SWT.TRAVERSE_MNEMONIC:
+            event.doit = true;
+            break;
+        default:
+    }
+}
+private int OnViewChange(int dwAspect, int lindex) {
+    return COM.S_OK;
+}
+protected int QueryInterface(REFIID riid, void ** ppvObject) {
+
+    if (riid is null || ppvObject is null)
+        return COM.E_NOINTERFACE;
+    GUID oGuid = *riid;
+    GUID* guid = &oGuid;
+    //COM.MoveMemory(guid, riid, GUID.sizeof);
+
+    if (COM.IsEqualGUID(guid, &COM.IIDIUnknown)) {
+        *ppvObject = cast(void*)cast(IUnknown)iUnknown;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(guid, &COM.IIDIAdviseSink)) {
+        *ppvObject = cast(void*)cast(IAdviseSink)iAdviseSink;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(guid, &COM.IIDIOleClientSite)) {
+        *ppvObject = cast(void*)cast(IOleClientSite)iOleClientSite;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(guid, &COM.IIDIOleInPlaceSite)) {
+        *ppvObject = cast(void*)cast(IOleInPlaceSite)iOleInPlaceSite;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(guid, &COM.IIDIOleDocumentSite )) {
+        String progID = getProgramID();
+        if (!progID.startsWith("PowerPoint")) { //$NON-NLS-1$
+            *ppvObject = cast(void*)cast(IOleDocumentSite)iOleDocumentSite;
+            AddRef();
+            return COM.S_OK;
+        }
+    }
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+/**
+ * Returns the status of the specified command.  The status is any bitwise OR'd combination of
+ * SWTOLE.OLECMDF_SUPPORTED, SWTOLE.OLECMDF_ENABLED, SWTOLE.OLECMDF_LATCHED, SWTOLE.OLECMDF_NINCHED.
+ * You can query the status of a command before invoking it with OleClientSite.exec.  The
+ * OLE Document or ActiveX Control must support the IOleCommandTarget to make use of this method.
+ *
+ * @param cmd the ID of a command; these are the OLE.OLECMDID_ values - a small set of common
+ *            commands
+ *
+ * @return the status of the specified command or 0 if unable to query the OLE Object; these are the
+ *            OLE.OLECMDF_ values
+ */
+public int queryStatus(int cmd) {
+
+    if (objIOleCommandTarget is null) {
+        if (objIUnknown.QueryInterface(&COM.IIDIOleCommandTarget, cast(void**)&objIOleCommandTarget) !is COM.S_OK)
+            return 0;
+    }
+
+    OLECMD* olecmd = new OLECMD();
+    olecmd.cmdID = cmd;
+
+    auto result = objIOleCommandTarget.QueryStatus(null, 1, olecmd, null);
+
+    if (result !is COM.S_OK) return 0;
+
+    return olecmd.cmdf;
+}
+protected int Release() {
+    refCount--;
+
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+    }
+    return refCount;
+}
+protected void releaseObjectInterfaces() {
+
+    if (objIOleInPlaceObject !is null)
+        objIOleInPlaceObject.Release();
+    objIOleInPlaceObject = null;
+
+    if (objIOleObject !is null) {
+        objIOleObject.Close(COM.OLECLOSE_NOSAVE);
+        objIOleObject.Release();
+    }
+    objIOleObject = null;
+
+    if (objDocumentView !is null){
+        objDocumentView.Release();
+    }
+    objDocumentView = null;
+
+    if (objIViewObject2 !is null) {
+        objIViewObject2.SetAdvise(aspect, 0, null);
+        objIViewObject2.Release();
+    }
+    objIViewObject2 = null;
+
+    if (objIOleCommandTarget !is null)
+        objIOleCommandTarget.Release();
+    objIOleCommandTarget = null;
+
+    if (objIUnknown !is null){
+        objIUnknown.Release();
+    }
+    objIUnknown = null;
+
+    COM.CoFreeUnusedLibraries();
+}
+/**
+ * Saves the document to the specified file and includes OLE specific information if specified.  
+ * This method must <b>only</b> be used for files that have an OLE Storage format.  For example, 
+ * a word file edited with Word.Document should be saved using this method because there is 
+ * formating information that should be stored in the OLE specific Storage format.
+ *
+ * @param file the file to which the changes are to be saved
+ * @param includeOleInfo the flag to indicate whether OLE specific information should be saved.
+ *
+ * @return true if the save was successful
+ */
+public bool save(File file, bool includeOleInfo) {
+    if (includeOleInfo)
+        return saveToStorageFile(file);
+    return saveToTraditionalFile(file);
+}
+private bool saveFromContents(IStream address, File file) {
+
+    bool success = false;
+
+    IStream tempContents = address;
+    tempContents.AddRef();
+
+    try {
+        FileOutputStream writer = new FileOutputStream(file);
+
+        int increment = 1024 * 4;
+        LPVOID pv = COM.CoTaskMemAlloc(increment);
+        uint pcbWritten;
+        while (tempContents.Read(pv, increment, &pcbWritten) is COM.S_OK && pcbWritten > 0) {
+            byte[] buffer = new byte[ pcbWritten];
+            OS.MoveMemory(buffer.ptr, pv, pcbWritten);
+            writer.write(buffer); // Note: if file does not exist, this will create the file the
+                                  // first time it is called
+            success = true;
+        }
+        COM.CoTaskMemFree(pv);
+
+        writer.close();
+
+    } catch (IOException err) {
+    }
+
+    tempContents.Release();
+
+    return success;
+}
+private bool saveFromOle10Native(IStream address, File file) {
+
+    bool success = false;
+
+    IStream tempContents = address;
+    tempContents.AddRef();
+
+    // The "\1Ole10Native" stream contains a DWORD header whose value is the length
+    // of the native data that follows.
+    LPVOID pv = COM.CoTaskMemAlloc(4);
+    uint size;
+    auto rc = tempContents.Read(pv, 4, null);
+    OS.MoveMemory(&size, pv, 4);
+    COM.CoTaskMemFree(pv);
+    if (rc is COM.S_OK && size > 0) {
+
+        // Read the data
+        byte[] buffer = new byte[size];
+        pv = COM.CoTaskMemAlloc(size);
+        rc = tempContents.Read(pv, size, null);
+        OS.MoveMemory(buffer.ptr, pv, size);
+        COM.CoTaskMemFree(pv);
+
+        // open the file and write data into it
+        try {
+            FileOutputStream writer = new FileOutputStream(file);
+            writer.write(buffer); // Note: if file does not exist, this will create the file
+            writer.close();
+
+            success = true;
+        } catch (IOException err) {
+        }
+    }
+    tempContents.Release();
+
+    return success;
+}
+private int SaveObject() {
+
+    updateStorage();
+
+    return COM.S_OK;
+}
+/**
+ * Saves the document to the specified file and includes OLE specific information.  This method
+ * must <b>only</b> be used for files that have an OLE Storage format.  For example, a word file
+ * edited with Word.Document should be saved using this method because there is formating information
+ * that should be stored in the OLE specific Storage format.
+ *
+ * @param file the file to which the changes are to be saved
+ *
+ * @return true if the save was successful
+ */
+private bool saveToStorageFile(File file) {
+    // The file will be saved using the formating of the current application - this
+    // may not be the format of the application that was originally used to create the file
+    // e.g. if an Excel file is opened in Word, the Word application will save the file in the
+    // Word format
+    // Note: if the file already exists, some applications will not overwrite the file
+    // In these cases, you should delete the file first (probably save the contents of the file in case the
+    // save fails)
+    if (file is null || file.isDirectory()) return false;
+    if (!updateStorage()) return false;
+
+    // get access to the persistent storage mechanism
+    IPersistStorage permStorage;
+    if (objIOleObject.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&permStorage) !is COM.S_OK) return false;
+    try {
+        IStorage storage;
+        wchar* path = StrToWCHARz(file.getAbsolutePath());
+        int mode = COM.STGM_TRANSACTED | COM.STGM_READWRITE | COM.STGM_SHARE_EXCLUSIVE | COM.STGM_CREATE;
+        int result = COM.StgCreateDocfile(path, mode, 0, &storage); //Does an AddRef if successful
+        if (result !is COM.S_OK) return false;
+        try {
+            if (COM.OleSave(permStorage, storage, false) is COM.S_OK) {
+                if (storage.Commit(COM.STGC_DEFAULT) is COM.S_OK) {
+                    return true;
+                }
+            }
+        } finally {
+            storage.Release();
+        }
+    } finally {
+        permStorage.Release();
+    }
+    return false;
+}
+/**
+ * Saves the document to the specified file.  This method must be used for
+ * files that do not have an OLE Storage format.  For example, a bitmap file edited with MSPaint
+ * should be saved using this method because bitmap is a standard format that does not include any
+ * OLE specific data.
+ *
+ * @param file the file to which the changes are to be saved
+ *
+ * @return true if the save was successful
+ */
+private bool saveToTraditionalFile(File file) {
+    // Note: if the file already exists, some applications will not overwrite the file
+    // In these cases, you should delete the file first (probably save the contents of the file in case the
+    // save fails)
+    if (file is null || file.isDirectory())
+        return false;
+    if (!updateStorage())
+        return false;
+
+    IStream stream;
+    // Look for a CONTENTS stream
+    if (tempStorage.OpenStream(("CONTENTS"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$
+        return saveFromContents(stream, file);
+
+    // Look for Ole 1.0 object stream
+    if (tempStorage.OpenStream(("\1Ole10Native"w).ptr, null, COM.STGM_DIRECT | COM.STGM_READ | COM.STGM_SHARE_EXCLUSIVE, 0, &stream) is COM.S_OK) //$NON-NLS-1$
+        return saveFromOle10Native(stream, file);
+
+    return false;
+}
+private int Scroll(int scrollExtant) {
+    return COM.S_OK;
+}
+void setBorderSpace(RECT* newBorderwidth) {
+    borderWidths = *newBorderwidth;
+    // readjust size and location of client site
+    Rectangle area = frame.getClientArea();
+    setBounds(borderWidths.left, borderWidths.top,
+                area.width - borderWidths.left - borderWidths.right,
+                area.height - borderWidths.top - borderWidths.bottom);
+    setObjectRects();
+}
+private void setExtent(int width, int height){
+    // Resize the width and height of the embedded/linked OLENatives object
+    // to the specified values.
+
+    if (objIOleObject is null || isStatic || inUpdate) return;
+    SIZE* currentExtent = getExtent();
+    if (width is currentExtent.cx && height is currentExtent.cy) return;
+
+    SIZE* newExtent = new SIZE();
+    newExtent.cx = width; newExtent.cy = height;
+    newExtent = xFormPixelsToHimetric(newExtent);
+
+   // Get the server running first, then do a SetExtent, then show it
+    bool alreadyRunning = cast(bool) COM.OleIsRunning(objIOleObject);
+    if (!alreadyRunning)
+        COM.OleRun(objIOleObject);
+
+    if (objIOleObject.SetExtent(aspect, newExtent) is COM.S_OK){
+        inUpdate = true;
+        objIOleObject.Update();
+        inUpdate = false;
+        if (!alreadyRunning)
+            // Close server if it wasn't already running upon entering this method.
+            objIOleObject.Close(COM.OLECLOSE_SAVEIFDIRTY);
+    }
+}
+/**
+ * The indent value is no longer being used by the client site.
+ * 
+ * @param newIndent the rectangle representing the indent amount
+ */
+public void setIndent(Rectangle newIndent) {
+    indent.left = newIndent.x;
+    indent.right = newIndent.width;
+    indent.top = newIndent.y;
+    indent.bottom = newIndent.height;
+}
+private void setObjectRects() {
+    if (objIOleInPlaceObject is null) return;
+    // size the object to fill the available space
+    // leave a border
+    RECT* rect = getRect();
+    objIOleInPlaceObject.SetObjectRects(rect, rect);
+}
+
+private int ShowObject() {
+    /* Tells the container to position the object so it is visible to
+     * the user. This method ensures that the container itself is
+     * visible and not minimized.
+     */
+    return COM.S_OK;
+}
+/**
+ * Displays a dialog with the property information for this OLE Object.  The OLE Document or
+ * ActiveX Control must support the ISpecifyPropertyPages interface.
+ *
+ * @param title the name that will appear in the titlebar of the dialog
+ */
+public void showProperties(String title) {
+
+    // Get the Property Page information from the OLE Object
+    ISpecifyPropertyPages objISPP;
+    if (objIUnknown.QueryInterface(&COM.IIDISpecifyPropertyPages, cast(void**)&objISPP) !is COM.S_OK) return;
+    CAUUID* caGUID = new CAUUID();
+    auto result = objISPP.GetPages(caGUID);
+    objISPP.Release();
+    if (result !is COM.S_OK) return;
+
+    // create a frame in which to display the pages
+    wchar* chTitle = null;
+    if (title !is null) {
+        chTitle = StrToWCHARz(title);
+    }
+    result = COM.OleCreatePropertyFrame(frame.handle, 10, 10, chTitle, 1, &objIUnknown, caGUID.cElems, caGUID.pElems, COM.LOCALE_USER_DEFAULT, 0, null);
+
+    // free the property page information
+    COM.CoTaskMemFree(caGUID.pElems);
+}
+private bool updateStorage() {
+
+    if (tempStorage is null) return false;
+
+    IPersistStorage iPersistStorage;
+    if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&iPersistStorage) !is COM.S_OK) return false;
+
+    auto result = COM.OleSave(iPersistStorage, tempStorage, true);
+
+    if (result !is COM.S_OK){
+        // OleSave will fail for static objects, so do what OleSave does.
+        COM.WriteClassStg(tempStorage, objClsid);
+        result = iPersistStorage.Save(tempStorage, true);
+    }
+
+    tempStorage.Commit(COM.STGC_DEFAULT);
+    result = iPersistStorage.SaveCompleted(null);
+    iPersistStorage.Release();
+
+    return true;
+}
+private SIZE* xFormHimetricToPixels(SIZE* aSize) {
+    // Return a new Size which is the pixel transformation of a
+    // size in HIMETRIC units.
+
+    auto hDC = OS.GetDC(null);
+    int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+    int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+    OS.ReleaseDC(null, hDC);
+    int cx = Compatibility.round(aSize.cx * xppi, 2540); // 2540 HIMETRIC units per inch
+    int cy = Compatibility.round(aSize.cy * yppi, 2540);
+    SIZE* size = new SIZE();
+    size.cx = cx;
+    size.cy = cy;
+    return size;
+}
+private SIZE* xFormPixelsToHimetric(SIZE* aSize) {
+    // Return a new size which is the HIMETRIC transformation of a
+    // size in pixel units.
+
+    auto hDC = OS.GetDC(null);
+    int xppi = OS.GetDeviceCaps(hDC, 88); // logical pixels/inch in x
+    int yppi = OS.GetDeviceCaps(hDC, 90); // logical pixels/inch in y
+    OS.ReleaseDC(null, hDC);
+    int cx = Compatibility.round(aSize.cx * 2540, xppi); // 2540 HIMETRIC units per inch
+    int cy = Compatibility.round(aSize.cy * 2540, yppi);
+    SIZE* size = new SIZE();
+    size.cx = cx;
+    size.cy = cy;
+    return size;
+}
+}
+
+class _IAdviseSinkImpl : IAdviseSink {
+
+    OleClientSite   parent;
+    this(OleClientSite  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IAdviseSink
+    void OnDataChange(FORMATETC *pFormatetc,STGMEDIUM *pStgmed) {return COM.S_OK; }
+    void OnViewChange(DWORD dwAspect, LONG lindex) {return COM.S_OK; }
+    void OnRename(IMoniker pmk) {return COM.S_OK; }
+    void OnSave() {return COM.S_OK; }
+    void OnClose() {return COM.S_OK; }
+}
+
+class _IOleClientSiteImpl : IOleClientSite {
+
+    OleClientSite   parent;
+    this(OleClientSite  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IOleClientSite
+    HRESULT SaveObject() {  if(parent) parent.updateStorage(); return COM.S_OK; }
+    HRESULT GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, IMoniker * ppmk ) {return COM.E_NOTIMPL; }
+    HRESULT GetContainer( IOleContainer* ppContainer ) { return parent.GetContainer(ppContainer);}
+    HRESULT ShowObject() {
+        /* Tells the container to position the object so it is visible to
+         * the user. This method ensures that the container itself is
+         * visible and not minimized.
+         */
+        return COM.S_OK;
+    }
+    HRESULT OnShowWindow(BOOL fShow ) {return COM.S_OK; }
+    HRESULT RequestNewObjectLayout() {return COM.E_NOTIMPL; }
+}
+
+class  _IOleDocumentSiteImpl : IOleDocumentSite {
+
+    OleClientSite   parent;
+    this(OleClientSite  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IOleDocumentSite
+    HRESULT ActivateMe(IOleDocumentView pViewToActivate) { return parent.ActivateMe(pViewToActivate);}
+}
+
+class _IOleInPlaceSiteImpl : IOleInPlaceSite {
+    OleClientSite   parent;
+    this(OleClientSite  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IOleWindow
+    HRESULT GetWindow( HWND*  phwnd ) { return parent.GetWindow(phwnd); }
+    HRESULT ContextSensitiveHelp( BOOL fEnterMode ) {return COM.S_OK; }
+
+    // interface of IOleInPlaceSite
+    HRESULT CanInPlaceActivate() { return parent.CanInPlaceActivate();}
+    HRESULT OnInPlaceActivate() { return parent.OnInPlaceActivate(); }
+    HRESULT OnUIActivate() { return parent.OnUIActivate(); }
+    HRESULT GetWindowContext( IOleInPlaceFrame * ppFrame, IOleInPlaceUIWindow * ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo ) {
+        return parent.GetWindowContext(ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
+    }
+    HRESULT Scroll( SIZE scrollExtant ) {return COM.S_OK; }
+    HRESULT OnUIDeactivate( BOOL fUndoable ) { return parent.OnUIDeactivate(fUndoable);}
+    HRESULT OnInPlaceDeactivate() { return parent.OnInPlaceDeactivate();}
+    HRESULT DiscardUndoState() {return COM.E_NOTIMPL; }
+    HRESULT DeactivateAndUndo() {return COM.E_NOTIMPL; }
+    HRESULT OnPosRectChange( LPCRECT lprcPosRect) { return parent.OnPosRectChange(lprcPosRect);}
+}
+
+class _IUnknownImpl : IUnknown
+{
+
+    OleClientSite   parent;
+    this(OleClientSite  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleControlSite.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,915 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleControlSite;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.ifs;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.OBJIDL;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OleEventSink;
+import org.eclipse.swt.ole.win32.OlePropertyChangeSink;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.Variant;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+
+/**
+ * OleControlSite provides a site to manage an embedded ActiveX Control within a container.
+ *
+ * <p>In addition to the behaviour provided by OleClientSite, this object provides the following:
+ * <ul>
+ *  <li>events from the ActiveX control
+ *  <li>notification of property changes from the ActiveX control
+ *  <li>simplified access to well known properties of the ActiveX Control (e.g. font, background color)
+ *  <li>expose ambient properties of the container to the ActiveX Control
+ * </ul>
+ *
+ * <p>This object implements the OLE Interfaces IOleControlSite, IDispatch, and IPropertyNotifySink.
+ *
+ * <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.
+ * </p><p>
+ * <dl>
+ *  <dt><b>Styles</b> <dd>BORDER
+ *  <dt><b>Events</b> <dd>Dispose, Move, Resize
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
+ */
+public class OleControlSite : OleClientSite
+{
+    // interfaces for this container
+    private _IOleControlSiteImpl iOleControlSite;
+    private _IDispatchImpl       iDispatch;
+
+    // supporting Property Change attributes
+    private OlePropertyChangeSink olePropertyChangeSink;
+
+    // supporting Event Sink attributes
+    private OleEventSink[] oleEventSink;
+    private GUID*[] oleEventSinkGUID;
+    private IUnknown[] oleEventSinkIUnknown;
+
+    // supporting information for the Control COM object
+    private CONTROLINFO* currentControlInfo;
+    private int[] sitePropertyIds;
+    private Variant[] sitePropertyValues;
+
+    // work around for IE destroying the caret
+    static int SWT_RESTORECARET;
+
+/**
+ * Create an OleControlSite child widget using style bits
+ * to select a particular look or set of properties.
+ *
+ * @param parent a composite widget; must be an OleFrame
+ * @param style the bitwise OR'ing of widget styles
+ * @param progId the unique program identifier which has been registered for this ActiveX Control;
+ *               the value of the ProgID key or the value of the VersionIndependentProgID key specified
+ *               in the registry for this Control (for example, the VersionIndependentProgID for
+ *               Internet Explorer is Shell.Explorer)
+ *
+ * @exception IllegalArgumentException <ul>
+ *     <li>ERROR_NULL_ARGUMENT when the parent is null
+ *</ul>
+ * @exception SWTException <ul>
+ *     <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ *     <li>ERROR_INVALID_CLASSID when the progId does not map to a registered CLSID
+ *     <li>ERROR_CANNOT_CREATE_OBJECT when failed to create OLE Object
+ *     <li>ERROR_CANNOT_ACCESS_CLASSFACTORY when Class Factory could not be found
+ *     <li>ERROR_CANNOT_CREATE_LICENSED_OBJECT when failed to create a licensed OLE Object
+ * </ul>
+ */
+public this(Composite parent, int style, String progId) {
+    super(parent, style);
+    try {
+
+        // check for licensing
+        appClsid = getClassID(progId);
+        if (appClsid is null) OLE.error(__FILE__, __LINE__, OLE.ERROR_INVALID_CLASSID);
+
+        BSTR licinfo = getLicenseInfo(appClsid);
+        if (licinfo is null) {
+
+            // Open a storage object
+            tempStorage = createTempStorage();
+
+            // Create ole object with storage object
+            HRESULT result = COM.OleCreate(appClsid, &COM.IIDIUnknown, COM.OLERENDER_DRAW, null, null, tempStorage, cast(void**)&objIUnknown);
+            if (result !is COM.S_OK)
+                OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_OBJECT, result);
+
+        } else {
+            // Prepare the ClassFactory
+            try {
+                IClassFactory2 classFactory;
+                HRESULT result = COM.CoGetClassObject(appClsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory);
+                if (result !is COM.S_OK) {
+                    OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_ACCESS_CLASSFACTORY, result);
+                }
+                // Create Com Object
+                result = classFactory.CreateInstanceLic(null, null, &COM.IIDIUnknown, licinfo, cast(void**)&objIUnknown);
+                classFactory.Release();
+                if (result !is COM.S_OK)
+                    OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CREATE_LICENSED_OBJECT, result);
+            } finally {
+                COM.SysFreeString(licinfo);
+            }
+
+            // Prepare a storage medium
+            IPersistStorage persist;
+            if (objIUnknown.QueryInterface(&COM.IIDIPersistStorage, cast(void**)&persist) is COM.S_OK) {
+                tempStorage = createTempStorage();
+                persist.InitNew(tempStorage);
+                persist.Release();
+            }
+        }
+
+        // Init sinks
+        addObjectReferences();
+
+        // Init site properties
+        setSiteProperty(COM.DISPID_AMBIENT_USERMODE, new Variant(true));
+        setSiteProperty(COM.DISPID_AMBIENT_UIDEAD, new Variant(false));
+
+        if (COM.OleRun(objIUnknown) is OLE.S_OK) state= STATE_RUNNING;
+
+    } catch (SWTError e) {
+        dispose();
+        disposeCOMInterfaces();
+        throw e;
+    }
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @param eventID the id of the event
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addEventListener(int eventID, OleListener listener) {
+    if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    GUID* riid = getDefaultEventSinkGUID(objIUnknown);
+    if (riid !is null) {
+        addEventListener(objIUnknown, riid, eventID, listener);
+    }
+}
+
+
+static GUID* getDefaultEventSinkGUID(IUnknown unknown) {
+    // get Event Sink I/F from IProvideClassInfo2
+    IProvideClassInfo2 pci2;
+    if (unknown.QueryInterface(&COM.IIDIProvideClassInfo2, cast(void**)&pci2) is COM.S_OK) {
+        GUID* riid = new GUID();
+        HRESULT result = pci2.GetGUID(COM.GUIDKIND_DEFAULT_SOURCE_DISP_IID, riid);
+        pci2.Release();
+        if (result is COM.S_OK) return riid;
+    }
+
+    // get Event Sink I/F from IProvideClassInfo
+    IProvideClassInfo pci;
+    if (unknown.QueryInterface(&COM.IIDIProvideClassInfo, cast(void**)&pci) is COM.S_OK) {
+        ITypeInfo classInfo;
+        ITypeInfo eventInfo;
+        HRESULT result = pci.GetClassInfo(&classInfo);
+        pci.Release();
+
+        if (result is COM.S_OK && classInfo !is null) {
+            TYPEATTR* typeAttribute;
+            result = classInfo.GetTypeAttr(&typeAttribute);
+            if (result is COM.S_OK  && typeAttribute !is null) {
+                int implMask = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE | COM.IMPLTYPEFLAG_FRESTRICTED;
+                int implBits = COM.IMPLTYPEFLAG_FDEFAULT | COM.IMPLTYPEFLAG_FSOURCE;
+
+                for (uint i = 0; i < typeAttribute.cImplTypes; i++) {
+                    int pImplTypeFlags;
+                    if (classInfo.GetImplTypeFlags(i, &pImplTypeFlags) is COM.S_OK) {
+                        if ((pImplTypeFlags & implMask) is implBits) {
+                            uint pRefType;
+                            if (classInfo.GetRefTypeOfImplType(i, &pRefType) is COM.S_OK) {
+                                classInfo.GetRefTypeInfo(pRefType, &eventInfo);
+                            }
+                        }
+                    }
+                }
+                classInfo.ReleaseTypeAttr(typeAttribute);
+            }
+            classInfo.Release();
+
+            if (eventInfo !is null) {
+                TYPEATTR* ppTypeAttr;
+                result = eventInfo.GetTypeAttr(&ppTypeAttr);
+                GUID* riid = null;
+                if (result is COM.S_OK && ppTypeAttr !is null) {
+                    riid = new GUID();
+                    *riid = ppTypeAttr.guid;
+                    eventInfo.ReleaseTypeAttr(ppTypeAttr);
+                }
+                eventInfo.Release();
+                return riid;
+            }
+        }
+    }
+    return null;
+}
+
+/**
+ * Adds the listener to receive events.
+ *
+ * @since 2.0
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventID the id of the event
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ *     <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addEventListener(OleAutomation automation, int eventID, OleListener listener) {
+    if (listener is null || automation is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    IUnknown unknown = automation.getAddress();
+    GUID* riid = getDefaultEventSinkGUID(unknown);
+    if (riid !is null) {
+        addEventListener(unknown, riid, eventID, listener);
+    }
+
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @since 3.2
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventSinkId the GUID of the event sink
+ * @param eventID the id of the event
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ *     <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addEventListener(OleAutomation automation, String eventSinkId, int eventID, OleListener listener) {
+    if (listener is null || automation is null || eventSinkId is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    auto address = automation.getAddress();
+    if (address is null) return;
+    wchar[] buffer = StrToWCHARs(0,eventSinkId,true);
+    GUID* guid = new GUID();
+    if (COM.IIDFromString(buffer.ptr, guid) !is COM.S_OK) return;
+    addEventListener(address, guid, eventID, listener);
+}
+
+void addEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
+    if (listener is null || iunknown is null || guid is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    // have we connected to this kind of event sink before?
+    int index = -1;
+    for (int i = 0; i < oleEventSinkGUID.length; i++) {
+        if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
+            if (iunknown is oleEventSinkIUnknown[i]) {
+                index = i;
+                break;
+            }
+        }
+    }
+    if (index !is -1) {
+        oleEventSink[index].addListener(eventID, listener);
+    } else {
+        int oldLength = oleEventSink.length;
+
+        oleEventSink ~= new OleEventSink(this, iunknown, guid);
+        oleEventSinkGUID ~= guid;
+        oleEventSinkIUnknown ~= iunknown;
+
+        oleEventSink[oldLength].AddRef();
+        oleEventSink[oldLength].connect();
+        oleEventSink[oldLength].addListener(eventID, listener);
+
+    }
+}
+protected void addObjectReferences() {
+
+    super.addObjectReferences();
+
+    // Get property change notification from control
+    connectPropertyChangeSink();
+
+    // Get access to the Control object
+    IOleControl objIOleControl;
+    if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl) is COM.S_OK) {
+        // ask the control for its info in case users
+        // need to act on it
+        currentControlInfo = new CONTROLINFO();
+        objIOleControl.GetControlInfo(currentControlInfo);
+        objIOleControl.Release();
+    }
+}
+/**
+ * Adds the listener to receive events.
+ *
+ * @param propertyID the identifier of the property
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void addPropertyListener(int propertyID, OleListener listener) {
+    if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    olePropertyChangeSink.addListener(propertyID, listener);
+}
+
+private void connectPropertyChangeSink() {
+    olePropertyChangeSink = new OlePropertyChangeSink(this);
+    olePropertyChangeSink.AddRef();
+    olePropertyChangeSink.connect(objIUnknown);
+}
+protected void createCOMInterfaces () {
+    super.createCOMInterfaces();
+    iOleControlSite = new _IOleControlSiteImpl(this);
+    iDispatch = new _IDispatchImpl(this);
+}
+private void disconnectEventSinks() {
+
+    for (int i = 0; i < oleEventSink.length; i++) {
+        OleEventSink sink = oleEventSink[i];
+        sink.disconnect();
+        sink.Release();
+    }
+    oleEventSink = null;
+    oleEventSinkGUID = null;
+    oleEventSinkIUnknown = null;
+}
+private void disconnectPropertyChangeSink() {
+
+    if (olePropertyChangeSink !is null) {
+        olePropertyChangeSink.disconnect(objIUnknown);
+        olePropertyChangeSink.Release();
+    }
+    olePropertyChangeSink = null;
+}
+protected void disposeCOMInterfaces() {
+    super.disposeCOMInterfaces();
+    iOleControlSite = null;
+    iDispatch = null;
+}
+public Color getBackground () {
+
+    if (objIUnknown !is null) {
+        // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
+        OleAutomation oleObject= new OleAutomation(this);
+        Variant varBackColor = oleObject.getProperty(COM.DISPID_BACKCOLOR);
+        oleObject.dispose();
+
+        if (varBackColor !is null){
+            COLORREF colorRef;
+            if (COM.OleTranslateColor(varBackColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
+                return Color.win32_new(getDisplay(), colorRef);
+        }
+    }
+
+    return super.getBackground();
+}
+public Font getFont () {
+
+    if (objIUnknown !is null) {
+        OleAutomation oleObject= new OleAutomation(this);
+        Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+        oleObject.dispose();
+
+        if (varDispFont !is null){
+            OleAutomation iDispFont = varDispFont.getAutomation();
+            Variant lfFaceName = iDispFont.getProperty(COM.DISPID_FONT_NAME);
+            Variant lfHeight   = iDispFont.getProperty(COM.DISPID_FONT_SIZE);
+            Variant lfItalic   = iDispFont.getProperty(COM.DISPID_FONT_ITALIC);
+            //Variant lfCharSet  = iDispFont.getProperty(COM.DISPID_FONT_CHARSET);
+            Variant lfBold     = iDispFont.getProperty(COM.DISPID_FONT_BOLD);
+            iDispFont.dispose();
+
+            if (lfFaceName !is null &&
+                lfHeight !is null &&
+                lfItalic !is null &&
+                lfBold !is null){
+                int style = 3 * lfBold.getInt() + 2 * lfItalic.getInt();
+                Device dev = getShell().getDisplay();
+                Font font = new Font(dev, lfFaceName.getString(), lfHeight.getInt(), style);
+                return font;
+            }
+        }
+    }
+
+    return super.getFont();
+}
+public Color getForeground () {
+
+    if (objIUnknown !is null) {
+        // !! We are getting the OLE_COLOR - should we change this to the COLORREF value?
+        OleAutomation oleObject= new OleAutomation(this);
+        Variant varForeColor = oleObject.getProperty(COM.DISPID_FORECOLOR);
+        oleObject.dispose();
+
+        if (varForeColor !is null){
+            COLORREF colorRef;
+            if (COM.OleTranslateColor(varForeColor.getInt(), getDisplay().hPalette, &colorRef) is COM.S_OK)
+                return Color.win32_new(getDisplay(), colorRef);
+        }
+    }
+
+    return super.getForeground();
+}
+protected BSTR getLicenseInfo(GUID* clsid) {
+    IClassFactory2 classFactory;
+    if (COM.CoGetClassObject(clsid, COM.CLSCTX_INPROC_HANDLER | COM.CLSCTX_INPROC_SERVER, null, &COM.IIDIClassFactory2, cast(void**)&classFactory) !is COM.S_OK) {
+        return null;
+    }
+    LICINFO licinfo;
+    if (classFactory.GetLicInfo(&licinfo) !is COM.S_OK) {
+        classFactory.Release();
+        return null;
+    }
+    BSTR pBstrKey;
+    if (licinfo.fRuntimeKeyAvail) {
+        if (classFactory.RequestLicKey(0, &pBstrKey) is COM.S_OK) {
+            classFactory.Release();
+            return pBstrKey;
+        }
+    }
+    classFactory.Release();
+    return null;
+}
+/**
+ *
+ * Get the control site property specified by the dispIdMember, or
+ * <code>null</code> if the dispId is not recognised.
+ *
+ * @param dispId the dispId
+ *
+ * @return the property value or <code>null</code>
+ * 
+ * @since 2.1
+ */
+public Variant getSiteProperty(int dispId){
+    for (int i = 0; i < sitePropertyIds.length; i++) {
+        if (sitePropertyIds[i] is dispId) {
+            return sitePropertyValues[i];
+        }
+    }
+    return null;
+}
+protected HRESULT GetWindow(HWND* phwnd) {
+
+    if (phwnd is null)
+        return COM.E_INVALIDARG;
+    if (frame is null) {
+        *phwnd = null;
+        return COM.E_NOTIMPL;
+    }
+
+    // Copy the Window's handle into the memory passed in
+    *phwnd = handle;
+    return COM.S_OK;
+}
+
+private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD dwFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* pArgErr) {
+    int nullv = 0;
+    if (pVarResult is null || dwFlags !is COM.DISPATCH_PROPERTYGET) {
+        if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+        if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+        return COM.DISP_E_MEMBERNOTFOUND;
+    }
+    Variant result = getSiteProperty(dispIdMember);
+    if (result !is null) {
+        if (pVarResult !is null) result.getData(pVarResult);
+        return COM.S_OK;
+    }
+    switch (dispIdMember) {
+            // indicate a false result
+        case COM.DISPID_AMBIENT_SUPPORTSMNEMONICS :
+        case COM.DISPID_AMBIENT_SHOWGRABHANDLES :
+        case COM.DISPID_AMBIENT_SHOWHATCHING :
+            if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+            if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+            if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+            return COM.S_FALSE;
+
+            // not implemented
+        case COM.DISPID_AMBIENT_OFFLINEIFNOTCONNECTED :
+        case COM.DISPID_AMBIENT_BACKCOLOR :
+        case COM.DISPID_AMBIENT_FORECOLOR :
+        case COM.DISPID_AMBIENT_FONT :
+        case COM.DISPID_AMBIENT_LOCALEID :
+        case COM.DISPID_AMBIENT_SILENT :
+        case COM.DISPID_AMBIENT_MESSAGEREFLECT :
+            if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+            if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+            if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+            return COM.E_NOTIMPL;
+
+        default :
+            if (pVarResult !is null) COM.MoveMemory(pVarResult, &nullv, 4);
+            if (pExcepInfo !is null) COM.MoveMemory(pExcepInfo, &nullv, 4);
+            if (pArgErr !is null) COM.MoveMemory(pArgErr, &nullv, 4);
+            return COM.DISP_E_MEMBERNOTFOUND;
+    }
+}
+private int OnControlInfoChanged() {
+    IOleControl objIOleControl;
+    if (objIUnknown.QueryInterface(&COM.IIDIOleControl, cast(void**)&objIOleControl ) is COM.S_OK) {
+        // ask the control for its info in case users
+        // need to act on it
+        currentControlInfo = new CONTROLINFO();
+        objIOleControl.GetControlInfo(currentControlInfo);
+        objIOleControl.Release();
+    }
+    return COM.S_OK;
+}
+void onFocusIn(Event e) {
+    if (objIOleInPlaceObject is null) return;
+    doVerb(OLE.OLEIVERB_UIACTIVATE);
+    if (isFocusControl()) return;
+    HWND phwnd;
+    objIOleInPlaceObject.GetWindow(&phwnd);
+    if (phwnd is null) return;
+    OS.SetFocus(phwnd);
+}
+void onFocusOut(Event e) {
+    if (objIOleInPlaceObject !is null) {
+        /*
+        * Bug in Windows.  When IE7 loses focus and UIDeactivate()
+        * is called, IE destroys the caret even though it is
+        * no longer owned by IE.  If focus has moved to a control
+        * that shows a caret then the caret disappears.  The fix
+        * is to detect this case and restore the caret.
+        */
+        auto threadId = OS.GetCurrentThreadId();
+        GUITHREADINFO* lpgui1 = new GUITHREADINFO();
+        lpgui1.cbSize = GUITHREADINFO.sizeof;
+        OS.GetGUIThreadInfo(threadId, lpgui1);
+        objIOleInPlaceObject.UIDeactivate();
+        if (lpgui1.hwndCaret !is null) {
+            GUITHREADINFO* lpgui2 = new GUITHREADINFO();
+            lpgui2.cbSize = GUITHREADINFO.sizeof;
+            OS.GetGUIThreadInfo(threadId, lpgui2);
+            if (lpgui2.hwndCaret is null && lpgui1.hwndCaret is OS.GetFocus()) {
+                if (SWT_RESTORECARET is 0) {
+                    SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz (0, "SWT_RESTORECARET"));
+                }
+                /*
+                * If the caret was not restored by SWT, put it back using
+                * the information from GUITHREADINFO.  Note that this will
+                * not be correct when the caret has a bitmap.  There is no
+                * API to query the bitmap that the caret is using.
+                */
+                if (OS.SendMessage (lpgui1.hwndCaret, SWT_RESTORECARET, 0, 0) is 0) {
+                    int width = lpgui1.rcCaret.right - lpgui1.rcCaret.left;
+                    int height = lpgui1.rcCaret.bottom - lpgui1.rcCaret.top;
+                    OS.CreateCaret (lpgui1.hwndCaret, null, width, height);
+                    OS.SetCaretPos (lpgui1.rcCaret.left, lpgui1.rcCaret.top);
+                    OS.ShowCaret (lpgui1.hwndCaret);
+                }
+            }
+        }
+    }
+}
+private int OnFocus(int fGotFocus) {
+    return COM.S_OK;
+}
+protected int OnUIDeactivate(int fUndoable) {
+    // controls don't need to do anything for
+    // border space or menubars
+    state = STATE_INPLACEACTIVE;
+    return COM.S_OK;
+}
+override protected HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+    int nullv = 0;
+    int result = super.QueryInterface(riid, ppvObject);
+    if (result is COM.S_OK)
+        return result;
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+    GUID oGuid = *riid;
+    GUID* guid = &oGuid;
+    //COM.MoveMemory(&guid, riid, GUID.sizeof);
+    if (COM.IsEqualGUID(guid, &COM.IIDIOleControlSite)) {
+        *ppvObject = cast(void*)cast(IOleControlSite)iOleControlSite;
+        AddRef();
+        return COM.S_OK;
+    }
+    if (COM.IsEqualGUID(guid, &COM.IIDIDispatch)) {
+        *ppvObject = cast(void*)cast(IDispatch)iDispatch;
+        AddRef();
+        return COM.S_OK;
+    }
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+protected int Release() {
+    int result = super.Release();
+    if (result is 0) {
+        for (int i = 0; i < sitePropertyIds.length; i++) {
+            sitePropertyValues[i].dispose();
+        }
+        sitePropertyIds = null;
+        sitePropertyValues = null;
+    }
+    return result;
+}
+protected void releaseObjectInterfaces() {
+
+    disconnectEventSinks();
+
+    disconnectPropertyChangeSink();
+
+    super.releaseObjectInterfaces();
+}
+/**
+ * Removes the listener.
+ *
+ * @param eventID the event identifier
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeEventListener(int eventID, OleListener listener) {
+    checkWidget();
+    if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+
+    GUID* riid = getDefaultEventSinkGUID(objIUnknown);
+    if (riid !is null) {
+        removeEventListener(objIUnknown, riid, eventID, listener);
+    }
+}
+/**
+ * Removes the listener.
+ *
+ * @since 2.0
+ * @deprecated - use OleControlSite.removeEventListener(OleAutomation, int, OleListener)
+ *
+ * @param automation the automation object that provides the event notification
+ *
+ * @param guid the identifier of the events COM interface
+ *
+ * @param eventID the event identifier
+ *
+ * @param listener the listener
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removeEventListener(OleAutomation automation, GUID* guid, int eventID, OleListener listener) {
+    checkWidget();
+    if (automation is null || listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    removeEventListener(automation.getAddress(), guid, eventID, listener);
+}
+/**
+ * Removes the listener.
+ *
+ * @param automation the automation object that provides the event notification
+ * @param eventID the event identifier
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ * 
+ * @since 2.0
+ */
+public void removeEventListener(OleAutomation automation, int eventID, OleListener listener) {
+    checkWidget();
+    if (automation is null || listener is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    auto unknown = automation.getAddress();
+    GUID* riid = getDefaultEventSinkGUID(unknown);
+    if (riid !is null) {
+        removeEventListener(unknown, riid, eventID, listener);
+    }
+}
+void removeEventListener(IUnknown iunknown, GUID* guid, int eventID, OleListener listener) {
+    if (listener is null || guid is null) SWT.error ( __FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    for (int i = 0; i < oleEventSink.length; i++) {
+        if (COM.IsEqualGUID(oleEventSinkGUID[i], guid)) {
+            if (iunknown is oleEventSinkIUnknown[i]) {
+                oleEventSink[i].removeListener(eventID, listener);
+                if (!oleEventSink[i].hasListeners()) {
+                    //free resources associated with event sink
+                    oleEventSink[i].disconnect();
+                    oleEventSink[i].Release();
+                    int oldLength = oleEventSink.length;
+                    if (oldLength is 1) {
+                        oleEventSink = null;
+                        oleEventSinkGUID = null;
+                        oleEventSinkIUnknown = null;
+                    } else {
+                        OleEventSink[] newOleEventSink = new OleEventSink[oldLength - 1];
+                        System.arraycopy(oleEventSink, 0, newOleEventSink, 0, i);
+                        System.arraycopy(oleEventSink, i + 1, newOleEventSink, i, oldLength - i - 1);
+                        oleEventSink = newOleEventSink;
+
+                        GUID*[] newOleEventSinkGUID = new GUID*[oldLength - 1];
+                        SimpleType!(GUID*).arraycopy(oleEventSinkGUID, 0, newOleEventSinkGUID, 0, i);
+                        SimpleType!(GUID*).arraycopy(oleEventSinkGUID, i + 1, newOleEventSinkGUID, i, oldLength - i - 1);
+                        oleEventSinkGUID = newOleEventSinkGUID;
+
+                        IUnknown[] newOleEventSinkIUnknown = new IUnknown[oldLength - 1];
+                        SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, 0, newOleEventSinkIUnknown, 0, i);
+                        SimpleType!(IUnknown).arraycopy(oleEventSinkIUnknown, i + 1, newOleEventSinkIUnknown, i, oldLength - i - 1);
+                        oleEventSinkIUnknown = newOleEventSinkIUnknown;
+                    }
+                }
+                return;
+            }
+        }
+    }
+}
+/**
+ * Removes the listener.
+ *
+ * @param propertyID the identifier of the property
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *      <li>ERROR_NULL_ARGUMENT when listener is null</li>
+ * </ul>
+ */
+public void removePropertyListener(int propertyID, OleListener listener) {
+    if (listener is null) SWT.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    olePropertyChangeSink.removeListener(propertyID, listener);
+}
+public void setBackground (Color color) {
+
+    super.setBackground(color);
+
+    //set the background of the ActiveX Control
+    if (objIUnknown !is null) {
+        OleAutomation oleObject= new OleAutomation(this);
+        oleObject.setProperty(COM.DISPID_BACKCOLOR, new Variant(cast(int)color.handle));
+        oleObject.dispose();
+    }
+}
+public void setFont (Font font) {
+
+    super.setFont(font);
+
+    //set the font of the ActiveX Control
+    if (objIUnknown !is null) {
+
+        OleAutomation oleObject= new OleAutomation(this);
+        Variant varDispFont = oleObject.getProperty(COM.DISPID_FONT);
+        oleObject.dispose();
+
+        if (varDispFont !is null){
+            OleAutomation iDispFont = varDispFont.getAutomation();
+            FontData[] fdata = font.getFontData();
+            iDispFont.setProperty(COM.DISPID_FONT_NAME,   new Variant(fdata[0].getName()));
+            iDispFont.setProperty(COM.DISPID_FONT_SIZE,   new Variant(fdata[0].getHeight()));
+            iDispFont.setProperty(COM.DISPID_FONT_ITALIC, new Variant(fdata[0].getStyle() & SWT.ITALIC));
+            //iDispFont.setProperty(COM.DISPID_FONT_CHARSET, new Variant(fdata[0].getCharset));
+            iDispFont.setProperty(COM.DISPID_FONT_BOLD,   new Variant((fdata[0].getStyle() & SWT.BOLD)));
+            iDispFont.dispose();
+        }
+    }
+
+    return;
+}
+public void setForeground (Color color) {
+
+    super.setForeground(color);
+
+    //set the foreground of the ActiveX Control
+    if (objIUnknown !is null) {
+        OleAutomation oleObject= new OleAutomation(this);
+        oleObject.setProperty(COM.DISPID_FORECOLOR, new Variant(cast(int)color.handle));
+        oleObject.dispose();
+    }
+}
+/**
+ * Sets the control site property specified by the dispIdMember to a new value.
+ * The value will be disposed by the control site when it is no longer required
+ * using Variant.dispose.  Passing a value of null will clear the dispId value.
+ *
+ * @param dispId the ID of the property as specified by the IDL of the ActiveX Control
+ * @param value The new value for the property as expressed in a Variant.
+ *
+ * @since 2.1
+ */
+public void setSiteProperty(int dispId, Variant value){
+    for (int i = 0; i < sitePropertyIds.length; i++) {
+        if (sitePropertyIds[i] is dispId) {
+            if (sitePropertyValues[i] !is null) {
+                sitePropertyValues[i].dispose();
+            }
+            if (value !is null) {
+                sitePropertyValues[i] = value;
+            } else {
+                int oldLength = sitePropertyIds.length;
+                int[] newSitePropertyIds = new int[oldLength - 1];
+                Variant[] newSitePropertyValues = new Variant[oldLength - 1];
+                System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, i);
+                System.arraycopy(sitePropertyIds, i + 1, newSitePropertyIds, i, oldLength - i - 1);
+                System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, i);
+                System.arraycopy(sitePropertyValues, i + 1, newSitePropertyValues, i, oldLength - i - 1);
+                sitePropertyIds = newSitePropertyIds;
+                sitePropertyValues = newSitePropertyValues;
+            }
+            return;
+        }
+    }
+    int oldLength = sitePropertyIds.length;
+    int[] newSitePropertyIds = new int[oldLength + 1];
+    Variant[] newSitePropertyValues = new Variant[oldLength + 1];
+    System.arraycopy(sitePropertyIds, 0, newSitePropertyIds, 0, oldLength);
+    System.arraycopy(sitePropertyValues, 0, newSitePropertyValues, 0, oldLength);
+    newSitePropertyIds[oldLength] = dispId;
+    newSitePropertyValues[oldLength] = value;
+    sitePropertyIds = newSitePropertyIds;
+    sitePropertyValues = newSitePropertyValues;
+}
+}
+
+class _IDispatchImpl : IDispatch {
+
+    OleControlSite  parent;
+    this(OleControlSite p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IDispatch : IUnknown
+    HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
+    HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
+    HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
+    // Note : <Shawn> one argument is short !!!
+    HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr) {
+        return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+    }
+}
+
+class _IOleControlSiteImpl : IOleControlSite {
+
+    OleControlSite  parent;
+    this(OleControlSite p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface IOleControlSite : IUnknown
+    HRESULT OnControlInfoChanged() { return parent.OnControlInfoChanged();}
+    HRESULT LockInPlaceActive(BOOL fLock) { return COM.E_NOTIMPL; }
+    HRESULT GetExtendedControl(LPDISPATCH* ppDisp) { return COM.E_NOTIMPL; }
+    HRESULT TransformCoords(
+      POINTL* pPtlHimetric ,  //Address of POINTL structure
+      POINTF* pPtfContainer ,  //Address of POINTF structure
+      DWORD dwFlags           //Flags indicating the exact conversion
+    ) { return COM.E_NOTIMPL; }
+    HRESULT TranslateAccelerator(
+      LPMSG pMsg ,        //Pointer to the structure
+      DWORD grfModifiers  //Flags describing the state of the keys
+    )
+    { return COM.E_NOTIMPL; }
+    HRESULT OnFocus(
+      BOOL fGotFocus  //Indicates whether the control gained focus
+    )
+    { return COM.S_OK; }
+    HRESULT ShowPropertyFrame() { return COM.E_NOTIMPL; }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEvent.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEvent;
+
+import org.eclipse.swt.ole.win32.Variant;
+
+import org.eclipse.swt.widgets.Widget;
+
+public class OleEvent {
+    public int type;
+    public Widget widget;
+    public int detail;
+    public bool doit = true;
+    public Variant[] arguments;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventSink.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEventSink;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.ole.win32.OleControlSite;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.Variant;
+
+final class OleEventSink
+{
+    private OleControlSite widget;
+
+    private _DispatchImpl iDispatch;
+    private int refCount;
+
+    private IUnknown objIUnknown;
+    private int  eventCookie;
+    private GUID* eventGuid;
+
+    private OleEventTable eventTable;
+
+this(OleControlSite widget, IUnknown iUnknown, GUID* riid) {
+
+    this.widget = widget;
+    this.eventGuid = riid;
+    this.objIUnknown = iUnknown;
+
+    createCOMInterfaces();
+}
+
+void connect () {
+    IConnectionPointContainer cpc;
+    if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+        IConnectionPoint cp;
+        if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) {
+            uint pCookie;
+            if (cp.Advise(iDispatch, &pCookie) is COM.S_OK)
+                eventCookie = pCookie;
+            cp.Release();
+        }
+        cpc.Release();
+    }
+}
+void addListener(int eventID, OleListener listener) {
+    if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) eventTable = new OleEventTable ();
+    eventTable.hook(eventID, listener);
+}
+int AddRef() {
+    refCount++;
+    return refCount;
+}
+private void createCOMInterfaces() {
+    iDispatch = new _DispatchImpl(this);
+}
+void disconnect() {
+    // disconnect event sink
+    if (eventCookie !is 0 && objIUnknown !is null) {
+        IConnectionPointContainer cpc;
+        if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+            IConnectionPoint cp;
+            if (cpc.FindConnectionPoint(eventGuid, &cp) is COM.S_OK) {
+                if (cp.Unadvise(eventCookie) is COM.S_OK) {
+                    eventCookie = 0;
+                }
+                cp.Release();
+            }
+            cpc.Release();
+        }
+    }
+}
+private void disposeCOMInterfaces() {
+    iDispatch = null;
+}
+
+private HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr)
+{
+    if (eventTable is null || !eventTable.hooks(dispIdMember)) return COM.S_OK;
+
+    // Construct an array of the parameters that are passed in
+    // Note: parameters are passed in reverse order - here we will correct the order
+    Variant[] eventInfo = null;
+    if (pDispParams !is null) {
+        DISPPARAMS* dispParams = new DISPPARAMS();
+        COM.MoveMemory(dispParams, pDispParams, DISPPARAMS.sizeof);
+        eventInfo = new Variant[dispParams.cArgs];
+        int size = Variant.sizeof;
+        int offset = (dispParams.cArgs - 1) * size;
+
+        for (int j = 0; j < dispParams.cArgs; j++){
+            eventInfo[j] = new Variant();
+            eventInfo[j].setData(dispParams.rgvarg + offset);
+            offset = offset - size;
+        }
+    }
+
+    OleEvent event = new OleEvent();
+    event.arguments = eventInfo;
+    notifyListener(dispIdMember,event);
+    return COM.S_OK;
+}
+/**
+* Notify listeners of an event.
+* <p>
+*   This method notifies all listeners that an event
+* has occurred.
+*
+* @param eventType the desired SWT event
+* @param event the event data
+*
+* @exception IllegalArgumentException <ul>
+*       <li>ERROR_NULL_ARGUMENT when handler is null</li>
+* </ul>
+* @exception SWTException <ul>
+*       <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+*       <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+*   </ul>
+*/
+private void notifyListener (int eventType, OleEvent event) {
+    if (event is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    event.type = eventType;
+    event.widget = widget;
+    eventTable.sendEvent (event);
+}
+
+private HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+
+    if ( COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIDispatch) ||
+            COM.IsEqualGUID(riid, eventGuid)) {
+        *ppvObject = cast(void*)cast(IDispatch)iDispatch;
+        AddRef();
+        return OLE.S_OK;
+    }
+
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+int Release() {
+    refCount--;
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+    }
+
+    return refCount;
+}
+void removeListener(int eventID, OleListener listener) {
+    if (listener is null) OLE.error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (eventID, listener);
+}
+bool hasListeners() {
+    return eventTable.hasEntries();
+}
+}
+
+private class _DispatchImpl : IDispatch {
+
+    OleEventSink parent;
+    this(OleEventSink sink) { parent = sink;}
+extern (Windows) :
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject){
+        return parent.QueryInterface(riid, ppvObject);
+    }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+    HRESULT GetTypeInfoCount(UINT * pctinfo) { return COM.E_NOTIMPL; }
+    HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo * ppTInfo) { return COM.E_NOTIMPL; }
+    HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) { return COM.E_NOTIMPL; }
+    HRESULT Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS* pDispParams,VARIANT* pVarResult,EXCEPINFO* pExcepInfo,UINT* puArgErr){
+        return parent.Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleEventTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleEventTable;
+
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+
+import java.lang.all;
+
+/**
+* The OleEventTable class implements a simple
+* look up mechanism that maps an event type
+* to a listener.  Multiple listeners for the
+* same event type are supported.
+*
+*/
+
+class OleEventTable {
+    int [] types;
+    OleListener [] handlers;
+void hook (int eventType, OleListener handler) {
+    if (types is null) types = new int [4];
+    if (handlers is null) handlers = new OleListener [4];
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is 0) {
+            types [i] = eventType;
+            handlers [i] = handler;
+            return;
+        }
+    }
+    int size = types.length;
+    int [] newTypes = new int [size + 4];
+    OleListener [] newHandlers = new OleListener [size + 4];
+    System.arraycopy (types, 0, newTypes, 0, size);
+    SimpleType!(OleListener).arraycopy (handlers, 0, newHandlers, 0, size);
+    types = newTypes;  handlers = newHandlers;
+    types [size] = eventType;  handlers [size] = handler;
+}
+bool hooks (int eventType) {
+    if (handlers is null) return false;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType) return true;
+    }
+    return false;
+}
+void sendEvent (OleEvent event) {
+    if (handlers is null) return;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is event.type) {
+            OleListener listener = handlers [i];
+            if (listener !is null) listener.handleEvent (event);
+        }
+    }
+}
+void unhook (int eventType, OleListener handler) {
+    if (handlers is null) return;
+    for (int i=0; i<types.length; i++) {
+        if ((types [i] is eventType) && (handlers [i] is handler)) {
+            types [i] = 0;
+            handlers [i] = null;
+            return;
+        }
+    }
+}
+bool hasEntries() {
+    for (int i=0; i<types.length; i++) {
+        if (types[i] !is 0) return true;
+    }
+    return false;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFrame.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,845 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleFrame;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.OLEIDL;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.ole.win32.OleClientSite;
+import org.eclipse.swt.ole.win32.OLE;
+
+import java.lang.all;
+import java.lang.Runnable;
+import tango.core.Array;
+
+/**
+ *
+ * OleFrame is an OLE Container's top level frame.
+ *
+ * <p>This object implements the OLE Interfaces IUnknown and IOleInPlaceFrame
+ *
+ * <p>OleFrame allows the container to do the following: <ul>
+ *  <li>position and size the ActiveX Control or OLE Document within the application
+ *  <li>insert menu items from the application into the OLE Document's menu
+ *  <li>activate and deactivate the OLE Document's menus
+ *  <li>position the OLE Document's menu in the application
+ *  <li>translate accelerator keystrokes intended for the container's frame</ul>
+ *
+ * <dl>
+ *  <dt><b>Styles</b> <dd>BORDER
+ *  <dt><b>Events</b> <dd>Dispose, Move, Resize
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#ole">OLE and ActiveX snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: OLEExample, OleWebBrowser</a>
+ */
+final public class OleFrame : Composite
+{
+    // Interfaces for this Ole Client Container
+    //private COMObject iUnknown;
+    private _IOleInPlaceFrameImpl iOleInPlaceFrame;
+
+    // Access to the embedded/linked Ole Object
+    private IOleInPlaceActiveObject objIOleInPlaceActiveObject;
+
+    private OleClientSite currentdoc;
+
+    private int refCount = 0;
+
+    private MenuItem[] fileMenuItems;
+    private MenuItem[] containerMenuItems;
+    private MenuItem[] windowMenuItems;
+
+    private Listener listener;
+
+    private static String CHECK_FOCUS = "OLE_CHECK_FOCUS"; //$NON-NLS-1$
+    private static String HHOOK = "OLE_HHOOK"; //$NON-NLS-1$
+    private static String HHOOKMSG = "OLE_HHOOK_MSG"; //$NON-NLS-1$
+
+    private static bool ignoreNextKey;
+    private static const short [] ACCENTS = [ cast(short)'~', '`', '\'', '^', '"'];
+
+    private static const String CONSUME_KEY = "org.eclipse.swt.OleFrame.ConsumeKey"; //$NON-NLS-1$
+
+/**
+ * Create an OleFrame child widget using style bits
+ * to select a particular look or set of properties.
+ *
+ * @param parent a composite widget (cannot be null)
+ * @param style the bitwise OR'ing of widget styles
+ *
+ * @exception IllegalArgumentException <ul>
+ *     <li>ERROR_NULL_ARGUMENT when the parent is null
+ * </ul>
+ * @exception SWTException <ul>
+ *     <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread
+ * </ul>
+ *
+ */
+public this(Composite parent, int style) {
+    super(parent, style);
+
+    createCOMInterfaces();
+
+    // setup cleanup proc
+    listener = new class() Listener  {
+        public void handleEvent(Event e) {
+            switch (e.type) {
+            case SWT.Activate :    onActivate(e); break;
+            case SWT.Deactivate :  onDeactivate(e); break;
+            case SWT.Dispose :  onDispose(e); break;
+            case SWT.Resize :
+            case SWT.Move :     onResize(e); break;
+            default :
+                OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
+            }
+        }
+    };
+
+
+    addListener(SWT.Activate, listener);
+    addListener(SWT.Deactivate, listener);
+    addListener(SWT.Dispose, listener);
+
+    // inform inplaceactiveobject whenever frame resizes
+    addListener(SWT.Resize, listener);
+
+    // inform inplaceactiveobject whenever frame moves
+    addListener(SWT.Move, listener);
+
+    // Maintain a reference to yourself so that when
+    // ClientSites close, they don't take the frame away
+    // with them.
+    this.AddRef();
+
+    // Check for focus change
+    Display display = getDisplay();
+    initCheckFocus(display);
+    initMsgHook(display);
+}
+private static void initCheckFocus (Display display_) {
+    if (display_.getData(CHECK_FOCUS) !is null) return;
+    display_.setData(CHECK_FOCUS, new ArrayWrapperString(CHECK_FOCUS));
+    static const int time = 50;
+    auto timer = new class(display_) Runnable {
+        Display display;
+        Control[1] lastFocus;
+        this( Display display){ this.display = display; }
+        public void run() {
+            if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) {
+                // ignore popup menus and dialogs
+                auto hwnd = OS.GetFocus();
+                while (hwnd !is null) {
+                    auto ownerHwnd = OS.GetWindow(hwnd, OS.GW_OWNER);
+                    if (ownerHwnd !is null) {
+                        display.timerExec(time, this);
+                        return;
+                    }
+                    hwnd = OS.GetParent(hwnd);
+                }
+            }
+            if (lastFocus[0] is null || lastFocus[0].isDisposed() || !lastFocus[0].isFocusControl()) {
+                Control currentFocus = display.getFocusControl();
+                if ( auto frame = cast(OleFrame)currentFocus ) {
+                    currentFocus = frame.getCurrentDocument();
+                }
+                if (lastFocus[0] !is currentFocus) {
+                    Event event = new Event();
+                    if (( null !is cast(OleClientSite)lastFocus[0] ) && !lastFocus[0].isDisposed()) {
+                        lastFocus[0].notifyListeners (SWT.FocusOut, event);
+                    }
+                    if (( null !is cast(OleClientSite)currentFocus ) && !currentFocus.isDisposed()) {
+                        currentFocus.notifyListeners(SWT.FocusIn, event);
+                    }
+                }
+                lastFocus[0] = currentFocus;
+            }
+            display.timerExec(time, this);
+        }
+    };
+    display_.timerExec(time, timer);
+}
+private static void initMsgHook(Display display) {
+    if (display.getData(HHOOK) !is null) return;
+    //final Callback callback = new Callback(OleFrame.class, "getMsgProc", 3); //$NON-NLS-1$
+    //int address = callback.getAddress();
+    //if (address is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+    int threadId = OS.GetCurrentThreadId();
+    auto hHook_ = OS.SetWindowsHookEx(OS.WH_GETMESSAGE, &getMsgProc, null, threadId);
+    if (hHook_ is null) {
+        //callback.dispose();
+        return;
+    }
+    display.setData(HHOOK, new ValueWrapperT!(void*)(hHook_));
+    display.setData(HHOOKMSG, new ValueWrapperT!(MSG*)(new MSG()));
+    display.disposeExec(new class(hHook_) Runnable {
+        void* hHook;
+        this( void* hHook ){ this.hHook = hHook; }
+        public void run() {
+            if (hHook !is null) OS.UnhookWindowsHookEx(hHook);
+            //if (callback !is null) callback.dispose();
+        }
+    });
+}
+static extern(Windows) int getMsgProc(int code, uint wParam, int lParam) {
+    Display display = Display.getCurrent();
+    if (display is null) return 0;
+    auto hHook = cast(ValueWrapperT!(void*))display.getData(HHOOK);
+    if (hHook is null) return 0;
+    if (code < 0) {
+        return OS.CallNextHookEx(hHook.value, code, wParam, lParam);
+    }
+    MSG* msg = cast(MSG*)(cast(ValueWrapperT!(MSG*))display.getData(HHOOKMSG)).value;
+    OS.MoveMemory(msg, lParam, MSG.sizeof);
+    int message = msg.message;
+    if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
+        if (display !is null) {
+            Widget widget = null;
+            auto hwnd = msg.hwnd;
+            while (hwnd !is null) {
+                widget = display.findWidget (hwnd);
+                if (widget !is null) break;
+                hwnd = OS.GetParent (hwnd);
+            }
+            if (widget !is null && (null !is cast(OleClientSite)widget )) {
+                OleClientSite site = cast(OleClientSite)widget;
+                if (site.handle is hwnd) {
+                    bool consumed = false;
+                    /* Allow activeX control to translate accelerators except when a menu is active. */
+                    int thread = OS.GetWindowThreadProcessId(msg.hwnd, null);
+                    GUITHREADINFO*  lpgui = new GUITHREADINFO();
+                    lpgui.cbSize = GUITHREADINFO.sizeof;
+                    bool rc = cast(bool) OS.GetGUIThreadInfo(thread, lpgui);
+                    int mask = OS.GUI_INMENUMODE | OS.GUI_INMOVESIZE | OS.GUI_POPUPMENUMODE | OS.GUI_SYSTEMMENUMODE;
+                    if (!rc || (lpgui.flags & mask) is 0) {
+                        OleFrame frame = site.frame;
+                        frame.setData(CONSUME_KEY, null);
+                        consumed = frame.translateOleAccelerator(msg);
+                        if (frame.getData(CONSUME_KEY) !is null) consumed = false;
+                        frame.setData(CONSUME_KEY, null);
+                    }
+                    bool accentKey = false;
+                    switch (msg.message) {
+                        case OS.WM_KEYDOWN:
+                        case OS.WM_SYSKEYDOWN: {
+                            static if (!OS.IsWinCE) {
+                                switch (msg.wParam) {
+                                    case OS.VK_SHIFT:
+                                    case OS.VK_MENU:
+                                    case OS.VK_CONTROL:
+                                    case OS.VK_CAPITAL:
+                                    case OS.VK_NUMLOCK:
+                                    case OS.VK_SCROLL:
+                                        break;
+                                    default: {
+                                        /*
+                                        * Bug in Windows. The high bit in the result of MapVirtualKey() on
+                                        * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+                                        * They should both be bit 32.  The fix is to test the right bit.
+                                        */
+                                        int mapKey = OS.MapVirtualKey (msg.wParam, 2);
+                                        if (mapKey !is 0) {
+                                            accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) !is 0;
+                                            if (!accentKey) {
+                                                for (int i=0; i<ACCENTS.length; i++) {
+                                                    int value = OS.VkKeyScan (ACCENTS [i]);
+                                                    if (value !is -1 && (value & 0xFF) is msg.wParam) {
+                                                        int state = value >> 8;
+                                                        if ((OS.GetKeyState (OS.VK_SHIFT) < 0) is ((state & 0x1) !is 0) &&
+                                                            (OS.GetKeyState (OS.VK_CONTROL) < 0) is ((state & 0x2) !is 0) &&
+                                                            (OS.GetKeyState (OS.VK_MENU) < 0) is ((state & 0x4) !is 0)) {
+                                                                if ((state & 0x7) !is 0) accentKey = true;
+                                                                break;
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                        break;
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                        default:
+                    }
+                    /* Allow OleClientSite to process key events before activeX control */
+                    if (!consumed && !accentKey && !ignoreNextKey) {
+                        auto hwndOld = msg.hwnd;
+                        msg.hwnd = site.handle;
+                        consumed = OS.DispatchMessage (msg) is 1;
+                        msg.hwnd = hwndOld;
+                    }
+                    switch (msg.message) {
+                        case OS.WM_KEYDOWN:
+                        case OS.WM_SYSKEYDOWN: {
+                            switch (msg.wParam) {
+                                case OS.VK_SHIFT:
+                                case OS.VK_MENU:
+                                case OS.VK_CONTROL:
+                                case OS.VK_CAPITAL:
+                                case OS.VK_NUMLOCK:
+                                case OS.VK_SCROLL:
+                                    break;
+                                default: {
+                                    ignoreNextKey = accentKey;
+                                    break;
+                                }
+                            }
+                        }
+                        default:
+                    }
+
+                    if (consumed) {
+                        // In order to prevent this message from also being processed
+                        // by the application, zero out message, wParam and lParam
+                        msg.message = OS.WM_NULL;
+                        msg.wParam = msg.lParam = 0;
+                        OS.MoveMemory(lParam, msg, MSG.sizeof);
+                        return 0;
+                    }
+                }
+            }
+        }
+    }
+    return OS.CallNextHookEx( hHook.value, code, wParam, lParam);
+}
+/**
+ * Increment the count of references to this instance
+ *
+ * @return the current reference count
+ */
+int AddRef() {
+    refCount++;
+    return refCount;
+}
+private int ContextSensitiveHelp(int fEnterMode) {
+    return COM.S_OK;
+}
+private void createCOMInterfaces() {
+    iOleInPlaceFrame = new _IOleInPlaceFrameImpl(this);
+}
+private void disposeCOMInterfaces () {
+    iOleInPlaceFrame = null;
+}
+private HRESULT GetBorder(LPRECT lprectBorder) {
+    /*
+    The IOleInPlaceUIWindow::GetBorder function, when called on a document or frame window
+    object, returns the outer rectangle (relative to the window) where the object can put
+    toolbars or similar controls.
+    */
+    if (lprectBorder is null) return COM.E_INVALIDARG;
+    RECT* rectBorder = new RECT();
+    // Coordinates must be relative to the window
+    OS.GetClientRect(handle, lprectBorder);
+    return COM.S_OK;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the Container location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the Container location when an OLE Document
+ *         is in-place activated.
+ *
+ */
+public MenuItem[] getContainerMenus(){
+    return containerMenuItems;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the File location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the File location when an OLE Document
+ *         is in-place activated.
+ *
+ */
+public MenuItem[] getFileMenus(){
+    return fileMenuItems;
+}
+IOleInPlaceFrame getIOleInPlaceFrame() {
+    return iOleInPlaceFrame;
+}
+private int getMenuItemID(HMENU hMenu, int index) {
+    int id = 0;
+    MENUITEMINFO lpmii;
+    lpmii.cbSize = OS.MENUITEMINFO_sizeof;
+    lpmii.fMask = OS.MIIM_STATE | OS.MIIM_SUBMENU | OS.MIIM_ID;
+    OS.GetMenuItemInfo(hMenu, index, true, &lpmii);
+    if ((lpmii.fState & OS.MF_POPUP) is OS.MF_POPUP) {
+        id = cast(int)lpmii.hSubMenu;
+    } else {
+        id = lpmii.wID;
+    }
+    return id;
+}
+private int GetWindow(HWND* phwnd) {
+    if (phwnd !is null) {
+        *phwnd = handle;
+    }
+    return COM.S_OK;
+}
+/**
+ *
+ * Returns the application menu items that will appear in the Window location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * @return the application menu items that will appear in the Window location when an OLE Document
+ *         is in-place activated.
+ *
+ */
+public MenuItem[] getWindowMenus(){
+    return windowMenuItems;
+}
+private HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ) {
+    // locate menu bar
+    Menu menubar = getShell().getMenuBar();
+    if (menubar is null || menubar.isDisposed()) {
+        int temp = 0;
+        COM.MoveMemory(lpMenuWidths, &temp, 4);
+        return COM.S_OK;
+    }
+    HMENU hMenu = menubar.handle;
+
+    // Create a holder for menu information.  This will be passed down to
+    // the OS and the OS will fill in the requested information for each menu.
+    MENUITEMINFO lpmii;
+    auto hHeap = OS.GetProcessHeap();
+    int cch = 128;
+    int byteCount = cch * TCHAR.sizeof;
+    auto pszText = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    lpmii.cbSize = OS.MENUITEMINFO_sizeof;
+    lpmii.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_SUBMENU | OS.MIIM_DATA;
+    lpmii.dwTypeData = pszText;
+    lpmii.cch = cch;
+
+    // Loop over all "File-like" menus in the menubar and get information about the
+    // item from the OS.
+    int fileMenuCount = 0;
+    int newindex = 0;
+    if (this.fileMenuItems !is null) {
+        for (int i = 0; i < this.fileMenuItems.length; i++) {
+            MenuItem item = this.fileMenuItems[i];
+            if (item !is null) {
+                int index = item.getParent().indexOf(item);
+                lpmii.cch = cch;  // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+                                  // exact number of characters in name.  Reset it to our max size
+                                  // before each call.
+                if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+                    if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+                        // keep track of the number of items
+                        fileMenuCount++;
+                        newindex++;
+                    }
+                }
+            }
+        }
+    }
+
+    // copy the menu item count information to the pointer
+    COM.MoveMemory(lpMenuWidths, &fileMenuCount, 4);
+
+    // Loop over all "Container-like" menus in the menubar and get information about the
+    // item from the OS.
+    int containerMenuCount = 0;
+    if (this.containerMenuItems !is null) {
+        for (int i = 0; i < this.containerMenuItems.length; i++) {
+            MenuItem item = this.containerMenuItems[i];
+            if (item !is null) {
+                int index = item.getParent().indexOf(item);
+                lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+                                           // exact number of characters in name.  Reset it to a large number
+                                           // before each call.
+                if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+                    if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+                        // keep track of the number of items
+                        containerMenuCount++;
+                        newindex++;
+                    }
+                }
+            }
+        }
+    }
+
+    // copy the menu item count information to the pointer
+    COM.MoveMemory((cast(void*)lpMenuWidths) + 8, &containerMenuCount, 4);
+
+    // Loop over all "Window-like" menus in the menubar and get information about the
+    // item from the OS.
+    int windowMenuCount = 0;
+    if (this.windowMenuItems !is null) {
+        for (int i = 0; i < this.windowMenuItems.length; i++) {
+            MenuItem item = this.windowMenuItems[i];
+            if (item !is null) {
+                int index = item.getParent().indexOf(item);
+                lpmii.cch = cch; // lpmii.cch gets updated by GetMenuItemInfo to indicate the
+                                           // exact number of characters in name.  Reset it to a large number
+                                           // before each call.
+                if (OS.GetMenuItemInfo(hMenu, index, true, &lpmii)) {
+                    if (OS.InsertMenuItem(hmenuShared, newindex, true, &lpmii)) {
+                        // keep track of the number of items
+                        windowMenuCount++;
+                        newindex++;
+                    }
+                }
+            }
+        }
+    }
+
+    // copy the menu item count information to the pointer
+    COM.MoveMemory((cast(void*)lpMenuWidths) + 16, &windowMenuCount, 4);
+
+    // free resources used in querying the OS
+    if (pszText !is null)
+        OS.HeapFree(hHeap, 0, pszText);
+    return COM.S_OK;
+}
+void onActivate(Event e) {
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.OnFrameWindowActivate(true);
+    }
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.OnDocWindowActivate(true);
+    }
+}
+void onDeactivate(Event e) {
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.OnFrameWindowActivate(false);
+    }
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.OnDocWindowActivate(false);
+    }
+}
+private void onDispose(Event e) {
+
+    releaseObjectInterfaces();
+    currentdoc = null;
+
+    this.Release();
+    removeListener(SWT.Activate, listener);
+    removeListener(SWT.Deactivate, listener);
+    removeListener(SWT.Dispose, listener);
+    removeListener(SWT.Resize, listener);
+    removeListener(SWT.Move, listener);
+}
+private void onResize(Event e) {
+    if (objIOleInPlaceActiveObject !is null) {
+        RECT lpRect;
+        OS.GetClientRect(handle, &lpRect);
+        objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true);
+    }
+}
+private HRESULT QueryInterface(REFIID riid, void** ppvObject) {
+//  implements IUnknown, IOleInPlaceFrame, IOleContainer, IOleInPlaceUIWindow
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+
+    if (COM.IsEqualGUID(riid, &COM.IIDIUnknown) || COM.IsEqualGUID(riid, &COM.IIDIOleInPlaceFrame) ) {
+        *ppvObject = cast(void*)cast(IOleInPlaceFrame)iOleInPlaceFrame;
+        AddRef();
+        return COM.S_OK;
+    }
+
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+/**
+ * Decrement the count of references to this instance
+ *
+ * @return the current reference count
+ */
+int Release() {
+    refCount--;
+    if (refCount is 0){
+        disposeCOMInterfaces();
+        COM.CoFreeUnusedLibraries();
+    }
+    return refCount;
+}
+private void releaseObjectInterfaces() {
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.Release();
+    }
+    objIOleInPlaceActiveObject = null;
+}
+private int RemoveMenus(HMENU hmenuShared) {
+
+    Menu menubar = getShell().getMenuBar();
+    if (menubar is null || menubar.isDisposed()) return COM.S_FALSE;
+
+    auto hMenu = menubar.handle;
+
+    int[] ids;
+    if (this.fileMenuItems !is null) {
+        for (int i = 0; i < this.fileMenuItems.length; i++) {
+            MenuItem item = this.fileMenuItems[i];
+            if (item !is null && !item.isDisposed()) {
+                int index = item.getParent().indexOf(item);
+                // get Id from original menubar
+                int id = getMenuItemID(hMenu, index);
+                ids ~= id;
+            }
+        }
+    }
+    if (this.containerMenuItems !is null) {
+        for (int i = 0; i < this.containerMenuItems.length; i++) {
+            MenuItem item = this.containerMenuItems[i];
+            if (item !is null && !item.isDisposed()) {
+                int index = item.getParent().indexOf(item);
+                int id = getMenuItemID(hMenu, index);
+                ids ~= id;
+            }
+        }
+    }
+    if (this.windowMenuItems !is null) {
+        for (int i = 0; i < this.windowMenuItems.length; i++) {
+            MenuItem item = this.windowMenuItems[i];
+            if (item !is null && !item.isDisposed()) {
+                int index = item.getParent().indexOf(item);
+                int id = getMenuItemID(hMenu, index);
+                ids ~= id;
+            }
+        }
+    }
+    int index = OS.GetMenuItemCount(hmenuShared) - 1;
+    for (int i = index; i >= 0; i--) {
+        int id = getMenuItemID(hmenuShared, i);
+        if ( ids.contains(id)){
+            OS.RemoveMenu(hmenuShared, i, OS.MF_BYPOSITION);
+        }
+    }
+    return COM.S_OK;
+}
+private int RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) {
+    return COM.S_OK;
+}
+HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) {
+    if (objIOleInPlaceActiveObject !is null) {
+        objIOleInPlaceActiveObject.Release();
+        objIOleInPlaceActiveObject = null;
+    }
+    if (pActiveObject !is null) {
+        objIOleInPlaceActiveObject = pActiveObject;
+        objIOleInPlaceActiveObject.AddRef();
+    }
+
+    return COM.S_OK;
+}
+
+private HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths ) {
+    // A Control/Document can :
+    // Use its own toolbars, requesting border space of a specific size, or,
+    // Use no toolbars, but force the container to remove its toolbars by passing a
+    //   valid BORDERWIDTHS structure containing nothing but zeros in the pborderwidths parameter, or,
+    // Use no toolbars but allow the in-place container to leave its toolbars up by
+    //   passing NULL as the pborderwidths parameter.
+    if (objIOleInPlaceActiveObject is null) return COM.S_OK;
+    RECT* borderwidth = new RECT();
+    if (pborderwidths is null || currentdoc is null ) return COM.S_OK;
+
+    COM.MoveMemory(borderwidth, pborderwidths, RECT.sizeof);
+    currentdoc.setBorderSpace(borderwidth);
+
+    return COM.S_OK;
+}
+/**
+ *
+ * Specify the menu items that should appear in the Container location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * <p>This method must be called before in place activation of the OLE Document.  After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param containerMenus an array of top level MenuItems to be inserted into the Container location of
+ *        the menubar
+ */
+public void setContainerMenus(MenuItem[] containerMenus){
+    containerMenuItems = containerMenus;
+}
+OleClientSite getCurrentDocument() {
+    return currentdoc;
+}
+void setCurrentDocument(OleClientSite doc) {
+    currentdoc = doc;
+
+    if (currentdoc !is null && objIOleInPlaceActiveObject !is null) {
+        RECT lpRect;
+        OS.GetClientRect(handle, &lpRect);
+        objIOleInPlaceActiveObject.ResizeBorder(&lpRect, iOleInPlaceFrame, true);
+    }
+}
+/**
+ *
+ * Specify the menu items that should appear in the File location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * <p>This method must be called before in place activation of the OLE Document.  After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param fileMenus an array of top level MenuItems to be inserted into the File location of
+ *        the menubar
+ */
+public void setFileMenus(MenuItem[] fileMenus){
+    fileMenuItems = fileMenus;
+}
+HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ) {
+    IOleInPlaceActiveObject inPlaceActiveObject;
+    if (objIOleInPlaceActiveObject !is null)
+        inPlaceActiveObject = objIOleInPlaceActiveObject;
+
+    Menu menubar = getShell().getMenuBar();
+    if (menubar is null || menubar.isDisposed()){
+        return COM.OleSetMenuDescriptor(null, getShell().handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject);
+    }
+
+    HWND handle = menubar.getShell().handle;
+
+    if (hmenuShared is null && holemenu is null) {
+        // re-instate the original menu - this occurs on deactivation
+        hmenuShared = menubar.handle;
+    }
+    if (hmenuShared is null) return COM.E_FAIL;
+
+    OS.SetMenu(handle, hmenuShared);
+    OS.DrawMenuBar(handle);
+
+    return COM.OleSetMenuDescriptor(holemenu, handle, hwndActiveObject, iOleInPlaceFrame, inPlaceActiveObject);
+}
+
+/**
+ *
+ * Set the menu items that should appear in the Window location when an OLE Document
+ * is in-place activated.
+ *
+ * <p>When an OLE Document is in-place active, the Document provides its own menus but the application
+ * is given the opportunity to merge some of its menus into the menubar.  The application
+ * is allowed to insert its menus in three locations: File (far left), Container(middle) and Window
+ * (far right just before Help).  The OLE Document retains control of the Edit, Object and Help
+ * menu locations.  Note that an application can insert more than one menu into a single location.
+ *
+ * <p>This method must be called before in place activation of the OLE Document.  After the Document
+ * is activated, the menu bar will not be modified until a subsequent activation.
+ *
+ * @param windowMenus an array of top level MenuItems to be inserted into the Window location of
+ *        the menubar
+ */
+public void setWindowMenus(MenuItem[] windowMenus){
+    windowMenuItems = windowMenus;
+}
+private bool translateOleAccelerator(MSG* msg) {
+    if (objIOleInPlaceActiveObject is null) return false;
+    int result = objIOleInPlaceActiveObject.TranslateAccelerator(msg);
+    return (result != COM.S_FALSE && result != COM.E_NOTIMPL);
+}
+
+HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ){
+    Menu menubar = getShell().getMenuBar();
+    if (menubar is null || menubar.isDisposed() || !menubar.isEnabled()) return COM.S_FALSE;
+    if (wID < 0) return COM.S_FALSE;
+
+    Shell shell = menubar.getShell();
+    HWND hwnd = shell.handle;
+    HACCEL hAccel = cast(HACCEL)OS.SendMessage(hwnd, OS.WM_APP+1, 0, 0);
+    if (hAccel is null) return COM.S_FALSE;
+
+    MSG msg = *lpmsg;
+    int result = OS.TranslateAccelerator(hwnd, hAccel, &msg);
+    return result == 0 ? COM.S_FALSE : COM.S_OK;
+}
+}
+
+//  implements IOleInPlaceFrame, IOleInPlaceUIWindow, IOleWindow, IUnknown
+class _IOleInPlaceFrameImpl : IOleInPlaceFrame {
+
+    OleFrame parent;
+    this(OleFrame p) { parent = p; }
+extern (Windows) :
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface IOleWindow
+    HRESULT GetWindow( HWND * phwnd ) { return parent.GetWindow(phwnd); }
+    HRESULT ContextSensitiveHelp( BOOL fEnterMode ){ return COM.S_OK; }
+
+    //interface IOleInPlaceUIWindow
+    HRESULT GetBorder( LPRECT lprectBorder ) { return parent.GetBorder(lprectBorder); }
+    HRESULT RequestBorderSpace( LPCBORDERWIDTHS pborderwidths ){ return COM.S_OK; }
+    HRESULT SetBorderSpace( LPCBORDERWIDTHS pborderwidths ) { return parent.SetBorderSpace(pborderwidths); }
+    HRESULT SetActiveObject( LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR pszObjName ) {
+        return parent.SetActiveObject(pActiveObject, pszObjName);
+    }
+
+    // interface IOleInPlaceFrame : IOleInPlaceUIWindow
+    HRESULT InsertMenus( HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths ){
+        return parent.InsertMenus(hmenuShared, lpMenuWidths);
+    }
+    HRESULT SetMenu( HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject ){
+        return parent.SetMenu(hmenuShared, holemenu, hwndActiveObject);
+    }
+    HRESULT RemoveMenus( HMENU hmenuShared ) {
+        return parent.RemoveMenus(hmenuShared);
+    }
+    HRESULT SetStatusText( LPCOLESTR pszStatusText ) { return COM.E_NOTIMPL; }
+    HRESULT EnableModeless( BOOL fEnable ) { return COM.E_NOTIMPL; }
+    HRESULT TranslateAccelerator( LPMSG lpmsg, WORD wID ) {
+        return parent.TranslateAccelerator(lpmsg, wID);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleFunctionDescription.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleFunctionDescription;
+
+import org.eclipse.swt.ole.win32.OleParameterDescription;
+import java.lang.all;
+
+public class OleFunctionDescription {
+
+    public int id;
+    public String name;
+    public OleParameterDescription[] args;
+    public int optionalArgCount;
+    public short returnType;
+    public int invokeKind;
+    public int funcKind;
+    public short flags;
+    public int callingConvention;
+    public String documentation;
+    public String helpFile;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleListener;
+
+import org.eclipse.swt.ole.win32.OleEvent;
+
+/**
+ * Implementers of <code>OleListener</code> provide a simple 
+ * <code>handleEvent()</code> method that is used internally 
+ * by SWT to dispatch events.
+ * <p>
+ * After creating an instance of a class that implements this
+ * interface it can be added to an <code>OleControlSite</code> 
+ * using the <code>addEventListener()</code> method and removed 
+ * using the <code>removeEventListener()</code> method.  When the
+ * specified event occurs, <code>handleEvent()</code> will be
+ * sent to the instance.
+ * </p>
+ *
+ * @see OleControlSite
+ */
+public interface OleListener {
+
+/**
+ * Sent when an event that the receiver has registered for occurs.
+ *
+ * @param event the event which occurred
+ */
+public void handleEvent(OleEvent event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OleParameterDescription.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OleParameterDescription;
+import java.lang.all;
+
+
+public class OleParameterDescription {
+    public String name;
+    public short flags;
+    public short type;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyChangeSink.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OlePropertyChangeSink;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.ifs;
+
+import org.eclipse.swt.ole.win32.OleControlSite;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OleListener;
+import org.eclipse.swt.ole.win32.OleEvent;
+import org.eclipse.swt.ole.win32.OleEventTable;
+import org.eclipse.swt.ole.win32.OLE;
+
+final class OlePropertyChangeSink {
+
+    private OleControlSite controlSite;
+    //private IUnknown objIUnknown;
+
+    //private COMObject iUnknown;
+    private _IPropertyNotifySinkImpl iPropertyNotifySink;
+
+    private int refCount;
+
+    private int propertyCookie;
+
+    private OleEventTable eventTable;
+
+this(OleControlSite controlSite) {
+
+    this.controlSite = controlSite;
+
+    createCOMInterfaces();
+}
+void addListener(int propertyID, OleListener listener) {
+    if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) eventTable = new OleEventTable ();
+    eventTable.hook(propertyID, listener);
+}
+int AddRef() {
+    refCount++;
+    return refCount;
+}
+void connect(IUnknown objIUnknown) {
+
+    // Set up property change notification sink
+    IConnectionPointContainer cpc;
+    if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+        IConnectionPoint cp;
+        if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
+            uint cookie;
+            if (cp.Advise(iPropertyNotifySink, &cookie) is COM.S_OK) {
+                propertyCookie = cookie;
+            }
+            cp.Release();
+        }
+        cpc.Release();
+    }
+}
+protected void createCOMInterfaces() {
+    // register each of the interfaces that this object implements
+    iPropertyNotifySink = new _IPropertyNotifySinkImpl(this);
+}
+void disconnect(IUnknown objIUnknown) {
+
+    // disconnect property notification sink
+    if (propertyCookie !is 0 && objIUnknown !is null) {
+        IConnectionPointContainer cpc;
+        if (objIUnknown.QueryInterface(&COM.IIDIConnectionPointContainer, cast(void**)&cpc) is COM.S_OK) {
+            IConnectionPoint cp;
+            if (cpc.FindConnectionPoint(&COM.IIDIPropertyNotifySink, &cp) is COM.S_OK) {
+                if (cp.Unadvise(propertyCookie) is COM.S_OK) {
+                    propertyCookie = 0;
+                }
+                cp.Release();
+            }
+            cpc.Release();
+        }
+    }
+}
+private void disposeCOMInterfaces() {
+    iPropertyNotifySink = null;
+}
+/**
+* Notify listeners of an event.
+* <p>
+*   This method notifies all listeners that an event
+* has occurred.
+*
+* @param eventType the desired SWT event
+* @param event the event data
+*
+* @exception IllegalArgumentException <ul>
+*       <li>ERROR_NULL_ARGUMENT when handler is null</li>
+* </ul>
+* @exception SWTException <ul>
+*       <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong thread</li>
+*       <li>ERROR_WIDGET_DISPOSED when the widget has been disposed</li>
+*   </ul>
+*/
+private void notifyListener (int eventType, OleEvent event) {
+    if (event is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    event.type = eventType;
+    event.widget = controlSite;
+    eventTable.sendEvent (event);
+}
+package int OnChanged(int dispID) {
+    if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
+    OleEvent event = new OleEvent();
+    event.detail = OLE.PROPERTY_CHANGED;
+    notifyListener(dispID,event);
+    return COM.S_OK;
+}
+package int OnRequestEdit(int dispID) {
+    if (eventTable is null || !eventTable.hooks(dispID)) return COM.S_OK;
+    OleEvent event = new OleEvent();
+    event.doit = true;
+    event.detail = OLE.PROPERTY_CHANGING;
+    notifyListener(dispID,event);
+    return (event.doit) ? COM.S_OK : COM.S_FALSE;
+}
+protected HRESULT QueryInterface(REFIID riid, void ** ppvObject) {
+    if (riid is null || ppvObject is null)
+        return COM.E_INVALIDARG;
+
+    if (COM.IsEqualGUID(riid, &COM.IIDIPropertyNotifySink)) {
+        *ppvObject = cast(void*)cast(IPropertyNotifySink)iPropertyNotifySink;
+        AddRef();
+        return COM.S_OK;
+    }
+    *ppvObject = null;
+    return COM.E_NOINTERFACE;
+}
+int Release() {
+    refCount--;
+    if (refCount is 0) {
+        disposeCOMInterfaces();
+    }
+    return refCount;
+}
+void removeListener(int propertyID, OleListener listener) {
+    if (listener is null) OLE.error (__FILE__, __LINE__, SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (propertyID, listener);
+}
+}
+
+
+private class _IPropertyNotifySinkImpl : IPropertyNotifySink {
+
+    OlePropertyChangeSink   parent;
+    this(OlePropertyChangeSink  p) { parent = p; }
+extern (Windows):
+    // interface of IUnknown
+    HRESULT QueryInterface(REFIID riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+    ULONG AddRef()  { return parent.AddRef(); }
+    ULONG Release() { return parent.Release(); }
+
+    // interface of IPropertyNotifySink
+    int OnChanged(int dispID) { return parent.OnChanged(dispID); }
+    int OnRequestEdit(int dispID) { return parent.OnRequestEdit(dispID); }
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/OlePropertyDescription.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.OlePropertyDescription;
+import java.lang.all;
+
+
+public class OlePropertyDescription {
+    public int id;
+    public String name;
+    public int type;
+    public int flags;
+    public int kind;
+    public String description;
+    public String helpFile;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/ole/win32/Variant.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1053 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.ole.win32.Variant;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.ole.win32.extras;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.COMTYPES;
+import org.eclipse.swt.internal.ole.win32.OAIDL;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.OLE;
+
+import tango.util.Convert;
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ *
+ * A Variant is a generic OLE mechanism for passing data of different types via a common interface.
+ *
+ * <p>It is used within the OleAutomation object for getting a property, setting a property or invoking
+ * a method on an OLE Control or OLE Document.
+ *
+ */
+public final class Variant {
+    /**
+    * The size in bytes of a native VARIANT struct.
+    */
+    /**
+     * A variant always takes up 16 bytes, no matter what you
+     * store in it. Objects, strings, and arrays are not physically
+     * stored in the Variant; in these cases, four bytes of the
+     * Variant are used to hold either an object reference, or a
+     * pointer to the string or array. The actual data are stored elsewhere.
+     */
+    //public static final int sizeof = 16;
+
+
+    private short type; // OLE.VT_* type
+    private bool booleanData;
+    private byte    byteData;
+    private short   shortData;
+    private wchar   charData;
+    private int     intData;
+    private long    longData;
+    private float   floatData;
+    private double  doubleData;
+    private String  stringData;
+    private void*   byRefPtr;
+    private IDispatch dispatchData;
+    private IUnknown unknownData;
+
+/**
+ * Invokes platform specific functionality to copy a variant
+ * into operating system memory.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Variant</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param pVarDest destination pointer to a variant
+ * @param varSrc source <code>Variant</code>
+ *
+ * @since 3.3
+ */
+public static void win32_copy (VARIANT* pVarDest, Variant varSrc) {
+    varSrc.getData (pVarDest);
+}
+
+/**
+ * Invokes platform specific functionality to wrap a variant
+ * that was allocated in operating system memory.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Variant</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param pVariant pointer to a variant
+ *
+ * @return a new <code>Variant</code>
+ *
+ * @since 3.3
+ */
+public static Variant win32_new (VARIANT* pVariant) {
+    Variant variant = new Variant ();
+    variant.setData (pVariant);
+    return variant;
+}
+
+/**
+ * Create an empty Variant object with type VT_EMPTY.
+ *
+ * @since 2.0
+ */
+public this(){
+    type = COM.VT_EMPTY;
+}
+/**
+ * Create a Variant object which represents a Java float as a VT_R4.
+ *
+ * @param val the Java float value that this Variant represents
+ *
+ */
+public this(float val) {
+    type = COM.VT_R4;
+    floatData = val;
+
+}
+/**
+ * Create a Variant object which represents a Java double as a VT_R8.
+ *
+ * @param val the Java double value that this Variant represents
+ *
+ * @since 3.2
+ */
+public this(double val) {
+    type = COM.VT_R8;
+    doubleData = val;
+}
+/**
+ * Create a Variant object which represents a Java int as a VT_I4.
+ *
+ * @param val the Java int value that this Variant represents
+ *
+ */
+public this(int val) {
+    type = COM.VT_I4;
+    intData = val;
+}
+public this(uint val) {
+    type = COM.VT_I4;
+    intData = val;
+}
+/**
+ * Create a Variant object which contains a reference to the data being transferred.
+ *
+ * <p>When creating a VT_BYREF Variant, you must give the full Variant type
+ * including VT_BYREF such as
+ *
+ * <pre><code>short byRefType = OLE.VT_BSTR | OLE.VT_BYREF</code></pre>.
+ *
+ * @param ptr a pointer to the data being transferred.
+ * @param byRefType the type of the data being transferred such as OLE.VT_BSTR | OLE.VT_BYREF
+ *
+ */
+public this(void* ptr, ushort byRefType) {
+    type = byRefType;
+    byRefPtr = ptr;
+}
+/**
+ * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
+ *
+ * @param automation the OleAutomation object that this Variant represents
+ *
+ */
+public this(OleAutomation automation) {
+    type = COM.VT_DISPATCH;
+    dispatchData = automation.getAddress();
+}
+/**
+ * Create a Variant object which represents an IDispatch interface as a VT_Dispatch.
+ * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
+ * this Variant.
+ *
+ * @since 2.0
+ *
+ * @param idispatch the IDispatch object that this Variant represents
+ *
+ */
+public this(IDispatch idispatch) {
+    type = COM.VT_DISPATCH;
+    dispatchData = idispatch;
+}
+/**
+ * Create a Variant object which represents an IUnknown interface as a VT_UNKNOWN.
+ *
+ * <p>The caller is expected to have appropriately invoked unknown.AddRef() before creating
+ * this Variant.
+ *
+ * @param unknown the IUnknown object that this Variant represents
+ *
+ */
+public this(IUnknown unknown) {
+    type = COM.VT_UNKNOWN;
+    unknownData = unknown;
+}
+/**
+ * Create a Variant object which represents a Java long as a VT_I8.
+ *
+ * @param val the Java long value that this Variant represents
+ *
+ * @since 3.2
+ */
+ public this(long val) {
+    type = COM.VT_I8;
+    longData = val;
+}
+/**
+ * Create a Variant object which represents a Java String as a VT_BSTR.
+ *
+ * @param string the Java String value that this Variant represents
+ *
+ */
+public this(String string) {
+    type = COM.VT_BSTR;
+    stringData = string;
+}
+/**
+ * Create a Variant object which represents a Java short as a VT_I2.
+ *
+ * @param val the Java short value that this Variant represents
+ *
+ */
+public this(short val) {
+    type = COM.VT_I2;
+    shortData = val;
+}
+/**
+ * Create a Variant object which represents a Java bool as a VT_BOOL.
+ *
+ * @param val the Java bool value that this Variant represents
+ *
+ */
+public this(bool val) {
+    type = COM.VT_BOOL;
+    booleanData = val;
+}
+
+/**
+ * Calling dispose will release resources associated with this Variant.
+ * If the resource is an IDispatch or IUnknown interface, Release will be called.
+ * If the resource is a ByRef pointer, nothing is released.
+ *
+ * @since 2.1
+ */
+public void dispose() {
+    if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+        return;
+    }
+
+    switch (type) {
+        case COM.VT_DISPATCH :
+            dispatchData.Release();
+            break;
+        case COM.VT_UNKNOWN :
+            unknownData.Release();
+            break;
+        default:
+    }
+
+}
+/**
+ * Returns the OleAutomation object represented by this Variant.
+ *
+ * <p>If this Variant does not contain an OleAutomation object, an attempt is made to
+ * coerce the Variant type into an OleAutomation object.  If this fails, an error is
+ * thrown.  Note that OleAutomation objects must be disposed when no longer
+ * needed.
+ *
+ * @return the OleAutomation object represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an OleAutomation object</li>
+ * </ul>
+ */
+public OleAutomation getAutomation() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_DISPATCH) {
+        return new OleAutomation(dispatchData);
+    }
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH);
+        if (result !is COM.S_OK)
+            OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant autoVar = new Variant();
+        autoVar.setData(&newPtr);
+        return autoVar.getAutomation();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+                                  // OleAutomation object is created as Variant Clear
+                                  // will result in a Release being performed on the
+                                  // Dispatch object
+    }
+}
+/**
+ * Returns the IDispatch object represented by this Variant.
+ *
+ * <p>If this Variant does not contain an IDispatch object, an attempt is made to
+ * coerce the Variant type into an IDIspatch object.  If this fails, an error is
+ * thrown.
+ *
+ * @since 2.0
+ *
+ * @return the IDispatch object represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into an IDispatch object</li>
+ * </ul>
+ */
+public IDispatch getDispatch() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+
+    if (type is COM.VT_DISPATCH) {
+        return dispatchData;
+    }
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_DISPATCH);
+        if (result !is COM.S_OK)
+            OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant autoVar = new Variant();
+        autoVar.setData(&newPtr);
+        return autoVar.getDispatch();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+                                  // OleAutomation object is created as Variant Clear
+                                  // will result in a Release being performed on the
+                                  // Dispatch object
+    }
+}
+/**
+ * Returns the Java bool represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java bool, an attempt is made to
+ * coerce the Variant type into a Java bool.  If this fails, an error is thrown.
+ *
+ * @return the Java bool represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a bool</li>
+ * </ul>
+ *
+ */
+public bool getBoolean() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_BOOL) {
+        return booleanData;
+    }
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        HRESULT result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BOOL);
+        if (result !is COM.S_OK)
+            OLE.error(__FILE__, __LINE__, OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant boolVar = new Variant();
+        boolVar.setData(&newPtr);
+        return boolVar.getBoolean();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+/**
+ * Returns a pointer to the referenced data represented by this Variant.
+ *
+ * <p>If this Variant does not contain a reference to data, zero is returned.
+ *
+ * @return a pointer to the referenced data represented by this Variant or 0
+ *
+ */
+public void* getByRef() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if ((type & COM.VT_BYREF)is COM.VT_BYREF) {
+        return byRefPtr;
+    }
+
+    return null;
+}
+/**
+ * Returns the Java byte represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java byte, an attempt is made to
+ * coerce the Variant type into a Java byte.  If this fails, an error is thrown.
+ *
+ * @return the Java byte represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a byte</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public byte getByte() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_I1) {
+        return byteData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I1);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant byteVar = new Variant();
+        byteVar.setData(&newPtr);
+        return byteVar.getByte();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+/**
+ * Returns the Java char represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java char, an attempt is made to
+ * coerce the Variant type into a Java char.  If this fails, an error is thrown.
+ *
+ * @return the Java char represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a char</li>
+ * </ul>
+ *
+ * @since 3.3
+ */
+public wchar getChar() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_UI2) {
+        return charData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UI2);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant charVar = new Variant();
+        charVar.setData(&newPtr);
+        return charVar.getChar();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+void getData(VARIANT* pData){
+    if (pData is null) OLE.error(OLE.ERROR_OUT_OF_MEMORY);
+
+    COM.VariantInit(pData);
+
+    // set type
+    pData.vt = type;
+    if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+        COM.MoveMemory((cast(void*)pData), &type, 2);
+        COM.MoveMemory((cast(void*)pData) + 8, &byRefPtr, 4);
+        return;
+    }
+
+    switch (type) {
+        case COM.VT_EMPTY :
+        case COM.VT_NULL :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            break;
+        case COM.VT_BOOL :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            auto v = booleanData ? COM.VARIANT_TRUE : COM.VARIANT_FALSE;
+            COM.MoveMemory((cast(void*)pData) + 8, &v, 2);
+            break;
+        case COM.VT_I1 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &byteData, 1);
+            break;
+        case COM.VT_I2 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &shortData, 2);
+            break;
+        case COM.VT_UI2 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &charData, 2);
+            break;
+        case COM.VT_I4 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &intData, 4);
+            break;
+        case COM.VT_I8 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &longData, 8);
+            break;
+        case COM.VT_R4 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &floatData, 4);
+            break;
+        case COM.VT_R8 :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            COM.MoveMemory((cast(void*)pData) + 8, &doubleData, 8);
+            break;
+        case COM.VT_DISPATCH :
+            dispatchData.AddRef();
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            auto v = cast(void*)dispatchData;
+            COM.MoveMemory((cast(void*)pData) + 8, &v, 4);
+            break;
+        case COM.VT_UNKNOWN :
+            unknownData.AddRef();
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            auto v = cast(void*)dispatchData;
+            COM.MoveMemory((cast(void*)pData) + 8, &v, 4);
+            break;
+        case COM.VT_BSTR :
+            COM.MoveMemory((cast(void*)pData), &type, 2);
+            wchar[] data = StrToWCHARs(stringData);
+            auto ptr = COM.SysAllocString(data.ptr);
+            COM.MoveMemory((cast(void*)pData) + 8, &ptr, 4);
+            break;
+
+        default :
+            OLE.error(SWT.ERROR_NOT_IMPLEMENTED);
+    }
+}
+/**
+ * Returns the Java double represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java double, an attempt is made to
+ * coerce the Variant type into a Java double.  If this fails, an error is thrown.
+ *
+ * @return the Java double represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a double</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public double getDouble() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_R8) {
+        return doubleData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R8);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant doubleVar = new Variant();
+        doubleVar.setData(&newPtr);
+        return doubleVar.getDouble();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+
+/**
+ * Returns the Java float represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java float, an attempt is made to
+ * coerce the Variant type into a Java float.  If this fails, an error is thrown.
+ *
+ * @return the Java float represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a float</li>
+ * </ul>
+ */
+public float getFloat() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_R4) {
+        return floatData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_R4);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant floatVar = new Variant();
+        floatVar.setData(&newPtr);
+        return floatVar.getFloat();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+
+}
+/**
+ * Returns the Java int represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java int, an attempt is made to
+ * coerce the Variant type into a Java int.  If this fails, an error is thrown.
+ *
+ * @return the Java int represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a int</li>
+ * </ul>
+ */
+public int getInt() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_I4) {
+        return intData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I4);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant intVar = new Variant();
+        intVar.setData(&newPtr);
+        return intVar.getInt();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+/**
+ * Returns the Java long represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java long, an attempt is made to
+ * coerce the Variant type into a Java long.  If this fails, an error is thrown.
+ *
+ * @return the Java long represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a long</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public long getLong() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_I8) {
+        return longData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I8);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant longVar = new Variant();
+        longVar.setData(&newPtr);
+        return longVar.getLong();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+/**
+ * Returns the Java short represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java short, an attempt is made to
+ * coerce the Variant type into a Java short.  If this fails, an error is thrown.
+ *
+ * @return the Java short represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a short</li>
+ * </ul>
+ */
+public short getShort() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_I2) {
+        return shortData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_I2);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant shortVar = new Variant();
+        shortVar.setData(&newPtr);
+        return shortVar.getShort();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+
+}
+/**
+ * Returns the Java String represented by this Variant.
+ *
+ * <p>If this Variant does not contain a Java String, an attempt is made to
+ * coerce the Variant type into a Java String.  If this fails, an error is thrown.
+ *
+ * @return the Java String represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into a String</li>
+ * </ul>
+ */
+public String getString() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_BSTR) {
+        return stringData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_BSTR);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+
+        Variant stringVar = new Variant();
+        stringVar.setData(&newPtr);
+        return stringVar.getString();
+
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr);
+    }
+}
+/**
+ * Returns the type of the variant type.  This will be an OLE.VT_* value or
+ * a bitwise combination of OLE.VT_* values as in the case of
+ * OLE.VT_BSTR | OLE.VT_BYREF.
+ *
+ * @return the type of the variant data
+ *
+ * @since 2.0
+ */
+public short getType() {
+    return type;
+}
+/**
+ * Returns the IUnknown object represented by this Variant.
+ *
+ * <p>If this Variant does not contain an IUnknown object, an attempt is made to
+ * coerce the Variant type into an IUnknown object.  If this fails, an error is
+ * thrown.
+ *
+ * @return the IUnknown object represented by this Variant
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant can not be coerced into
+ *          an IUnknown object</li>
+ * </ul>
+ */
+public IUnknown getUnknown() {
+    if (type is COM.VT_EMPTY) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, -1);
+    }
+    if (type is COM.VT_UNKNOWN) {
+        return unknownData;
+    }
+
+    // try to coerce the value to the desired type
+    VARIANT oldPtr, newPtr;
+    try {
+        getData(&oldPtr);
+        int result = COM.VariantChangeType(&newPtr, &oldPtr, 0, COM.VT_UNKNOWN);
+        if (result !is COM.S_OK)
+            OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE, result);
+        Variant unknownVar = new Variant();
+        unknownVar.setData(&newPtr);
+        return unknownVar.getUnknown();
+    } finally {
+        COM.VariantClear(&oldPtr);
+        COM.VariantClear(&newPtr); // Note: This must absolutely be done AFTER the
+                                  // IUnknown object is created as Variant Clear
+                                  // will result in a Release being performed on the
+                                  // Dispatch object
+    }
+}
+/**
+ * Update the by reference value of this variant with a new bool value.
+ *
+ * @param val the new bool value
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
+ *          a (VT_BYREF | VT_BOOL) object</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setByRef(bool val) {
+    if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_BOOL) is 0) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+    }
+    auto v = val ? COM.VARIANT_TRUE : COM.VARIANT_FALSE;
+    COM.MoveMemory(byRefPtr, &v, 2);
+}
+/**
+ * Update the by reference value of this variant with a new float value.
+ *
+ * @param val the new float value
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not
+ *          a (VT_BYREF | VT_R4) object</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setByRef(float val) {
+    if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_R4) is 0) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+    }
+    COM.MoveMemory(byRefPtr, &val, 4);
+}
+/**
+ * Update the by reference value of this variant with a new integer value.
+ *
+ * @param val the new integer value
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I4) object</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setByRef(int val) {
+    if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I4) is 0) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+    }
+    COM.MoveMemory(byRefPtr, &val, 4);
+}
+/**
+ * Update the by reference value of this variant with a new short value.
+ *
+ * @param val the new short value
+ *
+ * @exception SWTException <ul>
+ *     <li>ERROR_CANNOT_CHANGE_VARIANT_TYPE when type of Variant is not a (VT_BYREF | VT_I2) object
+ * </ul>
+ *
+ * @since 2.1
+ */
+public void setByRef(short val) {
+    if ((type & COM.VT_BYREF) is 0 || (type & COM.VT_I2) is 0) {
+        OLE.error(OLE.ERROR_CANNOT_CHANGE_VARIANT_TYPE);
+    }
+    COM.MoveMemory(byRefPtr, &val, 2);
+}
+
+void setData(VARIANT* pData){
+    if (pData is null) OLE.error(OLE.ERROR_INVALID_ARGUMENT);
+
+    short[1] dataType ;
+    COM.MoveMemory(dataType.ptr, (cast(void*)pData), 2);
+    type = dataType[0];
+
+    if ((type & COM.VT_BYREF) is COM.VT_BYREF) {
+        void*[1] newByRefPtr;
+        OS.MoveMemory(newByRefPtr.ptr, (cast(void*)pData) + 8, 4);
+        byRefPtr = newByRefPtr[0];
+        return;
+    }
+
+    switch (type) {
+        case COM.VT_EMPTY :
+        case COM.VT_NULL :
+            break;
+        case COM.VT_BOOL :
+            short[1] newBooleanData;
+            COM.MoveMemory(newBooleanData.ptr, (cast(void*)pData) + 8, 2);
+            booleanData = (newBooleanData[0] !is COM.VARIANT_FALSE);
+            break;
+        case COM.VT_I1 :
+            byte[1] newByteData;
+            COM.MoveMemory(newByteData.ptr, (cast(void*)pData) + 8, 1);
+            byteData = newByteData[0];
+            break;
+        case COM.VT_I2 :
+            short[1] newShortData;
+            COM.MoveMemory(newShortData.ptr, (cast(void*)pData) + 8, 2);
+            shortData = newShortData[0];
+            break;
+        case COM.VT_UI2 :
+            wchar[1] newCharData;
+            COM.MoveMemory(newCharData.ptr, (cast(void*)pData) + 8, 2);
+            charData = newCharData[0];
+            break;
+        case COM.VT_I4 :
+            int[1] newIntData;
+            OS.MoveMemory(newIntData.ptr, (cast(void*)pData) + 8, 4);
+            intData = newIntData[0];
+            break;
+        case COM.VT_I8 :
+            long[1] newLongData;
+            OS.MoveMemory(newLongData.ptr, (cast(void*)pData) + 8, 8);
+            longData = newLongData[0];
+            break;
+        case COM.VT_R4 :
+            float[1] newFloatData;
+            COM.MoveMemory(newFloatData.ptr, (cast(void*)pData) + 8, 4);
+            floatData = newFloatData[0];
+            break;
+        case COM.VT_R8 :
+            double[1] newDoubleData;
+            COM.MoveMemory(newDoubleData.ptr, (cast(void*)pData) + 8, 8);
+            doubleData = newDoubleData[0];
+            break;
+        case COM.VT_DISPATCH : {
+            IDispatch[1] ppvObject;
+            OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4);
+            if (ppvObject[0] is null) {
+                type = COM.VT_EMPTY;
+                break;
+            }
+            dispatchData = ppvObject[0];
+            dispatchData.AddRef();
+            break;
+        }
+        case COM.VT_UNKNOWN : {
+            IUnknown[1] ppvObject;
+            OS.MoveMemory(ppvObject.ptr, (cast(void*)pData) + 8, 4);
+            if (ppvObject[0] is null) {
+                type = COM.VT_EMPTY;
+                break;
+            }
+            unknownData = ppvObject[0];
+            unknownData.AddRef();
+            break;
+        }
+        case COM.VT_BSTR :
+            // get the address of the memory in which the string resides
+            wchar*[1] hMem;
+            OS.MoveMemory(hMem.ptr, (cast(void*)pData) + 8, 4);
+            if (hMem[0] is null) {
+                type = COM.VT_EMPTY;
+                break;
+            }
+            // Get the size of the string from the OS - the size is expressed in number
+            // of bytes - each unicode character is 2 bytes.
+            int size = COM.SysStringByteLen(hMem[0]);
+            if (size > 0){
+                // get the unicode character array from the global memory and create a String
+                wchar[] buffer = new wchar[(size + 1) /2]; // add one to avoid rounding errors
+                COM.MoveMemory(buffer.ptr, hMem[0], size);
+                stringData = WCHARsToStr( buffer );
+            } else {
+                stringData = ""; //$NON-NLS-1$
+            }
+            break;
+
+        default :
+            // try coercing it into one of the known forms
+            auto newPData = cast(VARIANT*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, VARIANT.sizeof);
+            if (COM.VariantChangeType(newPData, pData, 0, COM.VT_R4) is COM.S_OK) {
+                setData(newPData);
+            } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_I4) is COM.S_OK) {
+                setData(newPData);
+            } else if (COM.VariantChangeType(newPData, pData, 0, COM.VT_BSTR) is COM.S_OK) {
+                setData(newPData);
+            }
+            COM.VariantClear(newPData);
+            OS.GlobalFree(newPData);
+            break;
+    }
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the Variant
+ */
+public String toString () {
+    switch (type) {
+        case COM.VT_BOOL :
+            return "VT_BOOL{"~to!(String)(booleanData)~"}";
+        case COM.VT_I1 :
+            return "VT_I1{"~to!(String)(byteData)~"}";
+        case COM.VT_I2 :
+            return "VT_I2{"~to!(String)(shortData)~"}";
+        case COM.VT_UI2 :
+            return "VT_UI2{"~ dcharToString(charData) ~"}";
+        case COM.VT_I4 :
+            return "VT_I4{"~to!(String)(intData)~"}";
+        case COM.VT_I8 :
+            return "VT_I8{"~to!(String)(longData)~"}";
+        case COM.VT_R4 :
+            return "VT_R4{"~to!(String)(floatData)~"}";
+        case COM.VT_R8 :
+            return "VT_R8{"~to!(String)(doubleData)~"}";
+        case COM.VT_BSTR :
+            return "VT_BSTR{"~stringData~"}";
+        case COM.VT_DISPATCH :
+            return Format("VT_DISPATCH{{0x{:X}}", cast(void*) (dispatchData is null ? null : dispatchData));
+        case COM.VT_UNKNOWN :
+            return Format("VT_UNKNOWN{{0x{:X}}", cast(void*) (unknownData is null ? null : unknownData));
+        case COM.VT_EMPTY :
+            return "VT_EMPTY";
+        case COM.VT_NULL :
+            return "VT_NULL";
+        default:
+     }
+    if ((type & COM.VT_BYREF) !is 0) {
+        return Format("VT_BYREF|{}{{{}}",(type & ~COM.VT_BYREF), byRefPtr );
+    }
+    return "Unsupported Type "~to!(String)(type);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLCanvas.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D Programming Language:
+ *      John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module org.eclipse.swt.opengl.GLCanvas;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.opengl.win32.WGL;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.opengl.GLData;
+
+/**
+ * GLCanvas is a widget capable of displaying OpenGL content.
+ * 
+ * @see GLData
+ * @see <a href="http://www.eclipse.org/swt/snippets/#opengl">OpenGL snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+
+public class GLCanvas : Canvas {
+    HGLRC context;
+    int pixelFormat;
+
+/**
+ * Create a GLCanvas widget using the attributes described in the GLData
+ * object provided.
+ *
+ * @param parent a composite widget
+ * @param style the bitwise OR'ing of widget styles
+ * @param data the requested attributes of the GLCanvas
+ *
+ * @exception IllegalArgumentException
+ * <ul><li>ERROR_NULL_ARGUMENT when the data is null
+ *     <li>ERROR_UNSUPPORTED_DEPTH when the requested attributes cannot be provided</ul> 
+ * </ul>
+ */
+public this (Composite parent, int style, GLData data) {
+    super (parent, style);
+    if (data is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    PIXELFORMATDESCRIPTOR pfd;
+    pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof;
+    pfd.nVersion = 1;
+    pfd.dwFlags = WGL.PFD_DRAW_TO_WINDOW | WGL.PFD_SUPPORT_OPENGL;
+    pfd.dwLayerMask = WGL.PFD_MAIN_PLANE;
+    pfd.iPixelType = cast(byte) WGL.PFD_TYPE_RGBA;
+    if (data.doubleBuffer) pfd.dwFlags |= WGL.PFD_DOUBLEBUFFER;
+    if (data.stereo) pfd.dwFlags |= WGL.PFD_STEREO;
+    pfd.cRedBits = cast(byte) data.redSize;
+    pfd.cGreenBits = cast(byte) data.greenSize;
+    pfd.cBlueBits = cast(byte) data.blueSize;
+    pfd.cAlphaBits = cast(byte) data.alphaSize;
+    pfd.cDepthBits = cast(byte) data.depthSize;
+    pfd.cStencilBits = cast(byte) data.stencilSize;
+    pfd.cAccumRedBits = cast(byte) data.accumRedSize;
+    pfd.cAccumGreenBits = cast(byte) data.accumGreenSize;
+    pfd.cAccumBlueBits = cast(byte) data.accumBlueSize;
+    pfd.cAccumAlphaBits = cast(byte) data.accumAlphaSize;
+    pfd.cAccumBits = cast(byte) (pfd.cAccumRedBits + pfd.cAccumGreenBits + pfd.cAccumBlueBits + pfd.cAccumAlphaBits);
+    
+    //FIXME - use wglChoosePixelFormatARB
+//  if (data.sampleBuffers > 0) {
+//      wglAttrib [pos++] = WGL.WGL_SAMPLE_BUFFERS_ARB;
+//      wglAttrib [pos++] = data.sampleBuffers;
+//  }
+//  if (data.samples > 0) {
+//      wglAttrib [pos++] = WGL.WGL_SAMPLES_ARB;
+//      wglAttrib [pos++] = data.samples;
+//  }
+
+    auto hDC = OS.GetDC (handle);
+    pixelFormat = WGL.ChoosePixelFormat (hDC, &pfd);
+    if (pixelFormat is 0 || !WGL.SetPixelFormat (hDC, pixelFormat, &pfd)) {
+        OS.ReleaseDC (handle, hDC);
+        dispose ();
+        SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+    }
+    context = WGL.wglCreateContext (hDC);
+    if (context is null) {
+        OS.ReleaseDC (handle, hDC);
+        SWT.error (SWT.ERROR_NO_HANDLES);
+    }
+    OS.ReleaseDC (handle, hDC);
+    //FIXME- share lists
+    //if (share !is null) WGL.wglShareLists (context, share.context);
+    
+    Listener listener = new class() Listener {
+        public void handleEvent (Event event) {
+            switch (event.type) {
+                case SWT.Dispose:
+                    WGL.wglDeleteContext (context);
+                    break;
+                default:
+            }
+        }
+    };
+    addListener (SWT.Dispose, listener);
+}
+
+/**
+ * Returns a GLData object describing the created context.
+ *  
+ * @return GLData description of the OpenGL context attributes
+ * @exception SWTException <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 GLData getGLData () {
+    checkWidget ();
+    GLData data = new GLData ();
+    PIXELFORMATDESCRIPTOR pfd;
+    pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof;
+    auto hDC = OS.GetDC (handle);
+    WGL.DescribePixelFormat (hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, &pfd);
+    OS.ReleaseDC (handle, hDC);
+    data.doubleBuffer = (pfd.dwFlags & WGL.PFD_DOUBLEBUFFER) !is 0;
+    data.stereo = (pfd.dwFlags & WGL.PFD_STEREO) !is 0;
+    data.redSize = pfd.cRedBits;
+    data.greenSize = pfd.cGreenBits;
+    data.blueSize = pfd.cBlueBits;
+    data.alphaSize = pfd.cAlphaBits;
+    data.depthSize = pfd.cDepthBits;
+    data.stencilSize = pfd.cStencilBits;
+    data.accumRedSize = pfd.cAccumRedBits;
+    data.accumGreenSize = pfd.cAccumGreenBits;
+    data.accumBlueSize = pfd.cAccumBlueBits;
+    data.accumAlphaSize = pfd.cAccumAlphaBits;
+    return data;
+}
+
+/**
+ * Returns a bool indicating whether the receiver's OpenGL context
+ * is the current context.
+ *  
+ * @return true if the receiver holds the current OpenGL context,
+ * false otherwise
+ * @exception SWTException <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 isCurrent () {
+    checkWidget ();
+    return (WGL.wglGetCurrentContext is context);
+}
+
+/**
+ * Sets the OpenGL context associated with this GLCanvas to be the
+ * current GL context.
+ * 
+ * @exception SWTException <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 setCurrent () {
+    checkWidget ();
+    if (WGL.wglGetCurrentContext is context) return;
+    auto hDC = OS.GetDC (handle);
+    WGL.wglMakeCurrent (hDC, context);
+    OS.ReleaseDC (handle, hDC);
+}
+
+/**
+ * Swaps the front and back color buffers.
+ * 
+ * @exception SWTException <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 swapBuffers () {
+    checkWidget ();
+    auto hDC = OS.GetDC (handle);
+    WGL.SwapBuffers (hDC);
+    OS.ReleaseDC (handle, hDC);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/GLData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 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
+ * Port to the D Programming Language:
+ *     John Reimer <terminal.node@gmail.com>
+ *******************************************************************************/
+module org.eclipse.swt.opengl.GLData;
+
+import tango.text.Util;
+import tango.util.Convert;
+import java.lang.all;
+
+/**
+ * The GLData class is a device-independent description
+ * of the pixel format attributes of a GL drawable.
+ *
+ * @see GLCanvas
+ * @see <a href="http://www.eclipse.org/swt/snippets/#opengl">OpenGL snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+
+public class GLData {
+    /**
+     * Specifies a double-buffered surface.  During context
+     * creation, only double-buffered formats are considered
+     * when set to true.
+     */
+    public bool doubleBuffer;
+
+    /**
+     * Specifies a stereo surface.  During context creation,
+     * only stereo formats are considered when set to true.
+     */
+    public bool stereo;
+
+    /**
+     * The size in bits of the color buffer's red channel.
+     * During context creation, this specifies the minimum
+     * required red bits.
+     */
+    public int redSize;
+
+    /**
+     * The size in bits of the color buffer's green channel.
+     * During context creation, this specifies the minimum
+     * required green bits.
+     */
+    public int greenSize;
+
+    /**
+     * The size in bits of the color buffer's blue channel.
+     * During context creation, this specifies the minimum
+     * required blue bits.
+     */
+    public int blueSize;
+
+    /**
+     * The size in bits of the color buffer's alpha channel.
+     * During context creation, this specifies the minimum
+     * required alpha bits.
+     */
+    public int alphaSize;
+
+    /**
+     * The size in bits of the depth buffer.  During context
+     * creation, the smallest depth buffer of at least the
+     * specified value is preferred, or zero for no depth
+     * buffer.
+     */
+    public int depthSize;
+
+    /**
+     * The desired number of stencil bitplanes.  During
+     * context creation, the smallest stencil buffer of at
+     * least the specified value is preferred, or zero for
+     * no stencil buffer.
+     */
+    public int stencilSize;
+
+    /**
+     * The size in bits of the accumulation buffer's red
+     * channel. During context creation, this specifies the
+     * minimum required red bits.
+     */
+    public int accumRedSize;
+
+    /**
+     * The size in bits of the accumulation buffer's green
+     * channel. During context creation, this specifies the
+     * minimum required green bits.
+     */
+    public int accumGreenSize;
+
+    /**
+     * The size in bits of the accumulation buffer's blue
+     * channel. During context creation, this specifies the
+     * minimum required blue bits.
+     */
+    public int accumBlueSize;
+
+    /**
+     * The size in bits of the accumulation buffer's alpha
+     * channel. During context creation, this specifies the
+     * minimum required alpha bits.
+     */
+    public int accumAlphaSize;
+
+    /**
+     * The number of multisample buffers used by this context.
+     * During context creation, this specifies the minimum
+     * number of multisample buffers requested.
+     */
+    public int sampleBuffers;
+
+    /**
+     * The number of samples accepted in the multisample buffer.
+     * During creation, pixel formats with the smallest number of
+     * samples that meets or exceeds the specified minimum number
+     * are preferred.
+     */
+    public int samples;
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the data
+ */
+override public String toString() {
+    String string = doubleBuffer ? "doubleBuffer," : "";
+    string ~= stereo ? "stereo," : "";
+    string ~= "r:" ~     to!(String)(redSize)  ~ " g:" ~ to!(String)(greenSize) ~
+              " b:" ~    to!(String)(blueSize) ~ " a:" ~ to!(String)(alphaSize) ~ "," ~
+              "depth:" ~ to!(String)(depthSize) ~ ",stencil:" ~ to!(String)(stencilSize) ~
+              ",accum r:" ~ to!(String)(accumRedSize) ~ "g:" ~ to!(String)(accumGreenSize) ~
+              "b:" ~ to!(String)(accumBlueSize) ~ "a:" ~ to!(String)(accumAlphaSize) ~
+              ",sampleBuffers:" ~ to!(String)(sampleBuffers) ~ ",samples:" ~ to!(String)(samples);
+    return string;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/opengl/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,6 @@
+module org.eclipse.swt.opengl.all;
+
+public import org.eclipse.swt.opengl.GLCanvas;
+public import org.eclipse.swt.opengl.GLData;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrintDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.printing.PrintDialog;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.printing.Printer;
+import org.eclipse.swt.printing.PrinterData;
+
+import java.lang.all;
+
+/**
+ * Instances of this class allow the user to select
+ * a printer and various print-related parameters
+ * prior to starting a print job.
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class PrintDialog : Dialog {
+    PrinterData printerData;
+    int scope_ = PrinterData.ALL_PAGES;
+    int startPage = 1, endPage = 1;
+    bool printToFile = false;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a composite control which will be the parent of the new instance (cannot be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Shell parent) {
+    this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Shell parent, int style) {
+    super (parent, style);
+    checkSubclass ();
+}
+
+/**
+ * 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>PrinterData.ALL_PAGES</code></dt>
+ * <dd>Print all pages in the current document</dd>
+ * <dt><code>PrinterData.PAGE_RANGE</code></dt>
+ * <dd>Print the range of pages specified by startPage and endPage</dd>
+ * <dt><code>PrinterData.SELECTION</code></dt>
+ * <dd>Print the current selection</dd>
+ * </dl>
+ *
+ * @return the scope setting that the user selected
+ */
+public int getScope() {
+    return scope_;
+}
+
+/**
+ * Sets the scope of the print job. The user will see this
+ * setting when the dialog is opened. This can have one of
+ * the following values:
+ * <dl>
+ * <dt><code>PrinterData.ALL_PAGES</code></dt>
+ * <dd>Print all pages in the current document</dd>
+ * <dt><code>PrinterData.PAGE_RANGE</code></dt>
+ * <dd>Print the range of pages specified by startPage and endPage</dd>
+ * <dt><code>PrinterData.SELECTION</code></dt>
+ * <dd>Print the current selection</dd>
+ * </dl>
+ *
+ * @param scope the scope setting when the dialog is opened
+ */
+public void setScope(int scope_) {
+    this.scope_ = scope_;
+}
+
+/**
+ * Returns the start page setting that the user selected
+ * 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>PrinterData.PAGE_RANGE</code>.
+ * </p>
+ *
+ * @return the start page setting that the user selected
+ */
+public int getStartPage() {
+    return startPage;
+}
+
+/**
+ * Sets the start page that the user will see when the dialog
+ * 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>PrinterData.PAGE_RANGE</code>.
+ * </p>
+ *
+ * @param startPage the startPage setting when the dialog is opened
+ */
+public void setStartPage(int startPage) {
+    this.startPage = startPage;
+}
+
+/**
+ * Returns the end page setting that the user selected
+ * 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>PrinterData.PAGE_RANGE</code>.
+ * </p>
+ *
+ * @return the end page setting that the user selected
+ */
+public int getEndPage() {
+    return endPage;
+}
+
+/**
+ * Sets the end page that the user will see when the dialog
+ * 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>PrinterData.PAGE_RANGE</code>.
+ * </p>
+ *
+ * @param endPage the end page setting when the dialog is opened
+ */
+public void setEndPage(int endPage) {
+    this.endPage = endPage;
+}
+
+/**
+ * Returns the 'Print to file' setting that the user selected
+ * before pressing OK in the dialog.
+ *
+ * @return the 'Print to file' setting that the user selected
+ */
+public bool getPrintToFile() {
+    return printToFile;
+}
+
+/**
+ * Sets the 'Print to file' setting that the user will see
+ * when the dialog is opened.
+ *
+ * @param printToFile the 'Print to file' setting when the dialog is opened
+ */
+public void setPrintToFile(bool printToFile) {
+    this.printToFile = printToFile;
+}
+
+protected void checkSubclass() {
+    String name = this.classinfo.name;
+    String validName = PrintDialog.classinfo.name;
+    if (validName!=/*eq*/name) {
+        SWT.error(SWT.ERROR_INVALID_SUBCLASS);
+    }
+}
+
+/**
+ * Makes the receiver visible and brings it to the front
+ * of the display.
+ *
+ * @return a printer data object describing the desired print job parameters
+ *
+ * @exception SWTException <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 PrinterData open() {
+    PRINTDLG pd;
+    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_) {
+        case PrinterData.PAGE_RANGE: pd.Flags |= OS.PD_PAGENUMS; break;
+        case PrinterData.SELECTION: pd.Flags |= OS.PD_SELECTION; break;
+        default: pd.Flags |= OS.PD_ALLPAGES;
+    }
+    pd.nMinPage = 1;
+    pd.nMaxPage = cast(ushort)-1;
+    pd.nFromPage = cast(short) Math.min (0xFFFF, Math.max (1, startPage));
+    pd.nToPage = cast(short) Math.min (0xFFFF, Math.max (1, endPage));
+
+    Display display = parent.getDisplay();
+    Shell [] shells = display.getShells();
+    if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        for (int i=0; i<shells.length; i++) {
+            if (shells[i].isEnabled() && shells[i] !is parent) {
+                shells[i].setEnabled(false);
+            } else {
+                shells[i] = null;
+            }
+        }
+    }
+    PrinterData data = null;
+    String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+    Object oldValue = display.getData(key);
+    display.setData(key, new ValueWrapperBool(true));
+    bool success = cast(bool)OS.PrintDlg(&pd);
+    display.setData(key, oldValue);
+    if ((getStyle() & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        for (int i=0; i<shells.length; i++) {
+            if (shells[i] !is null && !shells[i].isDisposed ()) {
+                shells[i].setEnabled(true);
+            }
+        }
+    }
+
+    if (success) {
+        /* Get driver and device from the DEVNAMES struct */
+        auto hMem = pd.hDevNames;
+        /* Ensure size is a multiple of 2 bytes on UNICODE platforms */
+        int size = OS.GlobalSize(hMem) / TCHAR.sizeof * TCHAR.sizeof;
+        auto ptr = OS.GlobalLock(hMem);
+        short[4] offsets;
+        OS.MoveMemory(offsets.ptr, ptr, 2 * offsets.length);
+        TCHAR[] buffer = NewTCHARs(0, size);
+        OS.MoveMemory(buffer.ptr, ptr, size);
+        OS.GlobalUnlock(hMem);
+
+        int driverOffset = offsets[0];
+        int i = 0;
+        while (driverOffset + i < size) {
+            if (buffer[driverOffset + i] is 0) break;
+            i++;
+        }
+        String driver = TCHARsToStr( buffer[driverOffset .. driverOffset+i] );
+
+        int deviceOffset = offsets[1];
+        i = 0;
+        while (deviceOffset + i < size) {
+            if (buffer[deviceOffset + i] is 0) break;
+            i++;
+        }
+        String device = TCHARsToStr( buffer[deviceOffset .. deviceOffset+i] );
+
+        int outputOffset = offsets[2];
+        i = 0;
+        while (outputOffset + i < size) {
+            if (buffer[outputOffset + i] is 0) break;
+            i++;
+        }
+        String output = TCHARsToStr( buffer[outputOffset .. outputOffset+i] );
+
+        /* Create PrinterData object and set fields from PRINTDLG */
+        data = new PrinterData(driver, device);
+        if ((pd.Flags & OS.PD_PAGENUMS) !is 0) {
+            data.scope_ = PrinterData.PAGE_RANGE;
+            data.startPage = pd.nFromPage & 0xFFFF;
+            data.endPage = pd.nToPage & 0xFFFF;
+        } else if ((pd.Flags & OS.PD_SELECTION) !is 0) {
+            data.scope_ = PrinterData.SELECTION;
+        }
+        data.printToFile = (pd.Flags & OS.PD_PRINTTOFILE) !is 0;
+        if (data.printToFile) data.fileName = output;
+        data.copyCount = pd.nCopies;
+        data.collate = (pd.Flags & OS.PD_COLLATE) !is 0;
+
+        /* Bulk-save the printer-specific settings in the DEVMODE struct */
+        hMem = pd.hDevMode;
+        size = OS.GlobalSize(hMem);
+        ptr = OS.GlobalLock(hMem);
+        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;
+        scope_ = data.scope_;
+        startPage = data.startPage;
+    }
+    return data;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/Printer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,555 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.printing.Printer;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.DeviceData;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.printing.PrinterData;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are used to print to a printer.
+ * Applications create a GC on a printer using <code>new GC(printer)</code>
+ * and then draw on the printer GC using the usual graphics calls.
+ * <p>
+ * A <code>Printer</code> object may be constructed by providing
+ * a <code>PrinterData</code> object which identifies the printer.
+ * A <code>PrintDialog</code> presents a print dialog to the user
+ * and returns an initialized instance of <code>PrinterData</code>.
+ * Alternatively, calling <code>new Printer()</code> will construct a
+ * printer object for the user's default printer.
+ * </p><p>
+ * Application code must explicitly invoke the <code>Printer.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see PrinterData
+ * @see PrintDialog
+ * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class Printer : Device {
+    /**
+     * the handle to the printer DC
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HANDLE handle;
+
+    /**
+     * the printer data describing this printer
+     */
+    PrinterData data;
+
+    /**
+     * whether or not a GC was created for this printer
+     */
+    bool isGCCreated = false;
+
+    /**
+     * strings used to access the Windows registry
+     */
+    static TCHAR[] profile;
+    static TCHAR[] appName;
+    static TCHAR[] keyName;
+    static this() {
+        profile = StrToTCHARs(0, "PrinterPorts", true); //$NON-NLS-1$
+        appName = StrToTCHARs(0, "windows", true); //$NON-NLS-1$
+        keyName = StrToTCHARs(0, "device", true); //$NON-NLS-1$
+    }
+
+/**
+ * Returns an array of <code>PrinterData</code> objects
+ * representing all available printers.
+ *
+ * @return the list of available printers
+ */
+public static PrinterData[] getPrinterList() {
+    int length = 1024;
+    /* Use the character encoding for the default locale */
+    String buf = new String(length);
+    int n = OS.GetProfileString( TCHARsToStr(profile), null, null, buf, length);
+    if (n is 0) return null;
+    String[] deviceNames = new String[](5);
+    int nameCount = 0;
+    int index = 0;
+    for (int i = 0; i < n; i++) {
+        if (buf[i] is 0) {
+            if (nameCount is deviceNames.length) {
+                String[] newNames = new String[](deviceNames.length + 5);
+                System.arraycopy(deviceNames, 0, newNames, 0, deviceNames.length);
+                deviceNames = newNames;
+            }
+            deviceNames[nameCount] = buf[index .. i ].dup;
+            nameCount++;
+            index = i + 1;
+        }
+    }
+    PrinterData printerList[] = new PrinterData[nameCount];
+    for (int p = 0; p < nameCount; p++) {
+        String device = deviceNames[p];
+        String driver = ""; //$NON-NLS-1$
+        if (OS.GetProfileString(TCHARsToStr(profile), device, null, buf, length) > 0) {
+            int commaIndex = 0;
+            while (buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+            if (commaIndex < length) {
+                driver = buf[0 .. commaIndex].dup;
+            }
+        }
+        printerList[p] = new PrinterData(driver, device);
+    }
+    return printerList;
+}
+
+/**
+ * Returns a <code>PrinterData</code> object representing
+ * the default printer or <code>null</code> if there is no
+ * printer available on the System.
+ *
+ * @return the default printer data or null
+ *
+ * @since 2.1
+ */
+public static PrinterData getDefaultPrinterData() {
+    String deviceName = null;
+    int length = 1024;
+    /* Use the character encoding for the default locale */
+    String buf = new String(length);
+    int n = OS.GetProfileString(TCHARsToStr(appName), TCHARsToStr(keyName), null, buf, length);
+    if (n is 0) return null;
+    int commaIndex = 0;
+    while(buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+    if (commaIndex < length) {
+        deviceName = buf[0 .. commaIndex].dup;
+    }
+    String driver = ""; //$NON-NLS-1$
+    if (OS.GetProfileString(TCHARsToStr(profile), deviceName, null, buf, length) > 0) {
+        commaIndex = 0;
+        while (buf[commaIndex] !is ',' && commaIndex < length) commaIndex++;
+        if (commaIndex < length) {
+            driver = buf[0 .. commaIndex].dup;
+        }
+    }
+    return new PrinterData(driver, deviceName);
+}
+
+static DeviceData checkNull (PrinterData data) {
+    if (data is null) data = new PrinterData();
+    if (data.driver is null || data.name is null) {
+        PrinterData defaultPrinter = getDefaultPrinterData();
+        if (defaultPrinter is null) SWT.error(SWT.ERROR_NO_HANDLES);
+        data.driver = defaultPrinter.driver;
+        data.name = defaultPrinter.name;
+    }
+    return data;
+}
+
+/**
+ * Constructs a new printer representing the default printer.
+ * <p>
+ * You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if there are no valid printers
+ * </ul>
+ *
+ * @see Device#dispose
+ */
+public this() {
+    this(null);
+}
+
+/**
+ * Constructs a new printer given a <code>PrinterData</code>
+ * object representing the desired printer.
+ * <p>
+ * You must dispose the printer when it is no longer required.
+ * </p>
+ *
+ * @param data the printer data for the specified printer
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the specified printer data does not represent a valid printer
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES - if there are no valid printers
+ * </ul>
+ *
+ * @see Device#dispose
+ */
+public this(PrinterData data) {
+    super(checkNull(data));
+}
+
+/**
+ * Creates the printer handle.
+ * This method is called internally by the instance creation
+ * mechanism of the <code>Device</code> class.
+ * @param deviceData the device data
+ */
+protected void create(DeviceData deviceData) {
+    data = cast(PrinterData)deviceData;
+    /* Use the character encoding for the default locale */
+    TCHAR[] driver = StrToTCHARs(0, data.driver, true);
+    TCHAR[] device = StrToTCHARs(0, data.name, true);
+    DEVMODE* lpInitData;
+    byte buffer [] = data.otherData;
+    auto hHeap = OS.GetProcessHeap();
+    if (buffer !is null && buffer.length !is 0) {
+        /* If user setup info from a print dialog was specified, restore the DEVMODE struct. */
+        lpInitData = cast(DEVMODE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length);
+        OS.MoveMemory(lpInitData, buffer.ptr, buffer.length);
+    }
+    handle = OS.CreateDC(driver.ptr, device.ptr, null, lpInitData);
+    if (lpInitData !is null) OS.HeapFree(hHeap, 0, lpInitData);
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Printer</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public HDC internal_new_GC(GCData data) {
+    if (handle is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    if (data !is null) {
+        if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+        if ((data.style & mask) !is 0) {
+            data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
+        } else {
+            data.style |= SWT.LEFT_TO_RIGHT;
+        }
+        data.device = this;
+        data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT));
+        isGCCreated = true;
+    }
+    return handle;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Printer</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC(HDC hDC, GCData data) {
+    if (data !is null) isGCCreated = false;
+}
+
+/**
+ * Starts a print job and returns true if the job started successfully
+ * and false otherwise.
+ * <p>
+ * This must be the first method called to initiate a print job,
+ * followed by any number of startPage/endPage calls, followed by
+ * endJob. Calling startPage, endPage, or endJob before startJob
+ * will result in undefined behavior.
+ * </p>
+ *
+ * @param jobName the name of the print job to start
+ * @return true if the job started successfully and false otherwise.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startPage
+ * @see #endPage
+ * @see #endJob
+ */
+public bool startJob(String jobName) {
+    checkDevice();
+    DOCINFO di;
+    di.cbSize = DOCINFO.sizeof;
+    auto hHeap = OS.GetProcessHeap();
+    TCHAR* lpszDocName;
+    if (jobName !is null && jobName.length !is 0) {
+        /* Use the character encoding for the default locale */
+        TCHAR[] buffer = StrToTCHARs(0, jobName, true);
+        int byteCount = buffer.length * TCHAR.sizeof;
+        lpszDocName = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory(lpszDocName, buffer.ptr, byteCount);
+        di.lpszDocName = lpszDocName;
+    }
+    TCHAR* lpszOutput;
+    if (data.printToFile && data.fileName !is null) {
+        /* Use the character encoding for the default locale */
+        TCHAR[] buffer = StrToTCHARs(0, data.fileName, true);
+        int byteCount = buffer.length * TCHAR.sizeof;
+        lpszOutput = cast(TCHAR*) OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory(lpszOutput, buffer.ptr, byteCount);
+        di.lpszOutput = lpszOutput;
+    }
+    int rc = OS.StartDoc(handle, &di);
+    if (lpszDocName !is null) OS.HeapFree(hHeap, 0, lpszDocName);
+    if (lpszOutput !is null) OS.HeapFree(hHeap, 0, lpszOutput);
+    return rc > 0;
+}
+
+/**
+ * Ends the current print job.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startJob
+ * @see #startPage
+ * @see #endPage
+ */
+public void endJob() {
+    checkDevice();
+    OS.EndDoc(handle);
+}
+
+/**
+ * Cancels a print job in progress.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void cancelJob() {
+    checkDevice();
+    OS.AbortDoc(handle);
+}
+
+/**
+ * Starts a page and returns true if the page started successfully
+ * and false otherwise.
+ * <p>
+ * After calling startJob, this method may be called any number of times
+ * along with a matching endPage.
+ * </p>
+ *
+ * @return true if the page started successfully and false otherwise.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #endPage
+ * @see #startJob
+ * @see #endJob
+ */
+public bool startPage() {
+    checkDevice();
+    int rc = OS.StartPage(handle);
+    if (rc <= 0) OS.AbortDoc(handle);
+    return rc > 0;
+}
+
+/**
+ * Ends the current page.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #startPage
+ * @see #startJob
+ * @see #endJob
+ */
+public void endPage() {
+    checkDevice();
+    OS.EndPage(handle);
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the printer, and whose y coordinate
+ * is the vertical dots per inch of the printer.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point getDPI() {
+    checkDevice();
+    int dpiX = OS.GetDeviceCaps(handle, OS.LOGPIXELSX);
+    int dpiY = OS.GetDeviceCaps(handle, OS.LOGPIXELSY);
+    return new Point(dpiX, dpiY);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location.
+ * <p>
+ * For a printer, this is the size of the physical page, in pixels.
+ * </p>
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getClientArea
+ * @see #computeTrim
+ */
+public Rectangle getBounds() {
+    checkDevice();
+    int width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+    int height = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+    return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ * <p>
+ * For a printer, this is the size of the printable area
+ * of the page, in pixels.
+ * </p>
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ * @see #computeTrim
+ */
+public Rectangle getClientArea() {
+    checkDevice();
+    int width = OS.GetDeviceCaps(handle, OS.HORZRES);
+    int height = OS.GetDeviceCaps(handle, OS.VERTRES);
+    return new Rectangle(0, 0, width, height);
+}
+
+/**
+ * Given a <em>client area</em> (as described by the arguments),
+ * returns a rectangle, relative to the client area's coordinates,
+ * that is the client area expanded by the printer's trim (or minimum margins).
+ * <p>
+ * Most printers have a minimum margin on each edge of the paper where the
+ * printer device is unable to print.  This margin is known as the "trim."
+ * This method can be used to calculate the printer's minimum margins
+ * by passing in a client area of 0, 0, 0, 0 and then using the resulting
+ * x and y coordinates (which will be <= 0) to determine the minimum margins
+ * for the top and left edges of the paper, and the resulting width and height
+ * (offset by the resulting x and y) to determine the minimum margins for the
+ * bottom and right edges of the paper, as follows:
+ * <ul>
+ *      <li>The left trim width is -x pixels</li>
+ *      <li>The top trim height is -y pixels</li>
+ *      <li>The right trim width is (x + width) pixels</li>
+ *      <li>The bottom trim height is (y + height) pixels</li>
+ * </ul>
+ * </p>
+ *
+ * @param x the x coordinate of the client area
+ * @param y the y coordinate of the client area
+ * @param width the width of the client area
+ * @param height the height of the client area
+ * @return a rectangle, relative to the client area's coordinates, that is
+ *      the client area expanded by the printer's trim (or minimum margins)
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ * @see #getClientArea
+ */
+public Rectangle computeTrim(int x, int y, int width, int height) {
+    checkDevice();
+    int printX = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETX);
+    int printY = -OS.GetDeviceCaps(handle, OS.PHYSICALOFFSETY);
+    int printWidth = OS.GetDeviceCaps(handle, OS.HORZRES);
+    int printHeight = OS.GetDeviceCaps(handle, OS.VERTRES);
+    int paperWidth = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+    int paperHeight = OS.GetDeviceCaps(handle, OS.PHYSICALHEIGHT);
+    int hTrim = paperWidth - printWidth;
+    int vTrim = paperHeight - printHeight;
+    return new Rectangle(x + printX, y + printY, width + hTrim, height + vTrim);
+}
+
+/**
+ * Returns a <code>PrinterData</code> object representing the
+ * target printer for this print job.
+ *
+ * @return a PrinterData object describing the receiver
+ */
+public PrinterData getPrinterData() {
+    return data;
+}
+
+/**
+ * Checks the validity of this device.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+protected void checkDevice() {
+    if (handle is null) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+/**
+ * Releases any internal state prior to destroying this printer.
+ * This method is called internally by the dispose
+ * mechanism of the <code>Device</code> class.
+ */
+protected void release() {
+    super.release();
+    data = null;
+}
+
+/**
+ * Destroys the printer handle.
+ * This method is called internally by the dispose
+ * mechanism of the <code>Device</code> class.
+ */
+protected void destroy() {
+    if (handle !is null) OS.DeleteDC(handle);
+    handle = null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/PrinterData.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.printing.PrinterData;
+
+
+import org.eclipse.swt.graphics.DeviceData;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+/**
+ * Instances of this class are descriptions of a print job
+ * in terms of the printer, and the scope and type of printing
+ * that is desired. For example, the number of pages and copies
+ * can be specified, as well as whether or not the print job
+ * should go to a file.
+ * <p>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ * </p>
+ *
+ * @see Printer
+ * @see Printer#getPrinterList
+ * @see PrintDialog#open
+ * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public final class PrinterData : DeviceData {
+
+    /**
+     * the printer driver
+     * On Windows systems, this is the name of the driver (often "winspool").
+     * On Mac OSX, this is the destination type ("Printer", "Fax", "File", or "Preview").
+     * On X/Window systems, this is the name of a display connection to the
+     * Xprt server (the default is ":1").
+     * On GTK+, this is the backend type name (eg. GtkPrintBackendCups).
+     */
+    // TODO: note that this api is not finalized for GTK+
+    public String driver;
+
+    /**
+     * the name of the printer
+     * On Windows systems, this is the name of the 'device'.
+     * On Mac OSX, X/Window systems, and GTK+, this is the printer's 'name'.
+     */
+    public String name;
+
+    /**
+     * the scope of the print job, expressed as one of the following values:
+     * <dl>
+     * <dt><code>ALL_PAGES</code></dt>
+     * <dd>Print all pages in the current document</dd>
+     * <dt><code>PAGE_RANGE</code></dt>
+     * <dd>Print the range of pages specified by startPage and endPage</dd>
+     * <dt><code>SELECTION</code></dt>
+     * <dd>Print the current selection</dd>
+     * </dl>
+     */
+    public int scope_ = ALL_PAGES;
+
+    /**
+     * the start page of a page range, used when scope is PAGE_RANGE.
+     * This value can be from 1 to the maximum number of pages for the platform.
+     */
+    public int startPage = 0;
+
+    /**
+     * the end page of a page range, used when scope is PAGE_RANGE.
+     * This value can be from 1 to the maximum number of pages for the platform.
+     */
+    public int endPage = 0;
+
+    /**
+     * whether or not the print job should go to a file
+     */
+    public bool printToFile = false;
+
+    /**
+     * the name of the file to print to if printToFile is true.
+     * Note that this field is ignored if printToFile is false.
+     */
+    public String fileName;
+
+    /**
+     * the number of copies to print.
+     * Note that this field may be controlled by the printer driver
+     * In other words, the printer itself may be capable of printing
+     * multiple copies, and if so, the value of this field will always be 1.
+     */
+    public int copyCount = 1;
+
+    /**
+     * whether or not the printer should collate the printed paper
+     * Note that this field may be controlled by the printer driver.
+     * In other words, the printer itself may be capable of doing the
+     * collation, and if so, the value of this field will always be false.
+     */
+    public bool collate = false;
+
+    /**
+     * <code>scope</code> field value indicating that
+     * all pages should be printed
+     */
+    public static const int ALL_PAGES = 0;
+
+    /**
+     * <code>scope</code> field value indicating that
+     * the range of pages specified by startPage and endPage
+     * should be printed
+     */
+    public static const int PAGE_RANGE = 1;
+
+    /**
+     * <code>scope</code> field value indicating that
+     * the current selection should be printed
+     */
+    public static const int SELECTION = 2;
+
+    /**
+     * 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;
+
+    /**
+     * Constructs an instance of this class that can be
+     * used to print to the default printer.
+     *
+     * @see Printer#getDefaultPrinterData
+     */
+    public this() {
+    }
+
+    /**
+     * Constructs an instance of this class with the given
+     * printer driver and printer name.
+     *
+     * @param driver the printer driver for the printer
+     * @param name the name of the printer
+     *
+     * @see #driver
+     * @see #name
+     */
+    public this(String driver, String name) {
+        this.driver = driver;
+        this.name = name;
+    }
+
+    /**
+     * Returns a string containing a concise, human-readable
+     * description of the receiver.
+     *
+     * @return a string representation of the receiver
+     */
+    public String toString() {
+        return Format("PrinterData {{driver = {}, name = {}}", driver, name );  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/printing/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,7 @@
+module org.eclipse.swt.printing.all;
+
+public import org.eclipse.swt.printing.PrintDialog;
+public import org.eclipse.swt.printing.Printer;
+public import org.eclipse.swt.printing.PrinterData;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/Program.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,435 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D Programming language:
+ *      Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.program.Program;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+static import tango.text.convert.Utf;
+
+/**
+ * Instances of this class represent programs and
+ * their associated file extensions in the operating
+ * system.
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#program">Program snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public final class Program {
+    String name;
+    String command;
+    String iconName;
+    String extension;
+    static const String[] ARGUMENTS = ["%1"[], "%l", "%L"]; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+static String assocQueryString (int assocStr, TCHAR[] key, bool expand) {
+    TCHAR[] pszOut = NewTCHARs(0, 1024);
+    uint[1] pcchOut;
+    pcchOut[0] = pszOut.length;
+    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 (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
+    }
+    if (result is 0) {
+        if (!OS.IsWinCE && expand) {
+            int length_ = OS.ExpandEnvironmentStrings (pszOut.ptr, null, 0);
+            if (length_ !is 0) {
+                TCHAR[] lpDst = NewTCHARs (0, length_);
+                OS.ExpandEnvironmentStrings (pszOut.ptr, lpDst.ptr, length_);
+                return tango.text.convert.Utf.toString( lpDst[ 0 .. Math.max (0, length_ - 1) ] );
+            } else {
+                return "";
+            }
+        } else {
+            return tango.text.convert.Utf.toString( pszOut[ 0 .. Math.max (0, pcchOut [0] - 1)]);
+        }
+    }
+    return null;
+}
+
+/**
+ * Finds the program that is associated with an extension.
+ * The extension may or may not begin with a '.'.  Note that
+ * a <code>Display</code> must already exist to guarantee that
+ * this method returns an appropriate result.
+ *
+ * @param extension the program extension
+ * @return the program or <code>null</code>
+ *
+ */
+public static Program findProgram (String extension) {
+    // SWT extension: allow null string
+    //if (extension is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (extension.length is 0) return null;
+    if (extension.charAt (0) !is '.') extension = "." ~ extension; //$NON-NLS-1$
+    /* Use the character encoding for the default locale */
+    TCHAR[] key = StrToTCHARs (0, extension, true);
+    Program program = null;
+    if (OS.IsWinCE) {
+        void*[1] phkResult;
+        if (OS.RegOpenKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+            return null;
+        }
+        uint [1] lpcbData;
+        int result = OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr);
+        if (result is 0) {
+            TCHAR[] lpData = NewTCHARs (0, lpcbData [0] / TCHAR.sizeof);
+            result = OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr);
+            if (result is 0) program = getProgram ( TCHARzToStr( lpData.ptr ), extension);
+        }
+        OS.RegCloseKey (phkResult [0]);
+    } else {
+        String command = assocQueryString (OS.ASSOCSTR_COMMAND, key, true);
+        if (command !is null) {
+            String name = null;
+            if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYDOCNAME, key, false);
+            if (name is null) name = assocQueryString (OS.ASSOCSTR_FRIENDLYAPPNAME, key, false);
+            if (name is null) name = "";
+            String iconName = assocQueryString (OS.ASSOCSTR_DEFAULTICON, key, true);
+            if (iconName is null) iconName = "";
+            program = new Program ();
+            program.name = name;
+            program.command = command;
+            program.iconName = iconName;
+            program.extension = extension;
+        }
+    }
+    return program;
+}
+
+/**
+ * Answer all program extensions in the operating system.  Note
+ * that a <code>Display</code> must already exist to guarantee
+ * that this method returns an appropriate result.
+ *
+ * @return an array of extensions
+ */
+public static String [] getExtensions () {
+    String [] extensions = new String [1024];
+    /* Use the character encoding for the default locale */
+    TCHAR[] lpName = NewTCHARs (0, 1024);
+    uint [1] lpcName; lpcName[0] = lpName.length;
+    FILETIME ft;
+    int dwIndex = 0, count = 0;
+    while (OS.RegEnumKeyEx ( cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) {
+        String extension = TCHARsToStr( lpName[0 .. lpcName[0] ]);
+        lpcName [0] = lpName.length;
+        if (extension.length > 0 && extension.charAt (0) is '.') {
+            if (count is extensions.length) {
+                String[] newExtensions = new String[]( extensions.length + 1024 );
+                System.arraycopy (extensions, 0, newExtensions, 0, extensions.length);
+                extensions = newExtensions;
+            }
+            extensions [count++] = extension;
+        }
+        dwIndex++;
+    }
+    if (count !is extensions.length) {
+        String[] newExtension = new String[]( count );
+        System.arraycopy (extensions, 0, newExtension, 0, count);
+        extensions = newExtension;
+    }
+    return extensions;
+}
+
+static String getKeyValue (String string, bool expand) {
+    /* Use the character encoding for the default locale */
+    TCHAR[] key = StrToTCHARs (0, string, true);
+    void* [1] phkResult;
+    if (OS.RegOpenKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, key.ptr, 0, OS.KEY_READ, phkResult.ptr) !is 0) {
+        return null;
+    }
+    String result = null;
+    uint [1] lpcbData;
+    if (OS.RegQueryValueEx (phkResult [0], null, null, null, null, lpcbData.ptr) is 0) {
+        result = "";
+        int length_ = lpcbData [0] / TCHAR.sizeof;
+        if (length_ !is 0) {
+            /* Use the character encoding for the default locale */
+            TCHAR[] lpData = NewTCHARs (0, length_);
+            if (OS.RegQueryValueEx (phkResult [0], null, null, null, cast(ubyte*)lpData.ptr, lpcbData.ptr) is 0) {
+                if (!OS.IsWinCE && expand) {
+                    length_ = OS.ExpandEnvironmentStrings (lpData.ptr, null, 0);
+                    if (length_ !is 0) {
+                        TCHAR[] lpDst = NewTCHARs (0, length_);
+                        OS.ExpandEnvironmentStrings (lpData.ptr, lpDst.ptr, length_);
+                        result = tango.text.convert.Utf.toString ( lpDst[0 .. Math.max (0, length_ - 1) ] );
+                    }
+                } else {
+                    length_ = Math.max (0, lpData.length - 1);
+                    result = tango.text.convert.Utf.toString ( lpData[0 .. length_]);
+                }
+            }
+        }
+    }
+    if (phkResult [0] !is null) OS.RegCloseKey (phkResult [0]);
+    return result;
+}
+
+static Program getProgram (String key, String extension) {
+
+    /* Name */
+    String name = getKeyValue (key, false);
+    if (name is null || name.length is 0) {
+        name = key;
+    }
+
+    /* Command */
+    String DEFAULT_COMMAND = "\\shell"; //$NON-NLS-1$
+    String defaultCommand = getKeyValue (key ~ DEFAULT_COMMAND, true);
+    if (defaultCommand is null || defaultCommand.length is 0) defaultCommand = "open"; //$NON-NLS-1$
+    String COMMAND = "\\shell\\" ~ defaultCommand ~ "\\command"; //$NON-NLS-1$
+    String command = getKeyValue (key ~ COMMAND, true);
+    if (command is null || command.length is 0) return null;
+
+    /* Icon */
+    String DEFAULT_ICON = "\\DefaultIcon"; //$NON-NLS-1$
+    String iconName = getKeyValue (key ~ DEFAULT_ICON, true);
+    if (iconName is null) iconName = ""; //$NON-NLS-1$
+
+    /* Program */
+    Program program = new Program ();
+    program.name = name;
+    program.command = command;
+    program.iconName = iconName;
+    program.extension = extension;
+    return program;
+}
+
+/**
+ * Answers all available programs in the operating system.  Note
+ * that a <code>Display</code> must already exist to guarantee
+ * that this method returns an appropriate result.
+ *
+ * @return an array of programs
+ */
+public static Program [] getPrograms () {
+    Program [] programs = new Program [1024];
+    /* Use the character encoding for the default locale */
+    TCHAR[] lpName = NewTCHARs (0, 1024);
+    uint [1] lpcName; lpcName[0] = lpName.length;
+    FILETIME ft;
+    int dwIndex = 0, count = 0;
+    while (OS.RegEnumKeyEx (cast(void*)OS.HKEY_CLASSES_ROOT, dwIndex, lpName.ptr, lpcName.ptr, null, null, null, &ft) !is OS.ERROR_NO_MORE_ITEMS) {
+        String path = tango.text.convert.Utf.toString ( lpName[0 .. lpcName [0]]);
+        lpcName [0] = lpName.length ;
+        Program program = getProgram (path, null);
+        if (program !is null) {
+            if (count is programs.length) {
+                Program [] newPrograms = new Program [programs.length + 1024];
+                System.arraycopy (programs, 0, newPrograms, 0, programs.length);
+                programs = newPrograms;
+            }
+            programs [count++] = program;
+        }
+        dwIndex++;
+    }
+    if (count !is programs.length) {
+        Program [] newPrograms = new Program [count];
+        System.arraycopy (programs, 0, newPrograms, 0, count);
+        programs = newPrograms;
+    }
+    return programs;
+}
+
+/**
+ * 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 or URL (http:// or https://)
+ * @return <code>true</code> if the file is launched, otherwise <code>false</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when fileName is null</li>
+ * </ul>
+ */
+public static bool launch (String fileName) {
+    if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+
+    /* Use the character encoding for the default locale */
+    auto hHeap = OS.GetProcessHeap ();
+    TCHAR[] buffer = StrToTCHARs (0, fileName, true);
+    int byteCount = buffer.length * TCHAR.sizeof;
+    auto lpFile = cast(wchar*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    OS.MoveMemory (lpFile, buffer.ptr, byteCount);
+    SHELLEXECUTEINFO info;
+    info.cbSize = SHELLEXECUTEINFO.sizeof;
+    info.lpFile = lpFile;
+    info.nShow = OS.SW_SHOW;
+    bool result = cast(bool) OS.ShellExecuteEx (&info);
+    if (lpFile !is null) OS.HeapFree (hHeap, 0, lpFile);
+    return result;
+}
+
+/**
+ * Executes the program with the file as the single argument
+ * in the operating system.  It is the responsibility of the
+ * programmer to ensure that the file contains valid data for
+ * this program.
+ *
+ * @param fileName the file or program name
+ * @return <code>true</code> if the file is launched, otherwise <code>false</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT when fileName is null</li>
+ * </ul>
+ */
+public bool execute (String fileName) {
+    if (fileName is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    int index = 0;
+    bool append = true;
+    String prefix = command, suffix = ""; //$NON-NLS-1$
+    while (index < ARGUMENTS.length) {
+        int i = command.indexOf (ARGUMENTS [index]);
+        if (i !is -1) {
+            append = false;
+            prefix = command.substring (0, i);
+            suffix = command.substring (i + ARGUMENTS [index].length , command.length );
+            break;
+        }
+        index++;
+    }
+    if (append) fileName = " \"" ~ fileName ~ "\"";
+    String commandLine = prefix ~ fileName ~ suffix;
+    auto hHeap = OS.GetProcessHeap ();
+    /* Use the character encoding for the default locale */
+    TCHAR[] buffer = StrToTCHARs (0, commandLine, true);
+    int byteCount = buffer.length  * TCHAR.sizeof;
+    auto lpCommandLine = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    OS.MoveMemory (lpCommandLine, buffer.ptr, byteCount);
+    STARTUPINFO lpStartupInfo;
+    lpStartupInfo.cb = STARTUPINFO.sizeof;
+    PROCESS_INFORMATION lpProcessInformation;
+    bool success = cast(bool) OS.CreateProcess (null, lpCommandLine, null, null, false, 0, null, null, &lpStartupInfo, &lpProcessInformation);
+    if (lpCommandLine !is null) OS.HeapFree (hHeap, 0, lpCommandLine);
+    if (lpProcessInformation.hProcess !is null) OS.CloseHandle (lpProcessInformation.hProcess);
+    if (lpProcessInformation.hThread !is null) OS.CloseHandle (lpProcessInformation.hThread);
+    return success;
+}
+
+/**
+ * Returns the receiver's image data.  This is the icon
+ * that is associated with the receiver in the operating
+ * system.
+ *
+ * @return the image data for the program, may be null
+ */
+public ImageData getImageData () {
+    if (extension !is null) {
+        SHFILEINFOW shfi;
+        int flags = OS.SHGFI_ICON | OS.SHGFI_SMALLICON | OS.SHGFI_USEFILEATTRIBUTES;
+        TCHAR[] pszPath = StrToTCHARs (0, extension, true);
+        OS.SHGetFileInfo (pszPath.ptr, OS.FILE_ATTRIBUTE_NORMAL, &shfi, SHFILEINFO.sizeof, flags);
+        if (shfi.hIcon !is null) {
+            Image image = Image.win32_new (null, SWT.ICON, shfi.hIcon);
+            ImageData imageData = image.getImageData ();
+            image.dispose ();
+            return imageData;
+        }
+    }
+    int nIconIndex = 0;
+    String fileName = iconName;
+    int index = iconName.indexOf (',');
+    if (index !is -1) {
+        fileName = iconName.substring (0, index);
+        String iconIndex = iconName.substring (index + 1, iconName.length ).trim ();
+        try {
+            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;
+    OS.ExtractIconEx (lpszFile.ptr, nIconIndex, phiconLarge.ptr, phiconSmall.ptr, 1);
+    if (phiconSmall [0] is null) return null;
+    Image image = Image.win32_new (null, SWT.ICON, phiconSmall [0]);
+    ImageData imageData = image.getImageData ();
+    image.dispose ();
+    return imageData;
+}
+
+/**
+ * Returns the receiver's name.  This is as short and
+ * descriptive a name as possible for the program.  If
+ * the program has no descriptive name, this string may
+ * be the executable name, path or empty.
+ *
+ * @return the name of the program
+ */
+public String getName () {
+    return name;
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param other the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals(Object other) {
+    if (this is other) return true;
+    if ( auto program = cast(Program)other ) {
+        return name.equals(program.name) && command.equals(program.command)
+            && iconName.equals(program.iconName);
+    }
+    return false;
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash() {
+    return .toHash(name) ^ .toHash(command) ^ .toHash(iconName);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the program
+ */
+public String toString () {
+    return "Program {" ~ name ~ "}"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/program/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,5 @@
+module org.eclipse.swt.program.all;
+
+public import org.eclipse.swt.program.Program;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/std.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,13 @@
+module org.eclipse.swt.std;
+
+public import org.eclipse.swt.SWT;
+public import org.eclipse.swt.SWTError;
+public import org.eclipse.swt.SWTException;
+public import java.lang.all;
+
+public import org.eclipse.swt.events.all;
+public import org.eclipse.swt.graphics.all;
+public import org.eclipse.swt.layout.all;
+public import org.eclipse.swt.widgets.all;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Button.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1409 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Button;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object that
+ * issues notification when pressed and released.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>ARROW, CHECK, PUSH, RADIO, TOGGLE, FLAT</dd>
+ * <dd>UP, DOWN, LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles ARROW, CHECK, PUSH, RADIO, and TOGGLE
+ * may be specified.
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT, and CENTER may be specified.
+ * </p><p>
+ * Note: Only one of the styles UP, DOWN, LEFT, and RIGHT may be specified
+ * when the ARROW style is specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#button">Button snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Button : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.windowProc windowProc;
+
+    alias extern(Windows) int function( HWND, uint, uint, int ) TWindowProc;
+    String text = "", message = "";
+    Image image, image2, disabledImage;
+    ImageList imageList;
+    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;
+    static const bool COMMAND_LINK = false;
+    private static /+const+/ TWindowProc ButtonProc;
+    static const TCHAR[] ButtonClass = "BUTTON\0";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            auto hBitmap = OS.LoadBitmap (null, OS.OBM_CHECKBOXES);
+            if (hBitmap is null) {
+                CHECK_WIDTH = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CXSMICON : OS.SM_CXVSCROLL);
+                CHECK_HEIGHT = OS.GetSystemMetrics (OS.IsWinCE ? OS.SM_CYSMICON : OS.SM_CYVSCROLL);
+            } else {
+                BITMAP bitmap;
+                OS.GetObject (hBitmap, BITMAP.sizeof, &bitmap);
+                OS.DeleteObject (hBitmap);
+                CHECK_WIDTH = bitmap.bmWidth / 4;
+                CHECK_HEIGHT =  bitmap.bmHeight / 3;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ButtonClass.ptr, &lpWndClass);
+            ButtonProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#ARROW
+ * @see SWT#CHECK
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#TOGGLE
+ * @see SWT#FLAT
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+void _setImage (Image image) {
+    if ((style & SWT.COMMAND) !is 0) return;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (imageList !is null) imageList.dispose ();
+        imageList = null;
+        if (image !is null) {
+            imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+            if (OS.IsWindowEnabled (handle)) {
+                imageList.add (image);
+            } else {
+                if (disabledImage !is null) disabledImage.dispose ();
+                disabledImage = new Image (display, image, SWT.IMAGE_DISABLE);
+                imageList.add (disabledImage);
+            }
+            BUTTON_IMAGELIST buttonImageList;
+            buttonImageList.himl = imageList.getHandle ();
+            int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+            newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+            if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+            if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+            if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+            if (text.length is 0) {
+                if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+            } else {
+                buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                buttonImageList.margin.left = computeLeftMargin ();
+                buttonImageList.margin.right = MARGIN;
+                newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+                newBits |= OS.BS_LEFT;
+            }
+            if (newBits !is oldBits) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+                OS.InvalidateRect (handle, null, true);
+            }
+            OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+        } else {
+            OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, 0);
+        }
+        /*
+        * Bug in Windows.  Under certain cirumstances yet to be
+        * isolated, BCM_SETIMAGELIST does not redraw the control
+        * when a new image is set.  The fix is to force a redraw.
+        */
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        if (image2 !is null) image2.dispose ();
+        image2 = null;
+        HBITMAP hImage;
+        int imageBits = 0, fImageType = 0;
+        if (image !is null) {
+            switch (image.type) {
+                case SWT.BITMAP: {
+                    Rectangle rect = image.getBounds ();
+                    ImageData data = image.getImageData ();
+                    switch (data.getTransparencyType ()) {
+                        case SWT.TRANSPARENCY_PIXEL:
+                            if (rect.width <= ICON_WIDTH && rect.height <= ICON_HEIGHT) {
+                                image2 = new Image (display, data, data.getTransparencyMask ());
+                                hImage = image2.handle;
+                                imageBits = OS.BS_ICON;
+                                fImageType = OS.IMAGE_ICON;
+                                break;
+                            }
+                            //FALL THROUGH
+                        case SWT.TRANSPARENCY_ALPHA:
+                            image2 = new Image (display, rect.width, rect.height);
+                            GC gc = new GC (image2);
+                            gc.setBackground (getBackground ());
+                            gc.fillRectangle (rect);
+                            gc.drawImage (image, 0, 0);
+                            gc.dispose ();
+                            hImage = image2.handle;
+                            imageBits = OS.BS_BITMAP;
+                            fImageType = OS.IMAGE_BITMAP;
+                            break;
+                        case SWT.TRANSPARENCY_NONE:
+                            hImage = image.handle;
+                            imageBits = OS.BS_BITMAP;
+                            fImageType = OS.IMAGE_BITMAP;
+                            break;
+                        default:
+                    }
+                    break;
+                }
+                case SWT.ICON: {
+                    hImage = image.handle;
+                    imageBits = OS.BS_ICON;
+                    fImageType = OS.IMAGE_ICON;
+                    break;
+                }
+                default:
+            }
+            /*
+            * Feature in Windows.  The button control mirrors its image when the
+            * flag WS_EX_LAYOUTRTL is set. This behaviour is not desirable in SWT.
+            * The fix is to set a mirrored version of real image in the button.
+            */
+            if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+                    Rectangle rect = image.getBounds ();
+                    auto hDC = OS.GetDC (handle);
+                    auto dstHdc = OS.CreateCompatibleDC (hDC);
+                    auto hBitmap = OS.CreateCompatibleBitmap (hDC, rect.width, rect.height);
+                    auto oldBitmap = OS.SelectObject (dstHdc, hBitmap);
+                    OS.SetLayout (dstHdc, OS.LAYOUT_RTL);
+                    if (fImageType is OS.IMAGE_BITMAP) {
+                        auto srcHdc = OS.CreateCompatibleDC (hDC);
+                        auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+                        OS.SetLayout (dstHdc, 0);
+                        OS.BitBlt (dstHdc, 0, 0, rect.width, rect.height, srcHdc, 0, 0, OS.SRCCOPY);
+                        OS.SelectObject (srcHdc, oldSrcBitmap);
+                        OS.DeleteDC (srcHdc);
+                    } else {
+                        Control control = findBackgroundControl ();
+                        if (control is null) control = this;
+                        auto newBrush = OS.CreateSolidBrush (control.getBackgroundPixel ());
+                        auto oldBrush = OS.SelectObject (dstHdc, newBrush);
+                        OS.PatBlt (dstHdc, 0, 0, rect.width, rect.height, OS.PATCOPY);
+                        OS.DrawIconEx (dstHdc, 0, 0, hImage, 0, 0, 0, null, OS.DI_NORMAL);
+                        OS.SelectObject (dstHdc, oldBrush);
+                        OS.DeleteObject (newBrush);
+                    }
+                    OS.SelectObject (dstHdc, oldBitmap);
+                    OS.DeleteDC (dstHdc);
+                    OS.ReleaseDC (handle, hDC);
+                    if (image2 !is null) image2.dispose ();
+                    image2 = Image.win32_new (display, SWT.BITMAP, hBitmap);
+                    imageBits = OS.BS_BITMAP;
+                    fImageType = OS.IMAGE_BITMAP;
+                    hImage = hBitmap;
+                }
+            }
+        }
+        int newBits = OS.GetWindowLong (handle, OS.GWL_STYLE), oldBits = newBits;
+        newBits &= ~(OS.BS_BITMAP | OS.BS_ICON);
+        newBits |= imageBits;
+        if (newBits !is oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+        OS.SendMessage (handle, OS.BM_SETIMAGE, fImageType, hImage);
+    }
+}
+
+void _setText (String text) {
+    int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+        if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+        if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+        if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+        if (imageList !is null) {
+            BUTTON_IMAGELIST buttonImageList;
+            buttonImageList.himl = imageList.getHandle ();
+            if (text.length is 0) {
+                if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+            } else {
+                buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                buttonImageList.margin.left = computeLeftMargin ();
+                buttonImageList.margin.right = MARGIN;
+                newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+                newBits |= OS.BS_LEFT;
+            }
+            OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+        }
+    } else {
+        newBits &= ~(OS.BS_BITMAP | OS.BS_ICON);
+    }
+    if (newBits !is oldBits) {
+        OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+        OS.InvalidateRect (handle, null, true);
+    }
+    /*
+    * Bug in Windows.  When a Button control is right-to-left and
+    * is disabled, the first pixel of the text is clipped.  The
+    * fix is to add a space to both sides of the text.
+    */
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            text = OS.IsWindowEnabled (handle) ? text : " " ~ text ~ " ";
+        }
+    }
+    TCHAR* buffer = StrToTCHARz ( text );
+    OS.SetWindowText (handle, buffer);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the user.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc ( ButtonProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    style = checkBits (style, SWT.PUSH, SWT.ARROW, SWT.CHECK, SWT.RADIO, SWT.TOGGLE, COMMAND_LINK ? SWT.COMMAND : 0);
+    if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+        return checkBits (style, SWT.CENTER, SWT.LEFT, SWT.RIGHT, 0, 0, 0);
+    }
+    if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+        return checkBits (style, SWT.LEFT, SWT.RIGHT, SWT.CENTER, 0, 0, 0);
+    }
+    if ((style & SWT.ARROW) !is 0) {
+        style |= SWT.NO_FOCUS;
+        return checkBits (style, SWT.UP, SWT.DOWN, SWT.LEFT, SWT.RIGHT, 0, 0);
+    }
+    return style;
+}
+
+void click () {
+    /*
+    * Feature in Windows.  BM_CLICK sends a fake WM_LBUTTONDOWN and
+    * WM_LBUTTONUP in order to click the button.  This causes the
+    * application to get unexpected mouse events.  The fix is to
+    * ignore mouse events when they are caused by BM_CLICK.
+    */
+    ignoreMouse = true;
+    OS.SendMessage (handle, OS.BM_CLICK, 0, 0);
+    ignoreMouse = false;
+}
+
+int computeLeftMargin () {
+    if (OS.COMCTL32_MAJOR < 6) return MARGIN;
+    if ((style & (SWT.PUSH | SWT.TOGGLE)) is 0) return MARGIN;
+    int margin = 0;
+    if (image !is null && text.length !is 0) {
+        Rectangle bounds = image.getBounds ();
+        margin += bounds.width + MARGIN * 2;
+        HFONT oldFont;
+        auto hDC = OS.GetDC (handle);
+        HFONT newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        TCHAR* buffer = StrToTCHARz( getCodePage (), text);
+        RECT rect;
+        int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+        OS.DrawText (hDC, buffer, -1, &rect, flags);
+        margin += rect.right - rect.left;
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        OS.GetClientRect (handle, &rect);
+        margin = Math.max (MARGIN, (rect.right - rect.left - margin) / 2);
+    }
+    return margin;
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0, border = getBorderWidth ();
+    if ((style & SWT.ARROW) !is 0) {
+        if ((style & (SWT.UP | SWT.DOWN)) !is 0) {
+            width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+            height += OS.GetSystemMetrics (OS.SM_CYVSCROLL);
+        } else {
+            width += OS.GetSystemMetrics (OS.SM_CXHSCROLL);
+            height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+        }
+    } else {
+        if ((style & SWT.COMMAND) !is 0) {
+            SIZE size;
+            if (wHint !is SWT.DEFAULT) {
+                size.cx = wHint;
+                OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+                width = size.cx;
+                height = size.cy;
+            } else {
+                OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+                width = size.cy;
+                height = size.cy;
+                size.cy = 0;
+                while (size.cy !is height) {
+                    size.cx = width++;
+                    size.cy = 0;
+                    OS.SendMessage (handle, OS.BCM_GETIDEALSIZE, 0, &size);
+                }
+            }
+        } else {
+            int extra = 0;
+            bool hasImage = image !is null, hasText = true;
+            if (OS.COMCTL32_MAJOR < 6) {
+                if ((style & SWT.PUSH) is 0) {
+                    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                    hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) !is 0;
+                    if (hasImage) hasText = false;
+                }
+            }
+            if (hasImage) {
+                if (image !is null) {
+                    Rectangle rect = image.getBounds ();
+                    width = rect.width;
+                    if (hasText && text.length !is 0) {
+                        width += MARGIN * 2;
+                    }
+                    height = rect.height;
+                    extra = MARGIN * 2;
+                }
+            }
+            if (hasText) {
+                HFONT oldFont;
+                auto hDC = OS.GetDC (handle);
+                auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+                TEXTMETRIC lptm;
+                OS.GetTextMetrics (hDC, &lptm);
+                int length_ = text.length;
+                if (length_ is 0) {
+                    height = Math.max (height, lptm.tmHeight);
+                } else {
+                    extra = Math.max (MARGIN * 2, lptm.tmAveCharWidth);
+                    TCHAR* buffer = StrToTCHARz( getCodePage (), text);
+                    RECT rect;
+                    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+                    OS.DrawText (hDC, buffer, -1, &rect, flags);
+                    width += rect.right - rect.left;
+                    height = Math.max (height, rect.bottom - rect.top);
+                }
+                if (newFont !is null) OS.SelectObject (hDC, oldFont);
+                OS.ReleaseDC (handle, hDC);
+            }
+            if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+                width += CHECK_WIDTH + extra;
+                height = Math.max (height, CHECK_HEIGHT + 3);
+            }
+            if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+                width += 12;  height += 10;
+            }
+        }
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    width += border * 2;
+    height += border * 2;
+    return new Point (width, height);
+}
+
+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;
+
+    /* 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 & (SWT.PUSH | SWT.TOGGLE)) is 0) {
+                state |= THEME_BACKGROUND;
+            }
+        }
+    }
+
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the button uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_CTRLCOLOR.
+    *
+    * NOTE: For comctl32.dll 6.0 with themes disabled,
+    * drawing in WM_ERASEBKGND will draw on top of the
+    * text of the control.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if ((style & SWT.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 & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+                state |= DRAW_BACKGROUND;
+            }
+        }
+    }
+}
+
+override int defaultBackground () {
+    if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+        return OS.GetSysColor (OS.COLOR_BTNFACE);
+    }
+    return super.defaultBackground ();
+}
+
+override int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_BTNTEXT);
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    /*
+    * Bug in Windows.  When a button control is right-to-left and
+    * is disabled, the first pixel of the text is clipped.   The
+    * fix is to add a space to both sides of the text.
+    */
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            bool hasImage = (bits & (OS.BS_BITMAP | OS.BS_ICON)) !is 0;
+            if (!hasImage) {
+                String string = enabled ? text : " " ~ text ~ " ";
+                TCHAR* buffer = StrToTCHARz (getCodePage (), string);
+                OS.SetWindowText (handle, buffer);
+            }
+        }
+    }
+    /*
+    * Bug in Windows.  When a button has the style BS_CHECKBOX
+    * or BS_RADIOBUTTON, is checked, and is displaying both an
+    * image and some text, when BCM_SETIMAGELIST is used to
+    * assign an image list for each of the button states, the
+    * button does not draw properly.  When the user drags the
+    * mouse in and out of the button, it draws using a blank
+    * image.  The fix is to set the complete image list only
+    * when the button is disabled.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (imageList !is null) {
+            BUTTON_IMAGELIST buttonImageList;
+            OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, &buttonImageList);
+            if (imageList !is null) imageList.dispose ();
+            imageList = new ImageList (style & SWT.RIGHT_TO_LEFT);
+            if (OS.IsWindowEnabled (handle)) {
+                imageList.add (image);
+            } else {
+                if (disabledImage !is null) disabledImage.dispose ();
+                disabledImage = new Image (display, image, SWT.IMAGE_DISABLE);
+                imageList.add (disabledImage);
+            }
+            buttonImageList.himl = imageList.getHandle ();
+            OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+            /*
+            * Bug in Windows.  Under certain cirumstances yet to be
+            * isolated, BCM_SETIMAGELIST does not redraw the control
+            * when an image is set.  The fix is to force a redraw.
+            */
+            OS.InvalidateRect (handle, null, true);
+        }
+    }
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is an <code>ARROW</code> button, in
+ * which case, the alignment will indicate the direction of
+ * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>UP</code> or <code>DOWN</code>).
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <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 int getAlignment () {
+    checkWidget ();
+    if ((style & SWT.ARROW) !is 0) {
+        if ((style & SWT.UP) !is 0) return SWT.UP;
+        if ((style & SWT.DOWN) !is 0) return SWT.DOWN;
+        if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+        if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+        return SWT.UP;
+    }
+    if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+    if ((style & SWT.CENTER) !is 0) return SWT.CENTER;
+    if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+    return SWT.LEFT;
+}
+
+bool getDefault () {
+    if ((style & SWT.PUSH) is 0) return false;
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return (bits & OS.BS_DEFPUSHBUTTON) !is 0;
+}
+
+/**
+ * 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 SWTException <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 getGrayed () {
+    checkWidget();
+    if ((style & SWT.CHECK) is 0) return false;
+    return grayed;
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget ();
+    return image;
+}
+
+/**
+ * Returns the widget message. When the widget is created
+ * with the style <code>SWT.COMMAND</code>, the message text
+ * is displayed to provide further information for the user.
+ *
+ * @return the widget message
+ *
+ * @exception SWTException <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*/ String getMessage () {
+    checkWidget ();
+    return message;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
+ * it is selected when it is pushed in. If the receiver is of any other type,
+ * this method returns false.
+ *
+ * @return the selection state
+ *
+ * @exception SWTException <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 getSelection () {
+    checkWidget ();
+    if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) is 0) return false;
+    int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+    return flags !is OS.BST_UNCHECKED;
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * an <code>ARROW</code> button.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    if ((style & SWT.ARROW) !is 0) return "";
+    return text;
+}
+
+override bool isTabItem () {
+    if ((style & SWT.PUSH) !is 0) return isTabGroup ();
+    return super.isTabItem ();
+}
+
+override bool mnemonicHit (wchar ch) {
+    if (!setFocus ()) return false;
+    /*
+    * Feature in Windows.  When a radio button gets focus,
+    * it selects the button in WM_SETFOCUS.  Therefore, it
+    * is not necessary to click the button or send events
+    * because this has already happened in WM_SETFOCUS.
+    */
+    if ((style & SWT.RADIO) is 0) click ();
+    return true;
+}
+
+override bool mnemonicMatch (wchar key) {
+    wchar mnemonic = findMnemonic (getText ());
+    if (mnemonic is '\0') return false;
+    return CharacterToUpper (key) is CharacterToUpper (mnemonic);
+}
+
+void printWidget (HWND hwnd, GC gc) {
+    /*
+    * 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.
+    */
+    auto hDC = gc.handle;
+    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 ();
+    imageList = null;
+    if (disabledImage !is null) disabledImage.dispose ();
+    disabledImage = null;
+    if (image2 !is null) image2.dispose ();
+    image2 = null;
+    text = null;
+    image = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void selectRadio () {
+    /*
+    * This code is intentionally commented.  When two groups
+    * of radio buttons with the same parent are separated by
+    * another control, the correct behavior should be that
+    * the two groups act independently.  This is consistent
+    * with radio tool and menu items.  The commented code
+    * implements this behavior.
+    */
+//  int index = 0;
+//  Control [] children = parent._getChildren ();
+//  while (index < children.length && children [index] !is this) index++;
+//  int i = index - 1;
+//  while (i >= 0 && children [i].setRadioSelection (false)) --i;
+//  int j = index + 1;
+//  while (j < children.length && children [j].setRadioSelection (false)) j++;
+//  setSelection (true);
+    Control [] children = parent._getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (this !is child) child.setRadioSelection (false);
+    }
+    setSelection (true);
+}
+
+/**
+ * Controls how text, images and arrows will be displayed
+ * in the receiver. The argument should be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is an <code>ARROW</code> button, in
+ * which case, the argument indicates the direction of
+ * the arrow (one of <code>LEFT</code>, <code>RIGHT</code>,
+ * <code>UP</code> or <code>DOWN</code>).
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <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 setAlignment (int alignment) {
+    checkWidget ();
+    if ((style & SWT.ARROW) !is 0) {
+        if ((style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) is 0) return;
+        style &= ~(SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+        style |= alignment & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT);
+        OS.InvalidateRect (handle, null, true);
+        return;
+    }
+    if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return;
+    style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+    newBits &= ~(OS.BS_LEFT | OS.BS_CENTER | OS.BS_RIGHT);
+    if ((style & SWT.LEFT) !is 0) newBits |= OS.BS_LEFT;
+    if ((style & SWT.CENTER) !is 0) newBits |= OS.BS_CENTER;
+    if ((style & SWT.RIGHT) !is 0) newBits |= OS.BS_RIGHT;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (imageList !is null) {
+            BUTTON_IMAGELIST buttonImageList;
+            buttonImageList.himl = imageList.getHandle ();
+            if (text.length is 0) {
+                if ((style & SWT.LEFT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                if ((style & SWT.CENTER) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_CENTER;
+                if ((style & SWT.RIGHT) !is 0) buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_RIGHT;
+            } else {
+                buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                buttonImageList.margin.left = computeLeftMargin ();
+                buttonImageList.margin.right = MARGIN;
+                newBits &= ~(OS.BS_CENTER | OS.BS_RIGHT);
+                newBits |= OS.BS_LEFT;
+            }
+            OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+        }
+    }
+    if (newBits !is oldBits) {
+        OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+        OS.InvalidateRect (handle, null, true);
+    }
+}
+
+void setDefault (bool value) {
+    if ((style & SWT.PUSH) is 0) return;
+    auto hwndShell = menuShell ().handle;
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if (value) {
+        bits |= OS.BS_DEFPUSHBUTTON;
+        OS.SendMessage (hwndShell, OS.DM_SETDEFID, handle, 0);
+    } else {
+        bits &= ~OS.BS_DEFPUSHBUTTON;
+        OS.SendMessage (hwndShell, OS.DM_SETDEFID, 0, 0);
+    }
+    OS.SendMessage (handle, OS.BM_SETSTYLE, bits, 1);
+}
+
+override bool setFixedFocus () {
+    /*
+    * Feature in Windows.  When a radio button gets focus,
+    * it selects the button in WM_SETFOCUS.  The fix is to
+    * not assign focus to an unselected radio button.
+    */
+    if ((style & SWT.RADIO) !is 0 && !getSelection ()) return false;
+    return super.setFixedFocus ();
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * <code>null</code> indicating that no image should be displayed.
+ * <p>
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX.  On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ * </p>
+ * @param image the image to display on the receiver (may be <code>null</code>)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image image) {
+    checkWidget ();
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    if ((style & SWT.ARROW) !is 0) return;
+    this.image = image;
+    /* This code is intentionally commented */
+//  if (OS.COMCTL32_MAJOR < 6) {
+//      if (image is null || text.length !is 0) {
+//          _setText (text);
+//          return;
+//      }
+//  }
+    _setImage (image);
+}
+
+/**
+ * Sets the grayed state of the receiver.  This state change
+ * only applies if the control was created with the SWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed state
+ *
+ * @exception SWTException <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 setGrayed (bool grayed) {
+    checkWidget ();
+    if ((style & SWT.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>SWT.COMMAND</code>, the message text
+ * is displayed to provide further information for the user.
+ *
+ * @param message the new message
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ * @exception SWTException <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 setMessage (String message) {
+    checkWidget ();
+    // SWT externsion: allow null string
+    //if (message is null) error (SWT.ERROR_NULL_ARGUMENT);
+    this.message = message;
+    if (OS.COMCTL32_VERSION >= OS.VERSION (6, 1)) {
+        if ((style & SWT.COMMAND) !is 0) {
+            OS.SendMessage (handle, OS.BCM_SETNOTE, 0, StrToTCHARz( message ));
+        }
+    }
+}
+
+override bool setRadioFocus () {
+    if ((style & SWT.RADIO) is 0 || !getSelection ()) return false;
+    return setFocus ();
+}
+
+override bool setRadioSelection (bool value) {
+    if ((style & SWT.RADIO) is 0) return false;
+    if (getSelection () !is value) {
+        setSelection (value);
+        postEvent (SWT.Selection);
+    }
+    return true;
+}
+
+override bool setSavedFocus () {
+    /*
+    * Feature in Windows.  When a radio button gets focus,
+    * it selects the button in WM_SETFOCUS.  If the previous
+    * saved focus widget was a radio button, allowing the shell
+    * to automatically restore the focus to the previous radio
+    * button will unexpectedly check that button.  The fix is to
+    * not assign focus to an unselected radio button.
+    */
+    if ((style & SWT.RADIO) !is 0 && !getSelection ()) return false;
+    return super.setSavedFocus ();
+}
+
+/**
+ * Sets the selection state of the receiver, if it is of type <code>CHECK</code>,
+ * <code>RADIO</code>, or <code>TOGGLE</code>.
+ *
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked. When it is of type <code>TOGGLE</code>,
+ * it is selected when it is pushed in.
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException <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 setSelection (bool selected) {
+    checkWidget ();
+    if ((style & (SWT.CHECK | SWT.RADIO | SWT.TOGGLE)) is 0) return;
+    int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
+    if ((style & SWT.CHECK) !is 0) {
+        if (selected && grayed) flags = OS.BST_INDETERMINATE;
+    }
+    updateSelection (flags);
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * This method sets the button label.  The label may include
+ * the mnemonic character but must not contain line delimiters.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasized in a platform specific
+ * manner.  The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p><p>
+ * Note that a Button can display an image and text simultaneously
+ * on Windows (starting with XP), GTK+ and OSX.  On other platforms,
+ * a Button that has an image and text set into it will display the
+ * image or text that was set most recently.
+ * </p>
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT externsion: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((style & SWT.ARROW) !is 0) return;
+    text = string;
+    /* This code is intentionally commented */
+//  if (OS.COMCTL32_MAJOR < 6) {
+//      if (text.length is 0 && image !is null) {
+//          _setImage (image);
+//          return;
+//      }
+//  }
+    _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 & SWT.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 & SWT.FLAT) !is 0) bits |= OS.BS_FLAT;
+    if ((style & SWT.ARROW) !is 0) return bits | OS.BS_OWNERDRAW;
+    if ((style & SWT.LEFT) !is 0) bits |= OS.BS_LEFT;
+    if ((style & SWT.CENTER) !is 0) bits |= OS.BS_CENTER;
+    if ((style & SWT.RIGHT) !is 0) bits |= OS.BS_RIGHT;
+    if ((style & SWT.PUSH) !is 0) return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+    if ((style & SWT.CHECK) !is 0) return bits | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+    if ((style & SWT.RADIO) !is 0) return bits | OS.BS_RADIOBUTTON;
+    if ((style & SWT.TOGGLE) !is 0) return bits | OS.BS_PUSHLIKE | OS.BS_CHECKBOX | OS.WS_TABSTOP;
+    if ((style & SWT.COMMAND) !is 0) return bits | OS.BS_COMMANDLINK | OS.WS_TABSTOP;
+    return bits | OS.BS_PUSHBUTTON | OS.WS_TABSTOP;
+}
+
+override String windowClass () {
+    return TCHARzToStr( ButtonClass.ptr );
+}
+
+override int windowProc () {
+    return cast(int) ButtonProc;
+}
+
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the button uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_ERASEBKGND.
+    */
+    if (OS.COMCTL32_MAJOR < 6) {
+        if ((style & (SWT.RADIO | SWT.CHECK)) !is 0) {
+            if (findImageControl () !is null) {
+                drawBackground (cast(HWND)wParam);
+                return LRESULT.ONE;
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+    if ((style & SWT.ARROW) !is 0) {
+        return new LRESULT (OS.DLGC_STATIC);
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+    if ((style & SWT.PUSH) !is 0 && getDefault ()) {
+        menuShell ().setDefaultButton (null, false);
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    if (ignoreMouse) return null;
+    return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+    if (ignoreMouse) return null;
+    return super.WM_LBUTTONUP (wParam, lParam);
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    /*
+    * Feature in Windows. When Windows sets focus to
+    * a radio 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 = 0;
+    if ((style & SWT.RADIO) !is 0) {
+        bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    }
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    if ((style & SWT.RADIO) !is 0) {
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    }
+    if ((style & SWT.PUSH) !is 0) {
+        menuShell ().setDefaultButton (this, false);
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (result !is null) return result;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if ((style & (SWT.PUSH | SWT.TOGGLE)) !is 0) {
+            if (imageList !is null && text.length !is 0) {
+                BUTTON_IMAGELIST buttonImageList;
+                OS.SendMessage (handle, OS.BCM_GETIMAGELIST, 0, &buttonImageList);
+                buttonImageList.uAlign = OS.BUTTON_IMAGELIST_ALIGN_LEFT;
+                buttonImageList.margin.left = computeLeftMargin ();
+                buttonImageList.margin.right = MARGIN;
+                OS.SendMessage (handle, OS.BCM_SETIMAGELIST, 0, &buttonImageList);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    if (image2 !is null) _setImage (image);
+    return result;
+}
+
+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 button, it sends WM_CTLCOLORBTN to get the foreground
+    * and background.  If drawing happens in WM_CTLCOLORBTN,
+    * it will overwrite the contents of the control.  The
+    * fix is draw the button without drawing the background
+    * and avoid the button window proc.
+    *
+    * NOTE:  This only happens for radio, check and toggle
+    * buttons.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if ((style & (SWT.RADIO | SWT.CHECK | SWT.TOGGLE)) !is 0) {
+            bool redraw = findImageControl () !is null;
+            if (!redraw) {
+                if ((state & THEME_BACKGROUND) !is 0) {
+                    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                        redraw = findThemeControl () !is null;
+                    }
+                }
+                if (!redraw) redraw = findBackgroundControl () !is null;
+            }
+            if (redraw) {
+                OS.InvalidateRect (handle, null, false);
+                int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+                return new LRESULT (code);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    int code = OS.HIWORD (wParam);
+    switch (code) {
+        case OS.BN_CLICKED:
+        case OS.BN_DOUBLECLICKED:
+            if ((style & (SWT.CHECK | SWT.TOGGLE)) !is 0) {
+                setSelection (!getSelection ());
+            } else {
+                if ((style & SWT.RADIO) !is 0) {
+                    if ((parent.getStyle () & SWT.NO_RADIO_GROUP) !is 0) {
+                        setSelection (!getSelection ());
+                    } else {
+                        selectRadio ();
+                    }
+                }
+            }
+            postEvent (SWT.Selection);
+        default:
+    }
+    return super.wmCommandChild (wParam, lParam);
+}
+
+override LRESULT wmColorChild (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the button uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_ERASEBKGND.
+    */
+    LRESULT result = super.wmColorChild (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) {
+        if ((style & (SWT.RADIO | SWT.CHECK)) !is 0) {
+            if (findImageControl () !is null) {
+                OS.SetBkMode (cast(HANDLE)wParam, OS.TRANSPARENT);
+                return new LRESULT ( cast(int) OS.GetStockObject (OS.NULL_BRUSH));
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT wmDrawChild (int wParam, int lParam) {
+    if ((style & SWT.ARROW) is 0) return super.wmDrawChild (wParam, lParam);
+    auto struct_ = cast(DRAWITEMSTRUCT*)lParam;
+    //OS.MoveMemory (struct_, lParam, DRAWITEMSTRUCT.sizeof);
+    RECT rect;
+    OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, struct_.rcItem.right, struct_.rcItem.bottom);
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        int iStateId = OS.ABS_LEFTNORMAL;
+        switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) {
+            case SWT.UP: iStateId = OS.ABS_UPNORMAL; break;
+            case SWT.DOWN: iStateId = OS.ABS_DOWNNORMAL; break;
+            case SWT.LEFT: iStateId = OS.ABS_LEFTNORMAL; break;
+            case SWT.RIGHT: iStateId = OS.ABS_RIGHTNORMAL; break;
+            default:
+        }
+        /*
+        * NOTE: The normal, hot, pressed and disabled state is
+        * computed relying on the fact that the increment between
+        * the direction states is invariant (always separated by 4).
+        */
+        if (!getEnabled ()) iStateId += OS.ABS_UPDISABLED - OS.ABS_UPNORMAL;
+        if ((struct_.itemState & OS.ODS_SELECTED) !is 0) iStateId += OS.ABS_UPPRESSED - OS.ABS_UPNORMAL;
+        OS.DrawThemeBackground (display.hScrollBarTheme (), struct_.hDC, OS.SBP_ARROWBTN, iStateId, &rect, null);
+    } else {
+        int uState = OS.DFCS_SCROLLLEFT;
+        switch (style & (SWT.UP | SWT.DOWN | SWT.LEFT | SWT.RIGHT)) {
+            case SWT.UP: uState = OS.DFCS_SCROLLUP; break;
+            case SWT.DOWN: uState = OS.DFCS_SCROLLDOWN; break;
+            case SWT.LEFT: uState = OS.DFCS_SCROLLLEFT; break;
+            case SWT.RIGHT: uState = OS.DFCS_SCROLLRIGHT; break;
+            default:
+        }
+        if (!getEnabled ()) uState |= OS.DFCS_INACTIVE;
+        if ((style & SWT.FLAT) is SWT.FLAT) uState |= OS.DFCS_FLAT;
+        if ((struct_.itemState & OS.ODS_SELECTED) !is 0) uState |= OS.DFCS_PUSHED;
+        OS.DrawFrameControl (struct_.hDC, &rect, OS.DFC_SCROLL, uState);
+    }
+    return null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Canvas.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,503 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Canvas;
+
+import org.eclipse.swt.widgets.Composite;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Caret;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.IME;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide a surface for drawing
+ * arbitrary graphics.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are <em>not</em> constructed
+ * from aggregates of other controls. That is, they are either
+ * painted using SWT graphics calls or are handled by native
+ * methods.
+ * </p>
+ *
+ * @see Composite
+ * @see <a href="http://www.eclipse.org/swt/snippets/#canvas">Canvas snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Canvas : Composite {
+
+    alias Composite.drawBackground drawBackground;
+    alias Composite.windowProc windowProc;
+
+    Caret caret;
+    IME ime;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, style);
+}
+
+void clearArea (int x, int y, int width, int height) {
+    checkWidget ();
+    if (OS.IsWindowVisible (handle)) {
+        RECT rect;
+        OS.SetRect (&rect, x, y, x + width, y + height);
+        auto hDC = OS.GetDCEx (handle, null, OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS);
+        drawBackground (hDC, &rect);
+        OS.ReleaseDC (handle, hDC);
+    }
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * with the receiver's background.
+ *
+ * @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 SWTException <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.2
+ */
+public void drawBackground (GC gc, int x, int y, int width, int height) {
+    checkWidget ();
+    if (gc is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    auto hDC = gc.handle;
+    int pixel = background is -1 ? gc.getBackground ().handle : -1;
+    drawBackground (hDC, &rect, pixel);
+}
+
+/**
+ * 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 for the receiver, may be null
+ *
+ * @exception SWTException <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 SWTException <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
+ * be repainted. Children that intersect the rectangle are
+ * optionally moved during the operation. In addition, outstanding
+ * paint events are flushed before the source area is copied to
+ * ensure that the contents of the canvas are drawn correctly.
+ *
+ * @param destX the x coordinate of the destination
+ * @param destY the y coordinate of the destination
+ * @param x the x coordinate of the source
+ * @param y the y coordinate of the source
+ * @param width the width of the area
+ * @param height the height of the area
+ * @param all <code>true</code>if children should be scrolled, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 scroll (int destX, int destY, int x, int y, int width, int height, bool all) {
+    checkWidget ();
+    forceResize ();
+    bool isFocus = caret !is null && caret.isFocusCaret ();
+    if (isFocus) caret.killFocus ();
+    RECT sourceRect;
+    OS.SetRect (&sourceRect, x, y, x + width, y + height);
+    RECT clientRect;
+    OS.GetClientRect (handle, &clientRect);
+    if (OS.IntersectRect (&clientRect, &sourceRect, &clientRect)) {
+        static if (OS.IsWinCE) {
+            OS.UpdateWindow (handle);
+        } else {
+            int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (handle, null, null, flags);
+        }
+    }
+    int deltaX = destX - x, deltaY = destY - y;
+    if (findImageControl () !is null) {
+        static if (OS.IsWinCE) {
+            OS.InvalidateRect (handle, &sourceRect, true);
+        } else {
+            { // scope for flags
+            int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+            if (all) flags |= OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (handle, &sourceRect, null, flags);
+            }
+        }
+        OS.OffsetRect (&sourceRect, deltaX, deltaY);
+        static if (OS.IsWinCE) {
+            OS.InvalidateRect (handle, &sourceRect, true);
+        } else {
+            int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+            if (all) flags |= OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (handle, &sourceRect, null, flags);
+        }
+    } else {
+        int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
+        /*
+        * Feature in Windows.  If any child in the widget tree partially
+        * intersects the scrolling rectangle, Windows moves the child
+        * and copies the bits that intersect the scrolling rectangle but
+        * does not redraw the child.
+        *
+        * Feature in Windows.  When any child in the widget tree does not
+        * intersect the scrolling rectangle but the parent does intersect,
+        * Windows does not move the child.  This is the documented (but
+        * strange) Windows behavior.
+        *
+        * The fix is to not use SW_SCROLLCHILDREN and move the children
+        * explicitly after scrolling.
+        */
+//      if (all) flags |= OS.SW_SCROLLCHILDREN;
+        OS.ScrollWindowEx (handle, deltaX, deltaY, &sourceRect, null, null, null, flags);
+    }
+    if (all) {
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            Control child = children [i];
+            Rectangle rect = child.getBounds ();
+            if (Math.min (x + width, rect.x + rect.width) >= Math.max (x, rect.x) &&
+                Math.min (y + height, rect.y + rect.height) >= Math.max (y, rect.y)) {
+                    child.setLocation (rect.x + deltaX, rect.y + deltaY);
+            }
+        }
+    }
+    if (isFocus) caret.setFocus ();
+}
+
+/**
+ * Sets the receiver's 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>
+ * @param caret the new caret for the receiver, may be null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the caret has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setCaret (Caret caret) {
+    checkWidget ();
+    Caret newCaret = caret;
+    Caret oldCaret = this.caret;
+    this.caret = newCaret;
+    if (hasFocus ()) {
+        if (oldCaret !is null) oldCaret.killFocus ();
+        if (newCaret !is null) {
+            if (newCaret.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+            newCaret.setFocus ();
+        }
+    }
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    if (caret !is null) caret.setFont (font);
+    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 SWTException <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(SWT.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) {
+            if (caret !is null) {
+                caret.killFocus ();
+                caret.setFocus ();
+                return 1;
+            }
+        }
+    }
+    return super.windowProc (hwnd, msg, 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 SWT.DEL:
+            case SWT.BS:
+            case SWT.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
+    * in the top left corner of the screen, despite the fact
+    * that ImmSetCompositionWindow() was called to position
+    * the IME when focus is gained.  The fix is to position
+    * the IME on every WM_IME_COMPOSITION message.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION is OS.VERSION (5, 1)) {
+        if (OS.IsDBLocale) {
+            short langID = OS.GetSystemDefaultUILanguage ();
+            short primaryLang = OS.PRIMARYLANGID (langID);
+            if (primaryLang is OS.LANG_KOREAN) {
+                if (caret !is null && caret.isFocusCaret ()) {
+                    POINT ptCurrentPos;
+                    if (OS.GetCaretPos (&ptCurrentPos)) {
+                        COMPOSITIONFORM lpCompForm;
+                        lpCompForm.dwStyle = OS.CFS_POINT;
+                        lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
+                        lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
+                        auto hIMC = OS.ImmGetContext (handle);
+                        OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
+                        OS.ImmReleaseContext (handle, hIMC);
+                    }
+                }
+            }
+        }
+    }
+    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) {
+    LRESULT result  = super.WM_INPUTLANGCHANGE (wParam, lParam);
+    if (caret !is null && caret.isFocusCaret ()) {
+        caret.setIMEFont ();
+        caret.resizeIME ();
+    }
+    return result;
+}
+
+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 ();
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result  = super.WM_SIZE (wParam, lParam);
+    if (caret !is null && caret.isFocusCaret ()) caret.resizeIME ();
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
+    LRESULT result  = super.WM_WINDOWPOSCHANGED (wParam, lParam);
+    //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
+    * caret in relation to the mirrored origin in the top right.
+    * The fix is to hide the caret in WM_WINDOWPOSCHANGING and
+    * show the caret in WM_WINDOWPOSCHANGED.
+    */
+    bool isFocus = (style & SWT.RIGHT_TO_LEFT) !is 0 && caret !is null && caret.isFocusCaret ();
+    if (isFocus) caret.setFocus ();
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result  = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    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
+    * caret in relation to the mirrored origin in the top right.
+    * The fix is to hide the caret in WM_WINDOWPOSCHANGING and
+    * show the caret in WM_WINDOWPOSCHANGED.
+    */
+    bool isFocus = (style & SWT.RIGHT_TO_LEFT) !is 0 && caret !is null && caret.isFocusCaret ();
+    if (isFocus) caret.killFocus ();
+    return result;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Caret.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,612 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Caret;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.IME;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide an i-beam that is typically used
+ * as the insertion point for text.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#caret">Caret snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Canvas tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Caret : Widget {
+    Canvas parent;
+    int x, y, width, height;
+    bool moved, resized;
+    bool isVisible_;
+    Image image;
+    Font font;
+    LOGFONT* oldFont;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Canvas parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    createWidget ();
+}
+
+void createWidget () {
+    isVisible_ = true;
+    if (parent.getCaret () is null) {
+        parent.setCaret (this);
+    }
+}
+
+HFONT defaultFont () {
+    auto hwnd = parent.handle;
+    auto hwndIME = OS.ImmGetDefaultIMEWnd (hwnd);
+    HFONT hFont;
+    if (hwndIME !is null) {
+        hFont = cast(HFONT) OS.SendMessage (hwndIME, OS.WM_GETFONT, 0, 0);
+    }
+    if (hFont is null) {
+        hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+    }
+    if (hFont is null) return parent.defaultFont ();
+    return hFont;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    checkWidget();
+    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);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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 Font getFont () {
+    checkWidget();
+    if (font is null) {
+        HFONT hFont = defaultFont ();
+        return Font.win32_new (display, hFont);
+    }
+    return font;
+}
+
+/**
+ * Returns the image that the receiver will use to paint the caret.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget();
+    return image;
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's location
+ *
+ * @exception SWTException <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 Point getLocation () {
+    checkWidget();
+    return new Point (x, y);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Canvas</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Canvas getParent () {
+    checkWidget();
+    return parent;
+}
+
+/**
+ * Returns a point describing the receiver's size.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException <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 Point getSize () {
+    checkWidget();
+    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);
+}
+
+/**
+ * Returns <code>true</code> if the receiver 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 visibility state
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget();
+    return isVisible_;
+}
+
+bool hasFocus () {
+    return parent.handle is OS.GetFocus ();
+}
+
+bool isFocusCaret () {
+    return parent.caret is this && hasFocus ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException <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 #getVisible
+ */
+public bool isVisible () {
+    checkWidget();
+    return isVisible_ && parent.isVisible () && hasFocus ();
+}
+
+void killFocus () {
+    OS.DestroyCaret ();
+    restoreIMEFont ();
+}
+
+void move () {
+    moved = false;
+    if (!OS.SetCaretPos (x, y)) return;
+    resizeIME ();
+}
+
+void resizeIME () {
+    if (!OS.IsDBLocale) return;
+    POINT ptCurrentPos;
+    if (!OS.GetCaretPos (&ptCurrentPos)) return;
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    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);
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (this is parent.getCaret ()) parent.setCaret (null);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    parent = null;
+    image = null;
+    font = null;
+    oldFont = null;
+}
+
+void resize () {
+    resized = false;
+    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);
+    move ();
+}
+
+void restoreIMEFont () {
+    if (!OS.IsDBLocale) return;
+    if (oldFont is null) return;
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    OS.ImmSetCompositionFont (hIMC, oldFont);
+    OS.ImmReleaseContext (hwnd, hIMC);
+    oldFont = null;
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The <code>x</code> and
+ * <code>y</code> arguments are relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException <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 setBounds (int x, int y, int width, int height) {
+    checkWidget();
+    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;
+    if (sameExtent) {
+        moved = true;
+        if (isVisible_ && hasFocus ()) move ();
+    } else {
+        resized = true;
+        if (isVisible_ && hasFocus ()) resize ();
+    }
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The <code>x</code> and
+ * <code>y</code> fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @exception SWTException <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 setBounds (Rectangle rect) {
+    if (rect is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+void setFocus () {
+    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 ();
+    if (isVisible_) OS.ShowCaret (hwnd);
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * to the font specified by the argument, or to the default font for that
+ * kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setFont (Font font) {
+    checkWidget();
+    if (font !is null && font.isDisposed ()) {
+        error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.font = font;
+    if (hasFocus ()) setIMEFont ();
+}
+
+/**
+ * Sets the image that the receiver will use to paint the caret
+ * to the image specified by the argument, or to the default
+ * which is a filled rectangle if the argument is null
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.image = image;
+    if (isVisible_ && hasFocus ()) resize ();
+}
+
+void setIMEFont () {
+    if (!OS.IsDBLocale) return;
+    HFONT hFont;
+    if (font !is null) hFont = font.handle;
+    if (hFont is null) hFont = defaultFont ();
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    /* Save the current IME font */
+    if (oldFont is null) {
+        oldFont = new LOGFONT;
+        if (!OS.ImmGetCompositionFont (hIMC, oldFont)) oldFont = null;
+    }
+    /* Set new IME font */
+    LOGFONT logFont;
+    if (OS.GetObject (hFont, LOGFONT.sizeof, &logFont) !is 0) {
+        OS.ImmSetCompositionFont (hIMC, &logFont);
+    }
+    OS.ImmReleaseContext (hwnd, hIMC);
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException <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 setLocation (int x, int y) {
+    checkWidget();
+    if (this.x is x && this.y is y) return;
+    this.x = x;  this.y = y;
+    moved = true;
+    if (isVisible_ && hasFocus ()) move ();
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the argument which is relative to the receiver's
+ * parent (or its display if its parent is null).
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception SWTException <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 setLocation (Point location) {
+    checkWidget();
+    if (location is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException <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 setSize (int width, int height) {
+    checkWidget();
+    if (this.width is width && this.height is height) return;
+    this.width = width;  this.height = height;
+    resized = true;
+    if (isVisible_ && hasFocus ()) resize ();
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ *
+ * @param size the new extent for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSize (Point size) {
+    checkWidget();
+    if (size is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSize (size.x, size.y);
+}
+
+/**
+ * Marks the receiver 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 SWTException <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 setVisible (bool visible) {
+    checkWidget();
+    if (visible is isVisible_) return;
+    isVisible_ = visible;
+    auto hwnd = parent.handle;
+    if (OS.GetFocus () !is hwnd) return;
+    if (!isVisible_) {
+        OS.HideCaret (hwnd);
+    } else {
+        if (resized) {
+            resize ();
+        } else {
+            if (moved) move ();
+        }
+        OS.ShowCaret (hwnd);
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ColorDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ColorDialog;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.win32.OS;
+
+
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * Instances of this class allow the user to select a color
+ * from a predefined set of available colors.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class ColorDialog : Dialog {
+    Display display;
+    int width, height;
+    RGB rgb;
+    private static ColorDialog sThis;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a composite control which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Shell parent) {
+    this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (parent, style));
+    checkSubclass ();
+}
+
+private static extern(Windows) uint CCHookFunc (HWND hdlg, uint uiMsg, uint lParam, int lpData) {
+    return sThis.CCHookProc( hdlg, uiMsg, lParam );
+}
+
+int CCHookProc (HWND hdlg, uint uiMsg, uint lParam ) {
+    switch (uiMsg) {
+        case OS.WM_INITDIALOG: {
+            RECT rect;
+            OS.GetWindowRect (hdlg, &rect);
+            width = rect.right - rect.left;
+            height = rect.bottom - rect.top;
+            if (title !is null && title.length !is 0) {
+                /* Use the character encoding for the default locale */
+                OS.SetWindowText (hdlg, StrToTCHARz(title));
+            }
+            break;
+        }
+        case OS.WM_DESTROY: {
+            RECT rect;
+            OS.GetWindowRect (hdlg, &rect);
+            int newWidth = rect.right - rect.left;
+            int newHeight = rect.bottom - rect.top;
+            if (newWidth < width || newHeight < height) {
+                //display.fullOpen = false;
+            } else {
+                if (newWidth > width || newHeight > height) {
+                    //display.fullOpen = true;
+                }
+            }
+            break;
+        }
+        default:
+    }
+    return 0;
+}
+
+/**
+ * Returns the currently selected color in the receiver.
+ *
+ * @return the RGB value for the selected color, may be null
+ *
+ * @see PaletteData#getRGBs
+ */
+public RGB getRGB () {
+    return rgb;
+}
+
+/**
+ * Makes the receiver visible and brings it to the front
+ * of the display.
+ *
+ * @return the selected color, or null if the dialog was
+ *         cancelled, no color was selected, or an error
+ *         occurred
+ *
+ * @exception SWTException <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 RGB open () {
+
+    /* 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 & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is SWT.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$
+    //int lpfnHook = callback.getAddress ();
+    //if (lpfnHook is 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+
+    /* Allocate the Custom Colors */
+    display = parent.display;
+    if (display.lpCustColors is null) {
+        auto hHeap = OS.GetProcessHeap ();
+        display.lpCustColors = cast(uint*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, 16 * 4);
+    }
+
+    /* Open the dialog */
+    CHOOSECOLOR lpcc;
+    lpcc.lCustData = cast(int)cast(void*)this;
+    lpcc.lStructSize = CHOOSECOLOR.sizeof;
+    lpcc.Flags = OS.CC_ANYCOLOR | OS.CC_ENABLEHOOK;
+    //if (display.fullOpen) lpcc.Flags |= OS.CC_FULLOPEN;
+    lpcc.lpfnHook = &CCHookFunc;
+    lpcc.hwndOwner = hwndOwner;
+    lpcc.lpCustColors = display.lpCustColors;
+    if (rgb !is null) {
+        lpcc.Flags |= OS.CC_RGBINIT;
+        int red = rgb.red & 0xFF;
+        int green = (rgb.green << 8) & 0xFF00;
+        int blue = (rgb.blue << 16) & 0xFF0000;
+        lpcc.rgbResult = red | green | blue;
+    }
+
+    /* Make the parent shell be temporary modal */
+    Dialog oldModal = null;
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
+    }
+
+    /* Open the dialog */
+    bool success;
+    synchronized {
+        sThis = this;
+        success = cast(bool) OS.ChooseColor (&lpcc);
+        sThis = null;
+    }
+
+    /* Clear the temporary dialog modal parent */
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        display.setModalDialog (oldModal);
+    }
+
+    if (success) {
+        int red = lpcc.rgbResult & 0xFF;
+        int green = (lpcc.rgbResult >> 8) & 0xFF;
+        int blue = (lpcc.rgbResult >> 16) & 0xFF;
+        rgb = new RGB (red, green, blue);
+    }
+
+    /* Free the CCHookProc */
+    //callback.dispose ();
+
+    /* Free the Custom Colors */
+    /*
+    * This code is intentionally commented.  Currently,
+    * there is exactly one set of custom colors per display.
+    * The memory associated with these colors is released
+    * when the display is disposed.
+    */
+//  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
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+    display = null;
+    if (!success) return null;
+    return rgb;
+}
+
+/**
+ * Sets the receiver's selected color to be the argument.
+ *
+ * @param rgb the new RGB value for the selected color, may be
+ *        null to let the platform select a default when
+ *        open() is called
+ * @see PaletteData#getRGBs
+ */
+public void setRGB (RGB rgb) {
+    this.rgb = rgb;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Combo.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2552 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Combo;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are controls that allow the user
+ * to choose an item from a list of items, or optionally
+ * enter a new value by typing it into an editable text
+ * field. Often, <code>Combo</code>s are used in the same place
+ * where a single selection <code>List</code> widget could
+ * be used but space is limited. A <code>Combo</code> takes
+ * less space than a <code>List</code> widget and shows
+ * similar information.
+ * <p>
+ * Note: Since <code>Combo</code>s can contain both a list
+ * and an editable text field, it is possible to confuse methods
+ * which access one versus the other (compare for example,
+ * <code>clearSelection()</code> and <code>deselectAll()</code>).
+ * The API documentation is careful to indicate either "the
+ * receiver's list" or the "the receiver's text field" to
+ * distinguish between the two cases.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>DROP_DOWN, READ_ONLY, SIMPLE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, Modify, Selection, Verify</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see List
+ * @see <a href="http://www.eclipse.org/swt/snippets/#combo">Combo snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Combo : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.dragDetect dragDetect;
+    alias Composite.sendKeyEvent sendKeyEvent;
+    alias Composite.setBackgroundImage setBackgroundImage;
+    alias Composite.setBounds setBounds;
+    alias Composite.setToolTipText setToolTipText;
+
+    private static Combo pThis;
+    bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize;
+    HHOOK cbtHook;
+    int scrollWidth, visibleCount = 5;
+
+    /**
+     * the operating system limit for the number of characters
+     * that the text field in an instance of this class can hold
+     */
+    private static int LIMIT_ = 0;
+
+    /*
+     * These values can be different on different platforms.
+     * Therefore they are not initialized in the declaration
+     * to stop the compiler from inlining.
+     */
+    public static int LIMIT(){
+        if( LIMIT_ is 0 ){
+            synchronized {
+                LIMIT_ = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
+            }
+        }
+        return LIMIT_;
+    }
+    /*
+     * These are the undocumented control id's for the children of
+     * a combo box.  Since there are no constants for these values,
+     * they may change with different versions of Windows (but have
+     * been the same since Windows 3.0).
+     */
+    static const int CBID_LIST = 1000;
+    static const int CBID_EDIT = 1001;
+    static /*final*/ WNDPROC EditProc, ListProc;
+
+    static /+const+/ WNDPROC ComboProc;
+    static const TCHAR* ComboClass = "COMBOBOX\0";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ComboClass, &lpWndClass);
+            ComboProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DROP_DOWN
+ * @see SWT#READ_ONLY
+ * @see SWT#SIMPLE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+    /* This code is intentionally commented */
+    //if ((style & SWT.H_SCROLL) !is 0) this.style |= SWT.H_SCROLL;
+    this.style |= SWT.H_SCROLL;
+}
+
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception SWTException <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 #add(String,int)
+ */
+public void add (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    auto buffer = StrToTCHARs( getCodePage(), string, true );
+    int result = OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer.ptr );
+    if (result is OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+    if (result is OS.CB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ * <p>
+ * Note: To add an item at the end of the list, use the
+ * result of calling <code>getItemCount()</code> as the
+ * index or use <code>add(String)</code>.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 #add(String)
+ */
+public void add (String string, int index) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (!(0 <= index && index <= count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    auto buffer = StrToTCHARs( getCodePage(), string, true );
+    int result = OS.SendMessage (handle, OS.CB_INSERTSTRING, index, buffer.ptr);
+    if (result is OS.CB_ERRSPACE || result is OS.CB_ERR) {
+        error (SWT.ERROR_ITEM_NOT_ADDED);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the combo's list selection.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #removeVerifyListener
+ *
+ * @since 3.1
+ */
+public void addVerifyListener (VerifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Verify, typedListener);
+}
+
+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;
+            default:
+            }
+        }
+        return OS.CallWindowProc( ComboProc, hwnd, msg, wParam, lParam);
+    }
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwnd is hwndText) {
+        return OS.CallWindowProc( EditProc, hwnd, msg, wParam, lParam);
+    }
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwnd is hwndList) {
+        return OS.CallWindowProc( ListProc, hwnd, msg, wParam, lParam);
+    }
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+private static extern(Windows) int CBTFunc (int nCode, uint wParam, int lParam) {
+    return pThis.CBTProc( nCode, wParam, lParam );
+}
+
+int CBTProc (int nCode, int wParam, int lParam) {
+    if (nCode is OS.HCBT_CREATEWND) {
+        TCHAR[128] buffer = 0;
+        OS.GetClassName (cast(HANDLE)wParam, buffer.ptr, buffer.length );
+        String className = TCHARzToStr(buffer.ptr);
+        if (className=="Edit" || className=="EDIT") { //$NON-NLS-1$  //$NON-NLS-2$
+            int bits = OS.GetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE);
+            OS.SetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE, bits & ~OS.ES_NOHIDESEL);
+        }
+    }
+    return OS.CallNextHookEx (cbtHook, nCode, wParam, lParam);
+}
+
+override bool checkHandle (HWND hwnd) {
+    return hwnd is handle || hwnd is OS.GetDlgItem (handle, CBID_EDIT) || hwnd is OS.GetDlgItem (handle, CBID_LIST);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+    /*
+     * Feature in Windows.  It is not possible to create
+     * a combo box that has a border using Windows style
+     * bits.  All combo boxes draw their own border and
+     * do not use the standard Windows border styles.
+     * Therefore, no matter what style bits are specified,
+     * clear the BORDER bits so that the SWT style will
+     * match the Windows widget.
+     *
+     * The Windows behavior is currently implemented on
+     * all platforms.
+     */
+    style &= ~SWT.BORDER;
+
+    /*
+     * Even though it is legal to create this widget
+     * with scroll bars, they serve no useful purpose
+     * because they do not automatically scroll the
+     * widget's client area.  The fix is to clear
+     * the SWT style.
+     */
+    style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
+    style = checkBits (style, SWT.DROP_DOWN, SWT.SIMPLE, 0, 0, 0, 0);
+    if ((style & SWT.SIMPLE) !is 0) return style & ~SWT.READ_ONLY;
+    return style;
+}
+
+/**
+ * Sets the selection in the receiver's text field to an empty
+ * selection starting just before the first character. If the
+ * text field is editable, this has the effect of placing the
+ * i-beam at the start of the text.
+ * <p>
+ * Note: To clear the selected items in the receiver's list,
+ * use <code>deselectAll()</code>.
+ * </p>
+ *
+ * @exception SWTException <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 #deselectAll
+ */
+public void clearSelection () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, -1);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if (wHint is SWT.DEFAULT) {
+        HFONT newFont, oldFont;
+        auto hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+        RECT rect;
+        int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+        if ((style & SWT.READ_ONLY) is 0) flags |= OS.DT_EDITCONTROL;
+        int length_ = OS.GetWindowTextLength (handle);
+        int cp = getCodePage ();
+        TCHAR[] buffer = new TCHAR[ length_ + 1];
+        buffer[] = 0;
+        OS.GetWindowText (handle, buffer.ptr, length_ + 1);
+        OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
+        width = Math.max (width, rect.right - rect.left);
+        if ((style & SWT.H_SCROLL) !is 0) {
+            width = Math.max (width, scrollWidth);
+        } else {
+            for (int i=0; i<count; i++) {
+                length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, i, 0);
+                if (length_ !is OS.CB_ERR) {
+                    if (length_ + 1 > buffer.length ) buffer = new TCHAR[ length_ + 1 ], buffer[] =0;
+                    int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer.ptr);
+                    if (result !is OS.CB_ERR) {
+                        OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
+                        width = Math.max (width, rect.right - rect.left);
+                    }
+                }
+            }
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    }
+    if (hHint is SWT.DEFAULT) {
+        if ((style & SWT.SIMPLE) !is 0) {
+            int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+            int itemHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+            height = count * itemHeight;
+        }
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    if ((style & SWT.READ_ONLY) !is 0) {
+        width += 8;
+    } else {
+        auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+        if (hwndText !is null) {
+            int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+            int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
+            width += marginWidth + 3;
+        }
+    }
+    COMBOBOXINFO pcbi;
+    pcbi.cbSize = COMBOBOXINFO.sizeof;
+    if (((style & SWT.SIMPLE) is 0) && !OS.IsWinCE && OS.GetComboBoxInfo (handle, &pcbi)) {
+        width += pcbi.rcItem.left + (pcbi.rcButton.right - pcbi.rcButton.left);
+        height = (pcbi.rcButton.bottom - pcbi.rcButton.top) + pcbi.rcButton.top * 2;
+    } else {
+        int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL) + border * 2;
+        int textHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
+        if ((style & SWT.DROP_DOWN) !is 0) {
+            height = textHeight + 6;
+        } else {
+            height += textHeight + 10;
+        }
+    }
+    if ((style & SWT.SIMPLE) !is 0 && (style & SWT.H_SCROLL) !is 0) {
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    }
+    return new Point (width, height);
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 2.1
+ */
+public void copy () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.WM_COPY, 0, 0);
+}
+
+override void createHandle () {
+    /*
+    * Feature in Windows.  When the selection changes in a combo box,
+    * Windows draws the selection, even when the combo box does not
+    * have focus.  Strictly speaking, this is the correct Windows
+    * behavior because the combo box sets ES_NOHIDESEL on the text
+    * control that it creates.  Despite this, it looks strange because
+    * Windows also clears the selection and selects all the text when
+    * the combo box gets focus.  The fix is use the CBT hook to clear
+    * the ES_NOHIDESEL style bit when the text control is created.
+    */
+    if (OS.IsWinCE || (style & (SWT.READ_ONLY | SWT.SIMPLE)) !is 0) {
+        super.createHandle ();
+    } else {
+        int threadId = OS.GetCurrentThreadId ();
+        //Callback cbtCallback = new Callback (this, "CBTProc", 3); //$NON-NLS-1$
+        //int cbtProc = cbtCallback.getAddress ();
+        //if (cbtProc is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+        pThis = this;
+        cbtHook = OS.SetWindowsHookEx (OS.WH_CBT, &CBTFunc, null, threadId);
+        super.createHandle ();
+        if (cbtHook !is null) OS.UnhookWindowsHookEx (cbtHook);
+        pThis = null;
+        //cbtHook = 0;
+        //cbtCallback.dispose ();
+    }
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    /* 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.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC);
+    }
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null && ListProc is null) {
+        ListProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndList, OS.GWLP_WNDPROC);
+    }
+
+    /*
+    * Bug in Windows.  If the combo box has the CBS_SIMPLE style,
+    * the list portion of the combo box is not drawn correctly the
+    * first time, causing pixel corruption.  The fix is to ensure
+    * that the combo box has been resized more than once.
+    */
+    if ((style & SWT.SIMPLE) !is 0) {
+        int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+        SetWindowPos (handle, null, 0, 0, 0x3FFF, 0x3FFF, flags);
+        SetWindowPos (handle, null, 0, 0, 0, 0, flags);
+    }
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @exception SWTException <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 2.1
+ */
+public void cut () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (handle, OS.WM_CUT, 0, 0);
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+override void deregister () {
+    super.deregister ();
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) display.removeControl (hwndText);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) display.removeControl (hwndList);
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver's
+ * list.  If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException <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 deselect (int index) {
+    checkWidget ();
+    int selection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+    if (index !is selection) return;
+    OS.SendMessage (handle, OS.CB_SETCURSEL, -1, 0);
+    sendEvent (SWT.Modify);
+    // widget could be disposed at this point
+}
+
+/**
+ * Deselects all selected items in the receiver's list.
+ * <p>
+ * Note: To clear the selection in the receiver's text field,
+ * use <code>clearSelection()</code>.
+ * </p>
+ *
+ * @exception SWTException <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 #clearSelection
+ */
+public void deselectAll () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.CB_SETCURSEL, -1, 0);
+    sendEvent (SWT.Modify);
+    // widget could be disposed at this point
+}
+
+override bool dragDetect (HWND hwnd, int x, int y, bool filter, bool [] detect, bool [] consume) {
+    if (filter && (style & SWT.READ_ONLY) is 0) {
+        auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+        if (hwndText !is null) {
+            int start, end;
+            OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end);
+            if (start !is end ) {
+                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;
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+    return super.dragDetect (hwnd, x, y, filter, detect, consume);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver's list. Throws an exception if the index is out
+ * of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 String getItem (int index) {
+    checkWidget ();
+    int length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+    if (length_ !is OS.CB_ERR) {
+        TCHAR[] buffer = new TCHAR[ length_ + 1];
+        int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer.ptr);
+        if (result !is OS.CB_ERR) return TCHARzToStr( buffer.ptr );
+    }
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (0 <= index && index < count) error (SWT.ERROR_CANNOT_GET_ITEM);
+    error (SWT.ERROR_INVALID_RANGE);
+    return "";
+}
+
+/**
+ * Returns the number of items contained in the receiver's list.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (count is OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_COUNT);
+    return count;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the receiver's list.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException <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 int getItemHeight () {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
+    if (result is OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+    return result;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>String</code>s which are
+ * the items in the receiver's list.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <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 String [] getItems () {
+    checkWidget ();
+    int count = getItemCount ();
+    String [] result = new String [count];
+    for (int i=0; i<count; i++) result [i] = getItem (i);
+    return result;
+}
+
+/**
+ * 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 SWTException <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 ();
+    if ((style & SWT.DROP_DOWN) !is 0) {
+        return OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0;
+    }
+    return true;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * 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 SWTException <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
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public int getOrientation () {
+    checkWidget();
+    return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns a <code>Point</code> whose x coordinate is the
+ * character position representing the start of the selection
+ * in the receiver's text field, and whose y coordinate is the
+ * character position representing the end of the selection.
+ * An "empty" selection is indicated by the x and y coordinates
+ * having the same value.
+ * <p>
+ * Indexing is zero based.  The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ * </p>
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException <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 Point getSelection () {
+    checkWidget ();
+    if ((style & SWT.DROP_DOWN) !is 0 && (style & SWT.READ_ONLY) !is 0) {
+        return new Point (0, OS.GetWindowTextLength (handle));
+    }
+    int start, end;
+    OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end);
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        start = mbcsToWcsPos (start);
+        end = mbcsToWcsPos (end);
+    }
+    return new Point (start, end);
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver's list, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException <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 int getSelectionIndex () {
+    checkWidget ();
+    if (noSelection) return -1;
+    return OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+}
+
+/**
+ * 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 SWTException <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 String getText () {
+    checkWidget ();
+    int length_ = OS.GetWindowTextLength (handle);
+    if (length_ is 0) return "";
+    TCHAR[] buffer = new TCHAR[ length_ + 1];
+    OS.GetWindowText (handle, buffer.ptr, length_ + 1);
+    return TCHARzToStr( buffer.ptr );
+}
+
+/**
+ * Returns the height of the receivers's text field.
+ *
+ * @return the text height
+ *
+ * @exception SWTException <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 int getTextHeight () {
+    checkWidget ();
+    COMBOBOXINFO pcbi;
+    pcbi.cbSize = COMBOBOXINFO.sizeof;
+    if (((style & SWT.SIMPLE) is 0) && !OS.IsWinCE && OS.GetComboBoxInfo (handle, &pcbi)) {
+        return (pcbi.rcButton.bottom - pcbi.rcButton.top) + pcbi.rcButton.top * 2;
+    }
+    int result = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
+    if (result is OS.CB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+    return (style & SWT.DROP_DOWN) !is 0 ? result + 6 : result + 10;
+}
+
+/**
+ * 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>Combo.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @exception SWTException <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
+ */
+public int getTextLimit () {
+    checkWidget ();
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText is null) return LIMIT;
+    return OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+}
+
+/**
+ * Gets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @return the number of items that are visible
+ *
+ * @exception SWTException <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.0
+ */
+public int getVisibleItemCount () {
+    checkWidget ();
+    return visibleCount;
+}
+
+override bool hasFocus () {
+    auto hwndFocus = OS.GetFocus ();
+    if (hwndFocus is handle) return true;
+    if (hwndFocus is null) return false;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndFocus is hwndText) return true;
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndFocus is hwndList) return true;
+    return false;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string) {
+    return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to begin the search
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string, int start) {
+    checkWidget ();
+    // SWT externsion: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+
+    /*
+    * Bug in Windows.  For some reason, CB_FINDSTRINGEXACT
+    * will not find empty strings even though it is legal
+    * to insert an empty string into a combo.  The fix is
+    * to search the combo, an item at a time.
+    */
+    if (string.length  is 0) {
+        int count = getItemCount ();
+        for (int i=start; i<count; i++) {
+            if (string.equals (getItem (i))) return i;
+        }
+        return -1;
+    }
+
+    /* Use CB_FINDSTRINGEXACT to search for the item */
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (!(0 <= start && start < count)) return -1;
+    int index = start - 1, last = 0;
+    TCHAR* buffer = StrToTCHARz( string );
+    do {
+        index = OS.SendMessage (handle, OS.CB_FINDSTRINGEXACT, last = index, buffer);
+        if (index is OS.CB_ERR || index <= last) return -1;
+    } while (string!=/*eq*/getItem (index));
+    return index;
+}
+
+int mbcsToWcsPos (int mbcsPos) {
+    if (mbcsPos <= 0) return 0;
+    if (OS.IsUnicode) return mbcsPos;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText is null) return mbcsPos;
+    int mbcsSize = OS.GetWindowTextLengthA (hwndText);
+    if (mbcsSize is 0) return 0;
+    if (mbcsPos >= mbcsSize) return mbcsSize;
+    CHAR [] buffer = new CHAR [mbcsSize + 1];
+    buffer[] = 0;
+    OS.GetWindowTextA (hwndText, buffer.ptr, mbcsSize + 1);
+    return OS.MultiByteToWideChar (getCodePage (), OS.MB_PRECOMPOSED, buffer.ptr, mbcsPos, null, 0);
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 2.1
+ */
+public void paste () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (handle, OS.WM_PASTE, 0, 0);
+}
+
+override void register () {
+    super.register ();
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) display.addControl (hwndText, this);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) display.addControl (hwndList, this);
+}
+
+/**
+ * Removes the item from the receiver's list at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int index) {
+    checkWidget ();
+    remove (index, true);
+}
+
+void remove (int index, bool notify) {
+    TCHAR[] buffer = null;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        int length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
+        if (length_ is OS.CB_ERR) {
+            int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+            if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+        buffer = new TCHAR[ length_ + 1];
+        int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer.ptr);
+        if (result is OS.CB_ERR) {
+            int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+            if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+    }
+    int length_ = OS.GetWindowTextLength (handle);
+    int code = OS.SendMessage (handle, OS.CB_DELETESTRING, index, 0);
+    if (code is OS.CB_ERR) {
+        int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+        if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+    if (notify && length_ !is OS.GetWindowTextLength (handle)) {
+        sendEvent (SWT.Modify);
+        if (isDisposed ()) return;
+    }
+    /*
+    * Bug in Windows.  When the combo box is read only
+    * with exactly one item that is currently selected
+    * and that item is removed, the combo box does not
+    * redraw to clear the text area.  The fix is to
+    * force a redraw.
+    */
+    if ((style & SWT.READ_ONLY) !is 0) {
+        int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+        if (count is 0) OS.InvalidateRect (handle, null, true);
+    }
+}
+
+/**
+ * Removes the items from the receiver's list which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int start, int end) {
+    checkWidget ();
+    if (start > end) return;
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    int textLength = OS.GetWindowTextLength (handle);
+    RECT rect;
+    HDC hDC;
+    HFONT oldFont, newFont;
+    int newWidth = 0;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        //rect = new RECT ();
+        hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    }
+    int cp = getCodePage ();
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    for (int i=start; i<=end; i++) {
+        TCHAR[] buffer = null;
+        if ((style & SWT.H_SCROLL) !is 0) {
+            int length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, start, 0);
+            if (length_ is OS.CB_ERR) break;
+            buffer = new TCHAR[ length_ + 1];
+            int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, start, buffer.ptr);
+            if (result is OS.CB_ERR) break;
+        }
+        int result = OS.SendMessage (handle, OS.CB_DELETESTRING, start, 0);
+        if (result is OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_REMOVED);
+        if ((style & SWT.H_SCROLL) !is 0) {
+            OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+            newWidth = Math.max (newWidth, rect.right - rect.left);
+        }
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        setScrollWidth (newWidth, false);
+    }
+    if (textLength !is OS.GetWindowTextLength (handle)) {
+        sendEvent (SWT.Modify);
+        if (isDisposed ()) return;
+    }
+    /*
+    * Bug in Windows.  When the combo box is read only
+    * with exactly one item that is currently selected
+    * and that item is removed, the combo box does not
+    * redraw to clear the text area.  The fix is to
+    * force a redraw.
+    */
+    if ((style & SWT.READ_ONLY) !is 0) {
+        count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+        if (count is 0) OS.InvalidateRect (handle, null, true);
+    }
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li>
+ * </ul>
+ * @exception SWTException <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 remove (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int index = indexOf (string, 0);
+    if (index is -1) error (SWT.ERROR_INVALID_ARGUMENT);
+    remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver's list and clear the
+ * contents of receiver's text field.
+ * <p>
+ * @exception SWTException <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 removeAll () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.CB_RESETCONTENT, 0, 0);
+    sendEvent (SWT.Modify);
+    if (isDisposed ()) return;
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (0);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #addVerifyListener
+ *
+ * @since 3.1
+ */
+public void removeVerifyListener (VerifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Verify, listener);
+}
+
+override bool sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+    if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+        return false;
+    }
+    if ((style & SWT.READ_ONLY) !is 0) return true;
+    if (type !is SWT.KeyDown) return true;
+    if (msg !is OS.WM_CHAR && msg !is OS.WM_KEYDOWN && msg !is OS.WM_IME_CHAR) {
+        return true;
+    }
+    if (event.character is 0) return true;
+    if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
+    char key = event.character;
+    int stateMask = event.stateMask;
+
+    /*
+    * Disable all magic keys that could modify the text
+    * and don't send events when Alt, Shift or Ctrl is
+    * pressed.
+    */
+    switch (msg) {
+        case OS.WM_CHAR:
+            if (key !is 0x08 && key !is 0x7F && key !is '\r' && key !is '\t' && key !is '\n') break;
+            // FALL THROUGH
+        case OS.WM_KEYDOWN:
+            if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) !is 0) return false;
+            break;
+        default:
+    }
+
+    /*
+    * If the left button is down, the text widget refuses the character.
+    */
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+        return true;
+    }
+
+    /* Verify the character */
+    String oldText = "";
+    int start, end;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText is null) return true;
+    OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+    switch (key) {
+        case 0x08:  /* Bs */
+            if (start  is end ) {
+                if (start  is 0) return true;
+                start  = start  - 1;
+                if (!OS.IsUnicode && OS.IsDBLocale) {
+                    int newStart, newEnd;
+                    OS.SendMessage (hwndText, OS.EM_SETSEL, start , end );
+                    OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+                    if (start  !is newStart ) start  = start  - 1;
+                }
+                start  = Math.max (start , 0);
+            }
+            break;
+        case 0x7F:  /* Del */
+            if (start  is end ) {
+                int length_ = OS.GetWindowTextLength (hwndText);
+                if (start  is length_) return true;
+                end  = end  + 1;
+                if (!OS.IsUnicode && OS.IsDBLocale) {
+                    int newStart, newEnd;
+                    OS.SendMessage (hwndText, OS.EM_SETSEL, start , end );
+                    OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
+                    if (end  !is newEnd ) end  = end  + 1;
+                }
+                end  = Math.min (end , length_);
+            }
+            break;
+        case '\r':  /* Return */
+            return true;
+        default:    /* Tab and other characters */
+            if (key !is '\t' && key < 0x20) return true;
+            oldText = [key];
+            break;
+    }
+    String newText = verifyText (oldText, start, end, event);
+    if (newText is null) return false;
+    if (newText is oldText) return true;
+    TCHAR* buffer = StrToTCHARz( newText );
+    OS.SendMessage (hwndText, OS.EM_SETSEL, start, end);
+    OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+    return false;
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list.  If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 select (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (0 <= index && index < count) {
+        int selection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+        int code = OS.SendMessage (handle, OS.CB_SETCURSEL, index, 0);
+        if (code !is OS.CB_ERR && code !is selection) {
+            sendEvent (SWT.Modify);
+            // widget could be disposed at this point
+        }
+    }
+}
+
+override void setBackgroundImage (HBITMAP hBitmap) {
+    super.setBackgroundImage (hBitmap);
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) OS.InvalidateRect (hwndText, null, true);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) OS.InvalidateRect (hwndList, null, true);
+}
+
+override void setBackgroundPixel (int pixel) {
+    super.setBackgroundPixel (pixel);
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) OS.InvalidateRect (hwndText, null, true);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) OS.InvalidateRect (hwndList, null, true);
+}
+
+override void setBounds (int x, int y, int width, int height, int flags) {
+    /*
+    * Feature in Windows.  If the combo box has the CBS_DROPDOWN
+    * or CBS_DROPDOWNLIST style, Windows uses the height that the
+    * programmer sets in SetWindowPos () to control height of the
+    * drop down list.  When the width is non-zero, Windows remembers
+    * this value and sets the height to be the height of the text
+    * field part of the combo box.  If the width is zero, Windows
+    * allows the height to have any value.  Therefore, when the
+    * programmer sets and then queries the height, the values can
+    * be different depending on the width.  The problem occurs when
+    * the programmer uses computeSize () to determine the preferred
+    * height (always the height of the text field) and then uses
+    * this value to set the height of the combo box.  The result
+    * is a combo box with a zero size drop down list.  The fix, is
+    * to always set the height to show a fixed number of combo box
+    * items and ignore the height value that the programmer supplies.
+    */
+    if ((style & SWT.DROP_DOWN) !is 0) {
+        height = getTextHeight () + (getItemHeight () * visibleCount) + 2;
+        /*
+        * Feature in Windows.  When a drop down combo box is resized,
+        * the combo box resizes the height of the text field and uses
+        * the height provided in SetWindowPos () to determine the height
+        * of the drop down list.  For some reason, the combo box redraws
+        * the whole area, not just the text field.  The fix is to set the
+        * SWP_NOSIZE bits when the height of text field and the drop down
+        * list is the same as the requested height.
+        *
+        * NOTE:  Setting the width of a combo box to zero does not update
+        * the width of the drop down control rect.  If the width of the
+        * combo box is zero, then do not set SWP_NOSIZE.
+        */
+        RECT rect;
+        OS.GetWindowRect (handle, &rect);
+        if (rect.right - rect.left !is 0) {
+            if (OS.SendMessage (handle, OS.CB_GETDROPPEDCONTROLRECT, 0, &rect) !is 0) {
+                int oldWidth = rect.right - rect.left, oldHeight = rect.bottom - rect.top;
+                if (oldWidth is width && oldHeight is height) flags |= OS.SWP_NOSIZE;
+            }
+        }
+        SetWindowPos (handle, null, x, y, width, height, flags);
+    } else {
+        super.setBounds (x, y, width, height, flags);
+    }
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    super.setFont (font);
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth ();
+}
+
+override void setForegroundPixel (int pixel) {
+    super.setForegroundPixel (pixel);
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) OS.InvalidateRect (hwndText, null, true);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) OS.InvalidateRect (hwndList, null, true);
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 setItem (int index, String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int selection = getSelectionIndex ();
+    remove (index, false);
+    if (isDisposed ()) return;
+    add (string, index);
+    if (selection !is -1) select (selection);
+}
+
+/**
+ * Sets the receiver's list to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li>
+ * </ul>
+ * @exception SWTException <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 setItems (String [] items) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    for (int i=0; i<items.length; i++) {
+        if (items [i] is null) error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    RECT rect;
+    HDC hDC;
+    HFONT oldFont, newFont;
+    int newWidth = 0;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        //rect = new RECT ();
+        hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        setScrollWidth (0);
+    }
+    OS.SendMessage (handle, OS.CB_RESETCONTENT, 0, 0);
+    int codePage = getCodePage ();
+    for (int i=0; i<items.length; i++) {
+        String string = items [i];
+        TCHAR* buffer = StrToTCHARz( string );
+        int code = OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer);
+        if (code is OS.CB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+        if (code is OS.CB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+        if ((style & SWT.H_SCROLL) !is 0) {
+            int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+            OS.DrawText (hDC, buffer, -1, &rect, flags);
+            newWidth = Math.max (newWidth, rect.right - rect.left);
+        }
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        setScrollWidth (newWidth + 3);
+    }
+    sendEvent (SWT.Modify);
+    // widget could be disposed at this point
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ * <p>
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public void setOrientation (int orientation) {
+    checkWidget();
+    static if (OS.IsWinCE) return;
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
+    int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+    if ((orientation & flags) is 0 || (orientation & flags) is flags) return;
+    style &= ~flags;
+    style |= orientation & flags;
+    int bits  = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        style |= SWT.MIRRORED;
+        bits |= OS.WS_EX_LAYOUTRTL;
+    } else {
+        style &= ~SWT.MIRRORED;
+        bits &= ~OS.WS_EX_LAYOUTRTL;
+    }
+    OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+    HWND hwndText, hwndList;
+    COMBOBOXINFO pcbi;
+    pcbi.cbSize = COMBOBOXINFO.sizeof;
+    if (OS.GetComboBoxInfo (handle, &pcbi)) {
+        hwndText = pcbi.hwndItem;
+        hwndList = pcbi.hwndList;
+    }
+    if (hwndText !is null) {
+        int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
+        int bits2 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+            bits1 |= OS.WS_EX_RIGHT | OS.WS_EX_RTLREADING;
+            bits2 |= OS.ES_RIGHT;
+        } else {
+            bits1 &= ~(OS.WS_EX_RIGHT | OS.WS_EX_RTLREADING);
+            bits2 &= ~OS.ES_RIGHT;
+        }
+        OS.SetWindowLong (hwndText, OS.GWL_EXSTYLE, bits1);
+        OS.SetWindowLong (hwndText, OS.GWL_STYLE, bits2);
+
+        /*
+        * Bug in Windows.  For some reason, the single line text field
+        * portion of the combo box does not redraw to reflect the new
+        * style bits.  The fix is to force the widget to be resized by
+        * temporarily shrinking and then growing the width and height.
+        */
+        RECT rect;
+        OS.GetWindowRect (hwndText, &rect);
+        int width = rect.right - rect.left, height = rect.bottom - rect.top;
+        OS.GetWindowRect (handle, &rect);
+        int widthCombo = rect.right - rect.left, heightCombo = rect.bottom - rect.top;
+        int uFlags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+        SetWindowPos (hwndText, null, 0, 0, width - 1, height - 1, uFlags);
+        SetWindowPos (handle, null, 0, 0, widthCombo - 1, heightCombo - 1, uFlags);
+        SetWindowPos (hwndText, null, 0, 0, width, height, uFlags);
+        SetWindowPos (handle, null, 0, 0, widthCombo, heightCombo, uFlags);
+        OS.InvalidateRect (handle, null, true);
+    }
+    if (hwndList !is null) {
+        int bits1 = OS.GetWindowLong (hwndList, OS.GWL_EXSTYLE);
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+            bits1 |= OS.WS_EX_LAYOUTRTL;
+        } else {
+            bits1 &= ~OS.WS_EX_LAYOUTRTL;
+        }
+        OS.SetWindowLong (hwndList, OS.GWL_EXSTYLE, bits1);
+    }
+}
+
+void setScrollWidth () {
+    int newWidth = 0;
+    RECT rect;
+    HFONT newFont, oldFont;
+    HDC hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    int cp = getCodePage ();
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    for (int i=0; i<count; i++) {
+        int length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, i, 0);
+        if (length_ !is OS.CB_ERR) {
+            TCHAR[] buffer = new TCHAR [ length_ + 1];
+            int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer.ptr);
+            if (result !is OS.CB_ERR) {
+                OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+                newWidth = Math.max (newWidth, rect.right - rect.left);
+            }
+        }
+    }
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    setScrollWidth (newWidth + 3);
+}
+
+void setScrollWidth (int scrollWidth) {
+    this.scrollWidth = scrollWidth;
+    if ((style & SWT.SIMPLE) !is 0) {
+        OS.SendMessage (handle, OS.CB_SETHORIZONTALEXTENT, scrollWidth, 0);
+        return;
+    }
+    bool scroll = false;
+    int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
+    if (count > 3) {
+        int maxWidth = 0;
+        if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+            RECT rect;
+            OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
+            maxWidth = (rect.right - rect.left) / 4;
+        } else {
+            auto hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
+            MONITORINFO lpmi;
+            lpmi.cbSize = MONITORINFO.sizeof;
+            OS.GetMonitorInfo (hmonitor, &lpmi);
+            maxWidth = (lpmi.rcWork.right - lpmi.rcWork.left) / 4;
+        }
+        scroll = scrollWidth > maxWidth;
+    }
+    if (scroll) {
+        OS.SendMessage (handle, OS.CB_SETDROPPEDWIDTH, 0, 0);
+        OS.SendMessage (handle, OS.CB_SETHORIZONTALEXTENT, scrollWidth, 0);
+    } else {
+        scrollWidth += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+        OS.SendMessage (handle, OS.CB_SETDROPPEDWIDTH, scrollWidth, 0);
+        OS.SendMessage (handle, OS.CB_SETHORIZONTALEXTENT, 0, 0);
+    }
+}
+
+void setScrollWidth (TCHAR[] buffer, bool grow) {
+    RECT rect;
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    setScrollWidth (rect.right - rect.left, grow);
+}
+
+void setScrollWidth (int newWidth, bool grow) {
+    if (grow) {
+        if (newWidth <= scrollWidth) return;
+        setScrollWidth (newWidth + 3);
+    } else {
+        if (newWidth < scrollWidth) return;
+        setScrollWidth ();
+    }
+}
+
+/**
+ * Sets the selection in the receiver's text field to the
+ * range specified by the argument whose x coordinate is the
+ * start of the selection and whose y coordinate is the end
+ * of the selection.
+ *
+ * @param selection a point representing the new selection start and end
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSelection (Point selection) {
+    checkWidget ();
+    if (selection is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int start = selection.x, end = selection.y;
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        start = wcsToMbcsPos (start);
+        end = wcsToMbcsPos (end);
+    }
+    int /*long*/ bits = OS.MAKELPARAM (start, end);
+    OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits);
+}
+
+/**
+ * Sets the contents of the receiver's text field to the
+ * given string.
+ * <p>
+ * Note: The text field in a <code>Combo</code> is typically
+ * only capable of displaying a single line of text. Thus,
+ * setting the text to a string containing line breaks or
+ * other special characters will probably cause it to
+ * display incorrectly.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT externsion: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((style & SWT.READ_ONLY) !is 0) {
+        int index = indexOf (string);
+        if (index !is -1) select (index);
+        return;
+    }
+    int limit = LIMIT;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) {
+        limit = OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+    }
+    if (string.length  > limit) string = string.substring (0, limit);
+    TCHAR* buffer = StrToTCHARz( string );
+    if (OS.SetWindowText (handle, buffer)) {
+        sendEvent (SWT.Modify);
+        // widget could be disposed at this point
+    }
+}
+
+/**
+ * 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(Combo.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Combo.LIMIT</code> sets the
+ * receiver's limit to <code>Combo.LIMIT</code>.
+ * </p>
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
+ * </ul>
+ * @exception SWTException <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
+ */
+public void setTextLimit (int limit) {
+    checkWidget ();
+    if (limit is 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+    OS.SendMessage (handle, OS.CB_LIMITTEXT, limit, 0);
+}
+
+override void setToolTipText (Shell shell, String string) {
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndText !is null) shell.setToolTipText (hwndText, string);
+    if (hwndList !is null) shell.setToolTipText (hwndList, string);
+    shell.setToolTipText (handle, string);
+}
+
+/**
+ * Sets the number of items that are visible in the drop
+ * down portion of the receiver's list.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param count the new number of items to be visible
+ *
+ * @exception SWTException <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.0
+ */
+public void setVisibleItemCount (int count) {
+    checkWidget ();
+    if (count < 0) return;
+    visibleCount = count;
+    if ((style & SWT.DROP_DOWN) !is 0) {
+        forceResize ();
+        RECT rect;
+        OS.GetWindowRect (handle, &rect);
+        int flags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+        setBounds (0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
+    }
+}
+
+override void subclass () {
+    super.subclass ();
+    auto newProc = display.windowProc;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null) {
+        OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc);
+    }
+    auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+    if (hwndList !is null) {
+        OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, newProc);
+    }
+}
+
+override bool translateTraversal (MSG* msg) {
+    /*
+    * When the combo box is dropped down, allow return
+    * to select an item in the list and escape to close
+    * the combo box.
+    */
+    switch ((msg.wParam)) {
+        case OS.VK_RETURN:
+        case OS.VK_ESCAPE:
+            if ((style & SWT.DROP_DOWN) !is 0) {
+                if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0) {
+                    return false;
+                }
+            }
+        default:
+    }
+    return super.translateTraversal (msg);
+}
+
+override bool traverseEscape () {
+    if ((style & SWT.DROP_DOWN) !is 0) {
+        if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0) {
+            OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0);
+            return true;
+        }
+    }
+    return super.traverseEscape ();
+}
+
+override bool traverseReturn () {
+    if ((style & SWT.DROP_DOWN) !is 0) {
+        if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0) {
+            OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, 0, 0);
+            return true;
+        }
+    }
+    return super.traverseReturn ();
+}
+
+override void unsubclass () {
+    super.unsubclass ();
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText !is null && EditProc !is null) {
+        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.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, cast(LONG_PTR)ListProc);
+    }
+}
+
+String verifyText (String string, int start, int end, Event keyEvent) {
+    Event event = new Event ();
+    event.text = string;
+    event.start = start;
+    event.end = end;
+    if (keyEvent !is null) {
+        event.character = keyEvent.character;
+        event.keyCode = keyEvent.keyCode;
+        event.stateMask = keyEvent.stateMask;
+    }
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        event.start = mbcsToWcsPos (start);
+        event.end = mbcsToWcsPos (end);
+    }
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the verify
+    * event.  If this happens, answer null to cancel
+    * the operation.
+    */
+    sendEvent (SWT.Verify, event);
+    if (!event.doit || isDisposed ()) return null;
+    return event.text;
+}
+
+int wcsToMbcsPos (int wcsPos) {
+    if (wcsPos <= 0) return 0;
+    if (OS.IsUnicode) return wcsPos;
+    auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+    if (hwndText is null) return wcsPos;
+    int mbcsSize = OS.GetWindowTextLengthA (hwndText);
+    if (mbcsSize is 0) return 0;
+    CHAR [] buffer = new CHAR [mbcsSize + 1];
+    OS.GetWindowTextA (hwndText, buffer.ptr, mbcsSize + 1);
+    int mbcsPos = 0, wcsCount = 0;
+    while (mbcsPos < mbcsSize) {
+        if (wcsPos is wcsCount) break;
+        if (OS.IsDBCSLeadByte (buffer [mbcsPos++])) mbcsPos++;
+        wcsCount++;
+    }
+    return mbcsPos;
+}
+
+override int widgetExtStyle () {
+    return super.widgetExtStyle () & ~OS.WS_EX_NOINHERITLAYOUT;
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.CBS_AUTOHSCROLL | OS.CBS_NOINTEGRALHEIGHT | OS.WS_HSCROLL |OS.WS_VSCROLL;
+    if ((style & SWT.SIMPLE) !is 0) return bits | OS.CBS_SIMPLE;
+    if ((style & SWT.READ_ONLY) !is 0) return bits | OS.CBS_DROPDOWNLIST;
+    return bits | OS.CBS_DROPDOWN;
+}
+
+override String windowClass () {
+    return TCHARzToStr( ComboClass );
+}
+
+override int windowProc () {
+    return cast(int) ComboProc;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwnd !is handle) {
+        auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+        auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+        if ((hwndText !is null && hwnd is hwndText) || (hwndList !is null && hwnd is hwndList)) {
+            LRESULT result = null;
+            switch (msg) {
+                /* Keyboard messages */
+                case OS.WM_CHAR:        result = wmChar (hwnd, wParam, lParam); break;
+                case OS.WM_IME_CHAR:    result = wmIMEChar (hwnd, wParam, lParam); break;
+                case OS.WM_KEYDOWN:     result = wmKeyDown (hwnd, wParam, lParam); break;
+                case OS.WM_KEYUP:       result = wmKeyUp (hwnd, wParam, lParam); break;
+                case OS.WM_SYSCHAR:     result = wmSysChar (hwnd, wParam, lParam); break;
+                case OS.WM_SYSKEYDOWN:  result = wmSysKeyDown (hwnd, wParam, lParam); break;
+                case OS.WM_SYSKEYUP:    result = wmSysKeyUp (hwnd, wParam, lParam); break;
+
+                /* Mouse Messages */
+                case OS.WM_CAPTURECHANGED:  result = wmCaptureChanged (hwnd, wParam, lParam); break;
+                case OS.WM_LBUTTONDBLCLK:   result = wmLButtonDblClk (hwnd, wParam, lParam); break;
+                case OS.WM_LBUTTONDOWN:     result = wmLButtonDown (hwnd, wParam, lParam); break;
+                case OS.WM_LBUTTONUP:       result = wmLButtonUp (hwnd, wParam, lParam); break;
+                case OS.WM_MBUTTONDBLCLK:   result = wmMButtonDblClk (hwnd, wParam, lParam); break;
+                case OS.WM_MBUTTONDOWN:     result = wmMButtonDown (hwnd, wParam, lParam); break;
+                case OS.WM_MBUTTONUP:       result = wmMButtonUp (hwnd, wParam, lParam); break;
+                case OS.WM_MOUSEHOVER:      result = wmMouseHover (hwnd, wParam, lParam); break;
+                case OS.WM_MOUSELEAVE:      result = wmMouseLeave (hwnd, wParam, lParam); break;
+                case OS.WM_MOUSEMOVE:       result = wmMouseMove (hwnd, wParam, lParam); break;
+//              case OS.WM_MOUSEWHEEL:      result = wmMouseWheel (hwnd, wParam, lParam); break;
+                case OS.WM_RBUTTONDBLCLK:   result = wmRButtonDblClk (hwnd, wParam, lParam); break;
+                case OS.WM_RBUTTONDOWN:     result = wmRButtonDown (hwnd, wParam, lParam); break;
+                case OS.WM_RBUTTONUP:       result = wmRButtonUp (hwnd, wParam, lParam); break;
+                case OS.WM_XBUTTONDBLCLK:   result = wmXButtonDblClk (hwnd, wParam, lParam); break;
+                case OS.WM_XBUTTONDOWN:     result = wmXButtonDown (hwnd, wParam, lParam); break;
+                case OS.WM_XBUTTONUP:       result = wmXButtonUp (hwnd, wParam, lParam); break;
+
+                /* Paint messages */
+                case OS.WM_PAINT:           result = wmPaint (hwnd, wParam, lParam); break;
+
+                /* Menu messages */
+                case OS.WM_CONTEXTMENU:     result = wmContextMenu (hwnd, wParam, lParam); break;
+
+                /* Clipboard messages */
+                case OS.WM_CLEAR:
+                case OS.WM_CUT:
+                case OS.WM_PASTE:
+                case OS.WM_UNDO:
+                case OS.EM_UNDO:
+                case OS.WM_SETTEXT:
+                    if (hwnd is hwndText) {
+                        result = wmClipboard (hwnd, msg, wParam, lParam);
+                    }
+                    break;
+                default:
+            }
+            if (result !is null) return result.value;
+            return callWindowProc (hwnd, msg, wParam, lParam);
+        }
+    }
+    if (msg is OS.CB_SETCURSEL) {
+        if ((style & SWT.READ_ONLY) !is 0) {
+            if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+                String oldText = getText (), newText = null;
+                if (wParam is -1) {
+                    newText = "";
+                } else {
+                    if (0 <= wParam && wParam < getItemCount ()) {
+                        newText = getItem (wParam);
+                    }
+                }
+                if (newText !is null && newText!=/*eq*/oldText) {
+                    int length_ = OS.GetWindowTextLength (handle);
+                    oldText = newText;
+                    newText = verifyText (newText, 0, length_, null);
+                    if (newText is null) return 0;
+                    if (newText!=/*eq*/oldText) {
+                        int index = indexOf (newText);
+                        if (index !is -1 && index !is wParam) {
+                            return callWindowProc (handle, OS.CB_SETCURSEL, index, lParam);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_CTLCOLOR (int wParam, int lParam) {
+    return wmColorChild (wParam, lParam);
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+    return new LRESULT (code | OS.DLGC_WANTARROWS);
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When a combo box that is read only
+    * is disposed in CBN_KILLFOCUS, Windows segment faults.
+    * The fix is to send focus from WM_KILLFOCUS instead
+    * of CBN_KILLFOCUS.
+    *
+    * NOTE: In version 6 of COMCTL32.DLL, the bug is fixed.
+    */
+    if ((style & SWT.READ_ONLY) !is 0) {
+        return super.WM_KILLFOCUS (wParam, lParam);
+    }
+
+    /*
+    * Return NULL - Focus notification is
+    * done in WM_COMMAND by CBN_KILLFOCUS.
+    */
+    return null;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When an editable combo box is dropped
+    * down and the text in the entry field partially matches an
+    * item in the list, Windows selects the item but doesn't send
+    * WM_COMMAND with CBN_SELCHANGE.  The fix is to detect that
+    * the selection has changed and issue the notification.
+    */
+    int oldSelection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    if ((style & SWT.READ_ONLY) is 0) {
+        int newSelection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+        if (oldSelection !is newSelection) {
+            sendEvent (SWT.Modify);
+            if (isDisposed ()) return LRESULT.ZERO;
+            sendEvent (SWT.Selection);
+            if (isDisposed ()) return LRESULT.ZERO;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    /*
+    * Return NULL - Focus notification is
+    * done by WM_COMMAND with CBN_SETFOCUS.
+    */
+    return null;
+}
+
+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 SWT.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
+    * the size has changed.
+    */
+    if ((style & SWT.SIMPLE) !is 0) {
+        LRESULT result = super.WM_SIZE (wParam, lParam);
+        if (OS.IsWindowVisible (handle)) {
+            static if (OS.IsWinCE) {
+                auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
+                if (hwndText !is null) OS.InvalidateRect (hwndText, null, true);
+                auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
+                if (hwndList !is null) OS.InvalidateRect (hwndList, null, true);
+            } else {
+                int uFlags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                OS.RedrawWindow (handle, null, null, uFlags);
+            }
+        }
+        return result;
+    }
+
+    /*
+    * Feature in Windows.  When an editable drop down combo box
+    * contains text that does not correspond to an item in the
+    * list, when the widget is resized, it selects the closest
+    * match from the list.  The fix is to remember the original
+    * text and reset it after the widget is resized.
+    */
+    LRESULT result = null;
+    if ((style & SWT.READ_ONLY) !is 0) {
+        result = super.WM_SIZE (wParam, lParam);
+    } else {
+        int index = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+        bool redraw = false;
+        TCHAR[] buffer = null;
+        int start, end;
+        if (index is OS.CB_ERR) {
+            int length_ = OS.GetWindowTextLength (handle);
+            if (length_ !is 0) {
+                buffer = new TCHAR[ length_ + 1];
+                OS.GetWindowText (handle, buffer.ptr, length_ + 1);
+                OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end);
+                redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+                if (redraw) setRedraw (false);
+            }
+        }
+        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 (buffer !is null) {
+            OS.SetWindowText (handle, buffer.ptr);
+            int /*long*/ bits = OS.MAKELPARAM (start, end);
+            OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits);
+            if (redraw) setRedraw (true);
+        }
+    }
+    /*
+    * Feature in Windows.  When CB_SETDROPPEDWIDTH is called with
+    * a width that is smaller than the current size of the combo
+    * box, it is ignored.  This the fix is to set the width after
+    * the combo box has been resized.
+    */
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (scrollWidth);
+    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);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  For some reason, when the
+    * widget is a single line text widget, when the
+    * user presses tab, return or escape, Windows beeps.
+    * The fix is to look for these keys and not call
+    * the window proc.
+    *
+    * NOTE: This only happens when the drop down list
+    * is not visible.
+    */
+    switch (wParam) {
+        case SWT.TAB: return LRESULT.ZERO;
+        case SWT.CR:
+            if (!ignoreDefaultSelection) postEvent (SWT.DefaultSelection);
+            ignoreDefaultSelection = false;
+            // FALL THROUGH
+        case SWT.ESC:
+            if ((style & SWT.DROP_DOWN) !is 0) {
+                if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) is 0) {
+                    return LRESULT.ZERO;
+                }
+            }
+        default:
+    }
+    return result;
+}
+
+LRESULT wmClipboard (HWND hwndText, int msg, int wParam, int lParam) {
+    if ((style & SWT.READ_ONLY) !is 0) return null;
+    if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+    bool call = false;
+    int start, end;
+    String newText = null;
+    switch (msg) {
+        case OS.WM_CLEAR:
+        case OS.WM_CUT:
+            OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+            if (start  !is end ) {
+                newText = "";
+                call = true;
+            }
+            break;
+        case OS.WM_PASTE:
+            OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+            newText = getClipboardText ();
+            break;
+        case OS.EM_UNDO:
+        case OS.WM_UNDO:
+            if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) !is 0) {
+                ignoreModify = true;
+                OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                int length_ = OS.GetWindowTextLength (hwndText);
+                int newStart, newEnd;
+                OS.SendMessage (hwndText, OS.EM_GETSEL, &newStart, &newEnd);
+                if (length_ !is 0 && newStart  !is newEnd ) {
+                    TCHAR[] buffer = new TCHAR [ length_ + 1];
+                    OS.GetWindowText (hwndText, buffer.ptr, length_ + 1);
+                    newText = TCHARsToStr( buffer[newStart .. newEnd ] );
+                } else {
+                    newText = "";
+                }
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                ignoreModify = false;
+            }
+            break;
+        case OS.WM_SETTEXT:
+            end = OS.GetWindowTextLength (hwndText);
+            //int length_ = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam);
+            //TCHAR buffer = new TCHAR (getCodePage (), length_);
+            //int byteCount = buffer.length  * TCHAR.sizeof;
+            //OS.MoveMemory (buffer, lParam, byteCount);
+            //newText = buffer.toString (0, length_);
+            newText = TCHARzToStr( cast(TCHAR*)lParam );
+            break;
+        default:
+    }
+    if (newText !is null) {
+        String oldText = newText;
+        newText = verifyText (newText, start, end, null);
+        if (newText is null) return LRESULT.ZERO;
+        if (newText!=/*eq*/oldText) {
+            if (call) {
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+            }
+            if (msg is OS.WM_SETTEXT) {
+                TCHAR[] buffer = StrToTCHARs( getCodePage(), newText, true );
+                auto hHeap = OS.GetProcessHeap ();
+                int byteCount = buffer.length * TCHAR.sizeof;
+                auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                OS.MoveMemory (pszText, buffer.ptr, byteCount);
+                int code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, cast(int) pszText);
+                OS.HeapFree (hHeap, 0, pszText);
+                return new LRESULT (code);
+            } else {
+                TCHAR* buffer = StrToTCHARz( newText );
+                OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+                return LRESULT.ZERO;
+            }
+        }
+    }
+    return null;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    int code = OS.HIWORD (wParam);
+    switch (code) {
+        case OS.CBN_EDITCHANGE:
+            if (ignoreModify) break;
+            /*
+            * Feature in Windows.  If the combo box list selection is
+            * queried using CB_GETCURSEL before the WM_COMMAND (with
+            * CBN_EDITCHANGE) returns, CB_GETCURSEL returns the previous
+            * selection in the list.  It seems that the combo box sends
+            * the WM_COMMAND before it makes the selection in the list box
+            * match the entry field.  The fix is remember that no selection
+            * in the list should exist in this case.
+            */
+            noSelection = true;
+            sendEvent (SWT.Modify);
+            if (isDisposed ()) return LRESULT.ZERO;
+            noSelection = false;
+            break;
+        case OS.CBN_SELCHANGE:
+            /*
+            * Feature in Windows.  If the text in an editable combo box
+            * is queried using GetWindowText () before the WM_COMMAND
+            * (with CBN_SELCHANGE) returns, GetWindowText () returns is
+            * the previous text in the combo box.  It seems that the combo
+            * box sends the WM_COMMAND before it updates the text field to
+            * match the list selection.  The fix is to force the text field
+            * to match the list selection by re-selecting the list item.
+            */
+            int index = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+            if (index !is OS.CB_ERR) {
+                OS.SendMessage (handle, OS.CB_SETCURSEL, index, 0);
+            }
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the modify
+            * event.  If this happens, end the processing of the
+            * Windows message by returning zero as the result of
+            * the window proc.
+            */
+            sendEvent (SWT.Modify);
+            if (isDisposed ()) return LRESULT.ZERO;
+            postEvent (SWT.Selection);
+            break;
+        case OS.CBN_SETFOCUS:
+            sendFocusEvent (SWT.FocusIn);
+            if (isDisposed ()) return LRESULT.ZERO;
+            break;
+        case OS.CBN_KILLFOCUS:
+            /*
+            * Bug in Windows.  When a combo box that is read only
+            * is disposed in CBN_KILLFOCUS, Windows segment faults.
+            * The fix is to send focus from WM_KILLFOCUS instead
+            * of CBN_KILLFOCUS.
+            *
+            * NOTE: In version 6 of COMCTL32.DLL, the bug is fixed.
+            */
+            if ((style & SWT.READ_ONLY) !is 0) break;
+            sendFocusEvent (SWT.FocusOut);
+            if (isDisposed ()) return LRESULT.ZERO;
+            break;
+        default:
+    }
+    return super.wmCommandChild (wParam, lParam);
+}
+
+override LRESULT wmIMEChar (HWND hwnd, int wParam, int lParam) {
+
+    /* Process a DBCS character */
+    Display display = this.display;
+    display.lastKey = 0;
+    display.lastAscii = wParam;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
+        return LRESULT.ZERO;
+    }
+
+    /*
+    * Feature in Windows.  The Windows text widget uses
+    * two 2 WM_CHAR's to process a DBCS key instead of
+    * using WM_IME_CHAR.  The fix is to allow the text
+    * widget to get the WM_CHAR's but ignore sending
+    * them to the application.
+    */
+    ignoreCharacter = true;
+    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)) {
+        OS.TranslateMessage (&msg);
+        OS.DispatchMessage (&msg);
+    }
+    ignoreCharacter = false;
+
+    sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
+    // widget could be disposed at this point
+    display.lastKey = display.lastAscii = 0;
+    return new LRESULT (result);
+}
+
+override LRESULT wmKeyDown (HWND hwnd, int wParam, int lParam) {
+    if (ignoreCharacter) return null;
+    LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    ignoreDefaultSelection = false;
+    if (wParam is OS.VK_RETURN) {
+        if ((style & SWT.DROP_DOWN) !is 0) {
+            if (OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0) {
+                ignoreDefaultSelection = true;
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT wmSysKeyDown (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When an editable combo box is dropped
+    * down using Alt+Down and the text in the entry field partially
+    * matches an item in the list, Windows selects the item but doesn't
+    * send WM_COMMAND with CBN_SELCHANGE.  The fix is to detect that
+    * the selection has changed and issue the notification.
+    */
+    int oldSelection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
+    LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    if ((style & SWT.READ_ONLY) is 0) {
+        if (wParam is OS.VK_DOWN) {
+            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 (SWT.Modify);
+                if (isDisposed ()) return LRESULT.ZERO;
+                sendEvent (SWT.Selection);
+                if (isDisposed ()) return LRESULT.ZERO;
+            }
+            return new LRESULT (code);
+        }
+    }
+    return result;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Composite.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1786 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.ToolTip;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+import java.lang.System;
+import java.lang.all;
+
+/**
+ * Instances of this class are controls which are capable
+ * of containing other controls.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
+ * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
+ * They can be used with <code>Composite</code> if you are drawing your own, but their
+ * behavior is undefined if they are used with subclasses of <code>Composite</code> other
+ * than <code>Canvas</code>.
+ * </p><p>
+ * Note: The <code>CENTER</code> style, although undefined for composites, has the
+ * same value as <code>EMBEDDED</code> (which is used to embed widgets from other
+ * widget toolkits into SWT).  On some operating systems (GTK, Motif), this may cause
+ * the children of this composite to be obscured.  The <code>EMBEDDED</code> style
+ * is for use by other widget toolkits and should normally never be used.
+ * </p><p>
+ * This class may be subclassed by custom control implementors
+ * who are building controls that are constructed from aggregates
+ * of other controls.
+ * </p>
+ *
+ * @see Canvas
+ * @see <a href="http://www.eclipse.org/swt/snippets/#composite">Composite snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Composite : Scrollable {
+
+    alias Scrollable.setBounds setBounds;
+    alias Scrollable.computeSize computeSize;
+    alias Scrollable.translateMnemonic translateMnemonic;
+
+    Layout layout_;
+    WINDOWPOS* [] lpwp;
+    Control [] tabList;
+    int layoutCount, backgroundMode;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_FOCUS
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_RADIO_GROUP
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, style);
+}
+
+Control [] _getChildren () {
+    int count = 0;
+    auto hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    if (hwndChild is null) return new Control [0];
+    while (hwndChild !is null) {
+        count++;
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    Control [] children = new Control [count];
+    int index = 0;
+    hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is null) {
+        Control control = display.getControl (hwndChild);
+        if (control !is null && control !is this) {
+            children [index++] = control;
+        }
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    if (count is index) return children;
+    Control [] newChildren = new Control [index];
+    System.arraycopy (children, 0, newChildren, 0, index);
+    return newChildren;
+}
+
+Control [] _getTabList () {
+    if (tabList is null) return tabList;
+    int count = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (!tabList [i].isDisposed ()) count++;
+    }
+    if (count is tabList.length) return tabList;
+    Control [] newList = new Control [count];
+    int index = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (!tabList [i].isDisposed ()) {
+            newList [index++] = tabList [i];
+        }
+    }
+    tabList = newList;
+    return tabList;
+}
+
+/**
+ * Clears any data that has been cached by a Layout for all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver.  If an ancestor does not have a layout, it is skipped.
+ *
+ * @param changed an array of controls that changed state and require a recalculation of size
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void changed (Control[] changed) {
+    checkWidget ();
+    if (changed is null) error (SWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<changed.length; i++) {
+        Control control = changed [i];
+        if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        bool ancestor = false;
+        Composite composite = control.parent;
+        while (composite !is null) {
+            ancestor = composite is this;
+            if (ancestor) break;
+            composite = composite.parent;
+        }
+        if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
+    }
+    for (int i=0; i<changed.length; i++) {
+        Control child = changed [i];
+        Composite composite = child.parent;
+        while (child !is this) {
+            if (composite.layout_ is null || !composite.layout_.flushCache (child)) {
+                composite.state |= LAYOUT_CHANGED;
+            }
+            child = composite;
+            composite = child.parent;
+        }
+    }
+}
+
+override void checkBuffered () {
+    if (OS.IsWinCE || (state & CANVAS) is 0) {
+        super.checkBuffered ();
+    }
+}
+
+override void checkComposited () {
+    if ((state & CANVAS) !is 0) {
+        if ((style & SWT.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 */
+}
+
+override Control [] computeTabList () {
+    Control result [] = super.computeTabList ();
+    if (result.length is 0) return result;
+    Control [] list = tabList !is null ? _getTabList () : _getChildren ();
+    for (int i=0; i<list.length; i++) {
+        Control child = list [i];
+        Control [] childList = child.computeTabList ();
+        if (childList.length !is 0) {
+            Control [] newResult = new Control [result.length + childList.length];
+            System.arraycopy (result, 0, newResult, 0, result.length);
+            System.arraycopy (childList, 0, newResult, result.length, childList.length);
+            result = newResult;
+        }
+    }
+    return result;
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    Point size;
+    if (layout_ !is null) {
+        if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+            changed |= (state & LAYOUT_CHANGED) !is 0;
+            state &= ~LAYOUT_CHANGED;
+            size = layout_.computeSize (this, wHint, hHint, changed);
+        } else {
+            size = new Point (wHint, hHint);
+        }
+    } else {
+        size = minimumSize (wHint, hHint, changed);
+    }
+    if (size.x is 0) size.x = DEFAULT_WIDTH;
+    if (size.y is 0) size.y = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) size.x = wHint;
+    if (hHint !is SWT.DEFAULT) size.y = hHint;
+    Rectangle trim = computeTrim (0, 0, size.x, size.y);
+    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 SWTException <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 copyArea (GC gc, int x, int y, int width, int height) {
+    checkWidget ();
+    if (gc is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (SWT.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 & (SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+        state |= THEME_BACKGROUND;
+    }
+    if ((style & SWT.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 () {
+    return layoutCount > 0 ? this : parent.findDeferredControl ();
+}
+
+override Menu [] findMenus (Control control) {
+    if (control is this) return new Menu [0];
+    Menu result [] = super.findMenus (control);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        Menu [] menuList = child.findMenus (control);
+        if (menuList.length !is 0) {
+            Menu [] newResult = new Menu [result.length + menuList.length];
+            System.arraycopy (result, 0, newResult, 0, result.length);
+            System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
+            result = newResult;
+        }
+    }
+    return result;
+}
+
+override void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+    super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    }
+}
+
+void fixTabList (Control control) {
+    if (tabList is null) return;
+    int count = 0;
+    for (int i=0; i<tabList.length; i++) {
+        if (tabList [i] is control) count++;
+    }
+    if (count is 0) return;
+    Control [] newList = null;
+    int length = tabList.length - count;
+    if (length !is 0) {
+        newList = new Control [length];
+        int index = 0;
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] !is control) {
+                newList [index++] = tabList [i];
+            }
+        }
+    }
+    tabList = newList;
+}
+
+/**
+ * Returns the receiver's background drawing mode. This
+ * will be one of the following constants defined in class
+ * <code>SWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERTIT_FORCE</code>.
+ *
+ * @return the background mode
+ *
+ * @exception SWTException <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 SWT
+ *
+ * @since 3.2
+ */
+public int getBackgroundMode () {
+    checkWidget ();
+    return backgroundMode;
+}
+
+/**
+ * Returns a (possibly empty) array containing the receiver's children.
+ * Children are returned in the order that they are drawn.  The topmost
+ * control appears at the beginning of the array.  Subsequent controls
+ * draw beneath this control and appear later in the array.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of children, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return an array of children
+ *
+ * @see Control#moveAbove
+ * @see Control#moveBelow
+ *
+ * @exception SWTException <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 Control [] getChildren () {
+    checkWidget ();
+    return _getChildren ();
+}
+
+int getChildrenCount () {
+    /*
+    * NOTE: The current implementation will count
+    * non-registered children.
+    */
+    int count = 0;
+    auto hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is null) {
+        count++;
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    return count;
+}
+
+/**
+ * Returns layout which is associated with the receiver, or
+ * null if one has not been set.
+ *
+ * @return the receiver's layout or null
+ *
+ * @exception SWTException <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 Layout getLayout () {
+    checkWidget ();
+    return layout_;
+}
+
+/**
+ * Gets the (possibly empty) tabbing order for the control.
+ *
+ * @return tabList the ordered list of controls representing the tab order
+ *
+ * @exception SWTException <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 #setTabList
+ */
+public Control [] getTabList () {
+    checkWidget ();
+    Control [] tabList = _getTabList ();
+    if (tabList is null) {
+        int count = 0;
+        Control [] list =_getChildren ();
+        for (int i=0; i<list.length; i++) {
+            if (list [i].isTabGroup ()) count++;
+        }
+        tabList = new Control [count];
+        int index = 0;
+        for (int i=0; i<list.length; i++) {
+            if (list [i].isTabGroup ()) {
+                tabList [index++] = list [i];
+            }
+        }
+    }
+    return tabList;
+}
+
+bool hooksKeys () {
+    return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
+}
+
+/**
+ * Returns <code>true</code> if the receiver has deferred
+ * the performing of layout, and <code>false</code> otherwise.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception SWTException <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 #setLayoutDeferred(bool)
+ * @see #isLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public bool getLayoutDeferred () {
+    checkWidget ();
+    return layoutCount > 0 ;
+}
+
+/**
+ * Returns <code>true</code> if the receiver or any ancestor
+ * up to and including the receiver's nearest ancestor shell
+ * has deferred the performing of layouts.  Otherwise, <code>false</code>
+ * is returned.
+ *
+ * @return the receiver's deferred layout state
+ *
+ * @exception SWTException <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 #setLayoutDeferred(bool)
+ * @see #getLayoutDeferred()
+ *
+ * @since 3.1
+ */
+public bool isLayoutDeferred () {
+    checkWidget ();
+    return findDeferredControl () !is null;
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * This is equivalent to calling <code>layout(true)</code>.
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @exception SWTException <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 layout () {
+    checkWidget ();
+    layout (true);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the argument is <code>true</code> the layout must not rely
+ * on any information it has cached about the immediate children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the receiver does not have a layout, do nothing.
+ * <p>
+ * If a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child.  The layout
+ * will cascade down through all child widgets in the receiver's widget
+ * tree until a child is encountered that does not resize.  Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 layout (bool changed) {
+    checkWidget ();
+    if (layout_ is null) return;
+    layout (changed, false);
+}
+
+/**
+ * If the receiver has a layout, asks the layout to <em>lay out</em>
+ * (that is, set the size and location of) the receiver's children.
+ * If the changed argument is <code>true</code> the layout must not rely
+ * on any information it has cached about its children. If it
+ * is <code>false</code> the layout may (potentially) optimize the
+ * work it is doing by assuming that none of the receiver's
+ * children has changed state since the last layout.
+ * If the all argument is <code>true</code> the layout will cascade down
+ * through all child widgets in the receiver's widget tree, regardless of
+ * whether the child has changed size.  The changed argument is applied to
+ * all layouts.  If the all argument is <code>false</code>, the layout will
+ * <em>not</em> cascade down through all child widgets in the receiver's widget
+ * tree.  However, if a child is resized as a result of a call to layout, the
+ * resize event will invoke the layout of the child.  Note that
+ * a layout due to a resize will not flush any cached information
+ * (same as <code>layout(false)</code>).
+ * </p>
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
+ * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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.1
+ */
+public void layout (bool changed, bool all) {
+    checkWidget ();
+    if (layout_ is null && !all) return;
+    markLayout (changed, all);
+    updateLayout (true, all);
+}
+
+/**
+ * Forces a lay out (that is, sets the size and location) of all widgets that
+ * are in the parent hierarchy of the changed control up to and including the
+ * receiver.  The layouts in the hierarchy must not rely on any information
+ * cached about the changed control or any of its ancestors.  The layout may
+ * (potentially) optimize the work it is doing by assuming that none of the
+ * peers of the changed control have changed state since the last layout.
+ * If an ancestor does not have a layout, skip it.
+ * <p>
+ * Note: Layout is different from painting. If a child is
+ * moved or resized such that an area in the parent is
+ * exposed, then the parent will paint. If no child is
+ * affected, the parent will not paint.
+ * </p>
+ *
+ * @param changed a control that has had a state change which requires a recalculation of its size
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void layout (Control [] changed) {
+    checkWidget ();
+    if (changed is null) error (SWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<changed.length; i++) {
+        Control control = changed [i];
+        if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        bool ancestor = false;
+        Composite composite = control.parent;
+        while (composite !is null) {
+            ancestor = composite is this;
+            if (ancestor) break;
+            composite = composite.parent;
+        }
+        if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
+    }
+    int updateCount = 0;
+    Composite [] update = new Composite [16];
+    for (int i=0; i<changed.length; i++) {
+        Control child = changed [i];
+        Composite composite = child.parent;
+        while (child !is this) {
+            if (composite.layout_ !is null) {
+                composite.state |= LAYOUT_NEEDED;
+                if (!composite.layout_.flushCache (child)) {
+                    composite.state |= LAYOUT_CHANGED;
+                }
+            }
+            if (updateCount is update.length) {
+                Composite [] newUpdate = new Composite [update.length + 16];
+                System.arraycopy (update, 0, newUpdate, 0, update.length);
+                update = newUpdate;
+            }
+            child = update [updateCount++] = composite;
+            composite = child.parent;
+        }
+    }
+    for (int i=updateCount-1; i>=0; i--) {
+        update [i].updateLayout (true, false);
+    }
+}
+
+override void markLayout (bool changed, bool all) {
+    if (layout_ !is null) {
+        state |= LAYOUT_NEEDED;
+        if (changed) state |= LAYOUT_CHANGED;
+    }
+    if (all) {
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            children [i].markLayout (changed, all);
+        }
+    }
+}
+
+Point minimumSize (int wHint, int hHint, bool changed) {
+    Control [] children = _getChildren ();
+    int width = 0, height = 0;
+    for (int i=0; i<children.length; i++) {
+        Rectangle rect = children [i].getBounds ();
+        width = Math.max (width, rect.x + rect.width);
+        height = Math.max (height, rect.y + rect.height);
+    }
+    return new Point (width, height);
+}
+
+override bool redrawChildren () {
+    if (!super.redrawChildren ()) return false;
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        children [i].redrawChildren ();
+    }
+    return true;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if ((state & CANVAS) !is 0) {
+        if ((style & SWT.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++) {
+        Control child = children [i];
+        if (child !is null && !child.isDisposed ()) {
+            child.release (false);
+        }
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if ((state & CANVAS) !is 0 && (style & SWT.EMBEDDED) !is 0) {
+        auto hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+        if (hwndChild !is null) {
+            int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
+            if (threadId !is OS.GetCurrentThreadId ()) {
+                OS.ShowWindow (hwndChild, OS.SW_HIDE);
+                OS.SetParent (hwndChild, null);
+            }
+        }
+    }
+    layout_ = null;
+    tabList = null;
+    lpwp = null;
+}
+
+void removeControl (Control control) {
+    fixTabList (control);
+    resizeChildren ();
+}
+
+void resizeChildren () {
+    if (lpwp is null) return;
+    do {
+        WINDOWPOS* [] currentLpwp = lpwp;
+        lpwp = null;
+        if (!resizeChildren (true, currentLpwp)) {
+            resizeChildren (false, currentLpwp);
+        }
+    } while (lpwp !is null);
+}
+
+bool resizeChildren (bool defer, WINDOWPOS* [] pwp) {
+    if (pwp is null) return true;
+    HDWP hdwp;
+    if (defer) {
+        hdwp = OS.BeginDeferWindowPos (pwp.length);
+        if (hdwp is null) return false;
+    }
+    for (int i=0; i<pwp.length; i++) {
+        WINDOWPOS* wp = pwp [i];
+        if (wp !is null) {
+            /*
+            * This code is intentionally commented.  All widgets that
+            * are created by SWT have WS_CLIPSIBLINGS to ensure that
+            * application code does not draw outside of the control.
+            */
+//          int count = parent.getChildrenCount ();
+//          if (count > 1) {
+//              int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//              if ((bits & OS.WS_CLIPSIBLINGS) is 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//          }
+            if (defer) {
+                hdwp = DeferWindowPos (hdwp, wp._hwnd, null, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                if (hdwp is null) return false;
+            } else {
+                SetWindowPos (wp._hwnd, null, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+            }
+        }
+    }
+    if (defer) return cast(bool)OS.EndDeferWindowPos (hdwp);
+    return true;
+}
+
+void resizeEmbeddedHandle(HANDLE embeddedHandle, int width, int height) {
+    if (embeddedHandle is null) return;
+    uint processID;
+    int threadId = OS.GetWindowThreadProcessId (embeddedHandle, &processID);
+    if (threadId !is OS.GetCurrentThreadId ()) {
+        if (processID is OS.GetCurrentProcessId ()) {
+            if (display.msgHook is null) {
+                static if (!OS.IsWinCE) {
+                    //display.getMsgCallback = new Callback (display, "getMsgProc", 3);
+                    //display.getMsgProc = display.getMsgCallback.getAddress ();
+                    //if (display.getMsgProc is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+                    display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, &Display.getMsgFunc, OS.GetLibraryHandle(), threadId);
+                    OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+                }
+            }
+        }
+        int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS;
+        OS.SetWindowPos (embeddedHandle, null, 0, 0, width, height, flags);
+    }
+}
+
+override void sendResize () {
+    setResizeChildren (false);
+    super.sendResize ();
+    if (isDisposed ()) return;
+    if (layout_ !is null) {
+        markLayout (false, false);
+        updateLayout (false, false);
+    }
+    setResizeChildren (true);
+}
+
+/**
+ * Sets the background drawing mode to the argument which should
+ * be one of the following constants defined in class <code>SWT</code>:
+ * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
+ * <code>INHERIT_FORCE</code>.
+ *
+ * @param mode the new background mode
+ *
+ * @exception SWTException <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 SWT
+ *
+ * @since 3.2
+ */
+public void setBackgroundMode (int mode) {
+    checkWidget ();
+    backgroundMode = mode;
+    Control [] children = _getChildren ();
+    for (int i = 0; i < children.length; i++) {
+        children [i].updateBackgroundMode ();
+    }
+}
+
+override 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 ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setFixedFocus ()) return true;
+    }
+    return super.setFixedFocus ();
+}
+
+override public bool setFocus () {
+    checkWidget ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.setFocus ()) return true;
+    }
+    return super.setFocus ();
+}
+
+/**
+ * Sets the layout which is associated with the receiver to be
+ * the argument which may be null.
+ *
+ * @param layout the receiver's new layout or null
+ *
+ * @exception SWTException <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 setLayout (Layout layout_) {
+    checkWidget ();
+    this.layout_ = layout_;
+}
+
+/**
+ * If the argument is <code>true</code>, causes subsequent layout
+ * operations in the receiver or any of its children to be ignored.
+ * No layout of any kind can occur in the receiver or any of its
+ * children until the flag is set to false.
+ * Layout operations that occurred while the flag was
+ * <code>true</code> are remembered and when the flag is set to
+ * <code>false</code>, the layout operations are performed in an
+ * optimized manner.  Nested calls to this method are stacked.
+ *
+ * @param defer the new defer state
+ *
+ * @exception SWTException <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 #layout(bool)
+ * @see #layout(Control[])
+ *
+ * @since 3.1
+ */
+public void setLayoutDeferred (bool defer) {
+    if (!defer) {
+        if (--layoutCount is 0) {
+            if ((state & LAYOUT_CHILD) !is 0 || (state & LAYOUT_NEEDED) !is 0) {
+                updateLayout (true, true);
+            }
+        }
+    } else {
+        layoutCount++;
+    }
+}
+/**
+ * Sets the tabbing order for the specified controls to
+ * match the order that they occur in the argument list.
+ *
+ * @param tabList the ordered list of controls representing the tab order or null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setTabList (Control [] tabList) {
+    checkWidget ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            Control control = tabList [i];
+            if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
+            if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+            if (control.parent !is this) error (SWT.ERROR_INVALID_PARENT);
+        }
+        Control [] newList = new Control [tabList.length];
+        System.arraycopy (tabList, 0, newList, 0, tabList.length);
+        tabList = newList;
+    }
+    this.tabList = tabList;
+}
+
+void setResizeChildren (bool resize) {
+    if (resize) {
+        resizeChildren ();
+    } else {
+        if (display.resizeCount > Display.RESIZE_LIMIT) {
+            return;
+        }
+        int count = getChildrenCount ();
+        if (count > 1 && lpwp is null) {
+            lpwp = new WINDOWPOS* [count];
+        }
+    }
+}
+
+override bool setTabGroupFocus () {
+    if (isTabItem ()) return setTabItemFocus ();
+    bool takeFocus = (style & SWT.NO_FOCUS) is 0;
+    if ((state & CANVAS) !is 0) {
+        takeFocus = hooksKeys ();
+        if ((style & SWT.EMBEDDED) !is 0) takeFocus = true;
+    }
+    if (takeFocus && setTabItemFocus ()) return true;
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.isTabItem () && child.setRadioFocus ()) return true;
+    }
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        if (child.isTabItem () && !child.isTabGroup () && child.setTabItemFocus ()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+String toolTipText (NMTTDISPINFO* hdr) {
+    Shell shell = getShell ();
+    if ((hdr.uFlags & OS.TTF_IDISHWND) is 0) {
+        String string = null;
+        ToolTip toolTip = shell.findToolTip (hdr.hdr.idFrom);
+        if (toolTip !is null) {
+            string = toolTip.message;
+            if (string is null || string.length is 0) string = " ";
+        }
+        return string;
+    }
+    shell.setToolTipTitle (hdr.hdr.hwndFrom, null, null);
+    OS.SendMessage (hdr.hdr.hwndFrom, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    Control control = display.getControl ( cast(HANDLE) hdr.hdr.idFrom);
+    return control !is null ? control.toolTipText_ : null;
+}
+
+override bool translateMnemonic (Event event, Control control) {
+    if (super.translateMnemonic (event, control)) return true;
+    if (control !is null) {
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            Control child = children [i];
+            if (child.translateMnemonic (event, control)) return true;
+        }
+    }
+    return false;
+}
+
+override bool translateTraversal (MSG* msg) {
+    if ((state & CANVAS) !is 0 ) {
+        if ((style & SWT.EMBEDDED) !is 0) return false;
+        switch (msg.wParam) {
+            case OS.VK_UP:
+            case OS.VK_LEFT:
+            case OS.VK_DOWN:
+            case OS.VK_RIGHT:
+            case OS.VK_PRIOR:
+            case OS.VK_NEXT:
+                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:
+        }
+    }
+    return super.translateTraversal (msg);
+}
+
+override void updateBackgroundColor () {
+    super.updateBackgroundColor ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        if ((children [i].state & PARENT_BACKGROUND) !is 0) {
+            children [i].updateBackgroundColor ();
+        }
+    }
+}
+
+override void updateBackgroundImage () {
+    super.updateBackgroundImage ();
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        if ((children [i].state & PARENT_BACKGROUND) !is 0) {
+            children [i].updateBackgroundImage ();
+        }
+    }
+}
+
+override void updateBackgroundMode () {
+    super.updateBackgroundMode ();
+    Control [] children = _getChildren ();
+    for (int i = 0; i < children.length; i++) {
+        children [i].updateBackgroundMode ();
+    }
+}
+
+override void updateFont (Font oldFont, Font newFont) {
+    super.updateFont (oldFont, newFont);
+    Control [] children = _getChildren ();
+    for (int i=0; i<children.length; i++) {
+        Control control = children [i];
+        if (!control.isDisposed ()) {
+            control.updateFont (oldFont, newFont);
+        }
+    }
+}
+
+override void updateLayout (bool resize, bool all) {
+    Composite parent = findDeferredControl ();
+    if (parent !is null) {
+        parent.state |= LAYOUT_CHILD;
+        return;
+    }
+    if ((state & LAYOUT_NEEDED) !is 0) {
+        bool changed = (state & LAYOUT_CHANGED) !is 0;
+        state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
+        if (resize) setResizeChildren (false);
+        layout_.layout (this, changed);
+        if (resize) setResizeChildren (true);
+    }
+    if (all) {
+        state &= ~LAYOUT_CHILD;
+        Control [] children = _getChildren ();
+        for (int i=0; i<children.length; i++) {
+            children [i].updateLayout (resize, all);
+        }
+    }
+}
+
+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;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        /* Return zero to indicate that the background was not erased */
+        if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) !is 0) {
+            return LRESULT.ZERO;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        int flags = 0;
+        if (hooksKeys ()) {
+            flags |= OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
+        }
+        if ((style & SWT.NO_FOCUS) !is 0) flags |= OS.DLGC_STATIC;
+        if (OS.GetWindow (handle, OS.GW_CHILD) !is null) flags |= OS.DLGC_STATIC;
+        if (flags !is 0) return new LRESULT (flags);
+    }
+    return result;
+}
+
+override LRESULT WM_GETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_GETFONT (wParam, lParam);
+    if (result !is null) return result;
+    int /*long*/ code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+    if (code !is 0) return new LRESULT (code);
+    return new LRESULT ( cast(int)(font !is null ? font.handle : defaultFont ()));
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+
+    /* Set focus for a canvas with no children */
+    if ((state & CANVAS) !is 0) {
+        if ((style & SWT.NO_FOCUS) is 0 && hooksKeys ()) {
+            if (OS.GetWindow (handle, OS.GW_CHILD) is null) setFocus ();
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_NCHITTEST (int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * 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 & SWT.EMBEDDED) !is 0) {
+        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);
+        }
+    }
+    return super.WM_PARENTNOTIFY (wParam, lParam);
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    if ((state & CANVAS) is 0 || (state & FOREIGN_HANDLE) !is 0) {
+        return super.WM_PAINT (wParam, lParam);
+    }
+
+    /* Set the clipping bits */
+    int oldBits = 0, newBits = 0;
+    static if (!OS.IsWinCE) {
+        oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;
+        if (newBits !is oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+    }
+
+    /* Paint the control and the background */
+    PAINTSTRUCT ps;
+    if (hooks (SWT.Paint)) {
+
+        /* Use the buffered paint when possible */
+        bool bufferedPaint = false;
+        if ((style & SWT.DOUBLE_BUFFERED) !is 0) {
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if ((style & (SWT.NO_MERGE_PAINTS | SWT.RIGHT_TO_LEFT)) is 0) {
+                    if ((style & SWT.TRANSPARENT) is 0) bufferedPaint = true;
+                }
+            }
+        }
+        if (bufferedPaint) {
+            auto hDC = 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) {
+                HDC phdc;
+                int flags = OS.BPBF_COMPATIBLEBITMAP;
+                RECT prcTarget;
+                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 ();
+                data.device = display;
+                data.foreground = getForegroundPixel ();
+                Control control = findBackgroundControl ();
+                if (control is null) control = this;
+                data.background = control.getBackgroundPixel ();
+                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 & SWT.NO_BACKGROUND) !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 {
+                    RECT rect;
+                    OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+                    drawBackground (phdc, &rect);
+                }
+                GC gc = GC.win32_new (phdc, data);
+                Event event = new Event ();
+                event.gc = gc;
+                event.x = ps.rcPaint.left;
+                event.y = ps.rcPaint.top;
+                event.width = width;
+                event.height = height;
+                sendEvent (SWT.Paint, event);
+                if (data.focusDrawn && !isDisposed ()) updateUIState ();
+                gc.dispose ();
+                OS.EndBufferedPaint (hBufferedPaint, true);
+            }
+            OS.EndPaint (handle, &ps);
+        } else {
+
+            /* Create the paint GC */
+            GCData data = new GCData ();
+            data.ps = &ps;
+            data.hwnd = handle;
+            GC gc = GC.win32_new (this, data);
+
+            /* Get the system region for the paint HDC */
+            HRGN sysRgn;
+            if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) !is 0 || (style & SWT.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)) {
+                        if ((OS.GetLayout (gc.handle) & OS.LAYOUT_RTL) !is 0) {
+                            int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                            int [] lpRgnData = new int [nBytes / 4];
+                            OS.GetRegionData (sysRgn, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+                            HRGN newSysRgn = OS.ExtCreateRegion ( cast(XFORM*) [-1.0f, 0, 0, 1, 0, 0].ptr, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+                            OS.DeleteObject (sysRgn);
+                            sysRgn = newSysRgn;
+                        }
+                    }
+                    if (OS.IsWinNT) {
+                        POINT pt;
+                        OS.MapWindowPoints (null, handle, &pt, 1);
+                        OS.OffsetRgn (sysRgn, pt.x, pt.y);
+                    }
+                }
+            }
+
+            /* Send the paint event */
+            int width = ps.rcPaint.right - ps.rcPaint.left;
+            int height = ps.rcPaint.bottom - ps.rcPaint.top;
+            if (width !is 0 && height !is 0) {
+                GC paintGC = null;
+                Image image = null;
+                if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) !is 0) {
+                    image = new Image (display, width, height);
+                    paintGC = gc;
+                    gc = new GC (image, paintGC.getStyle() & SWT.RIGHT_TO_LEFT);
+                    GCData gcData = gc.getGCData ();
+                    gcData.uiState = data.uiState;
+                    gc.setForeground (getForeground ());
+                    gc.setBackground (getBackground ());
+                    gc.setFont (getFont ());
+                    if ((style & SWT.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 & (SWT.NO_BACKGROUND | SWT.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 {
+                        RECT rect;
+                        OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+                        drawBackground (gc.handle, &rect);
+                    }
+                }
+                Event event = new Event ();
+                event.gc = gc;
+                RECT rect;
+                if ((style & SWT.NO_MERGE_PAINTS) !is 0 && OS.GetRgnBox (sysRgn, &rect) is OS.COMPLEXREGION) {
+                    int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                    int [] lpRgnData = new int [nBytes / 4];
+                    OS.GetRegionData (sysRgn, nBytes, cast(RGNDATA*)lpRgnData.ptr);
+                    int count = lpRgnData [2];
+                    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 & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) is 0) {
+                            drawBackground (gc.handle, &rect);
+                        }
+                        event.x = rect.left;
+                        event.y = rect.top;
+                        event.width = rect.right - rect.left;
+                        event.height = rect.bottom - rect.top;
+                        event.count = count - 1 - i;
+                        sendEvent (SWT.Paint, event);
+                    }
+                } else {
+                    if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) is 0) {
+                        OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+                        drawBackground (gc.handle, &rect);
+                    }
+                    event.x = ps.rcPaint.left;
+                    event.y = ps.rcPaint.top;
+                    event.width = width;
+                    event.height = height;
+                    sendEvent (SWT.Paint, event);
+                }
+                // widget could be disposed at this point
+                event.gc = null;
+                if ((style & (SWT.DOUBLE_BUFFERED | SWT.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 ();
+                    gc = paintGC;
+                }
+            }
+            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 & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) is 0) {
+            RECT rect;
+            OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+            drawBackground (hDC, &rect);
+        }
+        OS.EndPaint (handle, &ps);
+    }
+
+    /* Restore the clipping bits */
+    if (!OS.IsWinCE && !isDisposed ()) {
+        if (newBits !is oldBits) {
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the paint
+            * event.  If this happens, don't attempt to restore
+            * the style.
+            */
+            if (!isDisposed ()) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
+            }
+        }
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    if (result !is null) return result;
+    if ((state & CANVAS) !is 0) {
+        forceResize ();
+        auto nSavedDC = OS.SaveDC (cast(HDC)wParam);
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) is 0) {
+            drawBackground ( cast(HDC)wParam, &rect);
+        }
+        if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+            GCData data = new GCData ();
+            data.device = display;
+            data.foreground = getForegroundPixel ();
+            Control control = findBackgroundControl ();
+            if (control is null) control = this;
+            data.background = control.getBackgroundPixel ();
+            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 ();
+            event.gc = gc;
+            event.x = rect.left;
+            event.y = rect.top;
+            event.width = rect.right - rect.left;
+            event.height = rect.bottom - rect.top;
+            sendEvent (SWT.Paint, event);
+            event.gc = null;
+            gc.dispose ();
+        }
+        OS.RestoreDC (cast(HDC)wParam, nSavedDC);
+    }
+    return result;
+}
+
+override LRESULT WM_SETFONT (int wParam, int lParam) {
+    if (lParam !is 0) OS.InvalidateRect (handle, null, true);
+    return super.WM_SETFONT (wParam, lParam);
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    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 */
+        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);
+    }
+
+    /* Damage the widget to cause a repaint */
+    if (OS.IsWindowVisible (handle)) {
+        if ((state & CANVAS) !is 0) {
+            if ((style & SWT.NO_REDRAW_RESIZE) is 0) {
+                if (hooks (SWT.Paint)) {
+                    OS.InvalidateRect (handle, null, true);
+                }
+            }
+        }
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            if (findThemeControl () !is null) redrawChildren ();
+        }
+    }
+
+    /* Resize the embedded window */
+    if ((state & CANVAS) !is 0 && (style & SWT.EMBEDDED) !is 0) {
+        resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam));
+    }
+    return result;
+}
+
+override LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    auto hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is null) {
+        OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    return result;
+}
+
+override LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * 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;
+
+    /*
+    * Bug in Windows.  When a vertical or horizontal scroll bar is
+    * hidden or shown while the opposite scroll bar is being scrolled
+    * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
+    * does not redraw properly.  The fix is to detect this case and
+    * redraw the non-client area.
+    */
+    static if (!OS.IsWinCE) {
+        int cmd = wParam & 0xFFF0;
+        switch (cmd) {
+            case OS.SC_HSCROLL:
+            case OS.SC_VSCROLL:
+                bool showHBar = horizontalBar !is null && horizontalBar.getVisible ();
+                bool showVBar = verticalBar !is null && verticalBar.getVisible ();
+                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;
+                        OS.RedrawWindow (handle, null, null, flags);
+                    }
+                if (code is 0) return LRESULT.ZERO;
+                return new LRESULT (code);
+            default:
+        }
+    }
+    /* Return the result */
+    return result;
+}
+
+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 && hooks (SWT.Paint)) {
+        OS.InvalidateRect (handle, null, true);
+    }
+    return result;
+}
+
+override LRESULT wmNCPaint (HWND hwnd, int wParam, int 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);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
+    static if (!OS.IsWinCE) {
+        switch (hdr.code) {
+            /*
+            * Feature in Windows.  When the tool tip control is
+            * created, the parent of the tool tip is the shell.
+            * If SetParent () is used to reparent the tool bar
+            * into a new shell, the tool tip is not reparented
+            * and pops up underneath the new shell.  The fix is
+            * to make sure the tool tip is a topmost window.
+            */
+            case OS.TTN_SHOW:
+            case OS.TTN_POP: {
+                /*
+                * Bug in Windows 98 and NT.  Setting the tool tip to be the
+                * top most window using HWND_TOPMOST can result in a parent
+                * dialog shell being moved behind its parent if the dialog
+                * has a sibling that is currently on top.  The fix is to
+                * lock the z-order of the active window.
+                *
+                * Feature in Windows.  Using SetWindowPos() with HWND_NOTOPMOST
+                * to clear the topmost state of a window whose parent is already
+                * topmost clears the topmost state of the parent.  The fix is to
+                * check if the parent is already on top and neither set or clear
+                * the topmost status of the tool tip.
+                */
+                auto hwndParent = hdr.hwndFrom;
+                do {
+                    hwndParent = OS.GetParent (hwndParent);
+                    if (hwndParent is null) break;
+                    int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                    if ((bits & OS.WS_EX_TOPMOST) !is 0) break;
+                } while (true);
+                if (hwndParent !is null) break;
+                display.lockActiveWindow = true;
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
+                HWND hwndInsertAfter = cast(HWND)( hdr.code is OS.TTN_SHOW ? OS.HWND_TOPMOST : OS.HWND_NOTOPMOST);
+                SetWindowPos (hdr.hwndFrom, hwndInsertAfter, 0, 0, 0, 0, flags);
+                display.lockActiveWindow = false;
+                break;
+            }
+            /*
+            * Bug in Windows 98.  For some reason, the tool bar control
+            * sends both TTN_GETDISPINFOW and TTN_GETDISPINFOA to get
+            * the tool tip text and the tab folder control sends only
+            * TTN_GETDISPINFOW.  The fix is to handle only TTN_GETDISPINFOW,
+            * even though it should never be sent on Windows 98.
+            *
+            * NOTE:  Because the size of NMTTDISPINFO differs between
+            * Windows 98 and NT, guard against the case where the wrong
+            * kind of message occurs by inlining the memory moves and
+            * the UNICODE conversion code.
+            */
+            case OS.TTN_GETDISPINFOA:
+            case OS.TTN_GETDISPINFOW: {
+                NMTTDISPINFO* lpnmtdi = cast(NMTTDISPINFO*)lParam;
+//                 if (hdr.code is OS.TTN_GETDISPINFOA) {
+//                     lpnmtdi = new NMTTDISPINFOA ();
+//                     OS.MoveMemory (cast(NMTTDISPINFOA)lpnmtdi, lParam, NMTTDISPINFOA.sizeof);
+//                 } else {
+//                     lpnmtdi = new NMTTDISPINFOW ();
+//                     OS.MoveMemory (cast(NMTTDISPINFOW)lpnmtdi, lParam, NMTTDISPINFOW.sizeof);
+//                 }
+                String string = toolTipText (lpnmtdi);
+                if (string !is null) {
+                    Shell shell = getShell ();
+                    string = Display.withCrLf (string);
+                    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 ((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 () & SWT.RIGHT_TO_LEFT) !is 0) {
+                            lpnmtdi.uFlags |= OS.TTF_RTLREADING;
+                        } else {
+                            lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
+                        }
+                    }
+
+                    if (hdr.code is OS.TTN_GETDISPINFOA) {
+                        auto bytes = MBCSsToStr( cast(CHAR[])chars, getCodePage () );
+                        //byte [] bytes = new byte [chars.length * 2];
+                        //OS.WideCharToMultiByte (getCodePage (), 0, chars.ptr, chars.length, bytes, bytes.length, null, null);
+                        shell.setToolTipText (lpnmtdi, bytes);
+                        //OS.MoveMemory (lParam, cast(NMTTDISPINFOA)lpnmtdi, NMTTDISPINFOA.sizeof);
+                    } else {
+                        shell.setToolTipText (lpnmtdi, StrToTCHARs(chars,true));
+                        //OS.MoveMemory (lParam, cast(NMTTDISPINFOW)lpnmtdi, NMTTDISPINFOW.sizeof);
+                    }
+                    return LRESULT.ZERO;
+                }
+                break;
+            }
+            default:
+        }
+    }
+    return super.wmNotify (hdr, wParam, lParam);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Control.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,4773 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Control;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DragDetectListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.MouseWheelListener;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Monitor;
+
+import java.lang.all;
+import java.lang.System;
+
+static import tango.sys.Common;
+
+/**
+ * Control is the abstract superclass of all windowed user interface classes.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b>
+ * <dd>BORDER</dd>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * <dt><b>Events:</b>
+ * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
+ *     MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize, Traverse</dd>
+ * </dl>
+ * </p><p>
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Control : Widget, Drawable {
+
+    alias Widget.dragDetect dragDetect;
+    alias Widget.callWindowProc callWindowProc;
+
+    /**
+     * the handle to the OS resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HANDLE handle;
+    Composite parent;
+    Cursor cursor;
+    Menu menu;
+    String toolTipText_;
+    Object layoutData;
+    Accessible accessible;
+    Image backgroundImage;
+    Region region;
+    Font font;
+    int drawCount, foreground, background;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Resize,typedListener);
+    addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when a drag gesture occurs, by sending it
+ * one of the messages defined in the <code>DragDetectListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 DragDetectListener
+ * @see #removeDragDetectListener
+ *
+ * @since 3.3
+ */
+public void addDragDetectListener (DragDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.DragDetect,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control gains or loses focus, by sending
+ * it one of the messages defined in the <code>FocusListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 FocusListener
+ * @see #removeFocusListener
+ */
+public void addFocusListener (FocusListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.FocusIn,typedListener);
+    addListener (SWT.FocusOut,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when help events are generated for the control,
+ * by sending it one of the messages defined in the
+ * <code>HelpListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard, by sending
+ * it one of the messages defined in the <code>KeyListener</code>
+ * interface.
+ * <p>
+ * When a key listener is added to a control, the control
+ * will take part in widget traversal.  By default, all
+ * traversal keys (such as the tab key and so on) are
+ * delivered to the control.  In order for a control to take
+ * part in traversal, it should listen for traversal events.
+ * Otherwise, the user can traverse into a control but not
+ * out.  Note that native controls such as table and tree
+ * implement key traversal in the operating system.  It is
+ * not necessary to add traversal listeners for these controls,
+ * unless you want to override the default traversal.
+ * </p>
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 KeyListener
+ * @see #removeKeyListener
+ */
+public void addKeyListener (KeyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.KeyUp,typedListener);
+    addListener (SWT.KeyDown,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the platform-specific context menu trigger
+ * has occurred, by sending it one of the messages defined in
+ * the <code>MenuDetectListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuDetectListener
+ * @see #removeMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void addMenuDetectListener (MenuDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MenuDetect, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when mouse buttons are pressed and released, by sending
+ * it one of the messages defined in the <code>MouseListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseListener
+ * @see #removeMouseListener
+ */
+public void addMouseListener (MouseListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MouseDown,typedListener);
+    addListener (SWT.MouseUp,typedListener);
+    addListener (SWT.MouseDoubleClick,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls, by sending
+ * it one of the messages defined in the <code>MouseTrackListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseTrackListener
+ * @see #removeMouseTrackListener
+ */
+public void addMouseTrackListener (MouseTrackListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MouseEnter,typedListener);
+    addListener (SWT.MouseExit,typedListener);
+    addListener (SWT.MouseHover,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse moves, by sending it one of the
+ * messages defined in the <code>MouseMoveListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseMoveListener
+ * @see #removeMouseMoveListener
+ */
+public void addMouseMoveListener (MouseMoveListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MouseMove,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the mouse wheel is scrolled, by sending
+ * it one of the messages defined in the
+ * <code>MouseWheelListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseWheelListener
+ * @see #removeMouseWheelListener
+ *
+ * @since 3.3
+ */
+public void addMouseWheelListener (MouseWheelListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MouseWheel, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver needs to be painted, by sending it
+ * one of the messages defined in the <code>PaintListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 PaintListener
+ * @see #removePaintListener
+ */
+public void addPaintListener (PaintListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Paint,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when traversal events occur, by sending it
+ * one of the messages defined in the <code>TraverseListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TraverseListener
+ * @see #removeTraverseListener
+ */
+public void addTraverseListener (TraverseListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Traverse,typedListener);
+}
+
+HANDLE borderHandle () {
+    return handle;
+}
+
+void checkBackground () {
+    Shell shell = getShell ();
+    if (this is shell) return;
+    state &= ~PARENT_BACKGROUND;
+    Composite composite = parent;
+    do {
+        auto mode = composite.backgroundMode;
+        if (mode !is 0) {
+            if (mode is SWT.INHERIT_DEFAULT) {
+                Control control = this;
+                do {
+                    if ((control.state & THEME_BACKGROUND) is 0) {
+                        return;
+                    }
+                    control = control.parent;
+                } while (control !is composite);
+            }
+            state |= PARENT_BACKGROUND;
+            return;
+        }
+        if (composite is shell) break;
+        composite = composite.parent;
+    } while (true);
+}
+
+void checkBorder () {
+    if (getBorderWidth () is 0) style &= ~SWT.BORDER;
+}
+
+void checkBuffered () {
+    style &= ~SWT.DOUBLE_BUFFERED;
+}
+
+void checkComposited () {
+    /* Do nothing */
+}
+
+bool checkHandle (HWND hwnd) {
+    return hwnd is handle;
+}
+
+void checkMirrored () {
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+        if ((bits & OS.WS_EX_LAYOUTRTL) !is 0) style |= SWT.MIRRORED;
+    }
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a control is the size that it would
+ * best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask a control questions such as "Given a particular
+ * width, how high does the control need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @return the preferred size of the control
+ *
+ * @exception SWTException <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 Layout
+ * @see #getBorderWidth
+ * @see #getBounds
+ * @see #getSize
+ * @see #pack(bool)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint) {
+    return computeSize (wHint, hHint, true);
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a control is the size that it would
+ * best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask a control questions such as "Given a particular
+ * width, how high does the control need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p><p>
+ * If the changed flag is <code>true</code>, it indicates that the receiver's
+ * <em>contents</em> have changed, therefore any caches that a layout manager
+ * containing the control may have been keeping need to be flushed. When the
+ * control is resized, the changed flag will be <code>false</code>, so layout
+ * manager caches can be retained.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
+ * @return the preferred size of the control.
+ *
+ * @exception SWTException <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 Layout
+ * @see #getBorderWidth
+ * @see #getBounds
+ * @see #getSize
+ * @see #pack(bool)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = DEFAULT_WIDTH;
+    int height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2;
+    height += border * 2;
+    return new Point (width, height);
+}
+
+Control computeTabGroup () {
+    if (isTabGroup ()) return this;
+    return parent.computeTabGroup ();
+}
+
+Control computeTabRoot () {
+    Control [] tabList = parent._getTabList ();
+    if (tabList !is null) {
+        int index = 0;
+        while (index < tabList.length) {
+            if (tabList [index] is this) break;
+            index++;
+        }
+        if (index is tabList.length) {
+            if (isTabGroup ()) return this;
+        }
+    }
+    return parent.computeTabRoot ();
+}
+
+Control [] computeTabList () {
+    if (isTabGroup ()) {
+        if (getVisible () && getEnabled ()) {
+            return [this];
+        }
+    }
+    return new Control [0];
+}
+
+void createHandle () {
+    auto hwndParent = widgetParent ();
+    handle = OS.CreateWindowEx (
+        widgetExtStyle (),
+        StrToTCHARz( windowClass () ),
+        null,
+        widgetStyle (),
+        OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+        hwndParent,
+        null,
+        OS.GetModuleHandle (null),
+        widgetCreateStruct ());
+    if (handle is null) error (SWT.ERROR_NO_HANDLES);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.WS_CHILD) !is 0) {
+        OS.SetWindowLongPtr (handle, OS.GWLP_ID, cast(LONG_PTR)handle);
+    }
+    if (OS.IsDBLocale && hwndParent !is null) {
+        auto hIMC = OS.ImmGetContext (hwndParent);
+        OS.ImmAssociateContext (handle, hIMC);
+        OS.ImmReleaseContext (hwndParent, hIMC);
+    }
+}
+
+void createWidget () {
+    state |= DRAG_DETECT;
+    foreground = background = -1;
+    checkOrientation (parent);
+    createHandle ();
+    checkBackground ();
+    checkBuffered ();
+    checkComposited ();
+    register ();
+    subclass ();
+    setDefaultFont ();
+    checkMirrored ();
+    checkBorder ();
+    if ((state & PARENT_BACKGROUND) !is 0) {
+        setBackground ();
+    }
+}
+
+int defaultBackground () {
+    static if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_WINDOW);
+    return OS.GetSysColor (OS.COLOR_BTNFACE);
+}
+
+HFONT defaultFont () {
+    return display.getSystemFont ().handle;
+}
+
+int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_WINDOWTEXT);
+}
+
+void deregister () {
+    display.removeControl (handle);
+}
+
+override void destroyWidget () {
+    auto hwnd = topHandle ();
+    releaseHandle ();
+    if (hwnd !is null) {
+        OS.DestroyWindow (hwnd);
+    }
+}
+
+/**
+ * Detects a drag and drop gesture.  This method is used
+ * to detect a drag gesture when called from within a mouse
+ * down listener.
+ *
+ * <p>By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior.  In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item.  Custom widget writers can use <code>setDragDetect</code>
+ * to disable the default detection, listen for mouse down,
+ * and then call <code>dragDetect()</code> from within the
+ * listener to conditionally detect a drag.
+ * </p>
+ *
+ * @param event the mouse down event
+ *
+ * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_NULL_ARGUMENT when the event is null</li>
+ * </ul>
+ * @exception SWTException <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 DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @see #getDragDetect
+ * @see #setDragDetect
+ *
+ * @since 3.3
+ */
+public bool dragDetect (Event event) {
+    checkWidget ();
+    if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
+}
+
+/**
+ * Detects a drag and drop gesture.  This method is used
+ * to detect a drag gesture when called from within a mouse
+ * down listener.
+ *
+ * <p>By default, a drag is detected when the gesture
+ * occurs anywhere within the client area of a control.
+ * Some controls, such as tables and trees, override this
+ * behavior.  In addition to the operating system specific
+ * drag gesture, they require the mouse to be inside an
+ * item.  Custom widget writers can use <code>setDragDetect</code>
+ * to disable the default detection, listen for mouse down,
+ * and then call <code>dragDetect()</code> from within the
+ * listener to conditionally detect a drag.
+ * </p>
+ *
+ * @param event the mouse down event
+ *
+ * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_NULL_ARGUMENT when the event is null</li>
+ * </ul>
+ * @exception SWTException <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 DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @see #getDragDetect
+ * @see #setDragDetect
+ *
+ * @since 3.3
+ */
+public bool dragDetect (MouseEvent event) {
+    checkWidget ();
+    if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
+}
+
+bool dragDetect (int button, int count, int stateMask, int x, int y) {
+    if (button !is 1 || count !is 1) return false;
+    bool dragging = dragDetect (handle, x, y, false, null, null);
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+        if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+    }
+    if (!dragging) {
+        /*
+        * Feature in Windows.  DragDetect() captures the mouse
+        * and tracks its movement until the user releases the
+        * left mouse button, presses the ESC key, or moves the
+        * mouse outside the drag rectangle.  If the user moves
+        * the mouse outside of the drag rectangle, DragDetect()
+        * returns true and a drag and drop operation can be
+        * started.  When the left mouse button is released or
+        * the ESC key is pressed, these events are consumed by
+        * DragDetect() so that application code that matches
+        * mouse down/up pairs or looks for the ESC key will not
+        * function properly.  The fix is to send the missing
+        * events when the drag has not started.
+        *
+        * NOTE: For now, don't send a fake WM_KEYDOWN/WM_KEYUP
+        * events for the ESC key.  This would require computing
+        * wParam (the key) and lParam (the repeat count, scan code,
+        * extended-key flag, context code, previous key-state flag,
+        * and transition-state flag) which is non-trivial.
+        */
+        if (button is 1 && OS.GetKeyState (OS.VK_ESCAPE) >= 0) {
+            int wParam = 0;
+            if ((stateMask & SWT.CTRL) !is 0) wParam |= OS.MK_CONTROL;
+            if ((stateMask & SWT.SHIFT) !is 0) wParam |= OS.MK_SHIFT;
+            if ((stateMask & SWT.ALT) !is 0) wParam |= OS.MK_ALT;
+            if ((stateMask & SWT.BUTTON1) !is 0) wParam |= OS.MK_LBUTTON;
+            if ((stateMask & SWT.BUTTON2) !is 0) wParam |= OS.MK_MBUTTON;
+            if ((stateMask & SWT.BUTTON3) !is 0) wParam |= OS.MK_RBUTTON;
+            if ((stateMask & SWT.BUTTON4) !is 0) wParam |= OS.MK_XBUTTON1;
+            if ((stateMask & SWT.BUTTON5) !is 0) wParam |= OS.MK_XBUTTON2;
+            int /*long*/ lParam = OS.MAKELPARAM (x, y);
+            OS.SendMessage (handle, OS.WM_LBUTTONUP, wParam, lParam);
+        }
+        return false;
+    }
+    return sendDragEvent (button, stateMask, x, y);
+}
+
+void drawBackground (HDC hDC) {
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    drawBackground (hDC, &rect);
+}
+
+void drawBackground (HDC hDC, RECT* rect) {
+    drawBackground (hDC, rect, -1);
+}
+
+void drawBackground (HDC hDC, RECT* rect, int pixel) {
+    Control control = findBackgroundControl ();
+    if (control !is null) {
+        if (control.backgroundImage !is null) {
+            fillImageBackground (hDC, control, rect);
+            return;
+        }
+        pixel = control.getBackgroundPixel ();
+    }
+    if (pixel is -1) {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                control = findThemeControl ();
+                if (control !is null) {
+                    fillThemeBackground (hDC, control, rect);
+                    return;
+                }
+            }
+        }
+    }
+    if (pixel is -1) pixel = getBackgroundPixel ();
+    fillBackground (hDC, pixel, rect);
+}
+
+void drawImageBackground (HDC hDC, HWND hwnd, HBITMAP hBitmap, RECT* rect) {
+    RECT rect2;
+    OS.GetClientRect (hwnd, &rect2);
+    OS.MapWindowPoints (hwnd, handle, cast(POINT*)&rect2, 2);
+    auto hBrush = findBrush ( cast(int)hBitmap, OS.BS_PATTERN);
+    POINT lpPoint;
+    OS.GetWindowOrgEx (hDC, &lpPoint);
+    OS.SetBrushOrgEx (hDC, -rect2.left - lpPoint.x, -rect2.top - lpPoint.y, &lpPoint);
+    auto hOldBrush = OS.SelectObject (hDC, hBrush);
+    OS.PatBlt (hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+    OS.SetBrushOrgEx (hDC, lpPoint.x, lpPoint.y, null);
+    OS.SelectObject (hDC, hOldBrush);
+}
+
+void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) {
+    /* Do nothing */
+}
+
+void enableDrag (bool enabled) {
+    /* Do nothing */
+}
+
+void enableWidget (bool enabled) {
+    OS.EnableWindow (handle, enabled);
+}
+
+void fillBackground (HDC hDC, int pixel, RECT* rect) {
+    if (rect.left > rect.right || rect.top > rect.bottom) return;
+    auto hPalette = display.hPalette;
+    if (hPalette !is null) {
+        OS.SelectPalette (hDC, hPalette, false);
+        OS.RealizePalette (hDC);
+    }
+    OS.FillRect (hDC, rect, findBrush (pixel, OS.BS_SOLID));
+}
+
+void fillImageBackground (HDC hDC, Control control, RECT* rect) {
+    if (rect.left > rect.right || rect.top > rect.bottom) return;
+    if (control !is null) {
+        Image image = control.backgroundImage;
+        if (image !is null) {
+            control.drawImageBackground (hDC, handle, image.handle, rect);
+        }
+    }
+}
+
+void fillThemeBackground (HDC hDC, Control control, RECT* rect) {
+    if (rect.left > rect.right || rect.top > rect.bottom) return;
+    if (control !is null) {
+        control.drawThemeBackground (hDC, handle, rect);
+    }
+}
+
+Control findBackgroundControl () {
+    if (background !is -1 || backgroundImage !is null) return this;
+    return (state & PARENT_BACKGROUND) !is 0 ? parent.findBackgroundControl () : null;
+}
+
+HBRUSH findBrush (int value, int lbStyle) {
+    return parent.findBrush (value, lbStyle);
+}
+
+Cursor findCursor () {
+    if (cursor !is null) return cursor;
+    return parent.findCursor ();
+}
+
+Control findImageControl () {
+    Control control = findBackgroundControl ();
+    return control !is null && control.backgroundImage !is null ? control : null;
+}
+
+Control findThemeControl () {
+    return background is -1 && backgroundImage is null ? parent.findThemeControl () : null;
+}
+
+Menu [] findMenus (Control control) {
+    if (menu !is null && this !is control) return [menu];
+    return new Menu [0];
+}
+
+char findMnemonic (String string) {
+    int index = 0;
+    int length_ = string.length;
+    do {
+        while (index < length_ && string.charAt (index) !is '&') index++;
+        if (++index >= length_) return '\0';
+        if (string.charAt (index) !is '&') return string.charAt (index);
+        index++;
+    } while (index < length_);
+    return '\0';
+}
+
+void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+    oldShell.fixShell (newShell, this);
+    oldDecorations.fixDecorations (newDecorations, this, menus);
+}
+
+void fixFocus (Control focusControl) {
+    Shell shell = getShell ();
+    Control control = this;
+    while (control !is shell && (control = control.parent) !is null) {
+        if (control.setFixedFocus ()) return;
+    }
+    shell.setSavedFocus (focusControl);
+    OS.SetFocus (null);
+}
+
+/**
+ * Forces the receiver to have the <em>keyboard focus</em>, causing
+ * all keyboard events to be delivered to it.
+ *
+ * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
+ *
+ * @exception SWTException <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 #setFocus
+ */
+public bool forceFocus () {
+    checkWidget ();
+    if (display.focusEvent is SWT.FocusOut) return false;
+    Decorations shell = menuShell ();
+    shell.setSavedFocus (this);
+    if (!isEnabled () || !isVisible () || !isActive ()) return false;
+    if (isFocusControl ()) return true;
+    shell.setSavedFocus (null);
+    /*
+    * This code is intentionally commented.
+    *
+    * When setting focus to a control, it is
+    * possible that application code can set
+    * the focus to another control inside of
+    * WM_SETFOCUS.  In this case, the original
+    * control will no longer have the focus
+    * and the call to setFocus() will return
+    * false indicating failure.
+    *
+    * We are still working on a solution at
+    * this time.
+    */
+//  if (OS.GetFocus () !is OS.SetFocus (handle)) return false;
+    OS.SetFocus (handle);
+    if (isDisposed ()) return false;
+    shell.setSavedFocus (this);
+    return isFocusControl ();
+}
+
+void forceResize () {
+    if (parent is null) return;
+    WINDOWPOS*[] lpwp = parent.lpwp;
+    if (lpwp is null) return;
+    for (int i=0; i<lpwp.length; i++) {
+        WINDOWPOS* wp = lpwp [i];
+        if (wp !is null && wp._hwnd is handle) {
+            /*
+            * This code is intentionally commented.  All widgets that
+            * are created by SWT have WS_CLIPSIBLINGS to ensure that
+            * application code does not draw outside of the control.
+            */
+//          int count = parent.getChildrenCount ();
+//          if (count > 1) {
+//              int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//              if ((bits & OS.WS_CLIPSIBLINGS) is 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//          }
+            SetWindowPos (wp._hwnd, null, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+            lpwp [i] = null;
+            return;
+        }
+    }
+}
+
+/**
+ * Returns the accessible object for the receiver.
+ * If this is the first time this object is requested,
+ * then the object is created and returned.
+ *
+ * @return the accessible object
+ *
+ * @exception SWTException <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 Accessible#addAccessibleListener
+ * @see Accessible#addAccessibleControlListener
+ *
+ * @since 2.0
+ */
+public Accessible getAccessible () {
+    checkWidget ();
+    if (accessible is null) accessible = new_Accessible (this);
+    return accessible;
+}
+
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @exception SWTException <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 Color getBackground () {
+    checkWidget ();
+    Control control = findBackgroundControl ();
+    if (control is null) control = this;
+    return Color.win32_new (display, control.getBackgroundPixel ());
+}
+
+/**
+ * Returns the receiver's background image.
+ *
+ * @return the background image
+ *
+ * @exception SWTException <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.2
+ */
+public Image getBackgroundImage () {
+    checkWidget ();
+    Control control = findBackgroundControl ();
+    if (control is null) control = this;
+    return control.backgroundImage;
+}
+
+int getBackgroundPixel () {
+    return background !is -1 ? background :  defaultBackground ();
+}
+
+/**
+ * Returns the receiver's border width.
+ *
+ * @return the border width
+ *
+ * @exception SWTException <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 int getBorderWidth () {
+    checkWidget ();
+    auto borderHandle = borderHandle ();
+    int bits1 = OS.GetWindowLong (borderHandle, OS.GWL_EXSTYLE);
+    if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) return OS.GetSystemMetrics (OS.SM_CXEDGE);
+    if ((bits1 & OS.WS_EX_STATICEDGE) !is 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
+    int bits2 = OS.GetWindowLong (borderHandle, OS.GWL_STYLE);
+    if ((bits2 & OS.WS_BORDER) !is 0) return OS.GetSystemMetrics (OS.SM_CXBORDER);
+    return 0;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null),
+ * unless the receiver is a shell. In this case, the location is
+ * relative to the display.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    OS.GetWindowRect (topHandle (), &rect);
+    auto hwndParent = parent is null ? null : parent.handle;
+    OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
+    int width = rect.right - rect.left;
+    int height =  rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+int getCodePage () {
+    if (OS.IsUnicode) return OS.CP_ACP;
+    auto hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    LOGFONT logFont;
+    OS.GetObject (hFont, LOGFONT.sizeof, &logFont);
+    int cs = logFont.lfCharSet & 0xFF;
+    int [] lpCs = new int [8];
+    if (OS.TranslateCharsetInfo (cast(uint*)cs, cast(CHARSETINFO*)lpCs.ptr, OS.TCI_SRCCHARSET)) {
+        return lpCs [1];
+    }
+    return OS.GetACP ();
+}
+
+String getClipboardText () {
+    String string = "";
+    if (OS.OpenClipboard (null)) {
+        auto hMem = OS.GetClipboardData (OS.IsUnicode ? OS.CF_UNICODETEXT : OS.CF_TEXT);
+        if (hMem !is null) {
+            /* Ensure byteCount is a multiple of 2 bytes on UNICODE platforms */
+            int byteCount = OS.GlobalSize (hMem) / TCHAR.sizeof * TCHAR.sizeof;
+            auto ptr = OS.GlobalLock (hMem);
+            if (ptr !is null) {
+                /* Use the character encoding for the default locale */
+                string = TCHARzToStr( cast(TCHAR*)ptr );
+                OS.GlobalUnlock (hMem);
+            }
+        }
+        OS.CloseClipboard ();
+    }
+    return string;
+}
+
+/**
+ * Returns the receiver's cursor, or null if it has not been set.
+ * <p>
+ * When the mouse pointer passes over a control its appearance
+ * is changed to match the control's cursor.
+ * </p>
+ *
+ * @return the receiver's cursor or <code>null</code>
+ *
+ * @exception SWTException <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 Cursor getCursor () {
+    checkWidget ();
+    return cursor;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is detecting
+ * drag gestures, and  <code>false</code> otherwise.
+ *
+ * @return the receiver's drag detect state
+ *
+ * @exception SWTException <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 bool getDragDetect () {
+    checkWidget ();
+    return (state & DRAG_DETECT) !is 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #isEnabled
+ */
+public bool getEnabled () {
+    checkWidget ();
+    return cast(bool)OS.IsWindowEnabled (handle);
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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 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);
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException <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 Color getForeground () {
+    checkWidget ();
+    return Color.win32_new (display, getForegroundPixel ());
+}
+
+int getForegroundPixel () {
+    return foreground !is -1 ? foreground : defaultForeground ();
+}
+
+/**
+ * Returns layout data which is associated with the receiver.
+ *
+ * @return the receiver's layout data
+ *
+ * @exception SWTException <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 Object getLayoutData () {
+    checkWidget ();
+    return layoutData;
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @return the receiver's location
+ *
+ * @exception SWTException <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 Point getLocation () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    OS.GetWindowRect (topHandle (), &rect);
+    auto hwndParent = parent is null ? null : parent.handle;
+    OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
+    return new Point (rect.left, rect.top);
+}
+
+/**
+ * Returns the receiver's pop up menu if it has one, or null
+ * if it does not. All controls may optionally have a pop up
+ * menu that is displayed when the user requests one for
+ * the control. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pop up
+ * menu is platform specific.
+ *
+ * @return the receiver's menu
+ *
+ * @exception SWTException <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>
+ */
+override public Menu getMenu () {
+    checkWidget ();
+    return menu;
+}
+
+/**
+ * Returns the receiver's monitor.
+ *
+ * @return the receiver's monitor
+ *
+ * @since 3.0
+ */
+public org.eclipse.swt.widgets.Monitor.Monitor getMonitor () {
+    checkWidget ();
+    if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+        return display.getPrimaryMonitor ();
+    }
+    auto hmonitor = OS.MonitorFromWindow (handle, OS.MONITOR_DEFAULTTONEAREST);
+    MONITORINFO lpmi;
+    lpmi.cbSize = MONITORINFO.sizeof;
+    OS.GetMonitorInfo (hmonitor, &lpmi);
+    org.eclipse.swt.widgets.Monitor.Monitor monitor = new org.eclipse.swt.widgets.Monitor.Monitor ();
+    monitor.handle = hmonitor;
+    monitor.x = lpmi.rcMonitor.left;
+    monitor.y = lpmi.rcMonitor.top;
+    monitor.width = lpmi.rcMonitor.right - lpmi.rcMonitor.left;
+    monitor.height = lpmi.rcMonitor.bottom - lpmi.rcMonitor.top;
+    monitor.clientX = lpmi.rcWork.left;
+    monitor.clientY = lpmi.rcWork.top;
+    monitor.clientWidth = lpmi.rcWork.right - lpmi.rcWork.left;
+    monitor.clientHeight = lpmi.rcWork.bottom - lpmi.rcWork.top;
+    return monitor;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Composite</code>
+ * or null when the receiver is a shell that was created with null or
+ * a display for a parent.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Composite getParent () {
+    checkWidget ();
+    return parent;
+}
+
+Control [] getPath () {
+    int count = 0;
+    Shell shell = getShell ();
+    Control control = this;
+    while (control !is shell) {
+        count++;
+        control = control.parent;
+    }
+    control = this;
+    Control [] result = new Control [count];
+    while (control !is shell) {
+        result [--count] = control;
+        control = control.parent;
+    }
+    return result;
+}
+
+/**
+ * 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 SWTException <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
+ * of other shells.
+ *
+ * @return the receiver's shell
+ *
+ * @exception SWTException <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 #getParent
+ */
+public Shell getShell () {
+    checkWidget ();
+    return parent.getShell ();
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException <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 Point getSize () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    OS.GetWindowRect (topHandle (), &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    return new Point (width, height);
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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 String getToolTipText () {
+    checkWidget ();
+    return toolTipText_;
+}
+
+/**
+ * Returns <code>true</code> if the receiver 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 visibility state
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget ();
+    if (drawCount !is 0) return (state & HIDDEN) is 0;
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return (bits & OS.WS_VISIBLE) !is 0;
+}
+
+bool hasCursor () {
+    RECT rect;
+    if (!OS.GetClientRect (handle, &rect)) return false;
+    OS.MapWindowPoints (handle, null, cast(POINT*)&rect, 2);
+    POINT pt;
+    return OS.GetCursorPos (&pt) && OS.PtInRect (&rect, pt);
+}
+
+bool hasFocus () {
+    /*
+    * If a non-SWT child of the control has focus,
+    * then this control is considered to have focus
+    * even though it does not have focus in Windows.
+    */
+    auto hwndFocus = OS.GetFocus ();
+    while (hwndFocus !is null) {
+        if (hwndFocus is handle) return true;
+        if (display.getControl (hwndFocus) !is null) {
+            return false;
+        }
+        hwndFocus = OS.GetParent (hwndFocus);
+    }
+    return false;
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Control</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public HDC internal_new_GC (GCData data) {
+    checkWidget();
+    auto hwnd = handle;
+    if (data !is null && data.hwnd !is null) hwnd = data.hwnd;
+    if (data !is null) data.hwnd = hwnd;
+    HDC hDC;
+    if (data is null || data.ps is null) {
+        hDC = OS.GetDC (hwnd);
+    } else {
+        hDC = OS.BeginPaint (hwnd, data.ps);
+    }
+    if (hDC is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    if (data !is null) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+            int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+            if ((data.style & mask) !is 0) {
+                data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
+            } else {
+                int flags = OS.GetLayout (hDC);
+                if ((flags & OS.LAYOUT_RTL) !is 0) {
+                    data.style |= SWT.RIGHT_TO_LEFT | SWT.MIRRORED;
+                } else {
+                    data.style |= SWT.LEFT_TO_RIGHT;
+                }
+            }
+        } else {
+            data.style |= SWT.LEFT_TO_RIGHT;
+        }
+        data.device = display;
+        auto foreground = getForegroundPixel ();
+        if (foreground !is OS.GetTextColor (hDC)) data.foreground = foreground;
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        auto background = control.getBackgroundPixel ();
+        if (background !is OS.GetBkColor (hDC)) data.background = background;
+        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;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Control</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (HDC hDC, GCData data) {
+    checkWidget ();
+    auto hwnd = handle;
+    if (data !is null && data.hwnd !is null) {
+        hwnd = data.hwnd;
+    }
+    if (data is null || data.ps is null) {
+        OS.ReleaseDC (hwnd, hDC);
+    } else {
+        OS.EndPaint (hwnd, data.ps);
+    }
+}
+
+bool isActive () {
+    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;
+    if (modalShells !is null) {
+        int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+        int index = modalShells.length;
+        while (--index >= 0) {
+            Shell modal = modalShells [index];
+            if (modal !is null) {
+                if ((modal.style & bits) !is 0) {
+                    Control control = this;
+                    while (control !is null) {
+                        if (control is modal) break;
+                        control = control.parent;
+                    }
+                    if (control !is modal) return false;
+                    break;
+                }
+                if ((modal.style & SWT.PRIMARY_MODAL) !is 0) {
+                    if (shell is null) shell = getShell ();
+                    if (modal.parent is shell) return false;
+                }
+            }
+        }
+    }
+    if (shell is null) shell = getShell ();
+    return shell.getEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are enabled.  Otherwise, <code>false</code> is returned.
+ * A disabled control is typically not selectable from the user
+ * interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #getEnabled
+ */
+public bool isEnabled () {
+    checkWidget ();
+    return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver has the user-interface
+ * focus, and <code>false</code> otherwise.
+ *
+ * @return the receiver's focus state
+ *
+ * @exception SWTException <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 isFocusControl () {
+    checkWidget ();
+    Control focusControl = display.focusControl;
+    if (focusControl !is null && !focusControl.isDisposed ()) {
+        return this is focusControl;
+    }
+    return hasFocus ();
+}
+
+bool isFocusAncestor (Control control) {
+    while (control !is null && control !is this && !(cast(Shell)control )) {
+        control = control.parent;
+    }
+    return control is this;
+}
+
+/**
+ * Returns <code>true</code> if the underlying operating
+ * system supports this reparenting, otherwise <code>false</code>
+ *
+ * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
+ *
+ * @exception SWTException <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 isReparentable () {
+    checkWidget ();
+    return true;
+}
+
+bool isShowing () {
+    /*
+    * This is not complete.  Need to check if the
+    * widget is obscured by a parent or sibling.
+    */
+    if (!isVisible ()) return false;
+    Control control = this;
+    while (control !is null) {
+        Point size = control.getSize ();
+        if (size.x is 0 || size.y is 0) {
+            return false;
+        }
+        control = control.parent;
+    }
+    return true;
+    /*
+    * Check to see if current damage is included.
+    */
+//  if (!OS.IsWindowVisible (handle)) return false;
+//  int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS;
+//  int /*long*/ hDC = OS.GetDCEx (handle, 0, flags);
+//  int result = OS.GetClipBox (hDC, new RECT ());
+//  OS.ReleaseDC (handle, hDC);
+//  return result !is OS.NULLREGION;
+}
+
+bool isTabGroup () {
+    Control [] tabList = parent._getTabList ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] is this) return true;
+        }
+    }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return (bits & OS.WS_TABSTOP) !is 0;
+}
+
+bool isTabItem () {
+    Control [] tabList = parent._getTabList ();
+    if (tabList !is null) {
+        for (int i=0; i<tabList.length; i++) {
+            if (tabList [i] is this) return false;
+        }
+    }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.WS_TABSTOP) !is 0) return false;
+    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;
+    if ((code & OS.DLGC_WANTTAB) !is 0) return false;
+    return true;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * ancestors up to and including the receiver's nearest ancestor
+ * shell are visible. Otherwise, <code>false</code> is returned.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException <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 #getVisible
+ */
+public bool isVisible () {
+    checkWidget ();
+    if (OS.IsWindowVisible (handle)) return true;
+    return getVisible () && parent.isVisible ();
+}
+
+override void mapEvent (HWND hwnd, Event event) {
+    if (hwnd !is handle) {
+        POINT point;
+        point.x = event.x;
+        point.y = event.y;
+        OS.MapWindowPoints (hwnd, handle, &point, 1);
+        event.x = point.x;
+        event.y = point.y;
+    }
+}
+
+void markLayout (bool changed, bool all) {
+    /* Do nothing */
+}
+
+Decorations menuShell () {
+    return parent.menuShell ();
+}
+
+bool mnemonicHit (wchar key) {
+    return false;
+}
+
+bool mnemonicMatch (wchar key) {
+    return false;
+}
+
+/**
+ * Moves the receiver above the specified control in the
+ * drawing order. If the argument is null, then the receiver
+ * is moved to the top of the drawing order. The control at
+ * the top of the drawing order will not be covered by other
+ * controls even if they occupy intersecting areas.
+ *
+ * @param control the sibling control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 Control#moveBelow
+ * @see Composite#getChildren
+ */
+public void moveAbove (Control control) {
+    checkWidget ();
+    auto topHandle_ = topHandle ();
+    HWND hwndAbove = cast(HWND) OS.HWND_TOP;
+    if (control !is null) {
+        if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+        if (parent !is control.parent) return;
+        auto hwnd = control.topHandle ();
+        if (hwnd is null || hwnd is topHandle_) return;
+        hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
+        /*
+        * Bug in Windows.  For some reason, when GetWindow ()
+        * with GW_HWNDPREV is used to query the previous window
+        * in the z-order with the first child, Windows returns
+        * the first child instead of NULL.  The fix is to detect
+        * this case and move the control to the top.
+        */
+        if (hwndAbove is null || hwndAbove is hwnd) {
+            hwndAbove = cast(HWND) OS.HWND_TOP;
+        }
+    }
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+    SetWindowPos (topHandle_, hwndAbove, 0, 0, 0, 0, flags);
+}
+
+/**
+ * Moves the receiver below the specified control in the
+ * drawing order. If the argument is null, then the receiver
+ * is moved to the bottom of the drawing order. The control at
+ * the bottom of the drawing order will be covered by all other
+ * controls which occupy intersecting areas.
+ *
+ * @param control the sibling control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 Control#moveAbove
+ * @see Composite#getChildren
+ */
+public void moveBelow (Control control) {
+    checkWidget ();
+    auto topHandle_ = topHandle ();
+    HWND hwndAbove = cast(HWND)OS.HWND_BOTTOM;
+    if (control !is null) {
+        if (control.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+        if (parent !is control.parent) return;
+        hwndAbove = control.topHandle ();
+    } else {
+        /*
+        * Bug in Windows.  When SetWindowPos() is called
+        * with HWND_BOTTOM on a dialog shell, the dialog
+        * and the parent are moved to the bottom of the
+        * desktop stack.  The fix is to move the dialog
+        * to the bottom of the dialog window stack by
+        * moving behind the first dialog child.
+        */
+        Shell shell = getShell ();
+        if (this is shell && parent !is null) {
+            /*
+            * Bug in Windows.  For some reason, when GetWindow ()
+            * with GW_HWNDPREV is used to query the previous window
+            * in the z-order with the first child, Windows returns
+            * the first child instead of NULL.  The fix is to detect
+            * this case and do nothing because the control is already
+            * at the bottom.
+            */
+            auto hwndParent = parent.handle;
+            auto hwnd = hwndParent;
+            hwndAbove = OS.GetWindow (hwnd, OS.GW_HWNDPREV);
+            while (hwndAbove !is null && hwndAbove !is hwnd) {
+                if (OS.GetWindow (hwndAbove, OS.GW_OWNER) is hwndParent) break;
+                hwndAbove = OS.GetWindow (hwnd = hwndAbove, OS.GW_HWNDPREV);
+            }
+            if (hwndAbove is hwnd) return;
+        }
+    }
+    if (hwndAbove is null || hwndAbove is topHandle_) return;
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+    SetWindowPos (topHandle_, hwndAbove, 0, 0, 0, 0, flags);
+}
+
+Accessible new_Accessible (Control control) {
+    return Accessible.internal_new_Accessible (this);
+}
+
+override GC new_GC (GCData data) {
+    return GC.win32_new (this, data);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @exception SWTException <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 #computeSize(int, int, bool)
+ */
+public void pack () {
+    checkWidget ();
+    pack (true);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ * <p>
+ * If the changed flag is <code>true</code>, it indicates that the receiver's
+ * <em>contents</em> have changed, therefore any caches that a layout manager
+ * containing the control may have been keeping need to be flushed. When the
+ * control is resized, the changed flag will be <code>false</code>, so layout
+ * manager caches can be retained.
+ * </p>
+ *
+ * @param changed whether or not the receiver's contents have changed
+ *
+ * @exception SWTException <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 #computeSize(int, int, bool)
+ */
+public void pack (bool changed) {
+    checkWidget ();
+    setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
+}
+
+/**
+ * Prints the receiver and all children.
+ *
+ * @param gc the gc where the drawing occurs
+ * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
+ *
+ * @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 SWTException <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 (SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (SWT.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);
+        if ((bits & OS.WS_VISIBLE) is 0) {
+            OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
+        }
+        return true;
+    }
+    return false;
+}
+
+void printWidget (HWND hwnd, GC gc) {
+    OS.PrintWindow (hwnd, gc.handle, 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,
+ * including the background.
+ *
+ * @exception SWTException <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 #update()
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#DOUBLE_BUFFERED
+ */
+public void redraw () {
+    checkWidget ();
+    redraw (false);
+}
+
+void redraw (bool all) {
+//  checkWidget ();
+    if (!OS.IsWindowVisible (handle)) return;
+    static if (OS.IsWinCE) {
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+        if (all) flags |= OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+/**
+ * Causes the rectangular area of the receiver specified by
+ * the arguments to be marked as needing to be redrawn.
+ * The next time a paint request is processed, that area of
+ * the receiver will be painted, including the background.
+ * If the <code>all</code> flag is <code>true</code>, any
+ * children of the receiver which intersect with the specified
+ * area will also paint their intersecting areas. If the
+ * <code>all</code> flag is <code>false</code>, the children
+ * will not be painted.
+ *
+ * @param x the x coordinate of the area to draw
+ * @param y the y coordinate of the area to draw
+ * @param width the width of the area to draw
+ * @param height the height of the area to draw
+ * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 #update()
+ * @see PaintListener
+ * @see SWT#Paint
+ * @see SWT#NO_BACKGROUND
+ * @see SWT#NO_REDRAW_RESIZE
+ * @see SWT#NO_MERGE_PAINTS
+ * @see SWT#DOUBLE_BUFFERED
+ */
+public void redraw (int x, int y, int width, int height, bool all) {
+    checkWidget ();
+    if (width <= 0 || height <= 0) return;
+    if (!OS.IsWindowVisible (handle)) return;
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    static if (OS.IsWinCE) {
+        OS.InvalidateRect (handle, &rect, true);
+    } else {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+        if (all) flags |= OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, &rect, null, flags);
+    }
+}
+
+bool redrawChildren () {
+    if (!OS.IsWindowVisible (handle)) return false;
+    Control control = findBackgroundControl ();
+    if (control is null) {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                OS.InvalidateRect (handle, null, true);
+                return true;
+            }
+        }
+    } else {
+        if (control.backgroundImage !is null) {
+            OS.InvalidateRect (handle, null, true);
+            return true;
+        }
+    }
+    return false;
+}
+
+void register () {
+    display.addControl (handle, this);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    handle = null;
+    parent = null;
+}
+
+override void releaseParent () {
+    parent.removeControl (this);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (OS.IsDBLocale) {
+        OS.ImmAssociateContext (handle, null);
+    }
+    if (toolTipText_ !is null) {
+        setToolTipText (getShell (), null);
+    }
+    toolTipText_ = null;
+    if (menu !is null && !menu.isDisposed ()) {
+        menu.dispose ();
+    }
+    backgroundImage = null;
+    menu = null;
+    cursor = null;
+    unsubclass ();
+    deregister ();
+    layoutData = null;
+    if (accessible !is null) {
+        accessible.internal_dispose_Accessible ();
+    }
+    accessible = null;
+    region = null;
+    font = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Move, listener);
+    eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when a drag gesture occurs.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 DragDetectListener
+ * @see #addDragDetectListener
+ *
+ * @since 3.3
+ */
+public void removeDragDetectListener(DragDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.DragDetect, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control gains or loses focus.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 FocusListener
+ * @see #addFocusListener
+ */
+public void removeFocusListener(FocusListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.FocusIn, listener);
+    eventTable.unhook (SWT.FocusOut, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.KeyUp, listener);
+    eventTable.unhook (SWT.KeyDown, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the platform-specific context menu trigger has
+ * occurred.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuDetectListener
+ * @see #addMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void removeMenuDetectListener (MenuDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MenuDetect, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse passes or hovers over controls.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseTrackListener
+ * @see #addMouseTrackListener
+ */
+public void removeMouseTrackListener(MouseTrackListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MouseEnter, listener);
+    eventTable.unhook (SWT.MouseExit, listener);
+    eventTable.unhook (SWT.MouseHover, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when mouse buttons are pressed and released.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseListener
+ * @see #addMouseListener
+ */
+public void removeMouseListener (MouseListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MouseDown, listener);
+    eventTable.unhook (SWT.MouseUp, listener);
+    eventTable.unhook (SWT.MouseDoubleClick, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse moves.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseMoveListener
+ * @see #addMouseMoveListener
+ */
+public void removeMouseMoveListener(MouseMoveListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MouseMove, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the mouse wheel is scrolled.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MouseWheelListener
+ * @see #addMouseWheelListener
+ *
+ * @since 3.3
+ */
+public void removeMouseWheelListener (MouseWheelListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MouseWheel, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver needs to be painted.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 PaintListener
+ * @see #addPaintListener
+ */
+public void removePaintListener(PaintListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook(SWT.Paint, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when traversal events occur.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TraverseListener
+ * @see #addTraverseListener
+ */
+public void removeTraverseListener(TraverseListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Traverse, listener);
+}
+
+void showWidget (bool visible) {
+    auto topHandle_ = topHandle ();
+    OS.ShowWindow (topHandle_, visible ? OS.SW_SHOW : OS.SW_HIDE);
+    if (handle !is topHandle_) OS.ShowWindow (handle, visible ? OS.SW_SHOW : OS.SW_HIDE);
+}
+
+override bool sendFocusEvent (int type) {
+    Shell shell = getShell ();
+
+    /*
+    * Feature in Windows.  During the processing of WM_KILLFOCUS,
+    * when the focus window is queried using GetFocus(), it has
+    * already been assigned to the new window.  The fix is to
+    * remember the control that is losing or gaining focus and
+    * answer it during WM_KILLFOCUS.  If a WM_SETFOCUS occurs
+    * during WM_KILLFOCUS, the focus control needs to be updated
+    * to the current control.  At any other time, the focus
+    * control matches Windows.
+    */
+    Display display = this.display;
+    display.focusEvent = type;
+    display.focusControl = this;
+    sendEvent (type);
+    // widget could be disposed at this point
+    display.focusEvent = SWT.None;
+    display.focusControl = null;
+
+    /*
+    * It is possible that the shell may be
+    * disposed at this point.  If this happens
+    * don't send the activate and deactivate
+    * events.
+    */
+    if (!shell.isDisposed ()) {
+        switch (type) {
+            case SWT.FocusIn:
+                shell.setActiveControl (this);
+                break;
+            case SWT.FocusOut:
+                if (shell !is display.getActiveShell ()) {
+                    shell.setActiveControl (null);
+                }
+                break;
+            default:
+        }
+    }
+    return true;
+}
+
+void sendMove () {
+    sendEvent (SWT.Move);
+}
+
+void sendResize () {
+    sendEvent (SWT.Resize);
+}
+
+void setBackground () {
+    Control control = findBackgroundControl ();
+    if (control is null) control = this;
+    if (control.backgroundImage !is null) {
+        Shell shell = getShell ();
+        shell.releaseBrushes ();
+        setBackgroundImage (control.backgroundImage.handle);
+    } else {
+        setBackgroundPixel (control.background is -1 ? control.defaultBackground() : control.background);
+    }
+}
+
+/**
+ * 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 SWTException <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 setBackground (Color color) {
+    checkWidget ();
+    int pixel = -1;
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        pixel = color.handle;
+    }
+    if (pixel is background) return;
+    background = pixel;
+    updateBackgroundColor ();
+}
+
+/**
+ * Sets the receiver's background image to the image specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.  The background image is tiled to fill
+ * the available space.
+ * <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 image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
+ * </ul>
+ * @exception SWTException <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.2
+ */
+public void setBackgroundImage (Image image) {
+    checkWidget ();
+    if (image !is null) {
+        if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (image.type !is SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (backgroundImage is image) return;
+    backgroundImage = image;
+    Shell shell = getShell ();
+    shell.releaseBrushes ();
+    updateBackgroundImage ();
+}
+
+void setBackgroundImage (HBITMAP hBitmap) {
+    static if (OS.IsWinCE) {
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+void setBackgroundPixel (int pixel) {
+    static if (OS.IsWinCE) {
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the arguments. The <code>x</code> and
+ * <code>y</code> arguments are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the <code>x</code>
+ * and <code>y</code> arguments are relative to the display.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException <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 setBounds (int x, int y, int width, int height) {
+    checkWidget ();
+    int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+    setBounds (x, y, Math.max (0, width), Math.max (0, height), flags);
+}
+
+void setBounds (int x, int y, int width, int height, int flags) {
+    setBounds (x, y, width, height, flags, true);
+}
+
+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 (parent.lpwp !is null) {
+            int index = 0;
+            auto lpwp = parent.lpwp;
+            while (index < lpwp.length) {
+                if (lpwp [index] is null) break;
+                index ++;
+            }
+            if (index is lpwp.length) {
+                WINDOWPOS* [] newLpwp = new WINDOWPOS* [lpwp.length + 4];
+                SimpleType!(WINDOWPOS*).arraycopy (lpwp, 0, newLpwp, 0, lpwp.length);
+                parent.lpwp = lpwp = newLpwp;
+            }
+            WINDOWPOS* wp = new WINDOWPOS;
+            wp._hwnd = topHandle_;
+            wp.x = x;
+            wp.y = y;
+            wp.cx = width;
+            wp.cy = height;
+            wp.flags = flags;
+            lpwp [index] = wp;
+            return;
+        }
+    }
+    SetWindowPos (topHandle_, null, x, y, width, height, flags);
+}
+
+/**
+ * Sets the receiver's size and location to the rectangular
+ * area specified by the argument. The <code>x</code> and
+ * <code>y</code> fields of the rectangle are relative to
+ * the receiver's parent (or its display if its parent is null).
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param rect the new bounds for the receiver
+ *
+ * @exception SWTException <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 setBounds (Rectangle rect) {
+    checkWidget ();
+    if (rect is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setBounds (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * 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.  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
+ *
+ * @exception SWTException <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 setCapture (bool capture) {
+    checkWidget ();
+    if (capture) {
+        OS.SetCapture (handle);
+    } else {
+        if (OS.GetCapture () is handle) {
+            OS.ReleaseCapture ();
+        }
+    }
+}
+
+void setCursor () {
+    int /*long*/ lParam = OS.MAKELPARAM (OS.HTCLIENT, OS.WM_MOUSEMOVE);
+    OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam);
+}
+
+/**
+ * Sets the receiver's cursor to the cursor specified by the
+ * argument, or to the default cursor for that kind of control
+ * if the argument is null.
+ * <p>
+ * When the mouse pointer passes over a control its appearance
+ * is changed to match the control's cursor.
+ * </p>
+ *
+ * @param cursor the new cursor (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setCursor (Cursor cursor) {
+    checkWidget ();
+    if (cursor !is null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    this.cursor = cursor;
+    static if (OS.IsWinCE) {
+        int /*long*/ hCursor = cursor !is null ? cursor.handle : 0;
+        OS.SetCursor (hCursor);
+        return;
+    }
+    auto hwndCursor = OS.GetCapture ();
+    if (hwndCursor is null) {
+        POINT pt;
+        if (!OS.GetCursorPos (&pt)) return;
+        auto hwnd = hwndCursor = OS.WindowFromPoint (pt);
+        while (hwnd !is null && hwnd !is handle) {
+            hwnd = OS.GetParent (hwnd);
+        }
+        if (hwnd is null) return;
+    }
+    Control control = display.getControl (hwndCursor);
+    if (control is null) control = this;
+    control.setCursor ();
+}
+
+void setDefaultFont () {
+    auto hFont = display.getSystemFont ().handle;
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+}
+
+/**
+ * Sets the receiver's drag detect state. If the argument is
+ * <code>true</code>, the receiver will detect drag gestures,
+ * otherwise these gestures will be ignored.
+ *
+ * @param dragDetect the new drag detect state
+ *
+ * @exception SWTException <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 setDragDetect (bool dragDetect) {
+    checkWidget ();
+    if (dragDetect) {
+        state |= DRAG_DETECT;
+    } else {
+        state &= ~DRAG_DETECT;
+    }
+    enableDrag (dragDetect);
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <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 setEnabled (bool enabled) {
+    checkWidget ();
+    /*
+    * Feature in Windows.  If the receiver has focus, disabling
+    * the receiver causes no window to have focus.  The fix is
+    * to assign focus to the first ancestor window that takes
+    * focus.  If no window will take focus, set focus to the
+    * desktop.
+    */
+    Control control = null;
+    bool fixFocus_ = false;
+    if (!enabled) {
+        if (display.focusEvent !is SWT.FocusOut) {
+            control = display.getFocusControl ();
+            fixFocus_ = isFocusAncestor (control);
+        }
+    }
+    enableWidget (enabled);
+    if (fixFocus_) fixFocus (control);
+}
+
+bool setFixedFocus () {
+    if ((style & SWT.NO_FOCUS) !is 0) return false;
+    return forceFocus ();
+}
+
+/**
+ * Causes the receiver to have the <em>keyboard focus</em>,
+ * such that all keyboard events will be delivered to it.  Focus
+ * reassignment will respect applicable platform constraints.
+ *
+ * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
+ *
+ * @exception SWTException <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 #forceFocus
+ */
+public bool setFocus () {
+    checkWidget ();
+    if ((style & SWT.NO_FOCUS) !is 0) return false;
+    return forceFocus ();
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * to the font specified by the argument, or to the default font for that
+ * kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setFont (Font font) {
+    checkWidget ();
+    HFONT hFont;
+    if (font !is null) {
+        if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        hFont = font.handle;
+    }
+    this.font = font;
+    if (hFont is null) hFont = defaultFont ();
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 1);
+}
+
+/**
+ * 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 SWTException <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 setForeground (Color color) {
+    checkWidget ();
+    int pixel = -1;
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        pixel = color.handle;
+    }
+    if (pixel is foreground) return;
+    foreground = pixel;
+    setForegroundPixel (pixel);
+}
+
+void setForegroundPixel (int pixel) {
+    OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * Sets the layout data associated with the receiver to the argument.
+ *
+ * @param layoutData the new layout data for the receiver.
+ *
+ * @exception SWTException <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 setLayoutData (Object layoutData) {
+    checkWidget ();
+    this.layoutData = layoutData;
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException <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 setLocation (int x, int y) {
+    checkWidget ();
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+    /*
+    * Feature in WinCE.  The SWP_DRAWFRAME flag for SetWindowPos()
+    * causes a WM_SIZE message to be sent even when the SWP_NOSIZE
+    * flag is specified.  The fix is to set SWP_DRAWFRAME only when
+    * not running on WinCE.
+    */
+    static if (!OS.IsWinCE) flags |= OS.SWP_DRAWFRAME;
+    setBounds (x, y, 0, 0, flags);
+}
+
+/**
+ * Sets the receiver's location to the point specified by
+ * the arguments which are relative to the receiver's
+ * parent (or its display if its parent is null), unless
+ * the receiver is a shell. In this case, the point is
+ * relative to the display.
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception SWTException <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 setLocation (Point location) {
+    checkWidget ();
+    if (location is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's pop up menu to the argument.
+ * All controls may optionally have a pop up
+ * menu that is displayed when the user requests one for
+ * the control. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pop up
+ * menu is platform specific.
+ * <p>
+ * Note: Disposing of a control that has a pop up menu will
+ * dispose of the menu.  To avoid this behavior, set the
+ * menu to null before the control is disposed.
+ * </p>
+ *
+ * @param menu the new pop up menu
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
+ *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setMenu (Menu menu) {
+    checkWidget ();
+    if (menu !is null) {
+        if (menu.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        if ((menu.style & SWT.POP_UP) is 0) {
+            error (SWT.ERROR_MENU_NOT_POP_UP);
+        }
+        if (menu.parent !is menuShell ()) {
+            error (SWT.ERROR_INVALID_PARENT);
+        }
+    }
+    this.menu = menu;
+}
+
+bool setRadioFocus () {
+    return false;
+}
+
+bool setRadioSelection (bool value) {
+    return false;
+}
+
+/**
+ * If the argument is <code>false</code>, causes subsequent drawing
+ * operations in the receiver to be ignored. No drawing of any kind
+ * can occur in the receiver until the flag is set to true.
+ * Graphics operations that occurred while the flag was
+ * <code>false</code> are lost. When the flag is set to <code>true</code>,
+ * the entire widget is marked as needing to be redrawn.  Nested calls
+ * to this method are stacked.
+ * <p>
+ * Note: This operation is a hint and may not be supported on some
+ * platforms or for some widgets.
+ * </p>
+ *
+ * @param redraw the new redraw state
+ *
+ * @exception SWTException <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 #redraw(int, int, int, int, bool)
+ * @see #update()
+ */
+public void setRedraw (bool redraw) {
+    checkWidget ();
+    /*
+     * Feature in Windows.  When WM_SETREDRAW is used to turn
+     * off drawing in a widget, it clears the WS_VISIBLE bits
+     * and then sets them when redraw is turned back on.  This
+     * means that WM_SETREDRAW will make a widget unexpectedly
+     * visible.  The fix is to track the visibility state while
+     * drawing is turned off and restore it when drawing is
+     * turned back on.
+     */
+    if (drawCount is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.WS_VISIBLE) is 0) state |= HIDDEN;
+    }
+    if (redraw) {
+        if (--drawCount is 0) {
+            auto topHandle_ = topHandle ();
+            OS.SendMessage (topHandle_, OS.WM_SETREDRAW, 1, 0);
+            if (handle !is topHandle_) OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            if ((state & HIDDEN) !is 0) {
+                state &= ~HIDDEN;
+                OS.ShowWindow (topHandle_, OS.SW_HIDE);
+                if (handle !is topHandle_) OS.ShowWindow (handle, OS.SW_HIDE);
+            } else {
+                static if (OS.IsWinCE) {
+                    OS.InvalidateRect (topHandle_, null, true);
+                    if (handle !is topHandle_) OS.InvalidateRect (handle, null, true);
+                } else {
+                    int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                    OS.RedrawWindow (topHandle_, null, null, flags);
+                }
+            }
+        }
+    } else {
+        if (drawCount++ is 0) {
+            auto topHandle_ = topHandle ();
+            OS.SendMessage (topHandle_, OS.WM_SETREDRAW, 0, 0);
+            if (handle !is topHandle_) OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+    }
+}
+
+/**
+ * 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 SWTException <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 (SWT.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 ();
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException <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 setSize (int width, int height) {
+    checkWidget ();
+    int flags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+    setBounds (0, 0, Math.max (0, width), Math.max (0, height), flags);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ * </p>
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSize (Point size) {
+    checkWidget ();
+    if (size is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSize (size.x, size.y);
+}
+
+bool setTabGroupFocus () {
+    return setTabItemFocus ();
+}
+
+bool setTabItemFocus () {
+    if (!isShowing ()) return false;
+    return forceFocus ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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 setToolTipText (String string) {
+    checkWidget ();
+    toolTipText_ = string;
+    setToolTipText (getShell (), string);
+}
+
+void setToolTipText (Shell shell, String string) {
+    shell.setToolTipText (handle, string);
+}
+
+/**
+ * Marks the receiver 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 SWTException <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 setVisible (bool visible) {
+    checkWidget ();
+    if (drawCount !is 0) {
+        if (((state & HIDDEN) is 0) is visible) return;
+    } else {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if (((bits & OS.WS_VISIBLE) !is 0) is visible) return;
+    }
+    if (visible) {
+        sendEvent (SWT.Show);
+        if (isDisposed ()) return;
+    }
+
+    /*
+    * Feature in Windows.  If the receiver has focus, hiding
+    * the receiver causes no window to have focus.  The fix is
+    * to assign focus to the first ancestor window that takes
+    * focus.  If no window will take focus, set focus to the
+    * desktop.
+    */
+    Control control = null;
+    bool fixFocus_ = false;
+    if (!visible) {
+        if (display.focusEvent !is SWT.FocusOut) {
+            control = display.getFocusControl ();
+            fixFocus_ = isFocusAncestor (control);
+        }
+    }
+    if (drawCount !is 0) {
+        state = visible ? state & ~HIDDEN : state | HIDDEN;
+    } else {
+        showWidget (visible);
+        if (isDisposed ()) return;
+    }
+    if (!visible) {
+        sendEvent (SWT.Hide);
+        if (isDisposed ()) return;
+    }
+    if (fixFocus_) fixFocus (control);
+}
+
+void sort (int [] items) {
+    /* Shell Sort from K&R, pg 108 */
+    int length = items.length;
+    for (int gap=length/2; gap>0; gap/=2) {
+        for (int i=gap; i<length; i++) {
+            for (int j=i-gap; j>=0; j-=gap) {
+                if (items [j] <= items [j + gap]) {
+                    int swap = items [j];
+                    items [j] = items [j + gap];
+                    items [j + gap] = swap;
+                }
+            }
+        }
+    }
+}
+
+void subclass () {
+    int /*long*/ oldProc = windowProc ();
+    int newProc = display.windowProc();
+    if (oldProc is newProc) return;
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in display relative coordinates,
+ * to coordinates relative to the receiver.
+ * <p>
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @exception SWTException <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 2.1
+ */
+public Point toControl (int x, int y) {
+    checkWidget ();
+    POINT pt;
+    pt.x = x;  pt.y = y;
+    OS.ScreenToClient (handle, &pt);
+    return new Point (pt.x, pt.y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in display relative coordinates,
+ * to coordinates relative to the receiver.
+ * <p>
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 Point toControl (Point point) {
+    checkWidget ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return toControl (point.x, point.y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in coordinates relative to
+ * the receiver, to display relative coordinates.
+ * <p>
+ * @param x the x coordinate to be translated
+ * @param y the y coordinate to be translated
+ * @return the translated coordinates
+ *
+ * @exception SWTException <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 2.1
+ */
+public Point toDisplay (int x, int y) {
+    checkWidget ();
+    POINT pt;
+    pt.x = x;  pt.y = y;
+    OS.ClientToScreen (handle, &pt);
+    return new Point (pt.x, pt.y);
+}
+
+/**
+ * Returns a point which is the result of converting the
+ * argument, which is specified in coordinates relative to
+ * the receiver, to display relative coordinates.
+ * <p>
+ * @param point the point to be translated (must not be null)
+ * @return the translated coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 Point toDisplay (Point point) {
+    checkWidget ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return toDisplay (point.x, point.y);
+}
+
+HANDLE topHandle () {
+    return handle;
+}
+
+bool translateAccelerator (MSG* msg) {
+    return menuShell ().translateAccelerator (msg);
+}
+
+bool translateMnemonic (Event event, Control control) {
+    if (control is this) return false;
+    if (!isVisible () || !isEnabled ()) return false;
+    event.doit = mnemonicMatch (event.character);
+    return traverse (event);
+}
+
+bool translateMnemonic (MSG* msg) {
+    if (msg.wParam < 0x20) return false;
+    auto hwnd = msg.hwnd;
+    if (OS.GetKeyState (OS.VK_MENU) >= 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;
+    }
+    Decorations shell = menuShell ();
+    if (shell.isVisible () && shell.isEnabled ()) {
+        display.lastAscii = msg.wParam;
+        display.lastNull = display.lastDead = false;
+        Event event = new Event ();
+        event.detail = SWT.TRAVERSE_MNEMONIC;
+        if (setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) {
+            return translateMnemonic (event, null) || shell.translateMnemonic (event, this);
+        }
+    }
+    return false;
+}
+
+bool translateTraversal (MSG* msg) {
+    auto hwnd = msg.hwnd;
+    int key = msg.wParam;
+    if (key is OS.VK_MENU) {
+        OS.SendMessage (hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+        return false;
+    }
+    int detail = SWT.TRAVERSE_NONE;
+    bool doit = true, all = false;
+    bool lastVirtual = false;
+    int lastKey = key, lastAscii = 0;
+    switch (key) {
+        case OS.VK_ESCAPE: {
+            all = true;
+            lastAscii = 27;
+            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 text widget.  A text widget normally wants
+                * all keys except VK_ESCAPE.  If this bit is not
+                * set, then assume the control wants all keys,
+                * including VK_ESCAPE.
+                */
+                if ((code & OS.DLGC_HASSETSEL) is 0) doit = false;
+            }
+            detail = SWT.TRAVERSE_ESCAPE;
+            break;
+        }
+        case OS.VK_RETURN: {
+            all = true;
+            lastAscii = '\r';
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            if ((code & OS.DLGC_WANTALLKEYS) !is 0) doit = false;
+            detail = SWT.TRAVERSE_RETURN;
+            break;
+        }
+        case OS.VK_TAB: {
+            lastAscii = '\t';
+            bool next = OS.GetKeyState (OS.VK_SHIFT) >= 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
+                * text widget.  If the control is a text widget, then
+                * Ctrl+Tab and Shift+Tab should traverse out of the widget.
+                * If the control is not a text widget, the correct behavior
+                * is to give every character, including Tab, Ctrl+Tab and
+                * Shift+Tab to the control.
+                */
+                if ((code & OS.DLGC_HASSETSEL) !is 0) {
+                    if (next && OS.GetKeyState (OS.VK_CONTROL) >= 0) {
+                        doit = false;
+                    }
+                } else {
+                    doit = false;
+                }
+            }
+            detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
+            break;
+        }
+        case OS.VK_UP:
+        case OS.VK_LEFT:
+        case OS.VK_DOWN:
+        case OS.VK_RIGHT: {
+            /*
+            * On WinCE SP there is no tab key.  Focus is assigned
+            * using the VK_UP and VK_DOWN keys, not with VK_LEFT
+            * or VK_RIGHT.
+            */
+            if (OS.IsSP) {
+                if (key is OS.VK_LEFT || key is OS.VK_RIGHT) return false;
+            }
+            lastVirtual = true;
+            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 & SWT.MIRRORED) !is 0) {
+                if (key is OS.VK_LEFT || key is OS.VK_RIGHT) next = !next;
+            }
+            detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
+            break;
+        }
+        case OS.VK_PRIOR:
+        case OS.VK_NEXT: {
+            all = true;
+            lastVirtual = true;
+            if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
+            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
+                * text widget.  If the control is a text widget, then
+                * Ctrl+PgUp and Ctrl+PgDn should traverse out of the widget.
+                */
+                if ((code & OS.DLGC_HASSETSEL) is 0) doit = false;
+            }
+            detail = key is OS.VK_PRIOR ? SWT.TRAVERSE_PAGE_PREVIOUS : SWT.TRAVERSE_PAGE_NEXT;
+            break;
+        }
+        default:
+            return false;
+    }
+    Event event = new Event ();
+    event.doit = doit;
+    event.detail = detail;
+    display.lastKey = lastKey;
+    display.lastAscii = lastAscii;
+    display.lastVirtual = lastVirtual;
+    display.lastNull = display.lastDead = false;
+    if (!setKeyState (event, SWT.Traverse, msg.wParam, msg.lParam)) return false;
+    Shell shell = getShell ();
+    Control control = this;
+    do {
+        if (control.traverse (event)) {
+            OS.SendMessage (hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            return true;
+        }
+        if (!event.doit && control.hooks (SWT.Traverse)) return false;
+        if (control is shell) return false;
+        control = control.parent;
+    } while (all && control !is null);
+    return false;
+}
+
+bool traverse (Event event) {
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the traverse
+    * event.  If this happens, return true to stop further
+    * event processing.
+    */
+    sendEvent (SWT.Traverse, event);
+    if (isDisposed ()) return true;
+    if (!event.doit) return false;
+    switch (event.detail) {
+        case SWT.TRAVERSE_NONE:         return true;
+        case SWT.TRAVERSE_ESCAPE:           return traverseEscape ();
+        case SWT.TRAVERSE_RETURN:           return traverseReturn ();
+        case SWT.TRAVERSE_TAB_NEXT:     return traverseGroup (true);
+        case SWT.TRAVERSE_TAB_PREVIOUS: return traverseGroup (false);
+        case SWT.TRAVERSE_ARROW_NEXT:       return traverseItem (true);
+        case SWT.TRAVERSE_ARROW_PREVIOUS:   return traverseItem (false);
+        case SWT.TRAVERSE_MNEMONIC:     return traverseMnemonic (event.character);
+        case SWT.TRAVERSE_PAGE_NEXT:        return traversePage (true);
+        case SWT.TRAVERSE_PAGE_PREVIOUS:    return traversePage (false);
+        default:
+    }
+    return false;
+}
+
+/**
+ * Based on the argument, perform one of the expected platform
+ * traversal action. The argument should be one of the constants:
+ * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
+ * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
+ * <code>SWT.TRAVERSE_ARROW_NEXT</code> and <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>.
+ *
+ * @param traversal the type of traversal
+ * @return true if the traversal succeeded
+ *
+ * @exception SWTException <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 traverse (int traversal) {
+    checkWidget ();
+    Event event = new Event ();
+    event.doit = true;
+    event.detail = traversal;
+    return traverse (event);
+}
+
+bool traverseEscape () {
+    return false;
+}
+
+bool traverseGroup (bool next) {
+    Control root = computeTabRoot ();
+    Control group = computeTabGroup ();
+    Control [] list = root.computeTabList ();
+    int length = list.length;
+    int index = 0;
+    while (index < length) {
+        if (list [index] is group) break;
+        index++;
+    }
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in focus in
+    * or out events.  Ensure that a disposed widget is
+    * not accessed.
+    */
+    if (index is length) return false;
+    int start = index, offset = (next) ? 1 : -1;
+    while ((index = ((index + offset + length) % length)) !is start) {
+        Control control = list [index];
+        if (!control.isDisposed () && control.setTabGroupFocus ()) {
+            return true;
+        }
+    }
+    if (group.isDisposed ()) return false;
+    return group.setTabGroupFocus ();
+}
+
+bool traverseItem (bool next) {
+    Control [] children = parent._getChildren ();
+    int length = children.length;
+    int index = 0;
+    while (index < length) {
+        if (children [index] is this) break;
+        index++;
+    }
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in focus in
+    * or out events.  Ensure that a disposed widget is
+    * not accessed.
+    */
+    if (index is length) return false;
+    int start = index, offset = (next) ? 1 : -1;
+    while ((index = (index + offset + length) % length) !is start) {
+        Control child = children [index];
+        if (!child.isDisposed () && child.isTabItem ()) {
+            if (child.setTabItemFocus ()) return true;
+        }
+    }
+    return false;
+}
+
+bool traverseMnemonic (char key) {
+    if (mnemonicHit (key)) {
+        OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+        return true;
+    }
+    return false;
+}
+
+bool traversePage (bool next) {
+    return false;
+}
+
+bool traverseReturn () {
+    return false;
+}
+
+void unsubclass () {
+    int /*long*/ newProc = windowProc ();
+    int /*long*/ oldProc = display.windowProc;
+    if (oldProc is newProc) return;
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
+}
+
+/**
+ * Forces all outstanding paint requests for the widget
+ * to be processed before this method returns. If there
+ * are no outstanding paint request, this method does
+ * nothing.
+ * <p>
+ * Note: This method does not cause a redraw.
+ * </p>
+ *
+ * @exception SWTException <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 #redraw()
+ * @see #redraw(int, int, int, int, bool)
+ * @see PaintListener
+ * @see SWT#Paint
+ */
+public void update () {
+    checkWidget ();
+    update (false);
+}
+
+void update (bool all) {
+//  checkWidget ();
+    static if (OS.IsWinCE) {
+        OS.UpdateWindow (handle);
+    } else {
+        int flags = OS.RDW_UPDATENOW;
+        if (all) flags |= OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+void updateBackgroundColor () {
+    Control control = findBackgroundControl ();
+    if (control is null) control = this;
+    setBackgroundPixel (control.background);
+}
+
+void updateBackgroundImage () {
+    Control control = findBackgroundControl ();
+    Image image = control !is null ? control.backgroundImage : backgroundImage;
+    setBackgroundImage (image !is null ? image.handle : null);
+}
+
+void updateBackgroundMode () {
+    int oldState = state & PARENT_BACKGROUND;
+    checkBackground ();
+    if (oldState !is (state & PARENT_BACKGROUND)) {
+        setBackground ();
+    }
+}
+
+void updateFont (Font oldFont, Font newFont) {
+    if (getFont () ==/*eq*/oldFont ) setFont (newFont);
+}
+
+void updateImages () {
+    /* Do nothing */
+}
+
+void updateLayout (bool resize, bool all) {
+    /* Do nothing */
+}
+
+CREATESTRUCT* widgetCreateStruct () {
+    return null;
+}
+
+int widgetExtStyle () {
+    int bits = 0;
+    if (!OS.IsPPC) {
+        if ((style & SWT.BORDER) !is 0) bits |= OS.WS_EX_CLIENTEDGE;
+    }
+//  if ((style & SWT.BORDER) !is 0) {
+//      if ((style & SWT.FLAT) is 0) bits |= OS.WS_EX_CLIENTEDGE;
+//  }
+    /*
+    * Feature in Windows NT.  When CreateWindowEx() is called with
+    * WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT, CreateWindowEx()
+    * fails to create the HWND. The fix is to not use these bits.
+    */
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+        return bits;
+    }
+    bits |= OS.WS_EX_NOINHERITLAYOUT;
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    return bits;
+}
+
+HWND widgetParent () {
+    return parent.handle;
+}
+
+int widgetStyle () {
+    /* Force clipping of siblings by setting WS_CLIPSIBLINGS */
+    int bits = OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS;
+//  if ((style & SWT.BORDER) !is 0) {
+//      if ((style & SWT.FLAT) !is 0) bits |= OS.WS_BORDER;
+//  }
+    if (OS.IsPPC) {
+        if ((style & SWT.BORDER) !is 0) bits |= OS.WS_BORDER;
+    }
+    return bits;
+
+    /*
+    * This code is intentionally commented.  When clipping
+    * of both siblings and children is not enforced, it is
+    * possible for application code to draw outside of the
+    * control.
+    */
+//  int bits = OS.WS_CHILD | OS.WS_VISIBLE;
+//  if ((style & SWT.CLIP_SIBLINGS) !is 0) bits |= OS.WS_CLIPSIBLINGS;
+//  if ((style & SWT.CLIP_CHILDREN) !is 0) bits |= OS.WS_CLIPCHILDREN;
+//  return bits;
+}
+
+/**
+ * Changes the parent of the widget to be the one provided if
+ * the underlying operating system supports this feature.
+ * Returns <code>true</code> if the parent is successfully changed.
+ *
+ * @param parent the new parent for the control.
+ * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li>
+ * </ul>
+ * @exception SWTException <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 setParent (Composite parent) {
+    checkWidget ();
+    if (parent is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (parent.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+    if (this.parent is parent) return true;
+    if (!isReparentable ()) return false;
+    releaseParent ();
+    Shell newShell = parent.getShell (), oldShell = getShell ();
+    Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
+    if (oldShell !is newShell || oldDecorations !is newDecorations) {
+        Menu [] menus = oldShell.findMenus (this);
+        fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+    }
+    auto topHandle_ = topHandle ();
+    if (OS.SetParent (topHandle_, parent.handle) is null) return false;
+    this.parent = parent;
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+    SetWindowPos (topHandle_, cast(HWND)OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
+    return true;
+}
+
+abstract String windowClass ();
+
+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;
+        case OS.WM_COMMAND:             result = WM_COMMAND (wParam, lParam); break;
+        case OS.WM_CONTEXTMENU:         result = WM_CONTEXTMENU (wParam, lParam); break;
+        case OS.WM_CTLCOLORBTN:
+        case OS.WM_CTLCOLORDLG:
+        case OS.WM_CTLCOLOREDIT:
+        case OS.WM_CTLCOLORLISTBOX:
+        case OS.WM_CTLCOLORMSGBOX:
+        case OS.WM_CTLCOLORSCROLLBAR:
+        case OS.WM_CTLCOLORSTATIC:      result = WM_CTLCOLOR (wParam, lParam); break;
+        case OS.WM_CUT:                 result = WM_CUT (wParam, lParam); break;
+        case OS.WM_DESTROY:             result = WM_DESTROY (wParam, lParam); break;
+        case OS.WM_DRAWITEM:            result = WM_DRAWITEM (wParam, lParam); break;
+        case OS.WM_ENDSESSION:          result = WM_ENDSESSION (wParam, lParam); break;
+        case OS.WM_ENTERIDLE:           result = WM_ENTERIDLE (wParam, lParam); break;
+        case OS.WM_ERASEBKGND:          result = WM_ERASEBKGND (wParam, lParam); break;
+        case OS.WM_GETDLGCODE:          result = WM_GETDLGCODE (wParam, lParam); break;
+        case OS.WM_GETFONT:             result = WM_GETFONT (wParam, lParam); break;
+        case OS.WM_GETOBJECT:           result = WM_GETOBJECT (wParam, lParam); break;
+        case OS.WM_GETMINMAXINFO:       result = WM_GETMINMAXINFO (wParam, lParam); break;
+        case OS.WM_HELP:                result = WM_HELP (wParam, lParam); break;
+        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;
+        case OS.WM_KEYDOWN:             result = WM_KEYDOWN (wParam, lParam); break;
+        case OS.WM_KEYUP:               result = WM_KEYUP (wParam, lParam); break;
+        case OS.WM_KILLFOCUS:           result = WM_KILLFOCUS (wParam, lParam); break;
+        case OS.WM_LBUTTONDBLCLK:       result = WM_LBUTTONDBLCLK (wParam, lParam); break;
+        case OS.WM_LBUTTONDOWN:         result = WM_LBUTTONDOWN (wParam, lParam); break;
+        case OS.WM_LBUTTONUP:           result = WM_LBUTTONUP (wParam, lParam); break;
+        case OS.WM_MBUTTONDBLCLK:       result = WM_MBUTTONDBLCLK (wParam, lParam); break;
+        case OS.WM_MBUTTONDOWN:         result = WM_MBUTTONDOWN (wParam, lParam); break;
+        case OS.WM_MBUTTONUP:           result = WM_MBUTTONUP (wParam, lParam); break;
+        case OS.WM_MEASUREITEM:         result = WM_MEASUREITEM (wParam, lParam); break;
+        case OS.WM_MENUCHAR:            result = WM_MENUCHAR (wParam, lParam); break;
+        case OS.WM_MENUSELECT:          result = WM_MENUSELECT (wParam, lParam); break;
+        case OS.WM_MOUSEACTIVATE:       result = WM_MOUSEACTIVATE (wParam, lParam); break;
+        case OS.WM_MOUSEHOVER:          result = WM_MOUSEHOVER (wParam, lParam); break;
+        case OS.WM_MOUSELEAVE:          result = WM_MOUSELEAVE (wParam, lParam); break;
+        case OS.WM_MOUSEMOVE:           result = WM_MOUSEMOVE (wParam, lParam); break;
+        case OS.WM_MOUSEWHEEL:          result = WM_MOUSEWHEEL (wParam, lParam); break;
+        case OS.WM_MOVE:                result = WM_MOVE (wParam, lParam); break;
+        case OS.WM_NCACTIVATE:          result = WM_NCACTIVATE (wParam, lParam); break;
+        case OS.WM_NCCALCSIZE:          result = WM_NCCALCSIZE (wParam, lParam); break;
+        case OS.WM_NCHITTEST:           result = WM_NCHITTEST (wParam, lParam); break;
+        case OS.WM_NCLBUTTONDOWN:       result = WM_NCLBUTTONDOWN (wParam, lParam); break;
+        case OS.WM_NCPAINT:             result = WM_NCPAINT (wParam, lParam); break;
+        case OS.WM_NOTIFY:              result = WM_NOTIFY (wParam, lParam); break;
+        case OS.WM_PAINT:               result = WM_PAINT (wParam, lParam); break;
+        case OS.WM_PALETTECHANGED:      result = WM_PALETTECHANGED (wParam, lParam); break;
+        case OS.WM_PARENTNOTIFY:        result = WM_PARENTNOTIFY (wParam, lParam); break;
+        case OS.WM_PASTE:               result = WM_PASTE (wParam, lParam); break;
+        case OS.WM_PRINT:               result = WM_PRINT (wParam, lParam); break;
+        case OS.WM_PRINTCLIENT:         result = WM_PRINTCLIENT (wParam, lParam); break;
+        case OS.WM_QUERYENDSESSION:     result = WM_QUERYENDSESSION (wParam, lParam); break;
+        case OS.WM_QUERYNEWPALETTE:     result = WM_QUERYNEWPALETTE (wParam, lParam); break;
+        case OS.WM_QUERYOPEN:           result = WM_QUERYOPEN (wParam, lParam); break;
+        case OS.WM_RBUTTONDBLCLK:       result = WM_RBUTTONDBLCLK (wParam, lParam); break;
+        case OS.WM_RBUTTONDOWN:         result = WM_RBUTTONDOWN (wParam, lParam); break;
+        case OS.WM_RBUTTONUP:           result = WM_RBUTTONUP (wParam, lParam); break;
+        case OS.WM_SETCURSOR:           result = WM_SETCURSOR (wParam, lParam); break;
+        case OS.WM_SETFOCUS:            result = WM_SETFOCUS (wParam, lParam); break;
+        case OS.WM_SETFONT:             result = WM_SETFONT (wParam, lParam); break;
+        case OS.WM_SETTINGCHANGE:       result = WM_SETTINGCHANGE (wParam, lParam); break;
+        case OS.WM_SETREDRAW:           result = WM_SETREDRAW (wParam, lParam); break;
+        case OS.WM_SHOWWINDOW:          result = WM_SHOWWINDOW (wParam, lParam); break;
+        case OS.WM_SIZE:                result = WM_SIZE (wParam, lParam); break;
+        case OS.WM_SYSCHAR:             result = WM_SYSCHAR (wParam, lParam); break;
+        case OS.WM_SYSCOLORCHANGE:      result = WM_SYSCOLORCHANGE (wParam, lParam); break;
+        case OS.WM_SYSCOMMAND:          result = WM_SYSCOMMAND (wParam, lParam); break;
+        case OS.WM_SYSKEYDOWN:          result = WM_SYSKEYDOWN (wParam, lParam); break;
+        case OS.WM_SYSKEYUP:            result = WM_SYSKEYUP (wParam, lParam); break;
+        case OS.WM_TIMER:               result = WM_TIMER (wParam, lParam); break;
+        case OS.WM_UNDO:                result = WM_UNDO (wParam, lParam); break;
+        case OS.WM_UPDATEUISTATE:       result = WM_UPDATEUISTATE (wParam, lParam); break;
+        case OS.WM_VSCROLL:             result = WM_VSCROLL (wParam, lParam); break;
+        case OS.WM_WINDOWPOSCHANGED:    result = WM_WINDOWPOSCHANGED (wParam, lParam); break;
+        case OS.WM_WINDOWPOSCHANGING:   result = WM_WINDOWPOSCHANGING (wParam, lParam); break;
+        case OS.WM_XBUTTONDBLCLK:       result = WM_XBUTTONDBLCLK (wParam, lParam); break;
+        case OS.WM_XBUTTONDOWN:         result = WM_XBUTTONDOWN (wParam, lParam); break;
+        case OS.WM_XBUTTONUP:           result = WM_XBUTTONUP (wParam, lParam); break;
+        default:
+    }
+    if (result !is null) return result.value;
+    return callWindowProc (hwnd, msg, wParam, lParam);
+}
+
+LRESULT WM_ACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_CAPTURECHANGED (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmCaptureChanged (handle, wParam, 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 /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_CLOSE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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.
+    */
+    if (lParam is 0) {
+        Decorations shell = menuShell ();
+        if (shell.isEnabled ()) {
+            int id = OS.LOWORD (wParam);
+            MenuItem item = display.getMenuItem (id);
+            if (item !is null && item.isEnabled ()) {
+                return item.wmCommandChild (wParam, lParam);
+            }
+        }
+        return null;
+    }
+    Control control = display.getControl (cast(HANDLE)lParam);
+    if (control is null) return null;
+    return control.wmCommandChild (wParam, lParam);
+}
+
+LRESULT WM_CONTEXTMENU (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmContextMenu (handle, wParam, 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);
+        OS.RealizePalette (cast(HPALETTE)wParam);
+    }
+    Control control = display.getControl (cast(HANDLE)lParam);
+    if (control is null) return null;
+    return control.wmColorChild (wParam, lParam);
+}
+
+LRESULT WM_CUT (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_DESTROY (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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);
+        if (item is null) return null;
+        return item.wmDrawChild (wParam, lParam);
+    }
+    Control control = display.getControl (struct_.hwndItem);
+    if (control is null) return null;
+    return control.wmDrawChild (wParam, lParam);
+}
+
+LRESULT WM_ENDSESSION (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_ENTERIDLE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_ERASEBKGND (int /*long*/ wParam, int /*long*/ lParam) {
+    if ((state & DRAW_BACKGROUND) !is 0) {
+        if (findImageControl () !is null) return LRESULT.ONE;
+    }
+    if ((state & THEME_BACKGROUND) !is 0) {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            if (findThemeControl () !is null) return LRESULT.ONE;
+        }
+    }
+    return null;
+}
+
+LRESULT WM_GETDLGCODE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_GETFONT (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) {
+    if (accessible !is null) {
+        int /*long*/ result = accessible.internal_WM_GETOBJECT (wParam, lParam);
+        if (result !is 0) return new LRESULT (result);
+    }
+    return null;
+}
+
+LRESULT WM_GETMINMAXINFO (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_HOTKEY (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_HELP (int /*long*/ wParam, int /*long*/ lParam) {
+    static if (OS.IsWinCE) return null;
+    HELPINFO* lphi = cast(HELPINFO*)lParam;
+    Decorations shell = menuShell ();
+    if (!shell.isEnabled ()) return null;
+    if (lphi.iContextType is OS.HELPINFO_MENUITEM) {
+        MenuItem item = display.getMenuItem (lphi.iCtrlId);
+        if (item !is null && item.isEnabled ()) {
+            Widget widget = null;
+            if (item.hooks (SWT.Help)) {
+                widget = item;
+            } else {
+                Menu menu = item.parent;
+                if (menu.hooks (SWT.Help)) widget = menu;
+            }
+            if (widget !is null) {
+                auto hwndShell = shell.handle;
+                OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
+                widget.postEvent (SWT.Help);
+                return LRESULT.ONE;
+            }
+        }
+        return null;
+    }
+    if (hooks (SWT.Help)) {
+        postEvent (SWT.Help);
+        return LRESULT.ONE;
+    }
+    return null;
+}
+
+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 /*long*/ wParam, int /*long*/ lParam) {
+    return wmIMEChar (handle, wParam, 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_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;
+
+    /*
+    * If the high order word of LPARAM is non-zero,
+    * the menu is the system menu and we can ignore
+    * WPARAM.  Otherwise, use WPARAM to find the menu.
+    */
+    Shell shell = getShell ();
+    Menu oldMenu = shell.activeMenu, newMenu = null;
+    if (OS.HIWORD (lParam) is 0) {
+        newMenu = menuShell ().findMenu (cast(HANDLE)wParam);
+        if (newMenu !is null) newMenu.update ();
+    }
+    Menu menu = newMenu;
+    while (menu !is null && menu !is oldMenu) {
+        menu = menu.getParentMenu ();
+    }
+    if (menu is null) {
+        menu = shell.activeMenu;
+        while (menu !is null) {
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the hide
+            * event.  If this happens, stop searching up the
+            * ancestor list because there is no longer a link
+            * to follow.
+            */
+            menu.sendEvent (SWT.Hide);
+            if (menu.isDisposed ()) break;
+            menu = menu.getParentMenu ();
+            Menu ancestor = newMenu;
+            while (ancestor !is null && ancestor !is menu) {
+                ancestor = ancestor.getParentMenu ();
+            }
+            if (ancestor !is null) break;
+        }
+    }
+
+    /*
+    * The shell and the new menu may be disposed because of
+    * sending the hide event to the ancestor menus but setting
+    * a field to null in a disposed shell is not harmful.
+    */
+    if (newMenu !is null && newMenu.isDisposed ()) newMenu = null;
+    shell.activeMenu = newMenu;
+
+    /* Send the show event */
+    if (newMenu !is null && newMenu !is oldMenu) {
+        newMenu.sendEvent (SWT.Show);
+        // widget could be disposed at this point
+    }
+    return null;
+}
+
+LRESULT WM_INPUTLANGCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmKeyDown (handle, wParam, lParam);
+}
+
+LRESULT WM_KEYUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmKeyUp (handle, wParam, lParam);
+}
+
+LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmKillFocus (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmLButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmLButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_LBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmLButtonUp (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmMButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmMButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_MBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmMButtonUp (handle, wParam, 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);
+        if (item is null) return null;
+        return item.wmMeasureChild (wParam, lParam);
+    }
+    auto hwnd = OS.GetDlgItem (handle, struct_.CtlID);
+    Control control = display.getControl (hwnd);
+    if (control is null) return null;
+    return control.wmMeasureChild (wParam, 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
+    * menu or the menu bar, Windows beeps.  This beep is
+    * unexpected and unwanted by applications that look
+    * for Alt+<key>.  The fix is to detect the case and
+    * stop Windows from beeping by closing the menu.
+    */
+    int type = OS.HIWORD (wParam);
+    if (type is 0 || type is OS.MF_SYSMENU) {
+        display.mnemonicKeyHit = false;
+        return new LRESULT (OS.MAKELRESULT (0, OS.MNC_CLOSE));
+    }
+    return null;
+}
+
+LRESULT WM_MENUSELECT (int /*long*/ wParam, int /*long*/ lParam) {
+    int code = OS.HIWORD (wParam);
+    Shell shell = getShell ();
+    if (code is 0xFFFF && lParam is 0) {
+        Menu menu = shell.activeMenu;
+        while (menu !is null) {
+            /*
+            * When the user cancels any menu that is not the
+            * menu bar, assume a mnemonic key was pressed to open
+            * the menu from WM_SYSCHAR.  When the menu was invoked
+            * using the mouse, this assumption is wrong but not
+            * harmful.  This variable is only used in WM_SYSCHAR
+            * and WM_SYSCHAR is only sent after the user has pressed
+            * a mnemonic.
+            */
+            display.mnemonicKeyHit = true;
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the hide
+            * event.  If this happens, stop searching up the
+            * parent list because there is no longer a link
+            * to follow.
+            */
+            menu.sendEvent (SWT.Hide);
+            if (menu.isDisposed ()) break;
+            menu = menu.getParentMenu ();
+        }
+        /*
+        * The shell may be disposed because of sending the hide
+        * event to the last active menu menu but setting a field
+        * to null in a destroyed widget is not harmful.
+        */
+        shell.activeMenu = null;
+        return null;
+    }
+    if ((code & OS.MF_SYSMENU) !is 0) return null;
+    if ((code & OS.MF_HILITE) !is 0) {
+        MenuItem item = null;
+        Decorations menuShell = menuShell ();
+        if ((code & OS.MF_POPUP) !is 0) {
+            int index = OS.LOWORD (wParam);
+            MENUITEMINFO info;
+            info.cbSize = OS.MENUITEMINFO_sizeof;
+            info.fMask = OS.MIIM_SUBMENU;
+            if (OS.GetMenuItemInfo (cast(HANDLE)lParam, index, true, &info)) {
+                Menu newMenu = menuShell.findMenu (info.hSubMenu);
+                if (newMenu !is null) item = newMenu.cascade;
+            }
+        } else {
+            Menu newMenu = menuShell.findMenu (cast(HANDLE)lParam);
+            if (newMenu !is null) {
+                int id = OS.LOWORD (wParam);
+                item = display.getMenuItem (id);
+            }
+            Menu oldMenu = shell.activeMenu;
+            if (oldMenu !is null) {
+                Menu ancestor = oldMenu;
+                while (ancestor !is null && ancestor !is newMenu) {
+                    ancestor = ancestor.getParentMenu ();
+                }
+                if (ancestor is newMenu) {
+                    ancestor = oldMenu;
+                    while (ancestor !is newMenu) {
+                        /*
+                        * It is possible (but unlikely), that application
+                        * code could have disposed the widget in the hide
+                        * event or the item about to be armed.  If this
+                        * happens, stop searching up the ancestor list
+                        * because there is no longer a link to follow.
+                        */
+                        ancestor.sendEvent (SWT.Hide);
+                        if (ancestor.isDisposed ()) break;
+                        ancestor = ancestor.getParentMenu ();
+                        if (ancestor is null) break;
+                    }
+                    /*
+                    * The shell and/or the item could be disposed when
+                    * processing hide events from above.  If this happens,
+                    * ensure that the shell is not accessed and that no
+                    * arm event is sent to the item.
+                    */
+                    if (!shell.isDisposed ()) {
+                        if (newMenu !is null && newMenu.isDisposed ()) {
+                            newMenu = null;
+                        }
+                        shell.activeMenu = newMenu;
+                    }
+                    if (item !is null && item.isDisposed ()) item = null;
+                }
+            }
+        }
+        if (item !is null) item.sendEvent (SWT.Arm);
+    }
+    return null;
+}
+
+LRESULT WM_MOUSEACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_MOUSEHOVER (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmMouseHover (handle, wParam, 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 /*long*/ wParam, int /*long*/ lParam) {
+    return wmMouseMove (handle, wParam, lParam);
+}
+
+LRESULT WM_MOUSEWHEEL (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmMouseWheel (handle, wParam, lParam);
+}
+
+LRESULT WM_MOVE (int /*long*/ wParam, int /*long*/ lParam) {
+    state |= MOVE_OCCURRED;
+    if (findImageControl () !is null) {
+        if (this !is getShell ()) redrawChildren ();
+    } else {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                if (OS.IsWindowVisible (handle)) {
+                    if (findThemeControl () !is null) redrawChildren ();
+                }
+            }
+        }
+    }
+    if ((state & MOVE_DEFERRED) is 0) sendEvent (SWT.Move);
+    // widget could be disposed at this point
+    return null;
+}
+
+LRESULT WM_NCACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_NCCALCSIZE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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 /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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 /*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 /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_PASTE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_PRINT (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmPrint (handle, wParam, lParam);
+}
+
+LRESULT WM_PRINTCLIENT (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_QUERYENDSESSION (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_QUERYNEWPALETTE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_QUERYOPEN (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_RBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmRButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_RBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmRButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_RBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmRButtonUp (handle, wParam, lParam);
+}
+
+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;
+        Cursor cursor = control.findCursor ();
+        if (cursor !is null) {
+            OS.SetCursor (cursor.handle);
+            return LRESULT.ONE;
+        }
+    }
+    return null;
+}
+
+LRESULT WM_SETFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmSetFocus (handle, wParam, lParam);
+}
+
+LRESULT WM_SETTINGCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_SETFONT (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_SETREDRAW (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_SHOWWINDOW (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) {
+    state |= RESIZE_OCCURRED;
+    if ((state & RESIZE_DEFERRED) is 0) sendEvent (SWT.Resize);
+    // widget could be disposed at this point
+    return null;
+}
+
+LRESULT WM_SYSCHAR (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmSysChar (handle, wParam, lParam);
+}
+
+LRESULT WM_SYSCOLORCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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 (OS.LOWORD (wParam));
+            if (item !is null) item.wmCommandChild (wParam, lParam);
+        }
+        return LRESULT.ZERO;
+    }
+
+    /* Process the System Command */
+    int cmd = wParam & 0xFFF0;
+    switch (cmd) {
+        case OS.SC_CLOSE:
+            auto hwndShell = menuShell ().handle;
+            int bits = OS.GetWindowLong (hwndShell, OS.GWL_STYLE);
+            if ((bits & OS.WS_SYSMENU) is 0) return LRESULT.ZERO;
+            break;
+        case OS.SC_KEYMENU:
+            /*
+            * When lParam is zero, one of F10, Shift+F10, Ctrl+F10 or
+            * Ctrl+Shift+F10 was pressed.  If there is no menu bar and
+            * the focus control is interested in keystrokes, give the
+            * key to the focus control.  Normally, F10 with no menu bar
+            * moves focus to the System menu but this can be achieved
+            * using Alt+Space.  To allow the application to see F10,
+            * avoid running the default window proc.
+            *
+            * NOTE:  When F10 is pressed, WM_SYSCOMMAND is sent to the
+            * shell, not the focus control.  This is undocumented Windows
+            * behavior.
+            */
+            if (lParam is 0) {
+                Decorations shell = menuShell ();
+                Menu menu = shell.getMenuBar ();
+                if (menu is null) {
+                    Control control = display._getFocusControl ();
+                    if (control !is null) {
+                        if (control.hooks (SWT.KeyDown) || control.hooks (SWT.KeyUp)) {
+                            display.mnemonicKeyHit = false;
+                            return LRESULT.ZERO;
+                        }
+                    }
+                }
+            } else {
+                /*
+                * When lParam is not zero, Alt+<key> was pressed.  If the
+                * application is interested in keystrokes and there is a
+                * menu bar, check to see whether the key that was pressed
+                * matches a mnemonic on the menu bar.  Normally, Windows
+                * matches the first character of a menu item as well as
+                * matching the mnemonic character.  To allow the application
+                * to see the keystrokes in this case, avoid running the default
+                * window proc.
+                *
+                * NOTE: When the user types Alt+Space, the System menu is
+                * activated.  In this case the application should not see
+                * the keystroke.
+                */
+                if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
+                    if (lParam !is ' ') {
+                        Decorations shell = menuShell ();
+                        Menu menu = shell.getMenuBar ();
+                        if (menu !is null) {
+                            char key = Display.mbcsToWcs (lParam);
+                            if (key !is 0) {
+                                key = CharacterToLower (key);
+                                MenuItem [] items = menu.getItems ();
+                                for (int i=0; i<items.length; i++) {
+                                    MenuItem item = items [i];
+                                    String text = item.getText ();
+                                    char mnemonic = findMnemonic (text);
+                                    if (text.length > 0 && mnemonic is 0) {
+                                        char ch = text.charAt (0);
+                                        if (CharacterToLower (ch) is key) {
+                                            display.mnemonicKeyHit = false;
+                                            return LRESULT.ZERO;
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            display.mnemonicKeyHit = false;
+                        }
+                    }
+                }
+            }
+            // FALL THROUGH
+        case OS.SC_HSCROLL:
+        case OS.SC_VSCROLL:
+            /*
+            * Do not allow keyboard traversal of the menu bar
+            * or scrolling when the shell is not enabled.
+            */
+            Decorations shell = menuShell ();
+            if (!shell.isEnabled () || !shell.isActive ()) {
+                return LRESULT.ZERO;
+            }
+            break;
+        case OS.SC_MINIMIZE:
+            /* Save the focus widget when the shell is minimized */
+            menuShell ().saveFocus ();
+            break;
+        default:
+    }
+    return null;
+}
+
+LRESULT WM_SYSKEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmSysKeyDown (handle, wParam, lParam);
+}
+
+LRESULT WM_SYSKEYUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmSysKeyUp (handle, wParam, lParam);
+}
+
+LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_UNDO (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_UPDATEUISTATE (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+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 /*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
+    * not redraw the area where the control once was in the parent.
+    * The fix is to detect this case and redraw the area.
+    */
+    if (drawCount !is 0) {
+        Shell shell = getShell ();
+        if (shell !is this) {
+            WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+            if ((lpwp.flags & OS.SWP_NOMOVE) is 0 || (lpwp.flags & OS.SWP_NOSIZE) is 0) {
+                RECT rect;
+                OS.GetWindowRect (topHandle (), &rect);
+                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 /*long*/ wParam, int /*long*/ lParam) {
+    return wmXButtonDblClk (handle, wParam, lParam);
+}
+
+LRESULT WM_XBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmXButtonDown (handle, wParam, lParam);
+}
+
+LRESULT WM_XBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmXButtonUp (handle, wParam, lParam);
+}
+
+LRESULT wmColorChild (int /*long*/ wParam, int /*long*/ lParam) {
+    Control control = findBackgroundControl ();
+    if (control is null) {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                control = findThemeControl ();
+                if (control !is null) {
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    OS.SetTextColor (cast(HANDLE)wParam, getForegroundPixel ());
+                    OS.SetBkColor (cast(HANDLE)wParam, getBackgroundPixel ());
+                    fillThemeBackground (cast(HANDLE)wParam, control, &rect);
+                    OS.SetBkMode (cast(HANDLE)wParam, OS.TRANSPARENT);
+                    return new LRESULT ( cast(int) OS.GetStockObject (OS.NULL_BRUSH));
+                }
+            }
+        }
+        if (foreground is -1) return null;
+    }
+    if (control is null) control = this;
+    int forePixel = getForegroundPixel ();
+    int backPixel = control.getBackgroundPixel ();
+    OS.SetTextColor (cast(HANDLE)wParam, forePixel);
+    OS.SetBkColor (cast(HANDLE)wParam, backPixel);
+    if (control.backgroundImage !is null) {
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        auto hwnd = control.handle;
+        auto hBitmap = control.backgroundImage.handle;
+        OS.MapWindowPoints (handle, hwnd, cast(POINT*)&rect, 2);
+        POINT lpPoint;
+        OS.GetWindowOrgEx (cast(HANDLE)wParam, &lpPoint);
+        OS.SetBrushOrgEx (cast(HANDLE)wParam, -rect.left - lpPoint.x, -rect.top - lpPoint.y, &lpPoint);
+        auto hBrush = findBrush (cast(int)hBitmap, OS.BS_PATTERN);
+        if ((state & DRAW_BACKGROUND) !is 0) {
+            auto hOldBrush = OS.SelectObject (cast(HANDLE)wParam, hBrush);
+            OS.MapWindowPoints (hwnd, handle, cast(POINT*)&rect, 2);
+            OS.PatBlt (cast(HANDLE)wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+            OS.SelectObject (cast(HANDLE)wParam, hOldBrush);
+        }
+        OS.SetBkMode (cast(HANDLE)wParam, OS.TRANSPARENT);
+        return new LRESULT ( cast(int) hBrush);
+    }
+    auto hBrush = findBrush (backPixel, OS.BS_SOLID);
+    if ((state & DRAW_BACKGROUND) !is 0) {
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        auto hOldBrush = OS.SelectObject (cast(HANDLE)wParam, hBrush);
+        OS.PatBlt (cast(HANDLE)wParam, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+        OS.SelectObject (cast(HANDLE)wParam, hOldBrush);
+    }
+    return new LRESULT ( cast(int) hBrush);
+}
+
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
+    Control control = display.getControl (hdr.hwndFrom);
+    if (control is null) return null;
+    return control.wmNotifyChild (hdr, wParam, lParam);
+}
+
+LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    return null;
+}
+
+LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/CoolBar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1223 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.CoolBar;
+
+import org.eclipse.swt.widgets.Composite;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.CoolItem;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide an area for dynamically
+ * positioning the items they contain.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>CoolItem</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.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>FLAT, HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#coolbar">CoolBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class CoolBar : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.windowProc windowProc;
+
+    CoolItem [] items;
+    CoolItem [] originalItems;
+    bool locked;
+    bool ignoreResize;
+    private static /+const+/ WNDPROC ReBarProc;
+    static const TCHAR* ReBarClass = OS.REBARCLASSNAME.ptr;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            INITCOMMONCONTROLSEX icex;
+            icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
+            icex.dwICC = OS.ICC_COOL_CLASSES;
+            OS.InitCommonControlsEx (&icex);
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ReBarClass, &lpWndClass);
+            ReBarProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+    static const int SEPARATOR_WIDTH = 2;
+    static const int MAX_WIDTH = 0x7FFF;
+    static const int DEFAULT_COOLBAR_WIDTH = 0;
+    static const int DEFAULT_COOLBAR_HEIGHT = 0;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+    /*
+    * Ensure that either of HORIZONTAL or VERTICAL is set.
+    * NOTE: HORIZONTAL and VERTICAL have the same values
+    * as H_SCROLL and V_SCROLL so it is necessary to first
+    * clear these bits to avoid scroll bars and then reset
+    * the bits using the original style supplied by the
+    * programmer.
+    *
+    * NOTE: The CCS_VERT style cannot be applied when the
+    * widget is created because of this conflict.
+    */
+    if ((style & SWT.VERTICAL) !is 0) {
+        this.style |= SWT.VERTICAL;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
+    } else {
+        this.style |= SWT.HORIZONTAL;
+    }
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc (ReBarProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    style |= SWT.NO_FOCUS;
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    int border = getBorderWidth ();
+    int newWidth = wHint is SWT.DEFAULT ? 0x3FFF : wHint + (border * 2);
+    int newHeight = hHint is SWT.DEFAULT ? 0x3FFF : hHint + (border * 2);
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (count !is 0) {
+        ignoreResize = true;
+        bool redraw = false;
+        if (OS.IsWindowVisible (handle)) {
+            if (OS.COMCTL32_MAJOR >= 6) {
+                redraw = true;
+                OS.UpdateWindow (handle);
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            } else {
+                redraw = drawCount is 0;
+                if (redraw) {
+                    OS.UpdateWindow (handle);
+                    OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+                }
+            }
+        }
+        RECT oldRect;
+        OS.GetWindowRect (handle, &oldRect);
+        int oldWidth = oldRect.right - oldRect.left;
+        int oldHeight = oldRect.bottom - oldRect.top;
+        int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+        SetWindowPos (handle, null, 0, 0, newWidth, newHeight, flags);
+        RECT rect;
+        OS.SendMessage (handle, OS.RB_GETRECT, count - 1, &rect);
+        height = Math.max (height, rect.bottom);
+        SetWindowPos (handle, null, 0, 0, oldWidth, oldHeight, flags);
+        REBARBANDINFO rbBand;
+        rbBand.cbSize = REBARBANDINFO.sizeof;
+        rbBand.fMask = OS.RBBIM_IDEALSIZE | OS.RBBIM_STYLE;
+        int rowWidth = 0;
+        for (int i = 0; i < count; i++) {
+            OS.SendMessage(handle, OS.RB_GETBANDINFO, i, &rbBand);
+            if ((rbBand.fStyle & OS.RBBS_BREAK) !is 0) {
+                width = Math.max(width, rowWidth);
+                rowWidth = 0;
+            }
+            rowWidth += rbBand.cxIdeal + getMargin (i);
+        }
+        width = Math.max(width, rowWidth);
+        if (redraw) {
+            if (OS.COMCTL32_MAJOR >= 6) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            } else {
+                OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            }
+        }
+        ignoreResize = false;
+    }
+    if (width is 0) width = DEFAULT_COOLBAR_WIDTH;
+    if (height is 0) height = DEFAULT_COOLBAR_HEIGHT;
+    if ((style & SWT.VERTICAL) !is 0) {
+        int tmp = width;
+        width = height;
+        height = tmp;
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    height += border * 2;
+    width += border * 2;
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    /*
+    * Feature in Windows.  When the control is created,
+    * it does not use the default system font.  A new HFONT
+    * is created and destroyed when the control is destroyed.
+    * This means that a program that queries the font from
+    * this control, uses the font in another control and then
+    * destroys this control will have the font unexpectedly
+    * destroyed in the other control.  The fix is to assign
+    * the font ourselves each time the control is created.
+    * The control will not destroy a font that it did not
+    * create.
+    */
+    auto hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+}
+
+void createItem (CoolItem item, int index) {
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+    int id = 0;
+    while (id < items.length && items [id] !is null) id++;
+    if (id is items.length) {
+        CoolItem [] newItems = new CoolItem [items.length + 4];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    auto hHeap = OS.GetProcessHeap ();
+    auto lpText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_TEXT | OS.RBBIM_STYLE | OS.RBBIM_ID;
+    rbBand.fStyle = OS.RBBS_VARIABLEHEIGHT | OS.RBBS_GRIPPERALWAYS;
+    if ((item.style & SWT.DROP_DOWN) !is 0) {
+        rbBand.fStyle |= OS.RBBS_USECHEVRON;
+    }
+    rbBand.lpText = lpText;
+    rbBand.wID = id;
+
+    /*
+    * Feature in Windows.  When inserting an item at end of a row,
+    * sometimes, Windows will begin to place the item on the right
+    * side of the cool bar.  The fix is to resize the new items to
+    * the maximum size and then resize the next to last item to the
+    * ideal size.
+    */
+    int lastIndex = getLastIndexOfRow (index - 1);
+    bool fixLast = index is lastIndex + 1;
+    if (fixLast) {
+        rbBand.fMask |= OS.RBBIM_SIZE;
+        rbBand.cx = MAX_WIDTH;
+    }
+
+    /*
+    * Feature in Windows. Is possible that the item at index zero
+    * has the RBBS_BREAK flag set. When a new item is inserted at
+    * position zero, the previous item at position zero moves to
+    * a new line.  The fix is to detect this case and clear the
+    * RBBS_BREAK flag on the previous item before inserting the
+    * new item.
+    */
+    if (index is 0 && count > 0) {
+        getItem (0).setWrap (false);
+    }
+
+    /* Insert the item */
+    if (OS.SendMessage (handle, OS.RB_INSERTBAND, index, &rbBand) is 0) {
+        error (SWT.ERROR_ITEM_NOT_ADDED);
+    }
+
+    /* Resize the next to last item to the ideal size */
+    if (fixLast) {
+        resizeToPreferredWidth (lastIndex);
+    }
+
+    OS.HeapFree (hHeap, 0, lpText);
+    items [item.id = id] = item;
+    int length = originalItems.length;
+    CoolItem [] newOriginals = new CoolItem [length + 1];
+    System.arraycopy (originalItems, 0, newOriginals, 0, index);
+    System.arraycopy (originalItems, index, newOriginals, index + 1, length - index);
+    newOriginals [index] = item;
+    originalItems = newOriginals;
+}
+
+override void createWidget () {
+    super.createWidget ();
+    items = new CoolItem [4];
+    originalItems = new CoolItem [0];
+}
+
+void destroyItem (CoolItem item) {
+    int index = OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (count !is 0) {
+        int lastIndex = getLastIndexOfRow (index);
+        if (index is lastIndex) {
+            /*
+            * Feature in Windows.  If the last item in a row is
+            * given its ideal size, it will be placed at the far
+            * right hand edge of the coolbar.  It is preferred
+            * that the last item appear next to the second last
+            * item.  The fix is to size the last item of each row
+            * so that it occupies all the available space to the
+            * right in the row.
+            */
+            resizeToMaximumWidth (lastIndex - 1);
+        }
+    }
+
+    /*
+    * Feature in Windows.  When Windows removed a rebar
+    * band, it makes the band child invisible.  The fix
+    * is to show the child.
+    */
+    Control control = item.control;
+    bool wasVisible = control !is null && !control.isDisposed() && control.getVisible ();
+
+    /*
+    * When a wrapped item is being deleted, make the next
+    * item in the row wrapped in order to preserve the row.
+    * In order to avoid an unnecessary layout, temporarily
+    * ignore WM_SIZE.  If the next item is wrapped then a
+    * row will be deleted and the WM_SIZE is necessary.
+    */
+    CoolItem nextItem = null;
+    if (item.getWrap ()) {
+        if (index + 1 < count) {
+            nextItem = getItem (index + 1);
+            ignoreResize = !nextItem.getWrap ();
+        }
+    }
+    if (OS.SendMessage (handle, OS.RB_DELETEBAND, index, 0) is 0) {
+        error (SWT.ERROR_ITEM_NOT_REMOVED);
+    }
+    items [item.id] = null;
+    item.id = -1;
+    if (ignoreResize) {
+        nextItem.setWrap (true);
+        ignoreResize = false;
+    }
+
+    /* Restore the visible state of the control */
+    if (wasVisible) control.setVisible (true);
+
+    index = 0;
+    while (index < originalItems.length) {
+        if (originalItems [index] is item) break;
+        index++;
+    }
+    int length = originalItems.length - 1;
+    CoolItem [] newOriginals = new CoolItem [length];
+    System.arraycopy (originalItems, 0, newOriginals, 0, index);
+    System.arraycopy (originalItems, index + 1, newOriginals, index, length - index);
+    originalItems = newOriginals;
+}
+
+override void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) {
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (background is -1 && (style & SWT.FLAT) !is 0) {
+            Control control = findBackgroundControl ();
+            if (control !is null && control.backgroundImage !is null) {
+                fillBackground (hDC, control.getBackgroundPixel (), rect);
+                return;
+            }
+        }
+    }
+    RECT rect2;
+    OS.GetClientRect (handle, &rect2);
+    OS.MapWindowPoints (handle, hwnd, cast(POINT*) &rect2, 2);
+    POINT lpPoint;
+    OS.SetWindowOrgEx (hDC, -rect2.left, -rect2.top, &lpPoint);
+    OS.SendMessage (handle, OS.WM_PRINT, hDC, OS.PRF_CLIENT | OS.PRF_ERASEBKGND);
+    OS.SetWindowOrgEx (hDC, lpPoint.x, lpPoint.y, null);
+}
+
+override Control findThemeControl () {
+    if ((style & SWT.FLAT) !is 0) return this;
+    return background is -1 && backgroundImage is null ? this : super.findThemeControl ();
+}
+
+int getMargin (int index) {
+    int margin = 0;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        MARGINS margins;
+        OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, &margins);
+        margin += margins.cxLeftWidth + margins.cxRightWidth;
+    }
+    RECT rect;
+    OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, &rect);
+    if ((style & SWT.FLAT) !is 0) {
+        /*
+        * Bug in Windows.  When the style bit  RBS_BANDBORDERS is not set
+        * the rectangle returned by RBS_BANDBORDERS is four pixels too small.
+        * The fix is to add four pixels to the result.
+        */
+        if ((style & SWT.VERTICAL) !is 0) {
+            margin += rect.top + 4;
+        } else {
+            margin += rect.left + 4;
+        }
+    } else {
+        if ((style & SWT.VERTICAL) !is 0) {
+            margin += rect.top + rect.bottom;
+        } else {
+            margin += rect.left + rect.right;
+        }
+    }
+    if ((style & SWT.FLAT) is 0) {
+        if (!isLastItemOfRow (index)) {
+            margin += CoolBar.SEPARATOR_WIDTH;
+        }
+    }
+    return margin;
+}
+
+/**
+ * Returns the item that is currently displayed at the given,
+ * zero-relative index. Throws an exception if the index is
+ * out of range.
+ *
+ * @param index the visual index of the item to return
+ * @return the item at the given visual index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 CoolItem getItem (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_ID;
+    OS.SendMessage (handle, OS.RB_GETBANDINFO, index, &rbBand);
+    return items [rbBand.wID];
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+}
+
+/**
+ * Returns an array of zero-relative ints that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException <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 int [] getItemOrder () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    int [] indices = new int [count];
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_ID;
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        CoolItem item = items [rbBand.wID];
+        int index = 0;
+        while (index<originalItems.length) {
+            if (originalItems [index] is item) break;
+            index++;
+        }
+        if (index is originalItems.length) error (SWT.ERROR_CANNOT_GET_ITEM);
+        indices [i] = index;
+    }
+    return indices;
+}
+
+/**
+ * Returns an array of <code>CoolItem</code>s in the order
+ * in which they are currently being displayed.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the receiver's items in their current visual order
+ *
+ * @exception SWTException <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 CoolItem [] getItems () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    CoolItem [] result = new CoolItem [count];
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_ID;
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        result [i] = items [rbBand.wID];
+    }
+    return result;
+}
+
+/**
+ * Returns an array of points whose x and y coordinates describe
+ * the widths and heights (respectively) of the items in the receiver
+ * in the order in which they are currently being displayed.
+ *
+ * @return the receiver's item sizes in their current visual order
+ *
+ * @exception SWTException <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 Point [] getItemSizes () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    Point [] sizes = new Point [count];
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_CHILDSIZE;
+    int separator = (style & SWT.FLAT) is 0 ? SEPARATOR_WIDTH : 0;
+    MARGINS margins;
+    for (int i=0; i<count; i++) {
+        RECT rect;
+        OS.SendMessage (handle, OS.RB_GETRECT, i, &rect);
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        if (OS.COMCTL32_MAJOR >= 6) {
+            OS.SendMessage (handle, OS.RB_GETBANDMARGINS, 0, &margins);
+            rect.left -= margins.cxLeftWidth;
+            rect.right += margins.cxRightWidth;
+        }
+        if (!isLastItemOfRow(i)) rect.right += separator;
+        if ((style & SWT.VERTICAL) !is 0) {
+            sizes [i] = new Point (rbBand.cyChild, rect.right - rect.left);
+        } else {
+            sizes [i] = new Point (rect.right - rect.left, rbBand.cyChild);
+        }
+    }
+    return sizes;
+}
+
+int getLastIndexOfRow (int index) {
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (count is 0) return -1;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_STYLE;
+    for (int i=index + 1; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        if ((rbBand.fStyle & OS.RBBS_BREAK) !is 0) {
+            return i - 1;
+        }
+    }
+    return count - 1;
+}
+
+bool isLastItemOfRow (int index) {
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (index + 1 is count) return true;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_STYLE;
+    OS.SendMessage (handle, OS.RB_GETBANDINFO, index + 1, &rbBand);
+    return (rbBand.fStyle & OS.RBBS_BREAK) !is 0;
+}
+
+/**
+ * Returns whether or not the receiver is 'locked'. When a coolbar
+ * is locked, its items cannot be repositioned.
+ *
+ * @return true if the coolbar is locked, false otherwise
+ *
+ * @exception SWTException <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 2.0
+ */
+public bool getLocked () {
+    checkWidget ();
+    return locked;
+}
+
+/**
+ * Returns an array of ints that describe the zero-relative
+ * indices of any item(s) in the receiver that will begin on
+ * a new row. The 0th visible item always begins the first row,
+ * therefore it does not count as a wrap index.
+ *
+ * @return an array containing the receiver's wrap indices, or an empty array if all items are in one row
+ *
+ * @exception SWTException <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 int [] getWrapIndices () {
+    checkWidget ();
+    CoolItem [] items = getItems ();
+    int [] indices = new int [items.length];
+    int count = 0;
+    for (int i=0; i<items.length; i++) {
+        if (items [i].getWrap ()) indices [count++] = i;
+    }
+    int [] result = new int [count];
+    System.arraycopy (indices, 0, result, 0, count);
+    return result;
+}
+
+/**
+ * Searches the receiver's items in the order they are currently
+ * being displayed, starting at the first item (index 0), until
+ * an item is found that is equal to the argument, and returns
+ * the index of that item. If no item is found, returns -1.
+ *
+ * @param item the search item
+ * @return the visual order index of the search item, or -1 if the item is not found
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item is disposed</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (CoolItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+    return OS.SendMessage (handle, OS.RB_IDTOINDEX, item.id, 0);
+}
+
+void resizeToPreferredWidth (int index) {
+    /*
+    * Bug in Windows.  When RB_GETBANDBORDERS is sent
+    * with an index out of range, Windows GP's.  The
+    * fix is to ensure the index is in range.
+    */
+    int count = OS.SendMessage(handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (0 <= index && index < count) {
+        REBARBANDINFO rbBand;
+        rbBand.cbSize = REBARBANDINFO.sizeof;
+        rbBand.fMask = OS.RBBIM_IDEALSIZE;
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, index, &rbBand);
+        RECT rect;
+        OS.SendMessage (handle, OS.RB_GETBANDBORDERS, index, &rect);
+        rbBand.cx = rbBand.cxIdeal + rect.left;
+        if ((style & SWT.FLAT) is 0) rbBand.cx += rect.right;
+        rbBand.fMask = OS.RBBIM_SIZE;
+        OS.SendMessage (handle, OS.RB_SETBANDINFO, index, &rbBand);
+    }
+}
+
+void resizeToMaximumWidth (int index) {
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_SIZE;
+    rbBand.cx = MAX_WIDTH;
+    OS.SendMessage (handle, OS.RB_SETBANDINFO, index, &rbBand);
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        for (int i=0; i<items.length; i++) {
+            CoolItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void removeControl (Control control) {
+    super.removeControl (control);
+    for (int i=0; i<items.length; i++) {
+        CoolItem item = items [i];
+        if (item !is null && item.control is control) {
+            item.setControl (null);
+        }
+    }
+}
+
+override void setBackgroundPixel (int pixel) {
+    if (pixel is -1) pixel = defaultBackground ();
+    OS.SendMessage (handle, OS.RB_SETBKCOLOR, 0, pixel);
+    setItemColors (OS.SendMessage (handle, OS.RB_GETTEXTCOLOR, 0, 0), pixel);
+    /*
+    * Feature in Windows.  For some reason, Windows
+    * does not fully erase the coolbar area and coolbar
+    * items when you set the background.  The fix is
+    * to invalidate the coolbar area.
+    */
+    if (!OS.IsWindowVisible (handle)) return;
+    static if (OS.IsWinCE) {
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+override void setForegroundPixel (int pixel) {
+    if (pixel is -1) pixel = defaultForeground ();
+    OS.SendMessage (handle, OS.RB_SETTEXTCOLOR, 0, pixel);
+    setItemColors (pixel, OS.SendMessage (handle, OS.RB_GETBKCOLOR, 0, 0));
+}
+
+void setItemColors (int foreColor, int backColor) {
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_COLORS;
+    rbBand.clrFore = foreColor;
+    rbBand.clrBack = backColor;
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_SETBANDINFO, i, &rbBand);
+    }
+}
+
+/**
+ * Sets the receiver's item order, wrap indices, and item sizes
+ * all at once. This method is typically used to restore the
+ * displayed state of the receiver to a previously stored state.
+ * <p>
+ * The item order is the order in which the items in the receiver
+ * should be displayed, given in terms of the zero-relative ordering
+ * of when the items were added.
+ * </p><p>
+ * The wrap indices are the indices of all item(s) in the receiver
+ * that will begin on a new row. The indices are given in the order
+ * specified by the item order. The 0th item always begins the first
+ * row, therefore it does not count as a wrap index. If wrap indices
+ * is null or empty, the items will be placed on one line.
+ * </p><p>
+ * The sizes are specified in an array of points whose x and y
+ * coordinates describe the new widths and heights (respectively)
+ * of the receiver's items in the order specified by the item order.
+ * </p>
+ *
+ * @param itemOrder an array of indices that describe the new order to display the items in
+ * @param wrapIndices an array of wrap indices, or null
+ * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+ *
+ * @exception SWTException <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_ARGUMENT - if item order or sizes is not the same length as the number of items</li>
+ * </ul>
+ */
+public void setItemLayout (int [] itemOrder, int [] wrapIndices, Point [] sizes) {
+    checkWidget ();
+    setRedraw (false);
+    setItemOrder (itemOrder);
+    setWrapIndices (wrapIndices);
+    setItemSizes (sizes);
+    setRedraw (true);
+}
+
+/*
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param itemOrder the new order to display the items in
+ *
+ * @exception SWTException <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_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ */
+void setItemOrder (int [] itemOrder) {
+    // SWT extension: allow null array
+    //if (itemOrder is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int itemCount = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (itemOrder.length !is itemCount) error (SWT.ERROR_INVALID_ARGUMENT);
+
+    /* Ensure that itemOrder does not contain any duplicates. */
+    bool [] set = new bool [itemCount];
+    for (int i=0; i<itemOrder.length; i++) {
+        int index = itemOrder [i];
+        if (index < 0 || index >= itemCount) error (SWT.ERROR_INVALID_RANGE);
+        if (set [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+        set [index] = true;
+    }
+
+    //REBARBANDINFO rbBand;
+    //rbBand.cbSize = REBARBANDINFO.sizeof;
+    for (int i=0; i<itemOrder.length; i++) {
+        int id = originalItems [itemOrder [i]].id;
+        int index = OS.SendMessage (handle, OS.RB_IDTOINDEX, id, 0);
+        if (index !is i) {
+            int lastItemSrcRow = getLastIndexOfRow (index);
+            int lastItemDstRow = getLastIndexOfRow (i);
+            if (index is lastItemSrcRow) {
+                resizeToPreferredWidth (index);
+            }
+            if (i is lastItemDstRow) {
+                resizeToPreferredWidth (i);
+            }
+
+            /* Move the item */
+            OS.SendMessage (handle, OS.RB_MOVEBAND, index, i);
+
+            if (index is lastItemSrcRow && index - 1 >= 0) {
+                resizeToMaximumWidth (index - 1);
+            }
+            if (i is lastItemDstRow) {
+                resizeToMaximumWidth (i);
+            }
+        }
+    }
+}
+
+/*
+ * Sets the width and height of the receiver's items to the ones
+ * specified by the argument, which is an array of points whose x
+ * and y coordinates describe the widths and heights (respectively)
+ * in the order in which the items are currently being displayed.
+ *
+ * @param sizes an array containing the new sizes for each of the receiver's items in visual order
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the array of sizes is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the array of sizes is not the same length as the number of items</li>
+ * </ul>
+ * @exception SWTException <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>
+ */
+void setItemSizes (Point [] sizes) {
+    // SWT extension: allow null array
+    //if (sizes is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    if (sizes.length !is count) error (SWT.ERROR_INVALID_ARGUMENT);
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_ID;
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        items [rbBand.wID].setSize (sizes [i].x, sizes [i].y);
+    }
+}
+
+/**
+ * Sets whether or not the receiver is 'locked'. When a coolbar
+ * is locked, its items cannot be repositioned.
+ *
+ * @param locked lock the coolbar if true, otherwise unlock the coolbar
+ *
+ * @exception SWTException <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 2.0
+ */
+public void setLocked (bool locked) {
+    checkWidget ();
+    this.locked = locked;
+    int count = OS.SendMessage (handle, OS.RB_GETBANDCOUNT, 0, 0);
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_STYLE;
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.RB_GETBANDINFO, i, &rbBand);
+        if (locked) {
+            rbBand.fStyle |= OS.RBBS_NOGRIPPER;
+        } else {
+            rbBand.fStyle &= ~OS.RBBS_NOGRIPPER;
+        }
+        OS.SendMessage (handle, OS.RB_SETBANDINFO, i, &rbBand);
+    }
+}
+
+/**
+ * Sets the indices of all item(s) in the receiver that will
+ * begin on a new row. The indices are given in the order in
+ * which they are currently being displayed. The 0th item
+ * always begins the first row, therefore it does not count
+ * as a wrap index. If indices is null or empty, the items
+ * will be placed on one line.
+ *
+ * @param indices an array of wrap indices, or null
+ *
+ * @exception SWTException <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 setWrapIndices (int [] indices) {
+    checkWidget ();
+    if (indices is null) indices = new int [0];
+    int count = getItemCount ();
+    for (int i=0; i<indices.length; i++) {
+        if (indices [i] < 0 || indices [i] >= count) {
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+    }
+    setRedraw (false);
+    CoolItem [] items = getItems ();
+    for (int i=0; i<items.length; i++) {
+        CoolItem item = items [i];
+        if (item.getWrap ()) {
+            resizeToPreferredWidth (i - 1);
+            item.setWrap (false);
+        }
+    }
+    resizeToMaximumWidth (count - 1);
+    for (int i=0; i<indices.length; i++) {
+        int index = indices [i];
+        if (0 <= index && index < items.length) {
+            CoolItem item = items [index];
+            item.setWrap (true);
+            resizeToMaximumWidth (index - 1);
+        }
+    }
+    setRedraw (true);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.CCS_NODIVIDER | OS.CCS_NORESIZE;
+    bits |= OS.RBS_VARHEIGHT | OS.RBS_DBLCLKTOGGLE;
+    if ((style & SWT.FLAT) is 0) bits |= OS.RBS_BANDBORDERS;
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARzToStr( ReBarClass );
+}
+
+override int windowProc () {
+    return cast(int) ReBarProc;
+}
+
+override LRESULT WM_COMMAND (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the coolbar window
+    * proc processes WM_COMMAND, it forwards this
+    * message to its parent.  This is done so that
+    * children of this control that send this message
+    * type to their parent will notify not only
+    * this control but also the parent of this control,
+    * which is typically the application window and
+    * the window that is looking for the message.
+    * If the control did not forward the message,
+    * applications would have to subclass the control
+    * window to see the message. Because the control
+    * window is subclassed by SWT, the message
+    * is delivered twice, once by SWT and once when
+    * the message is forwarded by the window proc.
+    * The fix is to avoid calling the window proc
+    * for this control.
+    */
+    LRESULT result = super.WM_COMMAND (wParam, lParam);
+    if (result !is null) return result;
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    /*
+    * Feature in Windows.  For some reason, Windows
+    * does not fully erase the area that the cool bar
+    * occupies when the size of the cool bar is larger
+    * than the space occupied by the cool bar items.
+    * The fix is to erase the cool bar background.
+    *
+    * NOTE: On versions of Windows prior to XP, for
+    * some reason, the cool bar draws separators in
+    * WM_ERASEBKGND.  Therefore it is essential to run
+    * the cool bar window proc after the background has
+    * been erased.
+    */
+    if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+        drawBackground ( cast(HDC) wParam);
+        return null;
+    }
+    return result;
+}
+
+override LRESULT WM_NOTIFY (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the cool bar window
+    * proc processes WM_NOTIFY, it forwards this
+    * message to its parent.  This is done so that
+    * children of this control that send this message
+    * type to their parent will notify not only
+    * this control but also the parent of this control,
+    * which is typically the application window and
+    * the window that is looking for the message.
+    * If the control did not forward the message,
+    * applications would have to subclass the control
+    * window to see the message. Because the control
+    * window is subclassed by SWT, the message
+    * is delivered twice, once by SWT and once when
+    * the message is forwarded by the window proc.
+    * The fix is to avoid calling the window proc
+    * for this control.
+    */
+    LRESULT result = super.WM_NOTIFY (wParam, lParam);
+    if (result !is null) return result;
+    return LRESULT.ZERO;
+}
+
+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 redraw is turned off, the rebar
+    * control does not call the default window proc.  This means
+    * that the rebar will redraw and children of the rebar will
+    * also redraw.  The fix is to call both the rebar window proc
+    * and the default window proc.
+    *
+    * NOTE: The rebar control can resize itself in WM_SETREDRAW.
+    * When redraw is turned off by the default window proc, this
+    * can leave pixel corruption in the parent.  The fix is to
+    * detect the size change and damage the previous area in the
+    * parent.
+    *
+    * NOTE:  In version 6.00 of COMCTL32.DLL, when WM_SETREDRAW
+    * is off, we cannot detect that the size has changed causing
+    * pixel corruption.  The fix is to disallow WM_SETREDRAW by
+    * not running the default window proc or the rebar window
+    * proc.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO;
+    Rectangle rect = getBounds ();
+    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);
+    }
+    return new LRESULT (code);
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    if (ignoreResize) {
+        int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+        if (code is 0) return LRESULT.ZERO;
+        return new LRESULT (code);
+    }
+    //TEMPORARY CODE
+//  if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+//      if (background is -1 && (style & SWT.FLAT) is 0) {
+//          OS.InvalidateRect (handle, null, true);
+//      }
+//  }
+    return super.WM_SIZE (wParam, lParam);
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    switch (hdr.code) {
+        case OS.RBN_BEGINDRAG: {
+            int pos = OS.GetMessagePos ();
+            POINT pt;
+            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;
+            break;
+        }
+        case OS.RBN_CHILDSIZE: {
+            /*
+            * Bug in Windows.  When Windows sets the size of the rebar band
+            * child and the child is a combo box, the size of the drop down
+            * portion of the combo box is resized to zero.  The fix is to set
+            * the size of the control to the current size after the rebar has
+            * already resized it.  If the control is not a combo, this does
+            * nothing.  If the control is a combo, the drop down portion is
+            * recalculated.
+            */
+            NMREBARCHILDSIZE* lprbcs = cast(NMREBARCHILDSIZE*)lParam;
+            //OS.MoveMemory (lprbcs, lParam, NMREBARCHILDSIZE.sizeof);
+            if (lprbcs.uBand !is -1) {
+                CoolItem item = items [lprbcs.wID];
+                Control control = item.control;
+                if (control !is null) {
+                    int width = lprbcs.rcChild.right - lprbcs.rcChild.left;
+                    int height = lprbcs.rcChild.bottom - lprbcs.rcChild.top;
+                    control.setBounds (lprbcs.rcChild.left, lprbcs.rcChild.top, width, height);
+                }
+            }
+            break;
+        }
+        case OS.RBN_HEIGHTCHANGE: {
+            if (!ignoreResize) {
+                Point size = getSize ();
+                int border = getBorderWidth ();
+                int barHeight = OS.SendMessage (handle, OS.RB_GETBARHEIGHT, 0, 0);
+                if ((style & SWT.VERTICAL) !is 0) {
+                    setSize (barHeight + 2 * border, size.y);
+                } else {
+                    setSize (size.x, barHeight + 2 * border);
+                }
+            }
+            break;
+        }
+        case OS.RBN_CHEVRONPUSHED: {
+            NMREBARCHEVRON* lpnm = cast(NMREBARCHEVRON*)lParam;
+            //OS.MoveMemory (lpnm, lParam, NMREBARCHEVRON.sizeof);
+            CoolItem item = items [lpnm.wID];
+            if (item !is null) {
+                Event event = new Event();
+                event.detail = SWT.ARROW;
+                if ((style & SWT.VERTICAL) !is 0) {
+                    event.x = lpnm.rc.right;
+                    event.y = lpnm.rc.top;
+                } else {
+                    event.x = lpnm.rc.left;
+                    event.y = lpnm.rc.bottom;
+                }
+                item.postEvent (SWT.Selection, event);
+            }
+            break;
+        }
+        case OS.NM_CUSTOMDRAW: {
+            /*
+            * Bug in Windows.  On versions of Windows prior to XP,
+            * drawing the background color in NM_CUSTOMDRAW erases
+            * the separators.  The fix is to draw the background
+            * in WM_ERASEBKGND.
+            */
+            if (OS.COMCTL32_MAJOR < 6) break;
+            if (findBackgroundControl () !is null || (style & SWT.FLAT) !is 0) {
+                NMCUSTOMDRAW* nmcd = cast(NMCUSTOMDRAW*)lParam;
+                //OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+                switch (nmcd.dwDrawStage) {
+                    case OS.CDDS_PREERASE:
+                        return new LRESULT (OS.CDRF_SKIPDEFAULT | OS.CDRF_NOTIFYPOSTERASE);
+                    case OS.CDDS_POSTERASE:
+                        drawBackground (nmcd.hdc);
+                        break;
+                    default:
+                }
+            }
+            break;
+        }
+        default:
+    }
+    return super.wmNotifyChild (hdr, wParam, lParam);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/CoolItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,728 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.CoolItem;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.CoolBar;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.TypedListener;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent the dynamically positionable
+ * areas of a <code>CoolBar</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>DROP_DOWN</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class CoolItem : Item {
+    CoolBar parent;
+    Control control;
+    int id;
+    bool ideal, minimum;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CoolBar</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (CoolBar parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>CoolBar</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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 at which to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (CoolBar parent, int style, int index) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners that will
+ * be notified when the control is selected by the user, by sending it one
+ * of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * If <code>widgetSelected</code> is called when the mouse is over
+ * the drop-down arrow (or 'chevron') portion of the cool item,
+ * the event object detail field contains the value <code>SWT.ARROW</code>,
+ * and the x and y fields in the event object represent the point at
+ * the bottom left of the chevron, where the menu should be popped up.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ *
+ * @since 2.0
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Returns the preferred size of the receiver.
+ * <p>
+ * The <em>preferred size</em> of a <code>CoolItem</code> is the size that
+ * it would best be displayed at. The width hint and height hint arguments
+ * allow the caller to ask the instance questions such as "Given a particular
+ * width, how high does it need to be to show all of the contents?"
+ * To indicate that the caller does not wish to constrain a particular
+ * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
+ * </p>
+ *
+ * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
+ * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
+ * @return the preferred size
+ *
+ * @exception SWTException <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 Layout
+ * @see #getBounds
+ * @see #getSize
+ * @see Control#getBorderWidth
+ * @see Scrollable#computeTrim
+ * @see Scrollable#getClientArea
+ */
+public Point computeSize (int wHint, int hHint) {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return new Point (0, 0);
+    int width = wHint, height = hHint;
+    if (wHint is SWT.DEFAULT) width = 32;
+    if (hHint is SWT.DEFAULT) height = 32;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        height += parent.getMargin (index);
+    } else {
+        width += parent.getMargin (index);
+    }
+    return new Point (width, height);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return new Rectangle (0, 0, 0, 0);
+    auto hwnd = parent.handle;
+    RECT rect;
+    OS.SendMessage (hwnd, OS.RB_GETRECT, index, &rect);
+    if (OS.COMCTL32_MAJOR >= 6) {
+        MARGINS margins;
+        OS.SendMessage (hwnd, OS.RB_GETBANDMARGINS, 0, &margins);
+        rect.left -= margins.cxLeftWidth;
+        rect.right += margins.cxRightWidth;
+    }
+    if (!parent.isLastItemOfRow (index)) {
+        rect.right += (parent.style & SWT.FLAT) is 0 ? CoolBar.SEPARATOR_WIDTH : 0;
+    }
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        return new Rectangle (rect.top, rect.left, height, width);
+    }
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+Rectangle getClientArea () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return new Rectangle (0, 0, 0, 0);
+    auto hwnd = parent.handle;
+    RECT insetRect;
+    OS.SendMessage (hwnd, OS.RB_GETBANDBORDERS, index, &insetRect);
+    RECT rect;
+    OS.SendMessage (hwnd, OS.RB_GETRECT, index, &rect);
+    int x = rect.left + insetRect.left;
+    int y = rect.top;
+    int width = rect.right - rect.left - insetRect.left;
+    int height = rect.bottom - rect.top;
+    if ((parent.style & SWT.FLAT) is 0) {
+        y += insetRect.top;
+        width -= insetRect.right;
+        height -= insetRect.top + insetRect.bottom;
+    }
+    if (index is 0) {
+        REBARBANDINFO rbBand;
+        rbBand.cbSize = REBARBANDINFO.sizeof;
+        rbBand.fMask = OS.RBBIM_HEADERSIZE;
+        OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+        width = width - rbBand.cxHeader + 1;
+    }
+    return new Rectangle (x, y, Math.max (0, width), Math.max (0, height));
+}
+
+/**
+ * Returns the control that is associated with the receiver.
+ *
+ * @return the control that is contained by the receiver
+ *
+ * @exception SWTException <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 Control getControl () {
+    checkWidget ();
+    return control;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>CoolBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 CoolBar getParent () {
+    checkWidget ();
+    return parent;
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+    id = -1;
+    control = null;
+}
+
+/**
+ * Sets the control that is associated with the receiver
+ * to the argument.
+ *
+ * @param control the new control that will be contained by the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setControl (Control control) {
+    checkWidget ();
+    if (control !is null) {
+        if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
+    }
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    if (this.control !is null && this.control.isDisposed ()) {
+        this.control = null;
+    }
+    Control oldControl = this.control, newControl = control;
+    auto hwnd = parent.handle;
+    auto hwndChild = newControl !is null ? control.topHandle () : null;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_CHILD;
+    rbBand.hwndChild = hwndChild;
+    this.control = newControl;
+
+    /*
+    * Feature in Windows.  When Windows sets the rebar band child,
+    * it makes the new child visible and hides the old child and
+    * moves the new child to the top of the Z-order.  The fix is
+    * to save and restore the visibility and Z-order.
+    */
+    HWND hwndAbove;
+    if (newControl !is null) {
+        hwndAbove = OS.GetWindow (hwndChild, OS.GW_HWNDPREV);
+    }
+    bool hideNew = newControl !is null && !newControl.getVisible ();
+    bool showOld = oldControl !is null && oldControl.getVisible ();
+    OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, &rbBand);
+    if (hideNew) newControl.setVisible (false);
+    if (showOld) oldControl.setVisible (true);
+    if (hwndAbove !is null && hwndAbove !is hwndChild) {
+        int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+        SetWindowPos (hwndChild, hwndAbove, 0, 0, 0, 0, flags);
+    }
+}
+
+/**
+ * Returns a point describing the receiver's ideal size.
+ * The x coordinate of the result is the ideal width of the receiver.
+ * The y coordinate of the result is the ideal height of the receiver.
+ *
+ * @return the receiver's ideal size
+ *
+ * @exception SWTException <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 Point getPreferredSize () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return new Point (0, 0);
+    auto hwnd = parent.handle;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_CHILDSIZE | OS.RBBIM_IDEALSIZE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+    int width = rbBand.cxIdeal + parent.getMargin (index);
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        return new Point (rbBand.cyMaxChild, width);
+    }
+    return new Point (width, rbBand.cyMaxChild);
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the arguments.
+ *
+ * @param width the new ideal width for the receiver
+ * @param height the new ideal height for the receiver
+ *
+ * @exception SWTException <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 setPreferredSize (int width, int height) {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    width = Math.max (0, width);
+    height = Math.max (0, height);
+    ideal = true;
+    auto hwnd = parent.handle;
+    int cxIdeal, cyMaxChild;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        cxIdeal = Math.max (0, height - parent.getMargin (index));
+        cyMaxChild = width;
+    } else {
+        cxIdeal = Math.max (0, width - parent.getMargin (index));
+        cyMaxChild = height;
+    }
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+
+    /* Get the child size fields first so we don't overwrite them. */
+    rbBand.fMask = OS.RBBIM_CHILDSIZE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+
+    /* Set the size fields we are currently modifying. */
+    rbBand.fMask = OS.RBBIM_CHILDSIZE | OS.RBBIM_IDEALSIZE;
+    rbBand.cxIdeal = cxIdeal;
+    rbBand.cyMaxChild = cyMaxChild;
+    if (!minimum) rbBand.cyMinChild = cyMaxChild;
+    OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, &rbBand);
+}
+
+/**
+ * Sets the receiver's ideal size to the point specified by the argument.
+ *
+ * @param size the new ideal size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setPreferredSize (Point size) {
+    checkWidget ();
+    if (size is null) error(SWT.ERROR_NULL_ARGUMENT);
+    setPreferredSize (size.x, size.y);
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException <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 Point getSize() {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) new Point (0, 0);
+    auto hwnd = parent.handle;
+    RECT rect;
+    OS.SendMessage (hwnd, OS.RB_GETRECT, index, &rect);
+    if (OS.COMCTL32_MAJOR >= 6) {
+        MARGINS margins;
+        OS.SendMessage (hwnd, OS.RB_GETBANDMARGINS, 0, &margins);
+        rect.left -= margins.cxLeftWidth;
+        rect.right += margins.cxRightWidth;
+    }
+    if (!parent.isLastItemOfRow (index)) {
+        rect.right += (parent.style & SWT.FLAT) is 0 ? CoolBar.SEPARATOR_WIDTH : 0;
+    }
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        return new Point (height, width);
+    }
+    return new Point (width, height);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the arguments.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause that
+ * value to be set to zero instead.
+ * </p>
+ *
+ * @param width the new width for the receiver
+ * @param height the new height for the receiver
+ *
+ * @exception SWTException <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 setSize (int width, int height) {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    width = Math.max (0, width);
+    height = Math.max (0, height);
+    auto hwnd = parent.handle;
+    int cx, cyChild, cxIdeal;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        cx = height;
+        cyChild = width;
+        cxIdeal = Math.max (0, height - parent.getMargin (index));
+    } else {
+        cx = width;
+        cyChild = height;
+        cxIdeal = Math.max (0, width - parent.getMargin (index));
+    }
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+
+    /* Get the child size fields first so we don't overwrite them. */
+    rbBand.fMask = OS.RBBIM_CHILDSIZE | OS.RBBIM_IDEALSIZE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+
+    /* Set the size fields we are currently modifying. */
+    if (!ideal) rbBand.cxIdeal = cxIdeal;
+    if (!minimum) rbBand.cyMinChild = cyChild;
+    rbBand.cyChild = cyChild;
+
+    /*
+    * Do not set the size for the last item on the row.
+    */
+    if (!parent.isLastItemOfRow (index)) {
+        if (OS.COMCTL32_MAJOR >= 6) {
+            MARGINS margins;
+            OS.SendMessage (hwnd, OS.RB_GETBANDMARGINS, 0, &margins);
+            cx -= margins.cxLeftWidth + margins.cxRightWidth;
+        }
+        int separator = (parent.style & SWT.FLAT) is 0 ? CoolBar.SEPARATOR_WIDTH : 0;
+        rbBand.cx = cx - separator;
+        rbBand.fMask |= OS.RBBIM_SIZE;
+    }
+    OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, &rbBand);
+}
+
+/**
+ * Sets the receiver's size to the point specified by the argument.
+ * <p>
+ * Note: Attempting to set the width or height of the
+ * receiver to a negative number will cause them to be
+ * set to zero instead.
+ * </p>
+ *
+ * @param size the new size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSize (Point size) {
+    if (size is null) error(SWT.ERROR_NULL_ARGUMENT);
+    setSize (size.x, size.y);
+}
+
+/**
+ * Returns the minimum size that the cool item can
+ * be resized to using the cool item's gripper.
+ *
+ * @return a point containing the minimum width and height of the cool item, in pixels
+ *
+ * @exception SWTException <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 2.0
+ */
+public Point getMinimumSize () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return new Point (0, 0);
+    auto hwnd = parent.handle;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_CHILDSIZE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        return new Point (rbBand.cyMinChild, rbBand.cxMinChild);
+    }
+    return new Point (rbBand.cxMinChild, rbBand.cyMinChild);
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the arguments.
+ *
+ * @param width the minimum width of the cool item, in pixels
+ * @param height the minimum height of the cool item, in pixels
+ *
+ * @exception SWTException <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 2.0
+ */
+public void setMinimumSize (int width, int height) {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    width = Math.max (0, width);
+    height = Math.max (0, height);
+    minimum = true;
+    auto hwnd = parent.handle;
+    int cxMinChild, cyMinChild;
+    if ((parent.style & SWT.VERTICAL) !is 0) {
+        cxMinChild = height;
+        cyMinChild = width;
+    } else {
+        cxMinChild = width;
+        cyMinChild = height;
+    }
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+
+    /* Get the child size fields first so we don't overwrite them. */
+    rbBand.fMask = OS.RBBIM_CHILDSIZE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+
+    /* Set the size fields we are currently modifying. */
+    rbBand.cxMinChild = cxMinChild;
+    rbBand.cyMinChild = cyMinChild;
+    OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, &rbBand);
+}
+
+/**
+ * Sets the minimum size that the cool item can be resized to
+ * using the cool item's gripper, to the point specified by the argument.
+ *
+ * @param size a point representing the minimum width and height of the cool item, in pixels
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ */
+public void setMinimumSize (Point size) {
+    checkWidget ();
+    if (size is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setMinimumSize (size.x, size.y);
+}
+
+bool getWrap() {
+    int index = parent.indexOf (this);
+    auto hwnd = parent.handle;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_STYLE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+    return (rbBand.fStyle & OS.RBBS_BREAK) !is 0;
+}
+
+void setWrap(bool wrap) {
+    int index = parent.indexOf (this);
+    auto hwnd = parent.handle;
+    REBARBANDINFO rbBand;
+    rbBand.cbSize = REBARBANDINFO.sizeof;
+    rbBand.fMask = OS.RBBIM_STYLE;
+    OS.SendMessage (hwnd, OS.RB_GETBANDINFO, index, &rbBand);
+    if (wrap) {
+        rbBand.fStyle |= OS.RBBS_BREAK;
+    } else {
+        rbBand.fStyle &= ~OS.RBBS_BREAK;
+    }
+    OS.SendMessage (hwnd, OS.RB_SETBANDINFO, index, &rbBand);
+}
+
+/**
+ * Removes the listener from the collection of listeners that
+ * will be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ *
+ * @since 2.0
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/DateTime.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,984 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.DateTime;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+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)
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that allow the user to enter and modify date
+ * or time values.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>DATE, TIME, CALENDAR, SHORT, MEDIUM, LONG</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles DATE, TIME, or CALENDAR may be specified,
+ * and only one of the styles SHORT, MEDIUM, or LONG may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#datetime">DateTime snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+
+public class DateTime : Composite {
+
+    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;
+    static /+const+/ WNDPROC CalendarProc;
+    static const TCHAR[] CalendarClass = OS.MONTHCAL_CLASS;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            INITCOMMONCONTROLSEX icex;
+            icex.dwSize = INITCOMMONCONTROLSEX.sizeof;
+            icex.dwICC = OS.ICC_DATE_CLASSES;
+            OS.InitCommonControlsEx (&icex);
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, DateTimeClass.ptr, &lpWndClass);
+            DateTimeProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The date time 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 SWT, 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 = DateTimeClass.length * TCHAR.sizeof;
+            auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, DateTimeClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
+            OS.GetClassInfo (null, CalendarClass.ptr, &lpWndClass);
+            CalendarProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The date time 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 SWT, could create a control with
+            * this class name, and fail unexpectedly.
+            */
+            hInstance = OS.GetModuleHandle (null);
+            hHeap = OS.GetProcessHeap ();
+            lpWndClass.hInstance = hInstance;
+            lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+            lpWndClass.style |= OS.CS_DBLCLKS;
+            byteCount = CalendarClass.length * TCHAR.sizeof;
+            lpszClassName = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, CalendarClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
+            static_this_completed = true;
+        }
+    }
+
+    static const int MARGIN = 4;
+    static const int MAX_DIGIT = 9;
+    static const int MAX_DAY = 31;
+    static const int MAX_12HOUR = 12;
+    static const int MAX_24HOUR = 24;
+    static const int MAX_MINUTE = 60;
+    static const int MONTH_DAY_YEAR = 0;
+    static const int DAY_MONTH_YEAR = 1;
+    static const int YEAR_MONTH_DAY = 2;
+    static const char SINGLE_QUOTE = '\''; //$NON-NLS-1$ short date format may include quoted text
+    static const char DAY_FORMAT_CONSTANT = 'd'; //$NON-NLS-1$ 1-4 lowercase 'd's represent day
+    static const char MONTH_FORMAT_CONSTANT = 'M'; //$NON-NLS-1$ 1-4 uppercase 'M's represent month
+    static const char YEAR_FORMAT_CONSTANT = 'y'; //$NON-NLS-1$ 1-5 lowercase 'y's represent year
+    static const char HOURS_FORMAT_CONSTANT = 'h'; //$NON-NLS-1$ 1-2 upper or lowercase 'h's represent hours
+    static const char MINUTES_FORMAT_CONSTANT = 'm'; //$NON-NLS-1$ 1-2 lowercase 'm's represent minutes
+    static const char SECONDS_FORMAT_CONSTANT = 's'; //$NON-NLS-1$ 1-2 lowercase 's's represent seconds
+    static const char AMPM_FORMAT_CONSTANT = 't'; //$NON-NLS-1$ 1-2 lowercase 't's represent am/pm
+    static const int[] MONTH_NAMES = [OS.LOCALE_SMONTHNAME1, OS.LOCALE_SMONTHNAME2, OS.LOCALE_SMONTHNAME3, OS.LOCALE_SMONTHNAME4, OS.LOCALE_SMONTHNAME5, OS.LOCALE_SMONTHNAME6, OS.LOCALE_SMONTHNAME7, OS.LOCALE_SMONTHNAME8, OS.LOCALE_SMONTHNAME9, OS.LOCALE_SMONTHNAME10, OS.LOCALE_SMONTHNAME11, OS.LOCALE_SMONTHNAME12];
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DATE
+ * @see SWT#TIME
+ * @see SWT#CALENDAR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+    if ((this.style & SWT.SHORT) !is 0) {
+        String buffer = ((this.style & SWT.DATE) !is 0) ? getCustomShortDateFormat() : getCustomShortTimeFormat();
+        TCHAR[] lpszFormat = StrToTCHARs (0, buffer, true);
+        OS.SendMessage (handle, OS.DTM_SETFORMAT, 0, lpszFormat.ptr);
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the control's value.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection, typedListener);
+    addListener (SWT.DefaultSelection, typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc ( cast(WNDPROC)windowProc(), hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
+    style = checkBits (style, SWT.DATE, SWT.TIME, SWT.CALENDAR, 0, 0, 0);
+    return checkBits (style, SWT.MEDIUM, SWT.SHORT, SWT.LONG, 0, 0, 0);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+        if ((style & SWT.CALENDAR) !is 0) {
+            RECT rect;
+            OS.SendMessage(handle, OS.MCM_GETMINREQRECT, 0, &rect);
+            width = rect.right;
+            height = rect.bottom;
+        } else {
+            TCHAR[] buffer = new TCHAR[128];
+            HFONT newFont, oldFont;
+            auto hDC = OS.GetDC (handle);
+            newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+            if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+            RECT rect;
+            int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+            SYSTEMTIME systime;
+            if ((style & SWT.DATE) !is 0) {
+                /* Determine the widest/tallest year string. */
+                systime.wMonth = 1;
+                systime.wDay = 1;
+                int widest = 0, secondWidest = 0, thirdWidest = 0;
+                for (int i = 0; i <= MAX_DIGIT; i++) {
+                    systime.wYear = cast(short) (2000 + i); // year 2000 + i is guaranteed to exist
+                    int size = OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, OS.DATE_SHORTDATE, &systime, null, buffer.ptr, buffer.length);
+                    if (size is 0) {
+                        buffer = new TCHAR[size];
+                        OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, OS.DATE_SHORTDATE, &systime, null, buffer.ptr, buffer.length);
+                    }
+                    rect.left = rect.top = rect.right = rect.bottom = 0;
+                    OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                    if (rect.right - rect.left >= width) {
+                        width = rect.right - rect.left;
+                        thirdWidest = secondWidest;
+                        secondWidest = widest;
+                        widest = i;
+                    }
+                    height = Math.max(height, rect.bottom - rect.top);
+                }
+                if (widest > 1) widest = widest * 1000 + widest * 100 + widest * 10 + widest;
+                else if (secondWidest > 1) widest = secondWidest * 1000 + widest * 100 + widest * 10 + widest;
+                else widest = thirdWidest * 1000 + widest * 100 + widest * 10 + widest;
+                systime.wYear = cast(short) widest;
+
+                /* Determine the widest/tallest month name string. */
+                width = widest = 0;
+                for (short i = 0; i < MONTH_NAMES.length; i++) {
+                    int name = MONTH_NAMES [i];
+                    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, name, buffer.ptr, buffer.length);
+                    if (size is 0) {
+                        buffer = new TCHAR[size];
+                        OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, name, buffer.ptr, buffer.length);
+                    }
+                    rect.left = rect.top = rect.right = rect.bottom = 0;
+                    OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                    if (rect.right - rect.left > width) {
+                        width = rect.right - rect.left;
+                        widest = i;
+                    }
+                    height = Math.max(height, rect.bottom - rect.top);
+                }
+                systime.wMonth = cast(short) (widest + 1);
+
+                /* Determine the widest/tallest date string in the widest month of the widest year. */
+                int dwFlags = ((style & SWT.MEDIUM) !is 0) ? OS.DATE_SHORTDATE : ((style & SWT.SHORT) !is 0) ? OS.DATE_YEARMONTH : OS.DATE_LONGDATE;
+                width = 0;
+                for (short i = 1; i <= MAX_DAY; i++) {
+                    systime.wDay = i;
+                    int size = OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    if (size is 0) {
+                        buffer = new TCHAR[size];
+                        OS.GetDateFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    }
+                    rect.left = rect.top = rect.right = rect.bottom = 0;
+                    OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                    width = Math.max(width, rect.right - rect.left);
+                    height = Math.max(height, rect.bottom - rect.top);
+                    if ((style & SWT.SHORT) !is 0) break;
+                }
+            } else if ((style & SWT.TIME) !is 0) {
+                /* Determine the widest/tallest hour string. This code allows for the possibility of ligatures. */
+                int dwFlags = ((style & SWT.SHORT) !is 0) ? OS.TIME_NOSECONDS : 0;
+                short widest = 0;
+                int max = is24HourTime () ? MAX_24HOUR : MAX_12HOUR;
+                for (short i = 0; i < max; i++) {
+                    systime.wHour = i;
+                    int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    if (size is 0) {
+                        buffer = new TCHAR[size];
+                        OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    }
+                    rect.left = rect.top = rect.right = rect.bottom = 0;
+                    OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                    if (rect.right - rect.left > width) {
+                        width = rect.right - rect.left;
+                        widest = i;
+                    }
+                    height = Math.max(height, rect.bottom - rect.top);
+                }
+                systime.wHour = widest;
+
+                /* Determine the widest/tallest minute and second string. */
+                width = widest = 0;
+                for (short i = 0; i < MAX_MINUTE; i++) {
+                    systime.wMinute = i;
+                    int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    if (size is 0) {
+                        buffer = new TCHAR[size];
+                        OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                    }
+                    rect.left = rect.top = rect.right = rect.bottom = 0;
+                    OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                    if (rect.right - rect.left > width) {
+                        width = rect.right - rect.left;
+                        widest = i;
+                    }
+                    height = Math.max(height, rect.bottom - rect.top);
+                }
+                systime.wMinute = widest;
+                systime.wSecond = widest;
+
+                /* Determine the widest/tallest time string for the widest hour, widest minute, and if applicable, widest second. */
+                int size = OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                if (size is 0) {
+                    buffer = new TCHAR[size];
+                    OS.GetTimeFormat(OS.LOCALE_USER_DEFAULT, dwFlags, &systime, null, buffer.ptr, buffer.length);
+                }
+                rect.left = rect.top = rect.right = rect.bottom = 0;
+                OS.DrawText (hDC, buffer.ptr, size, &rect, flags);
+                width = rect.right - rect.left;
+                height = Math.max(height, rect.bottom - rect.top);
+            }
+            if (newFont !is null) OS.SelectObject (hDC, oldFont);
+            OS.ReleaseDC (handle, hDC);
+            int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+            width += upDownWidth + MARGIN;
+            int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL);
+            // TODO: On Vista, can send DTM_GETDATETIMEPICKERINFO to ask the Edit control what its margins are
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) upDownHeight += 7;
+            height = Math.max (height, upDownHeight);
+        }
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2;
+    height += border * 2;
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    if ((style & SWT.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 () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+String getComputeSizeString () {
+    // TODO: Not currently used but might need for WinCE
+    if ((style & SWT.DATE) !is 0) {
+        if ((style & SWT.SHORT) !is 0) return getCustomShortDateFormat ();
+        if ((style & SWT.MEDIUM) !is 0) return getShortDateFormat ();
+        if ((style & SWT.LONG) !is 0) return getLongDateFormat ();
+    }
+    if ((style & SWT.TIME) !is 0) {
+        if ((style & SWT.SHORT) !is 0) return getCustomShortTimeFormat ();
+        return getTimeFormat ();
+    }
+    return "";
+}
+
+String getCustomShortDateFormat () {
+    if (true) {
+        TCHAR[] tchar = new TCHAR[80];
+        int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SYEARMONTH, tchar.ptr, 80);
+        return size !is 0 ? TCHARsToStr(tchar[0..size - 1])  : "M/yyyy"; //$NON-NLS-1$
+    }
+
+    //TODO: Not currently used, but may need for WinCE (or if numeric short date is required)
+    String buffer = getShortDateFormat ();
+    int length = buffer.length;
+    bool inQuotes = false;
+    int start = 0, end = 0;
+    while (start < length) {
+        char ch = buffer.charAt (start);
+        if (ch is SINGLE_QUOTE) inQuotes = !inQuotes;
+        else if (ch is DAY_FORMAT_CONSTANT && !inQuotes) {
+            end = start + 1;
+            while (end < length && buffer.charAt (end) is DAY_FORMAT_CONSTANT) end++;
+            int ordering = getShortDateFormatOrdering ();
+            switch (ordering) {
+            case MONTH_DAY_YEAR:
+                // skip the following separator
+                while (end < length && buffer.charAt (end) !is YEAR_FORMAT_CONSTANT) end++;
+                break;
+            case DAY_MONTH_YEAR:
+                // skip the following separator
+                while (end < length && buffer.charAt (end) !is MONTH_FORMAT_CONSTANT) end++;
+                break;
+            case YEAR_MONTH_DAY:
+                // skip the preceding separator
+                while (start > 0 && buffer.charAt (start) !is MONTH_FORMAT_CONSTANT) start--;
+                break;
+            default:
+            }
+            break;
+        }
+        start++;
+    }
+    if (start < end) buffer.length = start - 1;
+    return buffer;
+}
+
+String getCustomShortTimeFormat () {
+    String buffer = getTimeFormat ();
+    int length = buffer.length;
+    bool inQuotes = false;
+    int start = 0, end = 0;
+    while (start < length) {
+        char ch = buffer.charAt (start);
+        if (ch is SINGLE_QUOTE) inQuotes = !inQuotes;
+        else if (ch is SECONDS_FORMAT_CONSTANT && !inQuotes) {
+            end = start + 1;
+            while (end < length && buffer.charAt (end) is SECONDS_FORMAT_CONSTANT) end++;
+            // skip the preceding separator
+            while (start > 0 && buffer.charAt (start) !is MINUTES_FORMAT_CONSTANT) start--;
+            start++;
+            break;
+        }
+        start++;
+    }
+    if (start < end) buffer.length = start - 1;
+    return buffer;
+}
+
+String getLongDateFormat () {
+    //TODO: Not currently used, but may need for WinCE
+    TCHAR tchar[80];
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SLONGDATE, tchar.ptr, 80);
+    return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "dddd, MMMM dd, yyyy"; //$NON-NLS-1$
+}
+
+String getShortDateFormat () {
+    //TODO: Not currently used, but may need for WinCE
+    TCHAR tchar[80];
+    //TODO: May need to OR with LOCALE_ICENTURY
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SSHORTDATE, tchar.ptr, 80);
+    return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "M/d/yyyy"; //$NON-NLS-1$
+}
+
+int getShortDateFormatOrdering () {
+    //TODO: Not currently used, but may need for WinCE
+    TCHAR tchar[80];
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_IDATE, tchar.ptr, 4);
+    if (size > 0) {
+        String number = TCHARsToStr(tchar[0..size - 1]);
+        return Integer.parse (number);
+    }
+    return 0;
+}
+
+String getTimeFormat () {
+    TCHAR tchar[80];
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_STIMEFORMAT, tchar.ptr, 80);
+    return size > 0 ? TCHARsToStr(tchar[0..size - 1]) : "h:mm:ss tt"; //$NON-NLS-1$
+}
+
+bool is24HourTime () {
+    TCHAR tchar[4];
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_ITIME, tchar.ptr, 4);
+    if (size > 0) {
+        String number = TCHARsToStr(tchar[0..size - 1]);
+        return Integer.parse (number) !is 0;
+    }
+    return true;
+}
+
+/**
+ * Returns the receiver's date, or day of the month.
+ * <p>
+ * The first day of the month is 1, and the last day depends on the month and year.
+ * </p>
+ *
+ * @return a positive integer beginning with 1
+ *
+ * @exception SWTException <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 int getDay () {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    return systime.wDay;
+}
+
+/**
+ * Returns the receiver's hours.
+ * <p>
+ * Hours is an integer between 0 and 23.
+ * </p>
+ *
+ * @return an integer between 0 and 23
+ *
+ * @exception SWTException <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 int getHours () {
+    checkWidget ();
+    if ((style & SWT.CALENDAR) !is 0) return time.wHour;
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    return systime.wHour;
+}
+
+/**
+ * Returns the receiver's minutes.
+ * <p>
+ * Minutes is an integer between 0 and 59.
+ * </p>
+ *
+ * @return an integer between 0 and 59
+ *
+ * @exception SWTException <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 int getMinutes () {
+    checkWidget ();
+    if ((style & SWT.CALENDAR) !is 0) return time.wMinute;
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    return systime.wMinute;
+}
+
+/**
+ * Returns the receiver's month.
+ * <p>
+ * The first month of the year is 0, and the last month is 11.
+ * </p>
+ *
+ * @return an integer between 0 and 11
+ *
+ * @exception SWTException <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 int getMonth () {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    return systime.wMonth - 1;
+}
+
+override String getNameText () {
+    return (style & SWT.TIME) !is 0 ? Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds())
+            : Format("{}/{}/{}", (getMonth() + 1), getDay(), getYear());
+}
+
+/**
+ * Returns the receiver's seconds.
+ * <p>
+ * Seconds is an integer between 0 and 59.
+ * </p>
+ *
+ * @return an integer between 0 and 59
+ *
+ * @exception SWTException <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 int getSeconds () {
+    checkWidget ();
+    if ((style & SWT.CALENDAR) !is 0) return time.wSecond;
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    return systime.wSecond;
+}
+
+/**
+ * Returns the receiver's year.
+ * <p>
+ * The first year is 1752 and the last year is 9999.
+ * </p>
+ *
+ * @return an integer between 1752 and 9999
+ *
+ * @exception SWTException <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 int getYear () {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    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.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+/**
+ * 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 SWTException <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 & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.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.
+ * </p>
+ *
+ * @param day a positive integer beginning with 1
+ *
+ * @exception SWTException <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 setDay (int day) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wDay = cast(short)day;
+    OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
+}
+
+/**
+ * Sets the receiver's hours.
+ * <p>
+ * Hours is an integer between 0 and 23.
+ * </p>
+ *
+ * @param hours an integer between 0 and 23
+ *
+ * @exception SWTException <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 setHours (int hours) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wHour = cast(short)hours;
+    OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & SWT.CALENDAR) !is 0 && hours >= 0 && hours <= 23) time.wHour = cast(short)hours;
+}
+
+/**
+ * Sets the receiver's minutes.
+ * <p>
+ * Minutes is an integer between 0 and 59.
+ * </p>
+ *
+ * @param minutes an integer between 0 and 59
+ *
+ * @exception SWTException <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 setMinutes (int minutes) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wMinute = cast(short)minutes;
+    OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & SWT.CALENDAR) !is 0 && minutes >= 0 && minutes <= 59) time.wMinute = cast(short)minutes;
+}
+
+/**
+ * Sets the receiver's month.
+ * <p>
+ * The first month of the year is 0, and the last month is 11.
+ * </p>
+ *
+ * @param month an integer between 0 and 11
+ *
+ * @exception SWTException <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 setMonth (int month) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wMonth = cast(short)(month + 1);
+    OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
+}
+
+/**
+ * Sets the receiver's seconds.
+ * <p>
+ * Seconds is an integer between 0 and 59.
+ * </p>
+ *
+ * @param seconds an integer between 0 and 59
+ *
+ * @exception SWTException <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 setSeconds (int seconds) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wSecond = cast(short)seconds;
+    OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & SWT.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 SWTException <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 & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.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 & SWT.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;
+    }
+}
+
+/**
+ * Sets the receiver's year.
+ * <p>
+ * The first year is 1752 and the last year is 9999.
+ * </p>
+ *
+ * @param year an integer between 1752 and 9999
+ *
+ * @exception SWTException <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 setYear (int year) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & SWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & SWT.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 () {
+    int bits = super.widgetStyle () | OS.WS_TABSTOP;
+    if ((style & SWT.CALENDAR) !is 0) return bits | OS.MCS_NOTODAY;
+    /*
+    * Bug in Windows: When WS_CLIPCHILDREN is set in a
+    * Date and Time Picker, the widget draws on top of
+    * the updown control. The fix is to clear the bits.
+    */
+    bits &= ~OS.WS_CLIPCHILDREN;
+    if ((style & SWT.TIME) !is 0) bits |= OS.DTS_TIMEFORMAT;
+    if ((style & SWT.DATE) !is 0) bits |= ((style & SWT.MEDIUM) !is 0 ? OS.DTS_SHORTDATECENTURYFORMAT : OS.DTS_LONGDATEFORMAT) | OS.DTS_UPDOWN;
+    return bits;
+}
+
+override String windowClass () {
+    return (style & SWT.CALENDAR) !is 0 ? TCHARsToStr(CalendarClass) : TCHARsToStr(DateTimeClass);
+}
+
+override int windowProc () {
+    return (style & SWT.CALENDAR) !is 0 ? cast(int)CalendarProc : cast(int)DateTimeProc;
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    switch (hdr.code) {
+        case OS.MCN_SELCHANGE:
+        case OS.DTN_DATETIMECHANGE:
+            if (ignoreSelection) break;
+            SYSTEMTIME systime;
+            int msg = (style & SWT.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 (SWT.Selection);
+                if ((style & SWT.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);
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Decorations.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1833 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Decorations;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide the appearance and
+ * behavior of <code>Shells</code>, but are not top
+ * level shells or dialogs. Class <code>Shell</code>
+ * shares a significant amount of code with this class,
+ * and is a subclass.
+ * <p>
+ * IMPORTANT: This class was intended to be abstract and
+ * should <em>never</em> be referenced or instantiated.
+ * Instead, the class <code>Shell</code> should be used.
+ * </p>
+ * <p>
+ * Instances are always displayed in one of the maximized,
+ * minimized or normal states:
+ * <ul>
+ * <li>
+ * When an instance is marked as <em>maximized</em>, the
+ * window manager will typically resize it to fill the
+ * entire visible area of the display, and the instance
+ * is usually put in a state where it can not be resized
+ * (even if it has style <code>RESIZE</code>) until it is
+ * no longer maximized.
+ * </li><li>
+ * When an instance is in the <em>normal</em> state (neither
+ * maximized or minimized), its appearance is controlled by
+ * the style constants which were specified when it was created
+ * and the restrictions of the window manager (see below).
+ * </li><li>
+ * When an instance has been marked as <em>minimized</em>,
+ * its contents (client area) will usually not be visible,
+ * and depending on the window manager, it may be
+ * "iconified" (that is, replaced on the desktop by a small
+ * simplified representation of itself), relocated to a
+ * distinguished area of the screen, or hidden. Combinations
+ * of these changes are also possible.
+ * </li>
+ * </ul>
+ * </p>
+ * Note: The styles supported by this class must be treated
+ * as <em>HINT</em>s, since the window manager for the
+ * desktop on which the instance is visible has ultimate
+ * control over the appearance and behavior of decorations.
+ * For example, some window managers only support resizable
+ * windows and will always assume the RESIZE style, even if
+ * it is not set.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * Class <code>SWT</code> provides two "convenience constants"
+ * for the most commonly required style combinations:
+ * <dl>
+ * <dt><code>SHELL_TRIM</code></dt>
+ * <dd>
+ * the result of combining the constants which are required
+ * to produce a typical application top level shell: (that
+ * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
+ * </dd>
+ * <dt><code>DIALOG_TRIM</code></dt>
+ * <dd>
+ * the result of combining the constants which are required
+ * to produce a typical application dialog shell: (that
+ * is, <code>TITLE | CLOSE | BORDER</code>)
+ * </dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see #getMinimized
+ * @see #getMaximized
+ * @see Shell
+ * @see SWT
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Decorations : Canvas {
+
+    alias Canvas.setBounds setBounds;
+    alias Canvas.setParent setParent;
+    alias Canvas.setSavedFocus setSavedFocus;
+    alias Canvas.sort sort;
+    alias Canvas.windowProc windowProc;
+
+    Image image, smallImage, largeImage;
+    Image [] images;
+    Menu menuBar;
+    Menu [] menus;
+    Control savedFocus;
+    Button defaultButton, saveDefault;
+    int swFlags;
+    HACCEL hAccel;
+    int nAccel;
+    bool moved, resized, opened;
+    int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT;
+    int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#TOOL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, checkStyle (style));
+}
+
+void _setMaximized (bool maximized) {
+    swFlags = maximized ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
+    static if (OS.IsWinCE) {
+        /*
+        * Note: WinCE does not support SW_SHOWMAXIMIZED and SW_RESTORE. The
+        * workaround is to resize the window to fit the parent client area.
+        */
+        if (maximized) {
+            RECT rect;
+            OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
+            int width = rect.right - rect.left, height = rect.bottom - rect.top;
+            if (OS.IsPPC) {
+                /* Leave space for the menu bar */
+                if (menuBar !is null) {
+                    auto hwndCB = menuBar.hwndCB;
+                    RECT rectCB;
+                    OS.GetWindowRect (hwndCB, &rectCB);
+                    height -= rectCB.bottom - rectCB.top;
+                }
+            }
+            int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+            SetWindowPos (handle, null, rect.left, rect.top, width, height, flags);
+        }
+    } else {
+        if (!OS.IsWindowVisible (handle)) return;
+        if (maximized is OS.IsZoomed (handle)) return;
+        OS.ShowWindow (handle, swFlags);
+        OS.UpdateWindow (handle);
+    }
+}
+
+void _setMinimized (bool minimized) {
+    static if (OS.IsWinCE) return;
+    swFlags = minimized ? OS.SW_SHOWMINNOACTIVE : OS.SW_RESTORE;
+    if (!OS.IsWindowVisible (handle)) return;
+    if (minimized is OS.IsIconic (handle)) return;
+    int flags = swFlags;
+    if (flags is OS.SW_SHOWMINNOACTIVE && handle is OS.GetActiveWindow ()) {
+        flags = OS.SW_MINIMIZE;
+    }
+    OS.ShowWindow (handle, flags);
+    OS.UpdateWindow (handle);
+}
+
+void addMenu (Menu menu) {
+    if (menus is null) menus = new Menu [4];
+    for (int i=0; i<menus.length; i++) {
+        if (menus [i] is null) {
+            menus [i] = menu;
+            return;
+        }
+    }
+    Menu [] newMenus = new Menu [menus.length + 4];
+    newMenus [menus.length] = menu;
+    System.arraycopy (menus, 0, newMenus, 0, menus.length);
+    menus = newMenus;
+}
+
+void bringToTop () {
+    /*
+    * This code is intentionally commented.  On some platforms,
+    * the ON_TOP style creates a shell that will stay on top
+    * of every other shell on the desktop.  Using SetWindowPos ()
+    * with HWND_TOP caused problems on Windows 98 so this code is
+    * commented out until this functionality is specified and
+    * the problems are fixed.
+    */
+//  if ((style & SWT.ON_TOP) !is 0) {
+//      int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+//      OS.SetWindowPos (handle, OS.HWND_TOP, 0, 0, 0, 0, flags);
+//  } else {
+        OS.BringWindowToTop (handle);
+        // widget could be disposed at this point
+//  }
+}
+
+static int checkStyle (int style) {
+    if ((style & SWT.NO_TRIM) !is 0) {
+        style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER);
+    }
+    static if (OS.IsWinCE) {
+        /*
+        * Feature in WinCE PPC.  WS_MINIMIZEBOX or WS_MAXIMIZEBOX
+        * are not supposed to be used.  If they are, the result
+        * is a button which does not repaint correctly.  The fix
+        * is to remove this style.
+        */
+        if ((style & SWT.MIN) !is 0) style &= ~SWT.MIN;
+        if ((style & SWT.MAX) !is 0) style &= ~SWT.MAX;
+        return style;
+    }
+    if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) !is 0) {
+        style |= SWT.TITLE;
+    }
+
+    /*
+    * If either WS_MINIMIZEBOX or WS_MAXIMIZEBOX are set,
+    * we must also set WS_SYSMENU or the buttons will not
+    * appear.
+    */
+    if ((style & (SWT.MIN | SWT.MAX)) !is 0) style |= SWT.CLOSE;
+
+    /*
+    * Both WS_SYSMENU and WS_CAPTION must be set in order
+    * to for the system menu to appear.
+    */
+    if ((style & SWT.CLOSE) !is 0) style |= SWT.TITLE;
+
+    /*
+    * Bug in Windows.  The WS_CAPTION style must be
+    * set when the window is resizable or it does not
+    * draw properly.
+    */
+    /*
+    * This code is intentionally commented.  It seems
+    * that this problem originally in Windows 3.11,
+    * has been fixed in later versions.  Because the
+    * exact nature of the drawing problem is unknown,
+    * keep the commented code around in case it comes
+    * back.
+    */
+//  if ((style & SWT.RESIZE) !is 0) style |= SWT.TITLE;
+
+    return style;
+}
+
+override void checkBorder () {
+    /* Do nothing */
+}
+
+void checkComposited (Composite parent) {
+    /* Do nothing */
+}
+
+override void checkOpened () {
+    if (!opened) resized = false;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.DefMDIChildProc (hwnd, msg, wParam, lParam);
+}
+
+void closeWidget () {
+    Event event = new Event ();
+    sendEvent (SWT.Close, event);
+    if (event.doit && !isDisposed ()) dispose ();
+}
+
+int compare (ImageData data1, ImageData data2, int width, int height, int depth) {
+    int value1 = Math.abs (data1.width - width), value2 = Math.abs (data2.width - width);
+    if (value1 is value2) {
+        int transparent1 = data1.getTransparencyType ();
+        int transparent2 = data2.getTransparencyType ();
+        if (transparent1 is transparent2) {
+            if (data1.depth is data2.depth) return 0;
+            return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1;
+        }
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            if (transparent1 is SWT.TRANSPARENCY_ALPHA) return -1;
+            if (transparent2 is SWT.TRANSPARENCY_ALPHA) return 1;
+        }
+        if (transparent1 is SWT.TRANSPARENCY_MASK) return -1;
+        if (transparent2 is SWT.TRANSPARENCY_MASK) return 1;
+        if (transparent1 is SWT.TRANSPARENCY_PIXEL) return -1;
+        if (transparent2 is SWT.TRANSPARENCY_PIXEL) return 1;
+        return 0;
+    }
+    return value1 < value2 ? -1 : 1;
+}
+
+override Control computeTabGroup () {
+    return this;
+}
+
+override Control computeTabRoot () {
+    return this;
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+
+    /* Get the size of the trimmings */
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+    bool hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) !is null;
+    OS.AdjustWindowRectEx (&rect, bits1, hasMenu, bits2);
+
+    /* Get the size of the scroll bars */
+    if (horizontalBar !is null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    if (verticalBar !is null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+
+    /* Compute the height of the menu bar */
+    if (hasMenu) {
+        RECT testRect;
+        OS.SetRect (&testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
+        OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &testRect);
+        while ((testRect.bottom - testRect.top) < height) {
+            if (testRect.bottom - testRect.top is 0) break;
+            rect.top -= OS.GetSystemMetrics (OS.SM_CYMENU) - OS.GetSystemMetrics (OS.SM_CYBORDER);
+            OS.SetRect (&testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
+            OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &testRect);
+        }
+    }
+    return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void createAccelerators () {
+    hAccel = null;
+    nAccel = 0;
+    int maxAccel = 0;
+    MenuItem [] items = display.items;
+    if (menuBar is null || items is null) {
+        if (!OS.IsPPC) return;
+        maxAccel = 1;
+    } else {
+        maxAccel = OS.IsPPC ? items.length + 1 : items.length;
+    }
+    ACCEL accel;
+    byte [] buffer1 = new byte [ACCEL.sizeof];
+    byte [] buffer2 = new byte [maxAccel * ACCEL.sizeof];
+    if (menuBar !is null && items !is null) {
+        for (int i=0; i<items.length; i++) {
+            MenuItem item = items [i];
+            if (item !is null && item.accelerator !is 0) {
+                Menu menu = item.parent;
+                if (menu.parent is this) {
+                    while (menu !is null && menu !is menuBar) {
+                        menu = menu.getParentMenu ();
+                    }
+                    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);
+                        nAccel++;
+                    }
+                }
+            }
+        }
+    }
+    if (OS.IsPPC) {
+        /*
+        * Note on WinCE PPC.  Close the shell when user taps CTRL-Q.
+        * IDOK represents the "Done Button" which also closes the shell.
+        */
+        accel.fVirt = cast(byte) (OS.FVIRTKEY | OS.FCONTROL);
+        accel.key = cast(short) 'Q';
+        accel.cmd = cast(short) OS.IDOK;
+        *cast(ACCEL*)buffer1.ptr = accel;
+        //OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
+        System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
+        nAccel++;
+    }
+    if (nAccel !is 0) hAccel = OS.CreateAcceleratorTable ( cast(ACCEL*)buffer2.ptr, nAccel);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    if (parent !is null || ((style & SWT.TOOL) !is 0)) {
+        setParent ();
+        setSystemMenu ();
+    }
+}
+
+override void createWidget () {
+    super.createWidget ();
+    swFlags = OS.IsWinCE ? OS.SW_SHOWMAXIMIZED : OS.SW_SHOWNOACTIVATE;
+    hAccel = cast(HACCEL)-1;
+}
+
+void destroyAccelerators () {
+    if (hAccel !is null && hAccel !is cast(HACCEL)-1) OS.DestroyAcceleratorTable (hAccel);
+    hAccel = cast(HACCEL)-1;
+}
+
+override public void dispose () {
+    if (isDisposed()) return;
+    if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    if (!(cast(Shell)this)) {
+        if (!traverseDecorations (true)) {
+            Shell shell = getShell ();
+            shell.setFocus ();
+        }
+        setVisible (false);
+    }
+    super.dispose ();
+}
+
+Menu findMenu (HMENU hMenu) {
+    if (menus is null) return null;
+    for (int i=0; i<menus.length; i++) {
+        Menu menu = menus [i];
+        if (menu !is null && hMenu is menu.handle) return menu;
+    }
+    return null;
+}
+
+void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) {
+    if (this is newDecorations) return;
+    if (control is savedFocus) savedFocus = null;
+    if (control is defaultButton) defaultButton = null;
+    if (control is saveDefault) saveDefault = null;
+    if (menus is null) return;
+    Menu menu = control.menu;
+    if (menu !is null) {
+        int index = 0;
+        while (index <menus.length) {
+            if (menus [index] is menu) {
+                control.setMenu (null);
+                return;
+            }
+            index++;
+        }
+        menu.fixMenus (newDecorations);
+        destroyAccelerators ();
+        newDecorations.destroyAccelerators ();
+    }
+}
+
+override public Rectangle getBounds () {
+    checkWidget ();
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) {
+            WINDOWPLACEMENT lpwndpl;
+            lpwndpl.length = WINDOWPLACEMENT.sizeof;
+            OS.GetWindowPlacement (handle, &lpwndpl);
+            int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left;
+            int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top;
+            return new Rectangle (lpwndpl.rcNormalPosition.left, lpwndpl.rcNormalPosition.top, width, height);
+        }
+    }
+    return super.getBounds ();
+}
+
+override public Rectangle getClientArea () {
+    checkWidget ();
+    /*
+    * Note: The CommandBar is part of the client area,
+    * not the trim.  Applications don't expect this so
+    * subtract the height of the CommandBar.
+    */
+    static if (OS.IsHPC) {
+        Rectangle rect = super.getClientArea ();
+        if (menuBar !is null) {
+            auto hwndCB = menuBar.hwndCB;
+            int height = OS.CommandBar_Height (hwndCB);
+            rect.y += height;
+            rect.height = Math.max (0, rect.height - height);
+        }
+        return rect;
+    }
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) {
+            WINDOWPLACEMENT lpwndpl;
+            lpwndpl.length = WINDOWPLACEMENT.sizeof;
+            OS.GetWindowPlacement (handle, &lpwndpl);
+            int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left;
+            int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top;
+            /*
+            * Feature in Windows.  For some reason WM_NCCALCSIZE does
+            * not compute the client area when the window is minimized.
+            * The fix is to compute it using AdjustWindowRectEx() and
+            * GetSystemMetrics().
+            *
+            * NOTE: This code fails to compute the correct client area
+            * for a minimized window where the menu bar would wrap were
+            * the window restored.  There is no fix for this problem at
+            * this time.
+            */
+            if (horizontalBar !is null) width -= OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+            if (verticalBar !is null) height -= OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+            RECT rect;
+            int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+            bool hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) !is null;
+            OS.AdjustWindowRectEx (&rect, bits1, hasMenu, bits2);
+            width = Math.max (0, width - (rect.right - rect.left));
+            height = Math.max (0, height - (rect.bottom - rect.top));
+            return new Rectangle (0, 0, width, height);
+        }
+    }
+    return super.getClientArea ();
+}
+
+/**
+ * Returns the receiver's default button if one had
+ * previously been set, otherwise returns null.
+ *
+ * @return the default button or null
+ *
+ * @exception SWTException <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 #setDefaultButton(Button)
+ */
+public Button getDefaultButton () {
+    checkWidget ();
+    return defaultButton;
+}
+
+/**
+ * Returns the receiver's image if it had previously been
+ * set using <code>setImage()</code>. The image is typically
+ * displayed by the window manager when the instance is
+ * marked as iconified, and may also be displayed somewhere
+ * in the trim when the instance is in normal or maximized
+ * states.
+ * <p>
+ * Note: This method will return null if called before
+ * <code>setImage()</code> is called. It does not provide
+ * access to a window manager provided, "default" image
+ * even if one exists.
+ * </p>
+ *
+ * @return the image
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget ();
+    return image;
+}
+
+/**
+ * Returns the receiver's images if they had previously been
+ * set using <code>setImages()</code>. Images are typically
+ * displayed by the window manager when the instance is
+ * marked as iconified, and may also be displayed somewhere
+ * in the trim when the instance is in normal or maximized
+ * states. Depending where the icon is displayed, the platform
+ * chooses the icon with the "best" attributes.  It is expected
+ * that the array will contain the same icon rendered at different
+ * sizes, with different depth and transparency attributes.
+ *
+ * <p>
+ * Note: This method will return an empty array if called before
+ * <code>setImages()</code> is called. It does not provide
+ * access to a window manager provided, "default" image
+ * even if one exists.
+ * </p>
+ *
+ * @return the images
+ *
+ * @exception SWTException <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.0
+ */
+public Image [] getImages () {
+    checkWidget ();
+    if (images is null) return new Image [0];
+    Image [] result = new Image [images.length];
+    System.arraycopy (images, 0, result, 0, images.length);
+    return result;
+}
+
+override public Point getLocation () {
+    checkWidget ();
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) {
+            WINDOWPLACEMENT lpwndpl;
+            lpwndpl.length = WINDOWPLACEMENT.sizeof;
+            OS.GetWindowPlacement (handle, &lpwndpl);
+            return new Point (lpwndpl.rcNormalPosition.left, lpwndpl.rcNormalPosition.top);
+        }
+    }
+    return super.getLocation ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is currently
+ * maximized, and false otherwise.
+ * <p>
+ *
+ * @return the maximized state
+ *
+ * @exception SWTException <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 #setMaximized
+ */
+public bool getMaximized () {
+    checkWidget ();
+    static if (OS.IsWinCE) return swFlags is OS.SW_SHOWMAXIMIZED;
+    if (OS.IsWindowVisible (handle)) return cast(bool) OS.IsZoomed (handle);
+    return swFlags is OS.SW_SHOWMAXIMIZED;
+}
+
+/**
+ * Returns the receiver's menu bar if one had previously
+ * been set, otherwise returns null.
+ *
+ * @return the menu bar or null
+ *
+ * @exception SWTException <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 Menu getMenuBar () {
+    checkWidget ();
+    return menuBar;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is currently
+ * minimized, and false otherwise.
+ * <p>
+ *
+ * @return the minimized state
+ *
+ * @exception SWTException <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 #setMinimized
+ */
+public bool getMinimized () {
+    checkWidget ();
+    static if (OS.IsWinCE) return false;
+    if (OS.IsWindowVisible (handle)) return cast(bool) OS.IsIconic (handle);
+    return swFlags is OS.SW_SHOWMINNOACTIVE;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+override public Point getSize () {
+    checkWidget ();
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) {
+            WINDOWPLACEMENT lpwndpl;
+            lpwndpl.length = WINDOWPLACEMENT.sizeof;
+            OS.GetWindowPlacement (handle, &lpwndpl);
+            int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left;
+            int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top;
+            return new Point (width, height);
+        }
+    }
+    return super.getSize ();
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>. If the text has not previously been set,
+ * returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    int length = OS.GetWindowTextLength (handle);
+    if (length is 0) return "";
+    /* Use the character encoding for the default locale */
+    TCHAR[] buffer;
+    buffer.length = length + 1;
+    OS.GetWindowText (handle, buffer.ptr, length + 1);
+    return TCHARsToStr( buffer );
+}
+
+override public bool isReparentable () {
+    checkWidget ();
+    /*
+    * Feature in Windows.  Calling SetParent() for a shell causes
+    * a kind of fake MDI to happen.  It doesn't work well on Windows
+    * and is not supported on the other platforms.  The fix is to
+    * disallow the SetParent().
+    */
+    return false;
+}
+
+override bool isTabGroup () {
+    /*
+    * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+    */
+    return true;
+}
+
+override bool isTabItem () {
+    /*
+    * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
+    */
+    return false;
+}
+
+override Decorations menuShell () {
+    return this;
+}
+
+override void releaseChildren (bool destroy) {
+    if (menuBar !is null) {
+        menuBar.release (false);
+        menuBar = null;
+    }
+    super.releaseChildren (destroy);
+    if (menus !is null) {
+        for (int i=0; i<menus.length; i++) {
+            Menu menu = menus [i];
+            if (menu !is null && !menu.isDisposed ()) {
+                menu.dispose ();
+            }
+        }
+        menus = null;
+    }
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (smallImage !is null) smallImage.dispose ();
+    if (largeImage !is null) largeImage.dispose ();
+    smallImage = largeImage = image = null;
+    images = null;
+    savedFocus = null;
+    defaultButton = saveDefault = null;
+    if (hAccel !is null && hAccel !is cast(HACCEL)-1) OS.DestroyAcceleratorTable (hAccel);
+    hAccel = cast(HACCEL)-1;
+}
+
+void removeMenu (Menu menu) {
+    if (menus is null) return;
+    for (int i=0; i<menus.length; i++) {
+        if (menus [i] is menu) {
+            menus [i] = null;
+            return;
+        }
+    }
+}
+
+bool restoreFocus () {
+    if (display.ignoreRestoreFocus) return true;
+    if (savedFocus !is null && savedFocus.isDisposed ()) savedFocus = null;
+    if (savedFocus !is null && savedFocus.setSavedFocus ()) return true;
+    /*
+    * This code is intentionally commented.  When no widget
+    * has been given focus, some platforms give focus to the
+    * default button.  Windows doesn't do this.
+    */
+//  if (defaultButton !is null && !defaultButton.isDisposed ()) {
+//      if (defaultButton.setFocus ()) return true;
+//  }
+    return false;
+}
+
+void saveFocus () {
+    Control control = display._getFocusControl ();
+    if (control !is null && control !is this && this is control.menuShell ()) {
+        setSavedFocus (control);
+    }
+}
+
+override void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    static if (OS.IsWinCE) {
+        swFlags = OS.SW_RESTORE;
+    } else {
+        if (OS.IsIconic (handle)) {
+            setPlacement (x, y, width, height, flags);
+            return;
+        }
+    }
+    forceResize ();
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    bool sameOrigin = true;
+    if ((OS.SWP_NOMOVE & flags) is 0) {
+        sameOrigin = rect.left is x && rect.top is y;
+        if (!sameOrigin) moved = true;
+    }
+    bool sameExtent = true;
+    if ((OS.SWP_NOSIZE & flags) is 0) {
+        sameExtent = rect.right - rect.left is width && rect.bottom - rect.top is height;
+        if (!sameExtent) resized = true;
+    }
+    static if (!OS.IsWinCE) {
+        if (OS.IsZoomed (handle)) {
+            if (sameOrigin && sameExtent) return;
+            setPlacement (x, y, width, height, flags);
+            _setMaximized (false);
+            return;
+        }
+    }
+    super.setBounds (x, y, width, height, flags, defer);
+}
+
+/**
+ * If the argument is not null, sets the receiver's default
+ * button to the argument, and if the argument is null, sets
+ * the receiver's default button to the first button which
+ * was set as the receiver's default button (called the
+ * <em>saved default button</em>). If no default button had
+ * previously been set, or the saved default button was
+ * disposed, the receiver's default button will be set to
+ * null.
+ * <p>
+ * The default button is the button that is selected when
+ * the receiver is active and the user presses ENTER.
+ * </p>
+ *
+ * @param button the new default button
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setDefaultButton (Button button) {
+    checkWidget ();
+    if (button !is null) {
+        if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (button.menuShell () !is this) error(SWT.ERROR_INVALID_PARENT);
+    }
+    setDefaultButton (button, true);
+}
+
+void setDefaultButton (Button button, bool save) {
+    if (button is null) {
+        if (defaultButton is saveDefault) {
+            if (save) saveDefault = null;
+            return;
+        }
+    } else {
+        if ((button.style & SWT.PUSH) is 0) return;
+        if (button is defaultButton) return;
+    }
+    if (defaultButton !is null) {
+        if (!defaultButton.isDisposed ()) defaultButton.setDefault (false);
+    }
+    if ((defaultButton = button) is null) defaultButton = saveDefault;
+    if (defaultButton !is null) {
+        if (!defaultButton.isDisposed ()) defaultButton.setDefault (true);
+    }
+    if (save) saveDefault = defaultButton;
+    if (saveDefault !is null && saveDefault.isDisposed ()) saveDefault = null;
+}
+
+/**
+ * Sets the receiver's image to the argument, which may
+ * be null. The image is typically displayed by the window
+ * manager when the instance is marked as iconified, and
+ * may also be displayed somewhere in the trim when the
+ * instance is in normal or maximized states.
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image image) {
+    checkWidget ();
+    if (image !is null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    this.image = image;
+    setImages (image, null);
+}
+
+void setImages (Image image, Image [] images) {
+    /*
+    * Feature in WinCE.  WM_SETICON and WM_GETICON set the icon
+    * for the window class, not the window instance.  This means
+    * that it is possible to set an icon into a window and then
+    * later free the icon, thus freeing the icon for every window.
+    * The fix is to avoid the API.
+    *
+    * On WinCE PPC, icons in windows are not displayed.
+    */
+    static if (OS.IsWinCE) return;
+    if (smallImage !is null) smallImage.dispose ();
+    if (largeImage !is null) largeImage.dispose ();
+    smallImage = largeImage = null;
+    HICON hSmallIcon, hLargeIcon;
+    Image smallIcon = null, largeIcon = null;
+    if (image !is null) {
+        smallIcon = largeIcon = image;
+    } else {
+        if (images !is null && images.length > 0) {
+            int depth = display.getIconDepth ();
+            ImageData [] datas = null;
+            if (images.length > 1) {
+                Image [] bestImages = new Image [images.length];
+                System.arraycopy (images, 0, bestImages, 0, images.length);
+                datas = new ImageData [images.length];
+                for (int i=0; i<datas.length; i++) {
+                    datas [i] = images [i].getImageData ();
+                }
+                images = bestImages;
+                sort (images, datas, OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON), depth);
+            }
+            smallIcon = images [0];
+            if (images.length > 1) {
+                sort (images, datas, OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON), depth);
+            }
+            largeIcon = images [0];
+        }
+    }
+    if (smallIcon !is null) {
+        switch (smallIcon.type) {
+            case SWT.BITMAP:
+                smallImage = Display.createIcon (smallIcon);
+                hSmallIcon = smallImage.handle;
+                break;
+            case SWT.ICON:
+                hSmallIcon = smallIcon.handle;
+                break;
+            default:
+        }
+    }
+    OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_SMALL, hSmallIcon);
+    if (largeIcon !is null) {
+        switch (largeIcon.type) {
+            case SWT.BITMAP:
+                largeImage = Display.createIcon (largeIcon);
+                hLargeIcon = largeImage.handle;
+                break;
+            case SWT.ICON:
+                hLargeIcon = largeIcon.handle;
+                break;
+            default:
+        }
+    }
+    OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_BIG, hLargeIcon);
+
+    /*
+    * Bug in Windows.  When WM_SETICON is used to remove an
+    * icon from the window trimmings for a window with the
+    * extended style bits WS_EX_DLGMODALFRAME, the window
+    * trimmings do not redraw to hide the previous icon.
+    * The fix is to force a redraw.
+    */
+    static if (!OS.IsWinCE) {
+        if (hSmallIcon is null && hLargeIcon is null && (style & SWT.BORDER) !is 0) {
+            int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+            OS.RedrawWindow (handle, null, null, flags);
+        }
+    }
+}
+
+/**
+ * Sets the receiver's images to the argument, which may
+ * be an empty array. Images are typically displayed by the
+ * window manager when the instance is marked as iconified,
+ * and may also be displayed somewhere in the trim when the
+ * instance is in normal or maximized states. Depending where
+ * the icon is displayed, the platform chooses the icon with
+ * the "best" attributes. It is expected that the array will
+ * contain the same icon rendered at different sizes, with
+ * different depth and transparency attributes.
+ *
+ * @param images the new image array
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setImages (Image [] images) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (images is null) error (SWT.ERROR_INVALID_ARGUMENT);
+    for (int i = 0; i < images.length; i++) {
+        if (images [i] is null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.images = images;
+    setImages (null, images);
+}
+
+/**
+ * Sets the maximized state of the receiver.
+ * If the argument is <code>true</code> causes the receiver
+ * to switch to the maximized state, and if the argument is
+ * <code>false</code> and the receiver was previously maximized,
+ * causes the receiver to switch back to either the minimized
+ * or normal states.
+ * <p>
+ * Note: The result of intermixing calls to <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 maximized the new maximized state
+ *
+ * @exception SWTException <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 #setMinimized
+ */
+public void setMaximized (bool maximized) {
+    checkWidget ();
+    Display.lpStartupInfo = null;
+    _setMaximized (maximized);
+}
+
+/**
+ * Sets the receiver's menu bar to the argument, which
+ * may be null.
+ *
+ * @param menu the new menu bar
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setMenuBar (Menu menu) {
+    checkWidget ();
+    if (menuBar is menu) return;
+    if (menu !is null) {
+        if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+        if ((menu.style & SWT.BAR) is 0) error (SWT.ERROR_MENU_NOT_BAR);
+        if (menu.parent !is this) error (SWT.ERROR_INVALID_PARENT);
+    }
+    static if (OS.IsWinCE) {
+        if (OS.IsHPC) {
+            bool resize = menuBar !is menu;
+            if (menuBar !is null) OS.CommandBar_Show (menuBar.hwndCB, false);
+            menuBar = menu;
+            if (menuBar !is null) OS.CommandBar_Show (menuBar.hwndCB, true);
+            if (resize) {
+                sendEvent (SWT.Resize);
+                if (isDisposed ()) return;
+                if (layout !is null) {
+                    markLayout (false, false);
+                    updateLayout (true, false);
+                }
+            }
+        } else {
+            if (OS.IsPPC) {
+                /*
+                * Note in WinCE PPC.  The menu bar is a separate popup window.
+                * If the shell is full screen, resize its window to leave
+                * space for the menu bar.
+                */
+                bool resize = getMaximized () && menuBar !is menu;
+                if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE);
+                menuBar = menu;
+                if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW);
+                if (resize) _setMaximized (true);
+            }
+            if (OS.IsSP) {
+                if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE);
+                menuBar = menu;
+                if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW);
+            }
+        }
+    } else {
+        if (menu !is null) display.removeBar (menu);
+        menuBar = menu;
+        auto hMenu = menuBar !is null ? menuBar.handle: null;
+        OS.SetMenu (handle, hMenu);
+    }
+    destroyAccelerators ();
+}
+
+/**
+ * Sets the minimized stated of the receiver.
+ * If the argument is <code>true</code> causes the receiver
+ * to switch to the minimized state, and if the argument is
+ * <code>false</code> and the receiver was previously minimized,
+ * causes the receiver to switch back to either the maximized
+ * or normal states.
+ * <p>
+ * Note: The result of intermixing calls to <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 minimized the new maximized state
+ *
+ * @exception SWTException <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 #setMaximized
+ */
+public void setMinimized (bool minimized) {
+    checkWidget ();
+    Display.lpStartupInfo = null;
+    _setMinimized (minimized);
+}
+
+void setParent () {
+    /*
+    * In order for an MDI child window to support
+    * a menu bar, setParent () is needed to reset
+    * the parent.  Otherwise, the MDI child window
+    * will appear as a separate shell.  This is an
+    * undocumented and possibly dangerous Windows
+    * feature.
+    */
+    auto hwndParent = parent.handle;
+    display.lockActiveWindow = true;
+    OS.SetParent (handle, hwndParent);
+    if (!OS.IsWindowVisible (hwndParent)) {
+        OS.ShowWindow (handle, OS.SW_SHOWNA);
+    }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    bits &= ~OS.WS_CHILD;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP);
+    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;
+}
+
+void setPlacement (int x, int y, int width, int height, int flags) {
+    WINDOWPLACEMENT lpwndpl;
+    lpwndpl.length = WINDOWPLACEMENT.sizeof;
+    OS.GetWindowPlacement (handle, &lpwndpl);
+    lpwndpl.showCmd = OS.SW_SHOWNA;
+    if (OS.IsIconic (handle)) {
+        lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE;
+    } else {
+        if (OS.IsZoomed (handle)) {
+            lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED;
+        }
+    }
+    bool sameOrigin = true;
+    if ((flags & OS.SWP_NOMOVE) is 0) {
+        sameOrigin = lpwndpl.rcNormalPosition.left !is x || lpwndpl.rcNormalPosition.top !is y;
+        lpwndpl.rcNormalPosition.right = x + (lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left);
+        lpwndpl.rcNormalPosition.bottom = y + (lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top);
+        lpwndpl.rcNormalPosition.left = x;
+        lpwndpl.rcNormalPosition.top = y;
+    }
+    bool sameExtent = true;
+    if ((flags & OS.SWP_NOSIZE) is 0) {
+        sameExtent = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left !is width || lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top !is height;
+        lpwndpl.rcNormalPosition.right = lpwndpl.rcNormalPosition.left + width;
+        lpwndpl.rcNormalPosition.bottom = lpwndpl.rcNormalPosition.top + height;
+    }
+    OS.SetWindowPlacement (handle, &lpwndpl);
+    if (OS.IsIconic (handle)) {
+        if (sameOrigin) {
+            moved = true;
+            Point location = getLocation ();
+            oldX = location.x;
+            oldY = location.y;
+            sendEvent (SWT.Move);
+            if (isDisposed ()) return;
+        }
+        if (sameExtent) {
+            resized = true;
+            Rectangle rect = getClientArea ();
+            oldWidth = rect.width;
+            oldHeight = rect.height;
+            sendEvent (SWT.Resize);
+            if (isDisposed ()) return;
+            if (layout_ !is null) {
+                markLayout (false, false);
+                updateLayout (true, false);
+            }
+        }
+    }
+}
+
+void setSavedFocus (Control control) {
+    savedFocus = control;
+}
+
+void setSystemMenu () {
+    static if (OS.IsWinCE) return;
+    auto hMenu = OS.GetSystemMenu (handle, false);
+    if (hMenu is null) return;
+    int oldCount = OS.GetMenuItemCount (hMenu);
+    if ((style & SWT.RESIZE) is 0) {
+        OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND);
+    }
+    if ((style & SWT.MIN) is 0) {
+        OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND);
+    }
+    if ((style & SWT.MAX) is 0) {
+        OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND);
+    }
+    if ((style & (SWT.MIN | SWT.MAX)) is 0) {
+        OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND);
+    }
+    int newCount = OS.GetMenuItemCount (hMenu);
+    if ((style & SWT.CLOSE) is 0 || newCount !is oldCount) {
+        OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND);
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        info.fMask = OS.MIIM_ID;
+        int index = 0;
+        while (index < newCount) {
+            if (OS.GetMenuItemInfo (hMenu, index, true, &info)) {
+                if (info.wID is OS.SC_CLOSE) break;
+            }
+            index++;
+        }
+        if (index !is newCount) {
+            OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION);
+            if ((style & SWT.CLOSE) is 0) {
+                OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND);
+            }
+        }
+    }
+}
+
+/**
+ * Sets the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>, to the argument, which must not be null.
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    /* Use the character encoding for the default locale */
+    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) {
+    checkWidget ();
+    if (drawCount !is 0) {
+        if (((state & HIDDEN) is 0) is visible) return;
+    } else {
+        if (visible is OS.IsWindowVisible (handle)) return;
+    }
+    if (visible) {
+        /*
+        * It is possible (but unlikely), that application
+        * code could have disposed the widget in the show
+        * event.  If this happens, just return.
+        */
+        sendEvent (SWT.Show);
+        if (isDisposed ()) return;
+        static if (OS.IsHPC) {
+            if (menuBar !is null) {
+                auto hwndCB = menuBar.hwndCB;
+                OS.CommandBar_DrawMenuBar (hwndCB, 0);
+            }
+        }
+        if (drawCount !is 0) {
+            state &= ~HIDDEN;
+        } else {
+            static if (OS.IsWinCE) {
+                OS.ShowWindow (handle, OS.SW_SHOW);
+            } else {
+                if (menuBar !is null) {
+                    display.removeBar (menuBar);
+                    OS.DrawMenuBar (handle);
+                }
+                STARTUPINFO* lpStartUpInfo = Display.lpStartupInfo;
+                if (lpStartUpInfo !is null && (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) !is 0) {
+                    OS.ShowWindow (handle, lpStartUpInfo.wShowWindow);
+                } else {
+                    OS.ShowWindow (handle, swFlags);
+                }
+            }
+            if (isDisposed ()) return;
+            opened = true;
+            if (!moved) {
+                moved = true;
+                Point location = getLocation ();
+                oldX = location.x;
+                oldY = location.y;
+            }
+            if (!resized) {
+                resized = true;
+                Rectangle rect = getClientArea ();
+                oldWidth = rect.width;
+                oldHeight = rect.height;
+            }
+            /*
+            * Bug in Windows.  On Vista using the Classic theme, 
+            * when the window is hung and UpdateWindow() is called,
+            * nothing is drawn, and outstanding WM_PAINTs are cleared.
+            * This causes pixel corruption.  The fix is to avoid calling
+            * update on hung windows.  
+            */
+            bool update = true;
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && !OS.IsAppThemed ()) {
+                update = !OS.IsHungAppWindow (handle);
+            }
+            if (update) OS.UpdateWindow (handle);
+        }
+    } else {
+        static if (!OS.IsWinCE) {
+            if (OS.IsIconic (handle)) {
+                swFlags = OS.SW_SHOWMINNOACTIVE;
+            } else {
+                if (OS.IsZoomed (handle)) {
+                    swFlags = OS.SW_SHOWMAXIMIZED;
+                } else {
+                    swFlags = OS.SW_SHOWNOACTIVATE;
+                }
+            }
+        }
+        if (drawCount !is 0) {
+            state |= HIDDEN;
+        } else {
+            OS.ShowWindow (handle, OS.SW_HIDE);
+        }
+        if (isDisposed ()) return;
+        sendEvent (SWT.Hide);
+    }
+}
+
+void sort (Image [] images, ImageData [] datas, int width, int height, int depth) {
+    /* Shell Sort from K&R, pg 108 */
+    int length = images.length;
+    if (length <= 1) return;
+    for (int gap=length/2; gap>0; gap/=2) {
+        for (int i=gap; i<length; i++) {
+            for (int j=i-gap; j>=0; j-=gap) {
+                if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) {
+                    Image swap = images [j];
+                    images [j] = images [j + gap];
+                    images [j + gap] = swap;
+                    ImageData swapData = datas [j];
+                    datas [j] = datas [j + gap];
+                    datas [j + gap] = swapData;
+                }
+            }
+        }
+    }
+}
+
+override bool translateAccelerator (MSG* msg) {
+    if (!isEnabled () || !isActive ()) return false;
+    if (menuBar !is null && !menuBar.isEnabled ()) return false;
+    if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true;
+    Decorations decorations = parent.menuShell ();
+    return decorations.translateAccelerator (msg);
+}
+
+bool translateMenuAccelerator (MSG* msg) {
+    if (hAccel is cast(HACCEL)-1) createAccelerators ();
+    return hAccel !is null && OS.TranslateAccelerator (handle, hAccel, msg) !is 0;
+}
+
+bool translateMDIAccelerator (MSG* msg) {
+    if (!(cast(Shell)this)) {
+        Shell shell = getShell ();
+        auto hwndMDIClient = shell.hwndMDIClient_;
+        if (hwndMDIClient !is null && OS.TranslateMDISysAccel (hwndMDIClient, msg)) {
+            return true;
+        }
+        if (msg.message is OS.WM_KEYDOWN) {
+            if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
+            switch ((msg.wParam)) {
+                case OS.VK_F4:
+                    OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+                    return true;
+                case OS.VK_F6:
+                    if (traverseDecorations (true)) return true;
+                default:
+            }
+            return false;
+        }
+        if (msg.message is OS.WM_SYSKEYDOWN) {
+            switch ((msg.wParam)) {
+                case OS.VK_F4:
+                    OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
+                    return true;
+                default:
+            }
+            return false;
+        }
+    }
+    return false;
+}
+
+bool traverseDecorations (bool next) {
+    Control [] children = parent._getChildren ();
+    int length = children.length;
+    int index = 0;
+    while (index < length) {
+        if (children [index] is this) break;
+        index++;
+    }
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in focus in
+    * or out events.  Ensure that a disposed widget is
+    * not accessed.
+    */
+    int start = index, offset = (next) ? 1 : -1;
+    while ((index = (index + offset + length) % length) !is start) {
+        Control child = children [index];
+        if (!child.isDisposed () && ( null !is cast(Decorations)child)) {
+            if (child.setFocus ()) return true;
+        }
+    }
+    return false;
+}
+
+override bool traverseItem (bool next) {
+    return false;
+}
+
+override bool traverseReturn () {
+    if (defaultButton is null || defaultButton.isDisposed ()) return false;
+    if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false;
+    defaultButton.click ();
+    return true;
+}
+
+override CREATESTRUCT* widgetCreateStruct () {
+    return new CREATESTRUCT ();
+}
+
+override int widgetExtStyle () {
+    int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD;
+    bits &= ~OS.WS_EX_CLIENTEDGE;
+    if ((style & SWT.NO_TRIM) !is 0) return bits;
+    if (OS.IsPPC) {
+        if ((style & SWT.CLOSE) !is 0) bits |= OS.WS_EX_CAPTIONOKBTN;
+    }
+    if ((style & SWT.RESIZE) !is 0) return bits;
+    if ((style & SWT.BORDER) !is 0) bits |= OS.WS_EX_DLGMODALFRAME;
+    return bits;
+}
+
+override HWND widgetParent () {
+    Shell shell = getShell ();
+    return shell.hwndMDIClient ();
+}
+
+override int widgetStyle () {
+    /*
+    * Clear WS_VISIBLE and WS_TABSTOP.  NOTE: In Windows, WS_TABSTOP
+    * has the same value as WS_MAXIMIZEBOX so these bits cannot be
+    * used to control tabbing.
+    */
+    int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE);
+
+    /* Set the title bits and no-trim bits */
+    bits &= ~OS.WS_BORDER;
+    if ((style & SWT.NO_TRIM) !is 0) return bits;
+    if ((style & SWT.TITLE) !is 0) bits |= OS.WS_CAPTION;
+
+    /* Set the min and max button bits */
+    if ((style & SWT.MIN) !is 0) bits |= OS.WS_MINIMIZEBOX;
+    if ((style & SWT.MAX) !is 0) bits |= OS.WS_MAXIMIZEBOX;
+
+    /* Set the resize, dialog border or border bits */
+    if ((style & SWT.RESIZE) !is 0) {
+        /*
+        * Note on WinCE PPC.  SWT.RESIZE is used to resize
+        * the Shell according to the state of the IME.
+        * It does not set the WS_THICKFRAME style.
+        */
+        if (!OS.IsPPC) bits |= OS.WS_THICKFRAME;
+    } else {
+        if ((style & SWT.BORDER) is 0) bits |= OS.WS_BORDER;
+    }
+
+    /* Set the system menu and close box bits */
+    if (!OS.IsPPC && !OS.IsSP) {
+        if ((style & SWT.CLOSE) !is 0) bits |= OS.WS_SYSMENU;
+    }
+
+    return bits;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    switch (msg) {
+        case Display.SWT_GETACCEL:
+        case Display.SWT_GETACCELCOUNT:
+            if (hAccel is cast(HACCEL)-1) createAccelerators ();
+            return msg is Display.SWT_GETACCELCOUNT ? nAccel : cast(int)hAccel;
+        default:
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_ACTIVATE (int wParam, int lParam) {
+    LRESULT result = super.WM_ACTIVATE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in AWT.  When an AWT Window is activated,
+    * for some reason, it seems to forward the WM_ACTIVATE
+    * message to the parent.  Normally, the parent is an
+    * AWT Frame.  When AWT is embedded in SWT, the SWT
+    * shell gets the WM_ACTIVATE and assumes that it came
+    * from Windows.  When an SWT shell is activated it
+    * restores focus to the last control that had focus.
+    * If this control is an embedded composite, it takes
+    * focus from the AWT Window.  The fix is to ignore
+    * WM_ACTIVATE messages that come from AWT Windows.
+    */
+    if (OS.GetParent ( cast(HWND)lParam) is handle) {
+        TCHAR[128] buffer = 0;
+        OS.GetClassName (cast(HWND)lParam, buffer.ptr, buffer.length );
+        String className = TCHARzToStr( buffer.ptr );
+        if (className == Display.AWT_WINDOW_CLASS) {
+            return LRESULT.ZERO;
+        }
+    }
+    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 (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) {
+                sendEvent (SWT.Activate);
+                if (isDisposed ()) return LRESULT.ZERO;
+            }
+        }
+        if (restoreFocus ()) return LRESULT.ZERO;
+    } else {
+        Display display = this.display;
+        bool lockWindow = display.isXMouseActive ();
+        if (lockWindow) display.lockActiveWindow = true;
+        Control control = display.findControl (cast(HWND)lParam);
+        if (control is null || (null !is cast(Shell)control)) {
+            if (cast(Shell)this) {
+                sendEvent (SWT.Deactivate);
+                if (!isDisposed ()) {
+                    Shell shell = getShell ();
+                    shell.setActiveControl (null);
+                    // widget could be disposed at this point
+                }
+            }
+        }
+        if (lockWindow) display.lockActiveWindow = false;
+        if (isDisposed ()) return LRESULT.ZERO;
+        saveFocus ();
+    }
+    return result;
+}
+
+override LRESULT WM_CLOSE (int wParam, int lParam) {
+    LRESULT result = super.WM_CLOSE (wParam, lParam);
+    if (result !is null) return result;
+    if (isEnabled () && isActive ()) closeWidget ();
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_HOTKEY (int wParam, int lParam) {
+    LRESULT result = super.WM_HOTKEY (wParam, lParam);
+    if (result !is null) return result;
+    static if( OS.IsWinCE ){
+        if (OS.IsSP) {
+            /*
+            * Feature on WinCE SP.  The Back key is either used to close
+            * the foreground Dialog or used as a regular Back key in an EDIT
+            * control. The article 'Back Key' in MSDN for Smartphone
+            * describes how an application should handle it.  The
+            * workaround is to override the Back key when creating
+            * the menubar and handle it based on the style of the Shell.
+            * If the Shell has the SWT.CLOSE style, close the Shell.
+            * Otherwise, send the Back key to the window with focus.
+            */
+        if (OS.HIWORD (lParam) is OS.VK_ESCAPE) {
+                if ((style & SWT.CLOSE) !is 0) {
+                    OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+                } else {
+                    OS.SHSendBackToFocusWindow (OS.WM_HOTKEY, wParam, lParam);
+                }
+                return LRESULT.ZERO;
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+    saveFocus ();
+    return result;
+}
+
+override LRESULT WM_MOVE (int wParam, int lParam) {
+    if (moved) {
+        Point location = getLocation ();
+        if (location.x is oldX && location.y is oldY) {
+            return null;
+        }
+        oldX = location.x;
+        oldY = location.y;
+    }
+    return super.WM_MOVE (wParam, lParam);
+}
+
+override LRESULT WM_NCACTIVATE (int wParam, int lParam) {
+    LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
+    if (result !is null) return result;
+    if (wParam is 0) {
+        if (display.lockActiveWindow) return LRESULT.ZERO;
+        Control control = display.findControl (cast(HANDLE)lParam);
+        if (control !is null) {
+            Shell shell = getShell ();
+            Decorations decorations = control.menuShell ();
+            if (decorations.getShell () is shell) {
+                if (cast(Shell)this) return LRESULT.ONE;
+                if (display.ignoreRestoreFocus) {
+                    if (display.lastHittest !is OS.HTCLIENT) {
+                        result = LRESULT.ONE;
+                    }
+                }
+            }
+        }
+    }
+    if (!(cast(Shell)this)) {
+        auto hwndShell = getShell().handle;
+        OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam);
+    }
+    return result;
+}
+
+override LRESULT WM_QUERYOPEN (int wParam, int lParam) {
+    LRESULT result = super.WM_QUERYOPEN (wParam, lParam);
+    if (result !is null) return result;
+    sendEvent (SWT.Deiconify);
+    // widget could be disposed at this point
+    return result;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    if (savedFocus !is this) restoreFocus ();
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = null;
+    bool changed = true;
+    if (resized) {
+        int newWidth = 0, newHeight = 0;
+        switch (wParam) {
+            case OS.SIZE_RESTORED:
+            case OS.SIZE_MAXIMIZED:
+                newWidth = OS.LOWORD (lParam);
+                newHeight = OS.HIWORD (lParam);
+                break;
+            case OS.SIZE_MINIMIZED:
+                Rectangle rect = getClientArea ();
+                newWidth = rect.width;
+                newHeight = rect.height;
+                break;
+            default:
+        }
+        changed = newWidth !is oldWidth || newHeight !is oldHeight;
+        if (changed) {
+            oldWidth = newWidth;
+            oldHeight = newHeight;
+        }
+    }
+    if (changed) {
+        result = super.WM_SIZE (wParam, lParam);
+        if (isDisposed ()) return result;
+    }
+    if (wParam is OS.SIZE_MINIMIZED) {
+        sendEvent (SWT.Iconify);
+        // widget could be disposed at this point
+    }
+    return result;
+}
+
+override LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+    if (result !is null) return result;
+    if (!(cast(Shell)this)) {
+        int cmd = wParam & 0xFFF0;
+        switch (cmd) {
+            case OS.SC_CLOSE: {
+                OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
+                return LRESULT.ZERO;
+            }
+            case OS.SC_NEXTWINDOW: {
+                traverseDecorations (true);
+                return LRESULT.ZERO;
+            }
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    if (result !is null) return result;
+    if (display.lockActiveWindow) {
+        WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+        //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+        lpwp.flags |= OS.SWP_NOZORDER;
+        //OS.MoveMemory (lParam, &lpwp, WINDOWPOS.sizeof);
+    }
+    return result;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Dialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Dialog;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+import java.lang.all;
+
+/**
+ * This class is the abstract superclass of the classes
+ * that represent the built in platform dialogs.
+ * A <code>Dialog</code> typically contains other widgets
+ * that are not accessible. A <code>Dialog</code> is not
+ * a <code>Widget</code>.
+ * <p>
+ * This class can also be used as the abstract superclass
+ * for user-designed dialogs. Such dialogs usually consist
+ * of a Shell with child widgets. The basic template for a
+ * user-defined dialog typically looks something like this:
+ * <pre><code>
+ * public class MyDialog extends Dialog {
+ *  Object result;
+ *
+ *  public MyDialog (Shell parent, int style) {
+ *      super (parent, style);
+ *  }
+ *  public MyDialog (Shell parent) {
+ *      this (parent, 0); // your default style bits go here (not the Shell's style bits)
+ *  }
+ *  public Object open () {
+ *      Shell parent = getParent();
+ *      Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ *      shell.setText(getText());
+ *      // Your code goes here (widget creation, set result, etc).
+ *      shell.open();
+ *      Display display = parent.getDisplay();
+ *      while (!shell.isDisposed()) {
+ *          if (!display.readAndDispatch()) display.sleep();
+ *      }
+ *      return result;
+ *  }
+ * }
+ * </pre></code>
+ * <p>
+ * Note: The <em>modality</em> styles supported by this class
+ * are treated as <em>HINT</em>s, because not all are supported
+ * by every subclass on every platform. If a modality style is
+ * not supported, it is "upgraded" to a more restrictive modality
+ * style that is supported.  For example, if <code>PRIMARY_MODAL</code>
+ * is not supported by a particular dialog, it would be upgraded to
+ * <code>APPLICATION_MODAL</code>. In addition, as is the case
+ * for shells, the window manager for the desktop on which the
+ * instance is visible has ultimate control over the appearance
+ * and behavior of the instance, including its modality.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>APPLICATION_MODAL, PRIMARY_MODAL, SYSTEM_MODAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles APPLICATION_MODAL, PRIMARY_MODAL,
+ * and SYSTEM_MODAL may be specified.
+ * </p>
+ *
+ * @see Shell
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Dialog {
+    int style;
+    Shell parent;
+    String title;
+
+/**
+ * Constructs a new instance of this class given only its
+ * parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, SWT.PRIMARY_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public this (Shell parent, int style) {
+    checkParent (parent);
+    this.parent = parent;
+    this.style = style;
+    title = "";
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ */
+protected void checkSubclass () {
+    //PORTING_TODO: implement Display.isValidClass and Class?
+    /+if (!Display.isValidClass (getClass ())) {
+        error (SWT.ERROR_INVALID_SUBCLASS);
+    }+/
+}
+
+/**
+ * Throws an exception if the specified widget can not be
+ * used as a parent for the receiver.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ */
+void checkParent (Shell parent) {
+    if (parent is null) error (SWT.ERROR_NULL_ARGUMENT);
+    parent.checkWidget ();
+}
+
+static int checkStyle (Shell parent, int style) {
+    if ((style & (SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) is 0) {
+        style |= SWT.APPLICATION_MODAL;
+    }
+    style &= ~SWT.MIRRORED;
+    if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) is 0) {
+        if (parent !is null) {
+            if ((parent.style & SWT.LEFT_TO_RIGHT) !is 0) style |= SWT.LEFT_TO_RIGHT;
+            if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) style |= SWT.RIGHT_TO_LEFT;
+        }
+    }
+    return Widget.checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
+/**
+ * Does whatever dialog specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+    SWT.error(code);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Shell</code>
+ * or null.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Shell getParent () {
+    return parent;
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that, the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @exception SWTException <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 int getStyle () {
+    return style;
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>. If the text has not previously been set,
+ * returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException <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 String getText () {
+    return title;
+}
+
+/**
+ * Sets the receiver's text, which is the string that the
+ * window manager will typically display as the receiver's
+ * <em>title</em>, to the argument, which must not be null.
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    title = string;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/DirectoryDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.DirectoryDialog;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.C;
+
+import java.lang.all;
+static import tango.text.Text;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select a directory.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#directorydialog">DirectoryDialog snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class DirectoryDialog : Dialog {
+    static String message = "";
+    static String filterPath = "";  //$NON-NLS-1$//$NON-NLS-2$
+    static String directoryPath;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (parent, style));
+    checkSubclass ();
+}
+
+extern(Windows)static int BrowseCallbackProc (HWND hwnd, uint uMsg, int lParam, int lpData) {
+    DirectoryDialog pThis = cast(DirectoryDialog)cast(void*)lpData;
+    switch (uMsg) {
+        case OS.BFFM_INITIALIZED:
+            if (pThis.filterPath !is null && pThis.filterPath.length !is 0) {
+                /* Use the character encoding for the default locale */
+                TCHAR[] buffer = StrToTCHARs (0, pThis.filterPath.replace ('/', '\\'), true);
+                OS.SendMessage (hwnd, OS.BFFM_SETSELECTION, 1, buffer.ptr);
+            }
+            if (pThis.title !is null && pThis.title.length !is 0) {
+                /* Use the character encoding for the default locale */
+                TCHAR[] buffer = StrToTCHARs (0, pThis.title, true);
+                OS.SetWindowText (hwnd, buffer.ptr);
+            }
+            break;
+        case OS.BFFM_VALIDATEFAILEDA:
+        case OS.BFFM_VALIDATEFAILEDW:
+            /* Use the character encoding for the default locale */
+//            int length = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam);
+//            TCHAR buffer = new TCHAR (0, length);
+//            int byteCount = buffer.length * TCHAR.sizeof;
+//            OS.MoveMemory (buffer, lParam, byteCount);
+//            directoryPath = buffer.toString (0, length);
+            pThis.directoryPath = TCHARzToStr( cast(TCHAR*)lParam );
+            break;
+        default:
+    }
+    return 0;
+}
+
+/**
+ * Returns the path which the dialog will use to filter
+ * the directories it shows.
+ *
+ * @return the filter path
+ *
+ * @see #setFilterPath
+ */
+public String getFilterPath () {
+    return filterPath;
+}
+
+/**
+ * Returns the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+    return message;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the selected directory,
+ *         or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public String open () {
+    if (OS.IsWinCE) SWT.error (SWT.ERROR_NOT_IMPLEMENTED);
+
+    auto hHeap = OS.GetProcessHeap ();
+
+    /* Get the owner HWND for the dialog */
+    HWND hwndOwner;
+    if (parent !is null) hwndOwner = parent.handle;
+
+    /* Copy the message to OS memory */
+    TCHAR* lpszTitle;
+    if (message.length !is 0) {
+        String string = message;
+        if (string.indexOf ('&') !is -1) {
+            int length = string.length;
+            char [] buffer = new char [length * 2];
+            int index = 0;
+            for (int i=0; i<length; i++) {
+                char ch = string.charAt (i);
+                if (ch is '&') buffer [index++] = '&';
+                buffer [index++] = ch;
+            }
+//            string = new String (buffer, 0, index);
+        }
+        /* Use the character encoding for the default locale */
+        TCHAR[] buffer = StrToTCHARs (0, string, true);
+        int byteCount = buffer.length * TCHAR.sizeof;
+        lpszTitle = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory (lpszTitle, buffer.ptr, byteCount);
+    }
+
+    /* Create the BrowseCallbackProc */
+/+    Callback callback = new Callback (this, "BrowseCallbackProc", 4); //$NON-NLS-1$
+    int lpfn = callback.getAddress ();+/
+    BFFCALLBACK lpfn = &BrowseCallbackProc;
+    if (lpfn is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+    /* Make the parent shell be temporary modal */
+    Dialog oldModal = null;
+    Display display = parent.getDisplay ();
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
+    }
+
+    directoryPath = null;
+    BROWSEINFO lpbi;
+    lpbi.hwndOwner = hwndOwner;
+    lpbi.lpszTitle = lpszTitle;
+    lpbi.ulFlags = OS.BIF_NEWDIALOGSTYLE | OS.BIF_RETURNONLYFSDIRS | OS.BIF_EDITBOX | OS.BIF_VALIDATE;
+    lpbi.lpfn = lpfn;
+    lpbi.lParam = cast(int)cast(void*)this;
+    /*
+    * Bug in Windows.  On some hardware configurations, SHBrowseForFolder()
+    * causes warning dialogs with the message "There is no disk in the drive
+    * Please insert a disk into \Device\Harddisk0\DR0".  This is possibly
+    * caused by SHBrowseForFolder() calling internally GetVolumeInformation().
+    * MSDN for GetVolumeInformation() says:
+    *
+    * "If you are attempting to obtain information about a floppy drive
+    * that does not have a floppy disk or a CD-ROM drive that does not
+    * have a compact disc, the system displays a message box asking the
+    * user to insert a floppy disk or a compact disc, respectively.
+    * To prevent the system from displaying this message box, call the
+    * SetErrorMode function with SEM_FAILCRITICALERRORS."
+    *
+    * The fix is to save and restore the error mode using SetErrorMode()
+    * with the SEM_FAILCRITICALERRORS flag around SHBrowseForFolder().
+    */
+    int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
+
+    /*
+    * Bug in Windows.  When a WH_MSGFILTER hook is used to run code
+    * during the message loop for SHBrowseForFolder(), running code
+    * in the hook can cause a GP.  Specifically, SetWindowText()
+    * for static controls seemed to make the problem happen.
+    * The fix is to disable async messages while the directory
+    * dialog is open.
+    *
+    * NOTE:  This only happens in versions of the comctl32.dll
+    * earlier than 6.0.
+    */
+    bool oldRunMessages = display.runMessages;
+    if (OS.COMCTL32_MAJOR < 6) display.runMessages = false;
+    ITEMIDLIST* lpItemIdList = OS.SHBrowseForFolder (&lpbi);
+    if (OS.COMCTL32_MAJOR < 6) display.runMessages = oldRunMessages;
+    OS.SetErrorMode (oldErrorMode);
+
+    /* Clear the temporary dialog modal parent */
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        display.setModalDialog (oldModal);
+    }
+
+    bool success = lpItemIdList !is null;
+    if (success) {
+        /* Use the character encoding for the default locale */
+        TCHAR[OS.MAX_PATH] buffer;
+        if (OS.SHGetPathFromIDList (lpItemIdList, buffer.ptr)) {
+            directoryPath = TCHARzToStr (buffer.ptr);
+            filterPath = directoryPath;
+        }
+    }
+
+    /* Free the BrowseCallbackProc */
+//    callback.dispose ();
+
+    /* Free the OS memory */
+    if (lpszTitle !is null) OS.HeapFree (hHeap, 0, lpszTitle);
+
+    /* Free the pointer to the ITEMIDLIST */
+    LPVOID ppMalloc;
+    if (OS.SHGetMalloc (&ppMalloc) is OS.S_OK) {
+        /* void Free (struct IMalloc *this, void *pv); */
+        OS.VtblCall (5, ppMalloc , cast(int)lpItemIdList);
+    }
+
+    /*
+    * This code is intentionally commented.  On some
+    * platforms, the owner window is repainted right
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+    /* Return the directory path */
+    if (!success) return null;
+    return directoryPath;
+}
+
+/**
+ * Sets the path that the dialog will use to filter
+ * the directories it shows to the argument, which may
+ * be null. If the string is null, then the operating
+ * system's default filter path will be used.
+ * <p>
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ * </p>
+ *
+ * @param string the filter path
+ */
+public void setFilterPath (String string) {
+    filterPath = string;
+}
+
+/**
+ * Sets the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @param string the message
+ *
+ */
+public void setMessage (String string) {
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    message = string;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Display.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,4719 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Display;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.DeviceData;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Resource;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.Library;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Tray;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.EventTable;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Synchronizer;
+import org.eclipse.swt.widgets.Monitor;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.TrayItem;
+
+import java.lang.all;
+import java.lang.Runnable;
+import java.lang.System;
+import tango.core.Thread;
+import tango.stdc.stringz;
+import tango.util.Convert;
+static import tango.text.convert.Utf;
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * Instances of this class are responsible for managing the
+ * connection between SWT and the underlying operating
+ * system. Their most important function is to implement
+ * the SWT event loop in terms of the platform event model.
+ * They also provide various methods for accessing information
+ * about the operating system, and have overall control over
+ * the operating system resources which SWT allocates.
+ * <p>
+ * Applications which are built with SWT will <em>almost always</em>
+ * require only a single display. In particular, some platforms
+ * which SWT supports will not allow more than one <em>active</em>
+ * display. In other words, some platforms do not support
+ * creating a new display if one already exists that has not been
+ * sent the <code>dispose()</code> message.
+ * <p>
+ * In SWT, the thread which creates a <code>Display</code>
+ * instance is distinguished as the <em>user-interface thread</em>
+ * for that display.
+ * </p>
+ * The user-interface thread for a particular display has the
+ * following special attributes:
+ * <ul>
+ * <li>
+ * The event loop for that display must be run from the thread.
+ * </li>
+ * <li>
+ * Some SWT API methods (notably, most of the public methods in
+ * <code>Widget</code> and its subclasses), may only be called
+ * from the thread. (To support multi-threaded user-interface
+ * applications, class <code>Display</code> provides inter-thread
+ * communication methods which allow threads other than the
+ * user-interface thread to request that it perform operations
+ * on their behalf.)
+ * </li>
+ * <li>
+ * The thread is not allowed to construct other
+ * <code>Display</code>s until that display has been disposed.
+ * (Note that, this is in addition to the restriction mentioned
+ * above concerning platform support for multiple displays. Thus,
+ * the only way to have multiple simultaneously active displays,
+ * even on platforms which support it, is to have multiple threads.)
+ * </li>
+ * </ul>
+ * Enforcing these attributes allows SWT to be implemented directly
+ * on the underlying operating system's event model. This has
+ * numerous benefits including smaller footprint, better use of
+ * resources, safer memory management, clearer program logic,
+ * better performance, and fewer overall operating system threads
+ * required. The down side however, is that care must be taken
+ * (only) when constructing multi-threaded applications to use the
+ * inter-thread communication mechanisms which this class provides
+ * when required.
+ * </p><p>
+ * All SWT API methods which may only be called from the user-interface
+ * thread are distinguished in their documentation by indicating that
+ * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
+ * SWT exception.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Close, Dispose, Settings</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * @see #syncExec
+ * @see #asyncExec
+ * @see #wake
+ * @see #readAndDispatch
+ * @see #sleep
+ * @see Device#dispose
+ * @see <a href="http://www.eclipse.org/swt/snippets/#display">Display snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Display : Device {
+
+    /**
+     * the handle to the OS message queue
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public MSG* msg;
+
+    /* Windows and Events */
+    Event [] eventQueue;
+    //Callback windowCallback;
+    //int windowProc_;
+    int threadId;
+    TCHAR[] windowClass_, windowShadowClass;
+    static int WindowClassCount;
+    static const String WindowName = "SWT_Window"; //$NON-NLS-1$
+    static const String WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$
+    EventTable eventTable, filterTable;
+
+    /* Widget Table */
+    int freeSlot;
+    int [] indexTable;
+    Control lastControl, lastGetControl;
+    HANDLE lastHwnd;
+    HWND lastGetHwnd;
+    Control [] controlTable;
+    static const int GROW_SIZE = 1024;
+    private static /+const+/ int SWT_OBJECT_INDEX;
+    static const bool USE_PROPERTY = !OS.IsWinCE;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            static if (USE_PROPERTY) {
+                SWT_OBJECT_INDEX = OS.GlobalAddAtom (StrToTCHARz("SWT_OBJECT_INDEX")); //$NON-NLS-1$
+            } else {
+                SWT_OBJECT_INDEX = 0;
+            }
+            static_this_StartupInfo ();
+            static_this_DeviceFinder ();
+            static_this_completed = true;
+        }
+    }
+
+    /* Startup info */
+    private static STARTUPINFO* lpStartupInfo;
+    private static void static_this_StartupInfo (){
+        static if (!OS.IsWinCE) {
+            lpStartupInfo = new STARTUPINFO ();
+            lpStartupInfo.cb = STARTUPINFO.sizeof;
+            OS.GetStartupInfo (lpStartupInfo);
+        }
+    }
+    /* XP Themes */
+    HTHEME hButtonTheme_, hEditTheme_, hExplorerBarTheme_, hScrollBarTheme_, hTabTheme_;
+    static const wchar [] BUTTON = "BUTTON\0"w;
+    static const wchar [] EDIT = "EDIT\0"w;
+    static const wchar [] EXPLORER = "EXPLORER\0"w;
+    static const wchar [] EXPLORERBAR = "EXPLORERBAR\0"w;
+    static const wchar [] SCROLLBAR = "SCROLLBAR\0"w;
+    static const wchar [] LISTVIEW = "LISTVIEW\0"w;
+    static const wchar [] TAB = "TAB\0"w;
+    static const wchar [] TREEVIEW = "TREEVIEW\0"w;
+
+    /* Focus */
+    int focusEvent;
+    Control focusControl;
+
+    /* Menus */
+    Menu [] bars, popups;
+    MenuItem [] items;
+
+    /*
+    * The start value for WM_COMMAND id's.
+    * Windows reserves the values 0..100.
+    *
+    * The SmartPhone SWT resource file reserves
+    * the values 101..107.
+    */
+    static const int ID_START = 108;
+
+    /* Filter Hook */
+    //Callback msgFilterCallback;
+    //int msgFilterProc_,
+    HHOOK filterHook;
+    bool runDragDrop = true, dragCancelled = false;
+    MSG* hookMsg;
+
+    /* Idle Hook */
+    //Callback foregroundIdleCallback;
+    //int foregroundIdleProc_;
+    HHOOK idleHook;
+
+    /* Message Hook and Embedding */
+    bool ignoreNextKey;
+    //Callback getMsgCallback, embeddedCallback;
+    int getMsgProc_;
+    HHOOK msgHook;
+    HWND embeddedHwnd;
+    int embeddedProc_;
+    static const String AWT_WINDOW_CLASS = "SunAwtWindow";
+    static const short [] ACCENTS = [ cast(short) '~', '`', '\'', '^', '"'];
+
+    /* Sync/Async Widget Communication */
+    Synchronizer synchronizer;
+    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 = "org.eclipse.swt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$
+    Thread thread;
+
+    /* Display Shutdown */
+    Runnable [] disposeList;
+
+    /* System Tray */
+    Tray tray;
+    int nextTrayId;
+
+    /* Timers */
+    int /*long*/ [] timerIds;
+    Runnable [] timerList;
+    int /*long*/ nextTimerId = SETTINGS_ID + 1;
+    static const int SETTINGS_ID = 100;
+    static const int SETTINGS_DELAY = 2000;
+
+    /* Keyboard and Mouse */
+    RECT* clickRect;
+    int clickCount, lastTime, lastButton;
+    HWND lastClickHwnd;
+    int scrollRemainder;
+    int lastKey, lastAscii, lastMouse;
+    bool lastVirtual, lastNull, lastDead;
+    ubyte [256] keyboard;
+    bool accelKeyHit, mnemonicKeyHit;
+    bool lockActiveWindow, captureChanged, xMouse;
+
+    /* Tool Tips */
+    int nextToolTipId;
+
+    /* MDI */
+    bool ignoreRestoreFocus;
+    Control lastHittestControl;
+    int lastHittest;
+
+    /* Message Only Window */
+    HWND hwndMessage;
+
+    /* System Resources */
+    LOGFONT* lfSystemFont;
+    Font systemFont;
+    Image errorImage, infoImage, questionImage, warningIcon;
+    Cursor [] cursors;
+    Resource [] resources;
+    static const int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;
+
+    /* ImageList Cache */
+    ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList;
+
+    /* Custom Colors for ChooseColor */
+    COLORREF* lpCustColors;
+
+    /* Sort Indicators */
+    Image upArrow, downArrow;
+
+    /* 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;
+    String [] keys;
+    Object [] values;
+
+    /* Key Mappings */
+    static const int [] [] KeyTable = [
+
+        /* Keyboard and Mouse Masks */
+        [OS.VK_MENU,    SWT.ALT],
+        [OS.VK_SHIFT,   SWT.SHIFT],
+        [OS.VK_CONTROL, SWT.CONTROL],
+//      [OS.VK_????,    SWT.COMMAND],
+
+        /* NOT CURRENTLY USED */
+//      [OS.VK_LBUTTON, SWT.BUTTON1],
+//      [OS.VK_MBUTTON, SWT.BUTTON3],
+//      [OS.VK_RBUTTON, SWT.BUTTON2],
+
+        /* Non-Numeric Keypad Keys */
+        [OS.VK_UP,      SWT.ARROW_UP],
+        [OS.VK_DOWN,    SWT.ARROW_DOWN],
+        [OS.VK_LEFT,    SWT.ARROW_LEFT],
+        [OS.VK_RIGHT,   SWT.ARROW_RIGHT],
+        [OS.VK_PRIOR,   SWT.PAGE_UP],
+        [OS.VK_NEXT,    SWT.PAGE_DOWN],
+        [OS.VK_HOME,    SWT.HOME],
+        [OS.VK_END,     SWT.END],
+        [OS.VK_INSERT,  SWT.INSERT],
+
+        /* Virtual and Ascii Keys */
+        [OS.VK_BACK,    SWT.BS],
+        [OS.VK_RETURN,  SWT.CR],
+        [OS.VK_DELETE,  SWT.DEL],
+        [OS.VK_ESCAPE,  SWT.ESC],
+        [OS.VK_RETURN,  SWT.LF],
+        [OS.VK_TAB,     SWT.TAB],
+
+        /* Functions Keys */
+        [OS.VK_F1,  SWT.F1],
+        [OS.VK_F2,  SWT.F2],
+        [OS.VK_F3,  SWT.F3],
+        [OS.VK_F4,  SWT.F4],
+        [OS.VK_F5,  SWT.F5],
+        [OS.VK_F6,  SWT.F6],
+        [OS.VK_F7,  SWT.F7],
+        [OS.VK_F8,  SWT.F8],
+        [OS.VK_F9,  SWT.F9],
+        [OS.VK_F10, SWT.F10],
+        [OS.VK_F11, SWT.F11],
+        [OS.VK_F12, SWT.F12],
+        [OS.VK_F13, SWT.F13],
+        [OS.VK_F14, SWT.F14],
+        [OS.VK_F15, SWT.F15],
+
+        /* Numeric Keypad Keys */
+        [OS.VK_MULTIPLY,    SWT.KEYPAD_MULTIPLY],
+        [OS.VK_ADD,         SWT.KEYPAD_ADD],
+        [OS.VK_RETURN,      SWT.KEYPAD_CR],
+        [OS.VK_SUBTRACT,    SWT.KEYPAD_SUBTRACT],
+        [OS.VK_DECIMAL,     SWT.KEYPAD_DECIMAL],
+        [OS.VK_DIVIDE,      SWT.KEYPAD_DIVIDE],
+        [OS.VK_NUMPAD0,     SWT.KEYPAD_0],
+        [OS.VK_NUMPAD1,     SWT.KEYPAD_1],
+        [OS.VK_NUMPAD2,     SWT.KEYPAD_2],
+        [OS.VK_NUMPAD3,     SWT.KEYPAD_3],
+        [OS.VK_NUMPAD4,     SWT.KEYPAD_4],
+        [OS.VK_NUMPAD5,     SWT.KEYPAD_5],
+        [OS.VK_NUMPAD6,     SWT.KEYPAD_6],
+        [OS.VK_NUMPAD7,     SWT.KEYPAD_7],
+        [OS.VK_NUMPAD8,     SWT.KEYPAD_8],
+        [OS.VK_NUMPAD9,     SWT.KEYPAD_9],
+//      [OS.VK_????,        SWT.KEYPAD_EQUAL],
+
+        /* Other keys */
+        [OS.VK_CAPITAL,     SWT.CAPS_LOCK],
+        [OS.VK_NUMLOCK,     SWT.NUM_LOCK],
+        [OS.VK_SCROLL,      SWT.SCROLL_LOCK],
+        [OS.VK_PAUSE,       SWT.PAUSE],
+        [OS.VK_CANCEL,      SWT.BREAK],
+        [OS.VK_SNAPSHOT,    SWT.PRINT_SCREEN],
+//      [OS.VK_????,        SWT.HELP],
+
+    ];
+
+    /* Multiple Displays */
+    static Display Default;
+    static Display [] Displays;
+
+    /* Multiple Monitors */
+    org.eclipse.swt.widgets.Monitor.Monitor[] monitors = null;
+    int monitorCount = 0;
+
+    /* Modality */
+    Shell [] modalShells;
+    Dialog modalDialog;
+    static bool TrimEnabled = false;
+
+    /* Private SWT Window Messages */
+    static const int SWT_GETACCELCOUNT  = OS.WM_APP;
+    static const int SWT_GETACCEL       = OS.WM_APP + 1;
+    static const int SWT_KEYMSG         = OS.WM_APP + 2;
+    static const int SWT_DESTROY        = OS.WM_APP + 3;
+    static const int SWT_TRAYICONMSG    = OS.WM_APP + 4;
+    static const int SWT_NULL           = OS.WM_APP + 5;
+    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;
+
+    /* Package Name */
+    static const String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$
+    /*
+    * This code is intentionally commented.  In order
+    * to support CLDC, .class cannot be used because
+    * it does not compile on some Java compilers when
+    * they are targeted for CLDC.
+    */
+//  static {
+//      String name = Display.class.getName ();
+//      int index = name.lastIndexOf ('.');
+//      PACKAGE_PREFIX = name.substring (0, index + 1);
+//  }
+
+    /*
+    * TEMPORARY CODE.  Install the runnable that
+    * gets the current display. This code will
+    * be removed in the future.
+    */
+    private static void static_this_DeviceFinder () {
+        DeviceFinder = new class() Runnable {
+            public void run () {
+                Device device = getCurrent ();
+                if (device is null) {
+                    device = getDefault ();
+                }
+                setDevice (device);
+            }
+        };
+    }
+
+/*
+* TEMPORARY CODE.
+*/
+static void setDevice (Device device) {
+    static_this();
+    CurrentDevice = device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * Note: The resulting display is marked as the <em>current</em>
+ * display. If this is the first display which has been
+ * constructed since the application started, it is also
+ * marked as the <em>default</em> display.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see #getCurrent
+ * @see #getDefault
+ * @see Widget#checkSubclass
+ * @see Shell
+ */
+public this () {
+    this (null);
+}
+
+/**
+ * Constructs a new instance of this class using the parameter.
+ *
+ * @param data the device data
+ */
+public this (DeviceData data) {
+    static_this();
+    msg = new MSG();
+    hookMsg = new MSG();
+    super (data);
+    synchronizer = new Synchronizer (this);
+    cursors = new Cursor [SWT.CURSOR_HAND + 1];
+}
+
+Control _getFocusControl () {
+    return findControl (OS.GetFocus ());
+}
+
+void addBar (Menu menu) {
+    if (bars is null) bars = new Menu [4];
+    int length_ = bars.length;
+    for (int i=0; i<length_; i++) {
+        if (bars [i] is menu) return;
+    }
+    int index = 0;
+    while (index < length_) {
+        if (bars [index] is null) break;
+        index++;
+    }
+    if (index is length_) {
+        Menu [] newBars = new Menu [length_ + 4];
+        System.arraycopy (bars, 0, newBars, 0, length_);
+        bars = newBars;
+    }
+    bars [index] = menu;
+}
+
+void addControl (HANDLE handle, Control control) {
+    if (handle is null) return;
+    if (freeSlot is -1) {
+        int length_ = (freeSlot = indexTable.length) + GROW_SIZE;
+        int [] newIndexTable = new int [length_];
+        Control [] newControlTable = new Control [length_];
+        System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
+        System.arraycopy (controlTable, 0, newControlTable, 0, freeSlot);
+        for (int i=freeSlot; i<length_-1; i++) newIndexTable [i] = i + 1;
+        newIndexTable [length_ - 1] = -1;
+        indexTable = newIndexTable;
+        controlTable = newControlTable;
+    }
+    static if (USE_PROPERTY) {
+        OS.SetProp (handle, cast(wchar*)SWT_OBJECT_INDEX, cast(void*) freeSlot + 1);
+    } else {
+        OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, freeSlot + 1);
+    }
+    int oldSlot = freeSlot;
+    freeSlot = indexTable [oldSlot];
+    indexTable [oldSlot] = -2;
+    controlTable [oldSlot] = control;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an event of the given type occurs anywhere
+ * in a widget. The event type is one of the event constants
+ * defined in class <code>SWT</code>. When the event does occur,
+ * the listener is notified by sending it the <code>handleEvent()</code>
+ * message.
+ * <p>
+ * Setting the type of an event to <code>SWT.None</code> from
+ * within the <code>handleEvent()</code> method can be used to
+ * change the event type and stop subsequent Java listeners
+ * from running. Because event filters run before other listeners,
+ * event filters can both block other listeners and set arbitrary
+ * fields within an event. For this reason, event filters are both
+ * powerful and dangerous. They should generally be avoided for
+ * performance, debugging and code maintenance reasons.
+ * </p>
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeFilter
+ * @see #removeListener
+ *
+ * @since 3.0
+ */
+public void addFilter (int eventType, Listener listener) {
+    checkDevice ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (filterTable is null) filterTable = new EventTable ();
+    filterTable.hook (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection 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>SWT</code>.
+ * When the event does occur in the display, the listener is notified by
+ * sending it the <code>handleEvent()</code> message.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #removeListener
+ *
+ * @since 2.0
+ */
+public void addListener (int eventType, Listener listener) {
+    checkDevice ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) eventTable = new EventTable ();
+    eventTable.hook (eventType, listener);
+}
+
+void addMenuItem (MenuItem item) {
+    if (items is null) items = new MenuItem [64];
+    for (int i=0; i<items.length; i++) {
+        if (items [i] is null) {
+            item.id = i + ID_START;
+            items [i] = item;
+            return;
+        }
+    }
+    item.id = items.length + ID_START;
+    MenuItem [] newItems = new MenuItem [items.length + 64];
+    newItems [items.length] = item;
+    System.arraycopy (items, 0, newItems, 0, items.length);
+    items = newItems;
+}
+
+void addPopup (Menu menu) {
+    if (popups is null) popups = new Menu [4];
+    int length_ = popups.length;
+    for (int i=0; i<length_; i++) {
+        if (popups [i] is menu) return;
+    }
+    int index = 0;
+    while (index < length_) {
+        if (popups [index] is null) break;
+        index++;
+    }
+    if (index is length_) {
+        Menu [] newPopups = new Menu [length_ + 4];
+        System.arraycopy (popups, 0, newPopups, 0, length_);
+        popups = newPopups;
+    }
+    popups [index] = menu;
+}
+
+int asciiKey (int key) {
+    static if (OS.IsWinCE) return 0;
+
+    /* Get the current keyboard. */
+    for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
+    if (!OS.GetKeyboardState (keyboard.ptr)) return 0;
+
+    /* Translate the key to ASCII or UNICODE using the virtual keyboard */
+    static if (OS.IsUnicode) {
+        wchar result;
+        if (OS.ToUnicode (key, key, keyboard.ptr, &result, 1, 0) is 1) return result;
+    } else {
+        short [] result = new short [1];
+        if (OS.ToAscii (key, key, keyboard, result, 0) is 1) return result [0];
+    }
+    return 0;
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The caller of this method continues
+ * to run in parallel, and is not notified when the
+ * runnable has completed.  Specifying <code>null</code> as the
+ * runnable simply wakes the user-interface thread when run.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param runnable code to run on the user-interface thread or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #syncExec
+ */
+public void asyncExec (Runnable runnable) {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        synchronizer.asyncExec (runnable);
+    }
+}
+
+/**
+ * Causes the system hardware to emit a short sound
+ * (if it supports this capability).
+ *
+ * @exception SWTException <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>
+ */
+public void beep () {
+    checkDevice ();
+    OS.MessageBeep (OS.MB_OK);
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ */
+protected void checkSubclass () {
+    //if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override protected void checkDevice () {
+    if (thread is null) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (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 not been
+        * observed in all places where it is called. 
+        */
+        if (threadId !is OS.GetCurrentThreadId ()) {
+            error (SWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+    }
+    if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+}
+
+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) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
+                if (Displays [i].thread is thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
+            }
+        }
+    }
+}
+
+void clearModal (Shell shell) {
+    if (modalShells is null) return;
+    int index = 0, length_ = modalShells.length;
+    while (index < length_) {
+        if (modalShells [index] is shell) break;
+        if (modalShells [index] is null) return;
+        index++;
+    }
+    if (index is length_) return;
+    System.arraycopy (modalShells, index + 1, modalShells, index, --length_ - index);
+    modalShells [length_] = null;
+    if (index is 0 && modalShells [0] is null) modalShells = null;
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+int controlKey (int key) {
+    int upper = cast(int)OS.CharUpper (cast(wchar*) key);
+    if (64 <= upper && upper <= 95) return upper & 0xBF;
+    return key;
+}
+
+/**
+ * Requests that the connection between SWT and the underlying
+ * operating system be closed.
+ *
+ * @exception SWTException <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>
+ *
+ * @see Device#dispose
+ *
+ * @since 2.0
+ */
+public void close () {
+    checkDevice ();
+    Event event = new Event ();
+    sendEvent (SWT.Close, event);
+    if (event.doit) dispose ();
+}
+
+/**
+ * Creates the device in the operating system.  If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ * <p>
+ * This method is called before <code>init</code>.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+override protected void create (DeviceData data) {
+    checkSubclass ();
+    checkDisplay (thread = Thread.getThis (), true);
+    createDisplay (data);
+    register (this);
+    if (Default is null) Default = this;
+}
+
+void createDisplay (DeviceData data) {
+}
+
+static HBITMAP create32bitDIB (Image image) {
+    static_this();
+    int transparentPixel = -1, alpha = -1;
+    HBITMAP hMask;
+    HBITMAP hBitmap;
+    byte[] alphaData = null;
+    switch (image.type) {
+        case SWT.ICON:
+            ICONINFO info;
+            OS.GetIconInfo (image.handle, &info);
+            hBitmap = info.hbmColor;
+            hMask = info.hbmMask;
+            break;
+        case SWT.BITMAP:
+            ImageData data = image.getImageData ();
+            hBitmap = image.handle;
+            alpha = data.alpha;
+            alphaData = data.alphaData;
+            transparentPixel = data.transparentPixel;
+            break;
+        default:
+    }
+    BITMAP bm;
+    OS.GetObject (hBitmap, BITMAP.sizeof, &bm);
+    int imgWidth = bm.bmWidth;
+    int imgHeight = bm.bmHeight;
+    auto hDC = OS.GetDC (null);
+    auto srcHdc = OS.CreateCompatibleDC (hDC);
+    auto oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
+    auto memHdc = OS.CreateCompatibleDC (hDC);
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biWidth = imgWidth;
+    bmiHeader.biHeight = -imgHeight;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)32;
+    bmiHeader.biCompression = OS.BI_RGB;
+    byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+    bmi[ 0 .. BITMAPINFOHEADER.sizeof ] = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof ];
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+    if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+    auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+    BITMAP dibBM;
+    OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+    int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+    OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+    byte red = 0, green = 0, blue = 0;
+    if (transparentPixel !is -1) {
+        if (bm.bmBitsPixel <= 8) {
+            byte [4] color;
+            OS.GetDIBColorTable (srcHdc, transparentPixel, 1, cast(RGBQUAD*)color.ptr);
+            blue = color [0];
+            green = color [1];
+            red = color [2];
+        } else {
+            switch (bm.bmBitsPixel) {
+                case 16:
+                    blue = cast(byte)((transparentPixel & 0x1F) << 3);
+                    green = cast(byte)((transparentPixel & 0x3E0) >> 2);
+                    red = cast(byte)((transparentPixel & 0x7C00) >> 7);
+                    break;
+                case 24:
+                    blue = cast(byte)((transparentPixel & 0xFF0000) >> 16);
+                    green = cast(byte)((transparentPixel & 0xFF00) >> 8);
+                    red = cast(byte)(transparentPixel & 0xFF);
+                    break;
+                case 32:
+                    blue = cast(byte)((transparentPixel & 0xFF000000) >>> 24);
+                    green = cast(byte)((transparentPixel & 0xFF0000) >> 16);
+                    red = cast(byte)((transparentPixel & 0xFF00) >> 8);
+                    break;
+                default:
+            }
+        }
+    }
+    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) {
+            for (int x = 0; x < imgWidth; ++x) {
+                if (OS.GetPixel(srcHdc, x, y) !is 0) {
+                    srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData[dp + 3] = cast(byte)0;
+                } else {
+                    srcData[dp + 3] = cast(byte)0xFF;
+                }
+                dp += 4;
+            }
+        }
+    } else if (alpha !is -1) {
+        for (int y = 0, dp = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                srcData [dp + 3] = cast(byte)alpha;
+                if (srcData [dp + 3] is 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
+                dp += 4;
+            }
+        }
+    } else if (alphaData !is null) {
+        for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                srcData [dp + 3] = alphaData [ap++];
+                if (srcData [dp + 3] is 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
+                dp += 4;
+            }
+        }
+    } else if (transparentPixel !is -1) {
+        for (int y = 0, dp = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                if (srcData [dp] is blue && srcData [dp + 1] is green && srcData [dp + 2] is red) {
+                    srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData [dp + 3] = cast(byte)0;
+                } else {
+                    srcData [dp + 3] = cast(byte)0xFF;
+                }
+                dp += 4;
+            }
+        }
+    } else {
+        for (int y = 0, dp = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                srcData [dp + 3] = cast(byte)0xFF;
+                dp += 4;
+            }
+        }
+    }
+    (cast(byte*)pBits)[ 0 .. sizeInBytes] = srcData[];
+    OS.SelectObject (srcHdc, oldSrcBitmap);
+    OS.SelectObject (memHdc, oldMemBitmap);
+    OS.DeleteObject (srcHdc);
+    OS.DeleteObject (memHdc);
+    OS.ReleaseDC (null, hDC);
+    if (hBitmap !is image.handle && hBitmap !is null) OS.DeleteObject (hBitmap);
+    if (hMask !is null) OS.DeleteObject (hMask);
+    return memDib;
+}
+
+static HBITMAP create32bitDIB (HBITMAP hBitmap, int alpha, byte [] alphaData, int transparentPixel) {
+    static_this();
+    BITMAP bm;
+    OS.GetObject (hBitmap, BITMAP.sizeof, &bm);
+    int imgWidth = bm.bmWidth;
+    int imgHeight = bm.bmHeight;
+    auto hDC = OS.GetDC (null);
+    auto srcHdc = OS.CreateCompatibleDC (hDC);
+    auto oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
+    auto memHdc = OS.CreateCompatibleDC (hDC);
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biWidth = imgWidth;
+    bmiHeader.biHeight = -imgHeight;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)32;
+    bmiHeader.biCompression = OS.BI_RGB;
+    byte [] bmi = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof];
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+    if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+    auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+    BITMAP dibBM;
+    OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+    int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+    OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
+    byte red = 0, green = 0, blue = 0;
+    if (transparentPixel !is -1) {
+        if (bm.bmBitsPixel <= 8) {
+            byte [4] color;
+            OS.GetDIBColorTable (srcHdc, transparentPixel, 1, cast(RGBQUAD*)color.ptr);
+            blue = color [0];
+            green = color [1];
+            red = color [2];
+        } else {
+            switch (bm.bmBitsPixel) {
+                case 16:
+                    blue = cast(byte)((transparentPixel & 0x1F) << 3);
+                    green = cast(byte)((transparentPixel & 0x3E0) >> 2);
+                    red = cast(byte)((transparentPixel & 0x7C00) >> 7);
+                    break;
+                case 24:
+                    blue = cast(byte)((transparentPixel & 0xFF0000) >> 16);
+                    green = cast(byte)((transparentPixel & 0xFF00) >> 8);
+                    red = cast(byte)(transparentPixel & 0xFF);
+                    break;
+                case 32:
+                    blue = cast(byte)((transparentPixel & 0xFF000000) >>> 24);
+                    green = cast(byte)((transparentPixel & 0xFF0000) >> 16);
+                    red = cast(byte)((transparentPixel & 0xFF00) >> 8);
+                    break;
+                default:
+            }
+        }
+    }
+    OS.SelectObject (srcHdc, oldSrcBitmap);
+    OS.SelectObject (memHdc, oldMemBitmap);
+    OS.DeleteObject (srcHdc);
+    OS.DeleteObject (memHdc);
+    OS.ReleaseDC (null, hDC);
+    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) {
+                srcData [dp + 3] = cast(byte)alpha;
+                dp += 4;
+            }
+        }
+    } else if (alphaData !is null) {
+        for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                srcData [dp + 3] = alphaData [ap++];
+                dp += 4;
+            }
+        }
+    } else if (transparentPixel !is -1) {
+        for (int y = 0, dp = 0; y < imgHeight; ++y) {
+            for (int x = 0; x < imgWidth; ++x) {
+                if (srcData [dp] is blue && srcData [dp + 1] is green && srcData [dp + 2] is red) {
+                    srcData [dp + 3] = cast(byte)0;
+                } else {
+                    srcData [dp + 3] = cast(byte)0xFF;
+                }
+                dp += 4;
+            }
+        }
+    }
+    (cast(byte*)pBits)[ 0 .. sizeInBytes ] = srcData[];
+    return memDib;
+}
+
+static Image createIcon (Image image) {
+    static_this();
+    Device device = image.getDevice ();
+    ImageData data = image.getImageData ();
+    if (data.alpha is -1 && data.alphaData is null) {
+        ImageData mask = data.getTransparencyMask ();
+        return new Image (device, data, mask);
+    }
+    int width = data.width, height = data.height;
+    HBITMAP hMask, hBitmap;
+    auto hDC = device.internal_new_GC (null);
+    auto dstHdc = OS.CreateCompatibleDC (hDC);
+    HBITMAP oldDstBitmap;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        hBitmap = Display.create32bitDIB (image.handle, data.alpha, data.alphaData, data.transparentPixel);
+        hMask = OS.CreateBitmap (width, height, 1, 1, null);
+        oldDstBitmap = OS.SelectObject (dstHdc, hMask);
+        OS.PatBlt (dstHdc, 0, 0, width, height, OS.BLACKNESS);
+    } else {
+        hMask = Display.createMaskFromAlpha (data, width, height);
+        /* Icons need black pixels where the mask is transparent */
+        hBitmap = OS.CreateCompatibleBitmap (hDC, width, height);
+        oldDstBitmap = OS.SelectObject (dstHdc, hBitmap);
+        auto srcHdc = OS.CreateCompatibleDC (hDC);
+        auto oldSrcBitmap = OS.SelectObject (srcHdc, image.handle);
+        OS.PatBlt (dstHdc, 0, 0, width, height, OS.BLACKNESS);
+        OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCINVERT);
+        OS.SelectObject (srcHdc, hMask);
+        OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCAND);
+        OS.SelectObject (srcHdc, image.handle);
+        OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCINVERT);
+        OS.SelectObject (srcHdc, oldSrcBitmap);
+        OS.DeleteDC (srcHdc);
+    }
+    OS.SelectObject (dstHdc, oldDstBitmap);
+    OS.DeleteDC (dstHdc);
+    device.internal_dispose_GC (hDC, null);
+    ICONINFO info;
+    info.fIcon = true;
+    info.hbmColor = hBitmap;
+    info.hbmMask = hMask;
+    auto hIcon = OS.CreateIconIndirect (&info);
+    if (hIcon is null) SWT.error(SWT.ERROR_NO_HANDLES);
+    OS.DeleteObject (hBitmap);
+    OS.DeleteObject (hMask);
+    return Image.win32_new (device, SWT.ICON, hIcon);
+}
+
+static HBITMAP createMaskFromAlpha (ImageData data, int destWidth, int destHeight) {
+    static_this();
+    int srcWidth = data.width;
+    int srcHeight = data.height;
+    ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1,
+            new PaletteData([new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)]),
+            2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0);
+    int ap = 0;
+    for (int y = 0; y < mask.height; y++) {
+        for (int x = 0; x < mask.width; x++) {
+            mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0);
+        }
+    }
+    auto hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data.ptr);
+    if (srcWidth !is destWidth || srcHeight !is destHeight) {
+        auto hdc = OS.GetDC (null);
+        auto hdc1 = OS.CreateCompatibleDC (hdc);
+        OS.SelectObject (hdc1, hMask);
+        auto hdc2 = OS.CreateCompatibleDC (hdc);
+        auto hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
+        OS.SelectObject (hdc2, hMask2);
+        static if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
+        OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
+        OS.DeleteDC (hdc1);
+        OS.DeleteDC (hdc2);
+        OS.ReleaseDC (null, hdc);
+        OS.DeleteObject(hMask);
+        hMask = hMask2;
+    }
+    return hMask;
+}
+
+static void deregister (Display display) {
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (display is Displays [i]) Displays [i] = null;
+        }
+    }
+}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle.  If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ * <p>
+ * This method is called after <code>release</code>.
+ * </p>
+ * @see Device#dispose
+ * @see #release
+ */
+override protected void destroy () {
+    if (this is Default) Default = null;
+    deregister (this);
+    destroyDisplay ();
+}
+
+void destroyDisplay () {
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread just before the
+ * receiver is disposed.  Specifying a <code>null</code> runnable
+ * is ignored.
+ *
+ * @param runnable code to run at dispose time.
+ *
+ * @exception SWTException <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>
+ */
+public void disposeExec (Runnable runnable) {
+    checkDevice ();
+    if (disposeList is null) disposeList = new Runnable [4];
+    for (int i=0; i<disposeList.length; i++) {
+        if (disposeList [i] is null) {
+            disposeList [i] = runnable;
+            return;
+        }
+    }
+    Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
+    SimpleType!(Runnable).arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
+    newDisposeList [disposeList.length] = runnable;
+    disposeList = newDisposeList;
+}
+
+void drawMenuBars () {
+    if (bars is null) return;
+    for (int i=0; i<bars.length; i++) {
+        Menu menu = bars [i];
+        if (menu !is null && !menu.isDisposed ()) menu.update ();
+    }
+    bars = null;
+}
+
+private static extern(Windows) int embeddedFunc (HWND hwnd, int msg, int wParam, int lParam) {
+    switch (msg) {
+        case SWT_KEYMSG: {
+            MSG* keyMsg = cast(MSG*)lParam;
+            OS.TranslateMessage (keyMsg);
+            OS.DispatchMessage (keyMsg);
+            auto hHeap = OS.GetProcessHeap ();
+            OS.HeapFree (hHeap, 0, cast(void*)lParam);
+            break;
+        }
+        case SWT_DESTROY: {
+            OS.DestroyWindow (hwnd);
+            //if (embeddedCallback !is null) embeddedCallback.dispose ();
+            //if (getMsgCallback !is null) getMsgCallback.dispose ();
+            //embeddedCallback = getMsgCallback = null;
+            //embeddedProc_ = getMsgProc_ = 0;
+            break;
+        }
+        default:
+    }
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+/**
+ * Does whatever display specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+    SWT.error (code);
+}
+
+bool filterEvent (Event event) {
+    if (filterTable !is null) filterTable.sendEvent (event);
+    return false;
+}
+
+bool filters (int eventType) {
+    if (filterTable is null) return false;
+    return filterTable.hooks (eventType);
+}
+
+bool filterMessage (MSG* msg) {
+    int message = msg.message;
+    if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
+        Control control = findControl (msg.hwnd);
+        if (control !is null) {
+            if (translateAccelerator (msg, control) || translateMnemonic (msg, control) || translateTraversal (msg, control)) {
+                lastAscii = lastKey = 0;
+                lastVirtual = lastNull = lastDead = false;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+Control findControl (HANDLE handle) {
+    if (handle is null) return null;
+    HWND hwndOwner = null;
+    do {
+        Control control = getControl (handle);
+        if (control !is null) return control;
+        hwndOwner = OS.GetWindow (handle, OS.GW_OWNER);
+        handle = OS.GetParent (handle);
+    } while (handle !is null && handle !is hwndOwner);
+    return null;
+}
+
+/**
+ * Given the operating system handle for a widget, returns
+ * the instance of the <code>Widget</code> subclass which
+ * represents it in the currently running application, if
+ * such exists, or null if no matching widget can be found.
+ * <p>
+ * <b>IMPORTANT:</b> This method should not be called from
+ * application code. The arguments are platform-specific.
+ * </p>
+ *
+ * @param handle the handle for the widget
+ * @return the SWT widget that the handle represents
+ *
+ * @exception SWTException <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>
+ */
+public Widget findWidget (HANDLE handle) {
+    checkDevice ();
+    return getControl (handle);
+}
+
+/**
+ * Given the operating system handle for a widget,
+ * and widget-specific id, returns the instance of
+ * the <code>Widget</code> subclass which represents
+ * the handle/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ * <p>
+ * <b>IMPORTANT:</b> This method should not be called from
+ * application code. The arguments are platform-specific.
+ * </p>
+ *
+ * @param handle the handle for the widget
+ * @param id the id for the subwidget (usually an item)
+ * @return the SWT widget that the handle/id pair represents
+ *
+ * @exception SWTException <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.1
+ */
+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;
+}
+
+/**
+ * Given a widget and a widget-specific id, returns the
+ * instance of the <code>Widget</code> subclass which represents
+ * the widget/id pair in the currently running application,
+ * if such exists, or null if no matching widget can be found.
+ *
+ * @param widget the widget
+ * @param id the id for the subwidget (usually an item)
+ * @return the SWT subwidget (usually an item) that the widget/id pair represents
+ *
+ * @exception SWTException <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.3
+ */
+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);
+    }
+    return null;
+}
+
+private static extern(Windows) int foregroundIdleProcFunc (int code, uint wParam, int lParam) {
+    auto d = Display.getCurrent();
+    return d.foregroundIdleProc( code, wParam, lParam );
+}
+
+int foregroundIdleProc (int code, int wParam, int lParam) {
+    if (code >= 0) {
+        if (runMessages && getMessageCount () !is 0) {
+            if (runMessagesInIdle) {
+                if (runMessagesInMessageProc) {
+                    OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
+                } else {
+                    runAsyncMessages (false);
+                }
+            }
+            wakeThread ();
+        }
+    }
+    return OS.CallNextHookEx (idleHook, code, wParam, lParam);
+}
+
+/**
+ * Returns the display which the given thread is the
+ * user-interface thread for, or null if the given thread
+ * is not a user-interface thread for any display.  Specifying
+ * <code>null</code> as the thread will return <code>null</code>
+ * for the display.
+ *
+ * @param thread the user-interface thread
+ * @return the display for the given thread
+ */
+public static Display findDisplay (Thread thread) {
+    static_this();
+    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;
+    }
+}
+
+/**
+ * Returns the currently active <code>Shell</code>, or null
+ * if no shell belonging to the currently running application
+ * is active.
+ *
+ * @return the active shell or null
+ *
+ * @exception SWTException <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>
+ */
+public Shell getActiveShell () {
+    checkDevice ();
+    Control control = findControl (OS.GetActiveWindow ());
+    return control !is null ? control.getShell () : null;
+}
+
+/**
+ * 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
+ *
+ * @exception SWTException <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>
+ */
+override public Rectangle getBounds () {
+    checkDevice ();
+    if (OS.GetSystemMetrics (OS.SM_CMONITORS) < 2) {
+        int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+        int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+        return new Rectangle (0, 0, width, height);
+    }
+    int x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
+    int y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
+    int width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
+    int height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the display which the currently running thread is
+ * the user-interface thread for, or null if the currently
+ * running thread is not a user-interface thread for any display.
+ *
+ * @return the current display
+ */
+public static Display getCurrent () {
+    static_this();
+    return findDisplay (Thread.getThis ());
+}
+
+int getClickCount (int type, int button, HWND hwnd, int lParam) {
+    switch (type) {
+        case SWT.MouseDown:
+            int doubleClick = OS.GetDoubleClickTime ();
+            if (clickRect is null) clickRect = new RECT ();
+            int deltaTime = Math.abs (lastTime - getLastEventTime ());
+            POINT pt;
+            OS.POINTSTOPOINT (pt, lParam);
+            if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (clickRect, pt)) {
+                clickCount++;
+            } else {
+                clickCount = 1;
+            }
+            //FALL THROUGH
+        case SWT.MouseDoubleClick:
+            lastButton = button;
+            lastClickHwnd = hwnd;
+            lastTime = getLastEventTime ();
+            int xInset = OS.GetSystemMetrics (OS.SM_CXDOUBLECLK) / 2;
+            int yInset = OS.GetSystemMetrics (OS.SM_CYDOUBLECLK) / 2;
+            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 SWT.MouseUp:
+            return clickCount;
+        default:
+    }
+    return 0;
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ *
+ * @exception SWTException <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>
+ *
+ * @see #getBounds
+ */
+override public Rectangle getClientArea () {
+    checkDevice ();
+    if (OS.GetSystemMetrics (OS.SM_CMONITORS) < 2) {
+        RECT rect;
+        OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
+        int width = rect.right - rect.left;
+        int height = rect.bottom - rect.top;
+        return new Rectangle (rect.left, rect.top, width, height);
+    }
+    int x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
+    int y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
+    int width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
+    int height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+    return new Rectangle (x, y, width, height);
+}
+
+Control getControl (HANDLE handle) {
+    if (handle is null) return null;
+    if (lastControl !is null && lastHwnd is handle) {
+        return lastControl;
+    }
+    if (lastGetControl !is null && lastGetHwnd is handle) {
+        return lastGetControl;
+    }
+    int index;
+    static if (USE_PROPERTY) {
+        index = cast(int) OS.GetProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
+    } else {
+        index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
+    }
+    if (0 <= index && index < controlTable.length) {
+        Control control = controlTable [index];
+        /*
+        * Because GWL_USERDATA can be used by native widgets that
+        * do not belong to SWT, it is possible that GWL_USERDATA
+        * could return an index that is in the range of the table,
+        * but was not put there by SWT.  Therefore, it is necessary
+        * to check the handle of the control that is in the table
+        * against the handle that provided the GWL_USERDATA.
+        */
+        if (control !is null && control.checkHandle (handle)) {
+            lastGetHwnd = handle;
+            lastGetControl = control;
+            return control;
+        }
+    }
+    return null;
+}
+
+/**
+ * Returns the control which the on-screen pointer is currently
+ * over top of, or null if it is not currently over one of the
+ * controls built by the currently running application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException <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>
+ */
+public Control getCursorControl () {
+    checkDevice ();
+    POINT pt;
+    if (!OS.GetCursorPos (&pt)) return null;
+    return findControl (OS.WindowFromPoint (pt));
+}
+
+/**
+ * Returns the location of the on-screen pointer relative
+ * to the top left corner of the screen.
+ *
+ * @return the cursor location
+ *
+ * @exception SWTException <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>
+ */
+public Point getCursorLocation () {
+    checkDevice ();
+    POINT pt;
+    OS.GetCursorPos (&pt);
+    return new Point (pt.x, pt.y);
+}
+
+/**
+ * Returns an array containing the recommended cursor sizes.
+ *
+ * @return the array of cursor sizes
+ *
+ * @exception SWTException <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.0
+ */
+public Point [] getCursorSizes () {
+    checkDevice ();
+    return [
+        new Point (OS.GetSystemMetrics (OS.SM_CXCURSOR), OS.GetSystemMetrics (OS.SM_CYCURSOR))];
+}
+
+/**
+ * Returns the default display. One is created (making the
+ * thread that invokes this method its user-interface thread)
+ * if it did not already exist.
+ *
+ * @return the default display
+ */
+public static Display getDefault () {
+    static_this();
+    synchronized (Device.classinfo) {
+        if (Default is null) Default = new Display ();
+        return Default;
+    }
+}
+
+//PORTING_TODO
+/+static bool isValidClass (Class clazz) {
+    String name = clazz.getName ();
+    int index = name.lastIndexOf ('.');
+    return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
+}+/
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility to provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception SWTException <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>
+ *
+ * @see #setData(String, Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData (String key) {
+    checkDevice ();
+    // SWT extension: allow null string
+    //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
+    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];
+    }
+    return null;
+}
+
+/**
+ * Returns the application defined, display specific data
+ * associated with the receiver, or null if it has not been
+ * set. The <em>display specific data</em> is a single,
+ * unnamed field that is stored with every display.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility to provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @return the display specific data
+ *
+ * @exception SWTException <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>
+ *
+ * @see #setData(Object)
+ * @see #disposeExec(Runnable)
+ */
+public Object getData () {
+    checkDevice ();
+    return data;
+}
+
+/**
+ * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
+ * The button dismissal alignment is the ordering that should be used when positioning the
+ * default dismissal button for a dialog.  For example, in a dialog that contains an OK and
+ * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
+ * button ordering should be OK/CANCEL.  When button dismissal alignment is <code>RIGHT</code>,
+ * the button ordering should be CANCEL/OK.
+ *
+ * @return the button dismissal order
+ *
+ * @exception SWTException <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 2.1
+ */
+public int getDismissalAlignment () {
+    checkDevice ();
+    return SWT.LEFT;
+}
+
+
+/**
+ * Returns the longest duration, in milliseconds, between
+ * two mouse button clicks that will be considered a
+ * <em>double click</em> by the underlying operating system.
+ *
+ * @return the double click time
+ *
+ * @exception SWTException <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>
+ */
+public int getDoubleClickTime () {
+    checkDevice ();
+    return OS.GetDoubleClickTime ();
+}
+
+/**
+ * Returns the control which currently has keyboard focus,
+ * or null if keyboard events are not currently going to
+ * any of the controls built by the currently running
+ * application.
+ *
+ * @return the control under the cursor
+ *
+ * @exception SWTException <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>
+ */
+public Control getFocusControl () {
+    checkDevice ();
+    if (focusControl !is null && !focusControl.isDisposed ()) {
+        return focusControl;
+    }
+    return _getFocusControl ();
+}
+
+String getFontName (LOGFONT* logFont) {
+    wchar* chars;
+    static if (OS.IsUnicode) {
+        chars = logFont.lfFaceName.ptr;
+    } else {
+        chars = new char[OS.LF_FACESIZE];
+        byte[] bytes = logFont.lfFaceName;
+        OS.MultiByteToWideChar (OS.CP_ACP, OS.MB_PRECOMPOSED, bytes, bytes.length, chars, chars.length);
+    }
+    return TCHARzToStr( chars );
+}
+
+/**
+ * Returns true when the high contrast mode is enabled.
+ * Otherwise, false is returned.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @return the high contrast mode
+ *
+ * @exception SWTException <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.0
+ */
+public bool getHighContrast () {
+    checkDevice ();
+    static if (OS.IsWinCE) {
+        return false;
+    }
+    else {
+        HIGHCONTRAST pvParam;
+        pvParam.cbSize = HIGHCONTRAST.sizeof;
+        OS.SystemParametersInfo (OS.SPI_GETHIGHCONTRAST, 0, &pvParam, 0);
+        return (pvParam.dwFlags & OS.HCF_HIGHCONTRASTON) !is 0;
+    }
+}
+
+/**
+ * Returns the maximum allowed depth of icons on this display, in bits per pixel.
+ * On some platforms, this may be different than the actual depth of the display.
+ *
+ * @return the maximum icon depth
+ *
+ * @exception SWTException <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>
+ *
+ * @see Device#getDepth
+ */
+public int getIconDepth () {
+    checkDevice ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        if (getDepth () >= 24) return 32;
+    }
+
+    /* Use the character encoding for the default locale */
+    TCHAR* buffer1 = StrToTCHARz( "Control Panel\\Desktop\\WindowMetrics" ); //$NON-NLS-1$
+
+    void* phkResult;
+    int result = OS.RegOpenKeyEx ( cast(void*)OS.HKEY_CURRENT_USER, buffer1, 0, OS.KEY_READ, &phkResult);
+    if (result !is 0) return 4;
+    int depth = 4;
+    uint lpcbData;
+
+    /* Use the character encoding for the default locale */
+    TCHAR* buffer2 = StrToTCHARz( "Shell Icon BPP" ); //$NON-NLS-1$
+    result = OS.RegQueryValueEx (phkResult , buffer2, null, null, null, &lpcbData);
+    if (result is 0) {
+        ubyte[] lpData = new ubyte[ lpcbData  / TCHAR.sizeof ];
+        lpData[] = 0;
+        result = OS.RegQueryValueEx (phkResult , buffer2, null, null, lpData.ptr, &lpcbData);
+        if (result is 0) {
+            try {
+                depth = Integer.parseInt ( cast(String) lpData );
+            } catch (NumberFormatException e) {}
+        }
+    }
+    OS.RegCloseKey (phkResult );
+    return depth;
+}
+
+/**
+ * Returns an array containing the recommended icon sizes.
+ *
+ * @return the array of icon sizes
+ *
+ * @exception SWTException <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>
+ *
+ * @see Decorations#setImages(Image[])
+ *
+ * @since 3.0
+ */
+public Point [] getIconSizes () {
+    checkDevice ();
+    return [
+        new Point (OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON)),
+        new Point (OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON))
+    ];
+}
+
+ImageList getImageList (int style, int width, int height) {
+    if (imageList is null) imageList = new ImageList [4];
+
+    int i = 0;
+    int length_ = imageList.length;
+    while (i < length_) {
+        ImageList list = imageList [i];
+        if (list is null) break;
+        Point size = list.getImageSize();
+        if (size.x is width && size.y is height) {
+            if (list.getStyle () is style) {
+                list.addRef();
+                return list;
+            }
+        }
+        i++;
+    }
+
+    if (i is length_) {
+        ImageList [] newList = new ImageList [length_ + 4];
+        System.arraycopy (imageList, 0, newList, 0, length_);
+        imageList = newList;
+    }
+
+    ImageList list = new ImageList (style);
+    imageList [i] = list;
+    list.addRef();
+    return list;
+}
+
+ImageList getImageListToolBar (int style, int width, int height) {
+    if (toolImageList is null) toolImageList = new ImageList [4];
+
+    int i = 0;
+    int length_ = toolImageList.length;
+    while (i < length_) {
+        ImageList list = toolImageList [i];
+        if (list is null) break;
+        Point size = list.getImageSize();
+        if (size.x is width && size.y is height) {
+            if (list.getStyle () is style) {
+                list.addRef();
+                return list;
+            }
+        }
+        i++;
+    }
+
+    if (i is length_) {
+        ImageList [] newList = new ImageList [length_ + 4];
+        System.arraycopy (toolImageList, 0, newList, 0, length_);
+        toolImageList = newList;
+    }
+
+    ImageList list = new ImageList (style);
+    toolImageList [i] = list;
+    list.addRef();
+    return list;
+}
+
+ImageList getImageListToolBarDisabled (int style, int width, int height) {
+    if (toolDisabledImageList is null) toolDisabledImageList = new ImageList [4];
+
+    int i = 0;
+    int length_ = toolDisabledImageList.length;
+    while (i < length_) {
+        ImageList list = toolDisabledImageList [i];
+        if (list is null) break;
+        Point size = list.getImageSize();
+        if (size.x is width && size.y is height) {
+            if (list.getStyle () is style) {
+                list.addRef();
+                return list;
+            }
+        }
+        i++;
+    }
+
+    if (i is length_) {
+        ImageList [] newList = new ImageList [length_ + 4];
+        System.arraycopy (toolDisabledImageList, 0, newList, 0, length_);
+        toolDisabledImageList = newList;
+    }
+
+    ImageList list = new ImageList (style);
+    toolDisabledImageList [i] = list;
+    list.addRef();
+    return list;
+}
+
+ImageList getImageListToolBarHot (int style, int width, int height) {
+    if (toolHotImageList is null) toolHotImageList = new ImageList [4];
+
+    int i = 0;
+    int length_ = toolHotImageList.length;
+    while (i < length_) {
+        ImageList list = toolHotImageList [i];
+        if (list is null) break;
+        Point size = list.getImageSize();
+        if (size.x is width && size.y is height) {
+            if (list.getStyle () is style) {
+                list.addRef();
+                return list;
+            }
+        }
+        i++;
+    }
+
+    if (i is length_) {
+        ImageList [] newList = new ImageList [length_ + 4];
+        System.arraycopy (toolHotImageList, 0, newList, 0, length_);
+        toolHotImageList = newList;
+    }
+
+    ImageList list = new ImageList (style);
+    toolHotImageList [i] = list;
+    list.addRef();
+    return list;
+}
+
+int getLastEventTime () {
+    return OS.IsWinCE ? OS.GetTickCount () : OS.GetMessageTime ();
+}
+
+MenuItem getMenuItem (int id) {
+    if (items is null) return null;
+    id = id - ID_START;
+    if (0 <= id && id < items.length) return items [id];
+    return null;
+}
+
+int getMessageCount () {
+    return synchronizer.getMessageCount ();
+}
+
+
+Shell getModalShell () {
+    if (modalShells is null) return null;
+    int index = modalShells.length;
+    while (--index >= 0) {
+        Shell shell = modalShells [index];
+        if (shell !is null) return shell;
+    }
+    return null;
+}
+
+Dialog getModalDialog () {
+    return modalDialog;
+}
+
+/**
+ * Returns an array of monitors attached to the device.
+ *
+ * @return the array of monitors
+ *
+ * @since 3.0
+ */
+public org.eclipse.swt.widgets.Monitor.Monitor [] getMonitors () {
+    checkDevice ();
+    if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+        return [getPrimaryMonitor ()];
+    }
+    monitors = new org.eclipse.swt.widgets.Monitor.Monitor [4];
+    OS.EnumDisplayMonitors (null, null, &monitorEnumFunc, cast(int)cast(void*)this );
+    org.eclipse.swt.widgets.Monitor.Monitor [] result = new org.eclipse.swt.widgets.Monitor.Monitor [monitorCount];
+    System.arraycopy (monitors, 0, result, 0, monitorCount);
+    monitors = null;
+    monitorCount = 0;
+    return result;
+}
+
+static extern(Windows) int getMsgFunc (int code, uint wParam, int lParam) {
+    return Display.getCurrent().getMsgProc( code, wParam, lParam );
+}
+
+int getMsgProc (int code, int wParam, int lParam) {
+    if (embeddedHwnd is null) {
+        auto hInstance = OS.GetModuleHandle (null);
+        embeddedHwnd = OS.CreateWindowEx (0,
+            windowClass_.ptr,
+            null,
+            OS.WS_OVERLAPPED,
+            0, 0, 0, 0,
+            null,
+            null,
+            hInstance,
+            null);
+        //embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
+        //embeddedProc_ = embeddedCallback.getAddress ();
+        //if (embeddedProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+        OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) &embeddedFunc);
+    }
+    if (code >= 0 && (wParam & OS.PM_REMOVE) !is 0) {
+        MSG* msg = cast(MSG*)lParam;
+        switch (msg.message) {
+            case OS.WM_KEYDOWN:
+            case OS.WM_KEYUP:
+            case OS.WM_SYSKEYDOWN:
+            case OS.WM_SYSKEYUP: {
+                Control control = findControl (msg.hwnd);
+                if (control !is null) {
+                    auto hHeap = OS.GetProcessHeap ();
+                    MSG* keyMsg = cast(MSG*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, MSG.sizeof);
+                    *keyMsg = *msg;
+                    OS.PostMessage (hwndMessage, SWT_KEYMSG, wParam, cast(int)keyMsg);
+                    switch (msg.wParam) {
+                        case OS.VK_SHIFT:
+                        case OS.VK_MENU:
+                        case OS.VK_CONTROL:
+                        case OS.VK_CAPITAL:
+                        case OS.VK_NUMLOCK:
+                        case OS.VK_SCROLL:
+                            break;
+                        default:
+                            msg.message = OS.WM_NULL;
+                            //OS.MoveMemory (lParam, msg, MSG.sizeof);
+                    }
+                }
+            default:
+            }
+        }
+    }
+    return OS.CallNextHookEx (msgHook, code, wParam, lParam);
+}
+
+/**
+ * Returns the primary monitor for that device.
+ *
+ * @return the primary monitor
+ *
+ * @since 3.0
+ */
+public org.eclipse.swt.widgets.Monitor.Monitor getPrimaryMonitor () {
+    checkDevice ();
+    if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+        org.eclipse.swt.widgets.Monitor.Monitor monitor = new org.eclipse.swt.widgets.Monitor.Monitor();
+        int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+        int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+        monitor.width = width;
+        monitor.height = height;
+        RECT rect;
+        OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
+        monitor.clientX = rect.left;
+        monitor.clientY = rect.top;
+        monitor.clientWidth = rect.right - rect.left;
+        monitor.clientHeight = rect.bottom - rect.top;
+        return monitor;
+    }
+    monitors = new org.eclipse.swt.widgets.Monitor.Monitor [4];
+    OS.EnumDisplayMonitors (null, null, &monitorEnumFunc, cast(int)cast(void*)this);
+    org.eclipse.swt.widgets.Monitor.Monitor result = null;
+    MONITORINFO lpmi;
+    lpmi.cbSize = MONITORINFO.sizeof;
+    for (int i = 0; i < monitorCount; i++) {
+        org.eclipse.swt.widgets.Monitor.Monitor monitor = monitors [i];
+        OS.GetMonitorInfo (monitors [i].handle, &lpmi);
+        if ((lpmi.dwFlags & OS.MONITORINFOF_PRIMARY) !is 0) {
+            result = monitor;
+            break;
+        }
+    }
+    monitors = null;
+    monitorCount = 0;
+    return result;
+}
+
+/**
+ * Returns a (possibly empty) array containing all shells which have
+ * not been disposed and have the receiver as their display.
+ *
+ * @return the receiver's shells
+ *
+ * @exception SWTException <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>
+ */
+public Shell [] getShells () {
+    checkDevice ();
+    int index = 0;
+    Shell [] result = new Shell [16];
+    for (int i = 0; i < controlTable.length; i++) {
+        Control control = controlTable [i];
+        if (control !is null && (cast(Shell)control)) {
+            int j = 0;
+            while (j < index) {
+                if (result [j] is control) break;
+                j++;
+            }
+            if (j is index) {
+                if (index is result.length) {
+                    Shell [] newResult = new Shell [index + 16];
+                    System.arraycopy (result, 0, newResult, 0, index);
+                    result = newResult;
+                }
+                result [index++] = cast(Shell) control;
+            }
+        }
+    }
+    if (index is result.length) return result;
+    Shell [] newResult = new Shell [index];
+    System.arraycopy (result, 0, newResult, 0, index);
+    return newResult;
+}
+
+Image getSortImage (int direction) {
+    switch (direction) {
+        case SWT.UP: {
+            if (upArrow !is null) return upArrow;
+            Color c1 = getSystemColor (SWT.COLOR_WIDGET_NORMAL_SHADOW);
+            Color c2 = getSystemColor (SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+            Color c3 = getSystemColor (SWT.COLOR_WIDGET_BACKGROUND);
+            PaletteData palette = new PaletteData([c1.getRGB (), c2.getRGB (), c3.getRGB ()]);
+            ImageData imageData = new ImageData (8, 8, 4, palette);
+            imageData.transparentPixel = 2;
+            upArrow = new Image (this, imageData);
+            GC gc = new GC (upArrow);
+            gc.setBackground (c3);
+            gc.fillRectangle (0, 0, 8, 8);
+            gc.setForeground (c1);
+            int [] line1 = [0,6, 1,6, 1,4, 2,4, 2,2, 3,2, 3,1];
+            gc.drawPolyline (line1);
+            gc.setForeground (c2);
+            int [] line2 = [0,7, 7,7, 7,6, 6,6, 6,4, 5,4, 5,2, 4,2, 4,1];
+            gc.drawPolyline (line2);
+            gc.dispose ();
+            return upArrow;
+        }
+        case SWT.DOWN: {
+            if (downArrow !is null) return downArrow;
+            Color c1 = getSystemColor (SWT.COLOR_WIDGET_NORMAL_SHADOW);
+            Color c2 = getSystemColor (SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+            Color c3 = getSystemColor (SWT.COLOR_WIDGET_BACKGROUND);
+            PaletteData palette = new PaletteData ([c1.getRGB (), c2.getRGB (), c3.getRGB ()]);
+            ImageData imageData = new ImageData (8, 8, 4, palette);
+            imageData.transparentPixel = 2;
+            downArrow = new Image (this, imageData);
+            GC gc = new GC (downArrow);
+            gc.setBackground (c3);
+            gc.fillRectangle (0, 0, 8, 8);
+            gc.setForeground (c1);
+            int [] line1 = [7,0, 0,0, 0,1, 1,1, 1,3, 2,3, 2,5, 3,5, 3,6];
+            gc.drawPolyline (line1);
+            gc.setForeground (c2);
+            int [] line2 = [4,6, 4,5, 5,5, 5,3, 6,3, 6,1, 7,1];
+            gc.drawPolyline (line2);
+            gc.dispose ();
+            return downArrow;
+        }
+        default:
+    }
+    return null;
+}
+
+/**
+ * Gets the synchronizer used by the display.
+ *
+ * @return the receiver's synchronizer
+ *
+ * @exception SWTException <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.
+ * <p>
+ * Note: If a runnable invoked by asyncExec is currently
+ * running, this method will return null.
+ * </p>
+ *
+ * @return the receiver's sync-interface thread
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Thread getSyncThread () {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        return synchronizer.syncThread;
+    }
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class <code>SWT</code>. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be free'd because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException <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>
+ *
+ * @see SWT
+ */
+override public Color getSystemColor (int id) {
+    checkDevice ();
+    int pixel = 0x00000000;
+    switch (id) {
+        case SWT.COLOR_WIDGET_DARK_SHADOW:      pixel = OS.GetSysColor (OS.COLOR_3DDKSHADOW);   break;
+        case SWT.COLOR_WIDGET_NORMAL_SHADOW:    pixel = OS.GetSysColor (OS.COLOR_3DSHADOW);     break;
+        case SWT.COLOR_WIDGET_LIGHT_SHADOW:     pixel = OS.GetSysColor (OS.COLOR_3DLIGHT);      break;
+        case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW: pixel = OS.GetSysColor (OS.COLOR_3DHIGHLIGHT);  break;
+        case SWT.COLOR_WIDGET_BACKGROUND:       pixel = OS.GetSysColor (OS.COLOR_3DFACE);   break;
+        case SWT.COLOR_WIDGET_BORDER:       pixel = OS.GetSysColor (OS.COLOR_WINDOWFRAME);  break;
+        case SWT.COLOR_WIDGET_FOREGROUND:
+        case SWT.COLOR_LIST_FOREGROUND:         pixel = OS.GetSysColor (OS.COLOR_WINDOWTEXT);   break;
+        case SWT.COLOR_LIST_BACKGROUND:         pixel = OS.GetSysColor (OS.COLOR_WINDOW);   break;
+        case SWT.COLOR_LIST_SELECTION:      pixel = OS.GetSysColor (OS.COLOR_HIGHLIGHT);    break;
+        case SWT.COLOR_LIST_SELECTION_TEXT:     pixel = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);break;
+        case SWT.COLOR_INFO_FOREGROUND:     pixel = OS.GetSysColor (OS.COLOR_INFOTEXT); break;
+        case SWT.COLOR_INFO_BACKGROUND:     pixel = OS.GetSysColor (OS.COLOR_INFOBK);       break;
+        case SWT.COLOR_TITLE_FOREGROUND:        pixel = OS.GetSysColor (OS.COLOR_CAPTIONTEXT);  break;
+        case SWT.COLOR_TITLE_BACKGROUND:        pixel = OS.GetSysColor (OS.COLOR_ACTIVECAPTION);        break;
+        case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:
+            pixel = OS.GetSysColor (OS.COLOR_GRADIENTACTIVECAPTION);
+            if (pixel is 0) pixel = OS.GetSysColor (OS.COLOR_ACTIVECAPTION);
+            break;
+        case SWT.COLOR_TITLE_INACTIVE_FOREGROUND:       pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTIONTEXT);  break;
+        case SWT.COLOR_TITLE_INACTIVE_BACKGROUND:           pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTION);      break;
+        case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:
+            pixel = OS.GetSysColor (OS.COLOR_GRADIENTINACTIVECAPTION);
+            if (pixel is 0) pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTION);
+            break;
+        default:
+            return super.getSystemColor (id);
+    }
+    return Color.win32_new (this, pixel);
+}
+
+/**
+ * Returns the matching standard platform cursor for the given
+ * constant, which should be one of the cursor constants
+ * specified in class <code>SWT</code>. This cursor should
+ * not be free'd because it was allocated by the system,
+ * not the application.  A value of <code>null</code> will
+ * be returned if the supplied constant is not an SWT cursor
+ * constant.
+ *
+ * @param id the SWT cursor constant
+ * @return the corresponding cursor or <code>null</code>
+ *
+ * @exception SWTException <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>
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ *
+ * @since 3.0
+ */
+public Cursor getSystemCursor (int id) {
+    checkDevice ();
+    if (!(0 <= id && id < cursors.length)) return null;
+    if (cursors [id] is null) {
+        cursors [id] = new Cursor (this, id);
+    }
+    return cursors [id];
+}
+
+/**
+ * Returns a reasonable font for applications to use.
+ * On some platforms, this will match the "default font"
+ * or "system font" if such can be found.  This font
+ * should not be free'd because it was allocated by the
+ * system, not the application.
+ * <p>
+ * Typically, applications which want the default look
+ * should simply not set the font on the widgets they
+ * create. Widgets are always created with the correct
+ * default font for the class of user-interface component
+ * they represent.
+ * </p>
+ *
+ * @return a font
+ *
+ * @exception SWTException <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>
+ */
+override public Font getSystemFont () {
+    checkDevice ();
+    if (systemFont !is null) return systemFont;
+    HFONT hFont;
+    static if (!OS.IsWinCE) {
+        NONCLIENTMETRICS info;
+        info.cbSize = NONCLIENTMETRICS.sizeof;
+        if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
+            LOGFONT logFont = info.lfMessageFont;
+            hFont = OS.CreateFontIndirect (&logFont);
+            lfSystemFont = hFont !is null ? &logFont : null;
+        }
+    }
+    if (hFont is null) hFont = OS.GetStockObject (OS.DEFAULT_GUI_FONT);
+    if (hFont is null) hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    return systemFont = Font.win32_new (this, hFont);
+}
+
+/**
+ * Returns the matching standard platform image for the given
+ * constant, which should be one of the icon constants
+ * specified in class <code>SWT</code>. This image should
+ * not be free'd because it was allocated by the system,
+ * not the application.  A value of <code>null</code> will
+ * be returned either if the supplied constant is not an
+ * SWT icon constant or if the platform does not define an
+ * image that corresponds to the constant.
+ *
+ * @param id the SWT icon constant
+ * @return the corresponding image or <code>null</code>
+ *
+ * @exception SWTException <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>
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_QUESTION
+ * @see SWT#ICON_WARNING
+ * @see SWT#ICON_WORKING
+ *
+ * @since 3.0
+ */
+public Image getSystemImage (int id) {
+    checkDevice ();
+    switch (id) {
+        case SWT.ICON_ERROR: {
+            if (errorImage !is null) return errorImage;
+            auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_HAND, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
+            return errorImage = Image.win32_new (this, SWT.ICON, hIcon);
+        }
+        case SWT.ICON_WORKING:
+        case SWT.ICON_INFORMATION: {
+            if (infoImage !is null) return infoImage;
+            auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_INFORMATION, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
+            return infoImage = Image.win32_new (this, SWT.ICON, hIcon);
+        }
+        case SWT.ICON_QUESTION: {
+            if (questionImage !is null) return questionImage;
+            auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_QUES, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
+            return questionImage = Image.win32_new (this, SWT.ICON, hIcon);
+        }
+        case SWT.ICON_WARNING: {
+            if (warningIcon !is null) return warningIcon;
+            auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_BANG, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
+            return warningIcon = Image.win32_new (this, SWT.ICON, hIcon);
+        }
+        default:
+    }
+    return null;
+}
+
+/**
+ * Returns the single instance of the system tray or null
+ * when there is no system tray available for the platform.
+ *
+ * @return the system tray or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public Tray getSystemTray () {
+    checkDevice ();
+    if (tray !is null) return tray;
+    static if (!OS.IsWinCE) tray = new Tray (this, SWT.NONE);
+    return tray;
+}
+
+/**
+ * Returns the user-interface thread for the receiver.
+ *
+ * @return the receiver's user-interface thread
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Thread getThread () {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        return thread;
+    }
+}
+
+HTHEME hButtonTheme () {
+    if (hButtonTheme_ !is null) return hButtonTheme_;
+    return hButtonTheme_ = OS.OpenThemeData (hwndMessage, BUTTON.ptr);
+}
+
+HTHEME hEditTheme () {
+    if (hEditTheme_ !is null) return hEditTheme_;
+    return hEditTheme_ = OS.OpenThemeData (hwndMessage, EDIT.ptr);
+}
+
+HTHEME hExplorerBarTheme () {
+    if (hExplorerBarTheme_ !is null) return hExplorerBarTheme_;
+    return hExplorerBarTheme_ = OS.OpenThemeData (hwndMessage, EXPLORERBAR.ptr);
+}
+
+HTHEME hScrollBarTheme () {
+    if (hScrollBarTheme_ !is null) return hScrollBarTheme_;
+    return hScrollBarTheme_ = OS.OpenThemeData (hwndMessage, SCROLLBAR.ptr);
+}
+
+HTHEME hTabTheme () {
+    if (hTabTheme_ !is null) return hTabTheme_;
+    return hTabTheme_ = OS.OpenThemeData (hwndMessage, TAB.ptr);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Display</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param data the platform specific GC data
+ * @return the platform specific GC handle
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
+ * </ul>
+ */
+override public HDC internal_new_GC (GCData data) {
+    if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+    auto hDC = OS.GetDC (null);
+    if (hDC is null) SWT.error (SWT.ERROR_NO_HANDLES);
+    if (data !is null) {
+        int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+        if ((data.style & mask) !is 0) {
+            data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
+        } else {
+            data.style |= SWT.LEFT_TO_RIGHT;
+        }
+        data.device = this;
+        data.font = getSystemFont ();
+    }
+    return hDC;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ * <p>
+ * This method is called after <code>create</code>.
+ * </p>
+ *
+ * @see #create
+ */
+override protected void init_ () {
+    super.init_ ();
+
+    /* Create the callbacks */
+    //windowCallback = new Callback (this, "windowProc", 4); //$NON-NLS-1$
+    //windowProc_ = windowCallback.getAddress ();
+    //if (windowProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+
+    /* Remember the current thread id */
+    threadId = OS.GetCurrentThreadId ();
+
+    /* Use the character encoding for the default locale */
+    windowClass_ = StrToTCHARs ( 0, WindowName ~ to!(String)(WindowClassCount), true );
+    windowShadowClass = StrToTCHARs ( 0, WindowShadowName ~ to!(String)(WindowClassCount), true );
+    WindowClassCount++;
+
+    /* Register the SWT window class */
+    auto hHeap = OS.GetProcessHeap ();
+    auto hInstance = OS.GetModuleHandle (null);
+    WNDCLASS lpWndClass;
+    lpWndClass.hInstance = hInstance;
+    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 SWT
+    /+
+    /*
+    * 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);
+    OS.RegisterClass (&lpWndClass);
+    OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName);
+
+    /* Register the SWT drop shadow window class */
+    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);
+    OS.RegisterClass (&lpWndClass);
+    OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName);
+
+    /* Create the message only HWND */
+    hwndMessage = OS.CreateWindowEx (0,
+        windowClass_.ptr,
+        null,
+        OS.WS_OVERLAPPED,
+        0, 0, 0, 0,
+        null,
+        null,
+        hInstance,
+        null);
+    //messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$
+    //messageProc_ = messageCallback.getAddress ();
+    //if (messageProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+    OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, cast(LONG_PTR) &messageProcFunc);
+
+    /* Create the filter hook */
+    static if (!OS.IsWinCE) {
+        //msgFilterCallback = new Callback (this, "msgFilterProc", 3); //$NON-NLS-1$
+        //msgFilterProc_ = msgFilterCallback.getAddress ();
+        //if (msgFilterProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+        filterHook = OS.SetWindowsHookEx (OS.WH_MSGFILTER, &msgFilterProcFunc, null, threadId);
+    }
+
+    /* Create the idle hook */
+    static if (!OS.IsWinCE) {
+        //foregroundIdleCallback = new Callback (this, "foregroundIdleProc", 3); //$NON-NLS-1$
+        //foregroundIdleProc_ = foregroundIdleCallback.getAddress ();
+        //if (foregroundIdleProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+        idleHook = OS.SetWindowsHookEx (OS.WH_FOREGROUNDIDLE, &foregroundIdleProcFunc, null, threadId);
+    }
+
+    /* 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);
+
+    /* Initialize buffered painting */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)){
+        OS.BufferedPaintInit ();
+    }
+
+    /* Initialize the Widget Table */
+    indexTable = new int [GROW_SIZE];
+    controlTable = new Control [GROW_SIZE];
+    for (int i=0; i<GROW_SIZE-1; i++) indexTable [i] = i + 1;
+    indexTable [GROW_SIZE - 1] = -1;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Display</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+override public void internal_dispose_GC (HDC hDC, GCData data) {
+    OS.ReleaseDC (null, hDC);
+}
+
+bool isXMouseActive () {
+    /*
+    * NOTE: X-Mouse is active when bit 1 of the UserPreferencesMask is set.
+    */
+    bool xMouseActive = false;
+    TCHAR* key = StrToTCHARz( "Control Panel\\Desktop" ); //$NON-NLS-1$
+    void* phKey;
+    int result = OS.RegOpenKeyEx (cast(void*)OS.HKEY_CURRENT_USER, key, 0, OS.KEY_READ, &phKey);
+    if (result is 0) {
+        TCHAR* lpValueName = StrToTCHARz ( "UserPreferencesMask" ); //$NON-NLS-1$
+        uint[4] lpcbData;
+        uint lpData;
+        result = OS.RegQueryValueEx (phKey, lpValueName, null, null, cast(ubyte*)&lpData, lpcbData.ptr);
+        if (result is 0) xMouseActive = (lpData & 0x01) !is 0;
+        OS.RegCloseKey (phKey);
+    }
+    return xMouseActive;
+}
+
+bool isValidThread () {
+    return thread is Thread.getThis ();
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle.  When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction.  Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param point to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1.2
+ */
+public Point map (Control from, Control to, Point point) {
+    checkDevice ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return map (from, to, point.x, point.y);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle.  When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction.  Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @return point with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1.2
+ */
+public Point map (Control from, Control to, int x, int y) {
+    checkDevice ();
+    if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (from is to) return new Point (x, y);
+    auto hwndFrom = from !is null ? from.handle : null;
+    auto hwndTo = to !is null ? to.handle : null;
+    POINT point;
+    point.x = x;
+    point.y = y;
+    OS.MapWindowPoints (hwndFrom, hwndTo, &point, 1);
+    return new Point (point.x, point.y);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle.  When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction.  Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param rectangle to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1.2
+ */
+public Rectangle map (Control from, Control to, Rectangle rectangle) {
+    checkDevice ();
+    if (rectangle is null) error (SWT.ERROR_NULL_ARGUMENT);
+    return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * <p>
+ * NOTE: On right-to-left platforms where the coordinate
+ * systems are mirrored, special care needs to be taken
+ * when mapping coordinates from one control to another
+ * to ensure the result is correctly mirrored.
+ *
+ * Mapping a point that is the origin of a rectangle and
+ * then adding the width and height is not equivalent to
+ * mapping the rectangle.  When one control is mirrored
+ * and the other is not, adding the width and height to a
+ * point that was mapped causes the rectangle to extend
+ * in the wrong direction.  Mapping the entire rectangle
+ * instead of just one point causes both the origin and
+ * the corner of the rectangle to be mapped.
+ * </p>
+ *
+ * @param from the source <code>Control</code> or <code>null</code>
+ * @param to the destination <code>Control</code> or <code>null</code>
+ * @param x coordinates to be mapped
+ * @param y coordinates to be mapped
+ * @param width coordinates to be mapped
+ * @param height coordinates to be mapped
+ * @return rectangle with mapped coordinates
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.1.2
+ */
+public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
+    checkDevice ();
+    if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (from is to) return new Rectangle (x, y, width, height);
+    auto hwndFrom = from !is null ? from.handle : null;
+    auto hwndTo = to !is null ? to.handle : null;
+    RECT rect;
+    rect.left = x;
+    rect.top  = y;
+    rect.right = x + width;
+    rect.bottom = y + height;
+    OS.MapWindowPoints (hwndFrom, hwndTo, cast(POINT*)&rect, 2);
+    return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+
+/*
+ * Returns a single character, converted from the default
+ * multi-byte character set (MBCS) used by the operating
+ * system widgets to a wide character set (WCS) used by Java.
+ *
+ * @param ch the MBCS character
+ * @return the WCS character
+ */
+static wchar mbcsToWcs (int ch) {
+    return mbcsToWcs (ch, 0);
+}
+
+/*
+ * Returns a single character, converted from the specified
+ * multi-byte character set (MBCS) used by the operating
+ * system widgets to a wide character set (WCS) used by Java.
+ *
+ * @param ch the MBCS character
+ * @param codePage the code page used to convert the character
+ * @return the WCS character
+ */
+static wchar mbcsToWcs (int ch, int codePage) {
+    if (OS.IsUnicode) return cast(wchar) ch;
+    int key = ch & 0xFFFF;
+    if (key <= 0x7F) return cast(wchar) ch;
+    CHAR[] buffer;
+    if (key <= 0xFF) {
+        buffer = new CHAR [1];
+        buffer [0] = cast(CHAR) key;
+    } else {
+        buffer = new CHAR [2];
+        buffer [0] = cast(CHAR) ((key >> 8) & 0xFF);
+        buffer [1] = cast(CHAR) (key & 0xFF);
+    }
+    wchar [] unicode = new wchar [1];
+    int cp = codePage !is 0 ? codePage : OS.CP_ACP;
+    int count = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer.ptr, buffer.length, unicode.ptr, 1);
+    if (count is 0) return 0;
+    return unicode [0];
+}
+
+private static extern(Windows) int messageProcFunc (HWND hwnd, uint msg, uint wParam, int lParam) {
+    Display d = Display.getCurrent();
+    return d.messageProc( hwnd, msg, wParam, lParam );
+}
+
+int messageProc (HWND hwnd, uint msg, uint wParam, int lParam) {
+    switch (msg) {
+        case SWT_RUNASYNC: {
+            if (runMessagesInIdle) runAsyncMessages (false);
+            break;
+        }
+        case SWT_KEYMSG: {
+            bool consumed = false;
+            MSG* keyMsg = cast(MSG*) lParam;
+            Control control = findControl (keyMsg.hwnd);
+            if (control !is null) {
+                /*
+                * Feature in Windows.  When the user types an accent key such
+                * as ^ in order to get an accented character on a German keyboard,
+                * calling TranslateMessage(), ToUnicode() or ToAscii() consumes
+                * the key.  This means that a subsequent call to TranslateMessage()
+                * will see a regular key rather than the accented key.  The fix
+                * is to use MapVirtualKey() and VkKeyScan () to detect an accent
+                * and avoid calls to TranslateMessage().
+                */
+                bool accentKey = false;
+                switch (keyMsg.message) {
+                    case OS.WM_KEYDOWN:
+                    case OS.WM_SYSKEYDOWN: {
+                        static if (!OS.IsWinCE) {
+                            switch (keyMsg.wParam) {
+                                case OS.VK_SHIFT:
+                                case OS.VK_MENU:
+                                case OS.VK_CONTROL:
+                                case OS.VK_CAPITAL:
+                                case OS.VK_NUMLOCK:
+                                case OS.VK_SCROLL:
+                                    break;
+                                default: {
+                                    /*
+                                    * Bug in Windows. The high bit in the result of MapVirtualKey() on
+                                    * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+                                    * They should both be bit 32.  The fix is to test the right bit.
+                                    */
+                                    int mapKey = OS.MapVirtualKey (keyMsg.wParam, 2);
+                                    if (mapKey !is 0) {
+                                        accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) !is 0;
+                                        if (!accentKey) {
+                                            for (int i=0; i<ACCENTS.length; i++) {
+                                                int value = OS.VkKeyScan (ACCENTS [i]);
+                                                if (value !is -1 && (value & 0xFF) is keyMsg.wParam) {
+                                                    int state = value >> 8;
+                                                    if ((OS.GetKeyState (OS.VK_SHIFT) < 0) is ((state & 0x1) !is 0) &&
+                                                        (OS.GetKeyState (OS.VK_CONTROL) < 0) is ((state & 0x2) !is 0) &&
+                                                        (OS.GetKeyState (OS.VK_MENU) < 0) is ((state & 0x4) !is 0)) {
+                                                            if ((state & 0x7) !is 0) accentKey = true;
+                                                            break;
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                    break;
+                                }
+                            }
+                        }
+                        break;
+                    }
+                    default:
+                }
+                if (!accentKey && !ignoreNextKey) {
+                    keyMsg.hwnd = control.handle;
+                    int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+                    do {
+                        if (!(consumed |= filterMessage (keyMsg))) {
+                            OS.TranslateMessage (keyMsg);
+                            consumed |= OS.DispatchMessage (keyMsg) is 1;
+                        }
+                    } while (OS.PeekMessage (keyMsg, keyMsg.hwnd, OS.WM_KEYFIRST, OS.WM_KEYLAST, flags));
+                }
+                switch (keyMsg.message) {
+                    case OS.WM_KEYDOWN:
+                    case OS.WM_SYSKEYDOWN: {
+                        switch (keyMsg.wParam) {
+                            case OS.VK_SHIFT:
+                            case OS.VK_MENU:
+                            case OS.VK_CONTROL:
+                            case OS.VK_CAPITAL:
+                            case OS.VK_NUMLOCK:
+                            case OS.VK_SCROLL:
+                                break;
+                            default: {
+                                ignoreNextKey = accentKey;
+                                break;
+                            }
+                        }
+                    }
+                    default:
+                }
+            }
+            switch (keyMsg.wParam) {
+                case OS.VK_SHIFT:
+                case OS.VK_MENU:
+                case OS.VK_CONTROL:
+                case OS.VK_CAPITAL:
+                case OS.VK_NUMLOCK:
+                case OS.VK_SCROLL:
+                    consumed = true;
+                default:
+            }
+            if (consumed) {
+                auto hHeap = OS.GetProcessHeap ();
+                OS.HeapFree (hHeap, 0, cast(void*)lParam);
+            } else {
+                OS.PostMessage (embeddedHwnd, SWT_KEYMSG, wParam, lParam);
+            }
+            return 0;
+        }
+        case SWT_TRAYICONMSG: {
+            if (tray !is null) {
+                TrayItem [] items = tray.items;
+                for (int i=0; i<items.length; i++) {
+                    TrayItem item = items [i];
+                    if (item !is null && item.id is wParam) {
+                        return item.messageProc (hwnd, msg, wParam, lParam);
+                    }
+                }
+            }
+            return 0;
+        }
+        case OS.WM_ACTIVATEAPP: {
+            /*
+            * Feature in Windows.  When multiple shells are
+            * disabled and one of the shells has an enabled
+            * dialog child and the user selects a disabled
+            * shell that does not have the enabled dialog
+            * child using the Task bar, Windows brings the
+            * disabled shell to the front.  As soon as the
+            * user clicks on the disabled shell, the enabled
+            * dialog child comes to the front.  This behavior
+            * is unspecified and seems strange.  Normally, a
+            * disabled shell is frozen on the screen and the
+            * user cannot change the z-order by clicking with
+            * the mouse.  The fix is to look for WM_ACTIVATEAPP
+            * and force the enabled dialog child to the front.
+            * This is typically what the user is expecting.
+            *
+            * NOTE: If the modal shell is disabled for any
+            * reason, it should not be brought to the front.
+            */
+            if (wParam !is 0) {
+                if (!isXMouseActive ()) {
+                    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 ();
+                            if (modal.isDisposed ()) break;
+                        }
+                        auto hwndPopup = OS.GetLastActivePopup (hwndModal);
+                        if (hwndPopup !is null && hwndPopup !is modal.handle) {
+                            if (getControl (hwndPopup) is null) {
+                                if (OS.IsWindowEnabled (hwndPopup)) {
+                                    OS.SetActiveWindow (hwndPopup);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case OS.WM_ENDSESSION: {
+            if (wParam !is 0) {
+                dispose ();
+                /*
+                * When the session is ending, no SWT program can continue
+                * to run.  In order to avoid running code after the display
+                * has been disposed, exit from Java.
+                */
+                /* This code is intentionally commented */
+//              System.exit (0);
+            }
+            break;
+        }
+        case OS.WM_QUERYENDSESSION: {
+            Event event = new Event ();
+            sendEvent (SWT.Close, event);
+            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:
+                case OS.SPI_SETHIGHCONTRAST:
+                    OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
+                default:
+            }
+            break;
+        }
+        case OS.WM_THEMECHANGED: {
+            if (OS.COMCTL32_MAJOR >= 6) {
+                if (hButtonTheme_ !is null) OS.CloseThemeData (hButtonTheme_);
+                if (hEditTheme_ !is null) OS.CloseThemeData (hEditTheme_);
+                if (hExplorerBarTheme_ !is null) OS.CloseThemeData (hExplorerBarTheme_);
+                if (hScrollBarTheme_ !is null) OS.CloseThemeData (hScrollBarTheme_);
+                if (hTabTheme_ !is null) OS.CloseThemeData (hTabTheme_);
+                hButtonTheme_ = hEditTheme_ = hExplorerBarTheme_ = hScrollBarTheme_ = hTabTheme_ = null;
+            }
+            break;
+        }
+        case OS.WM_TIMER: {
+            if (wParam is SETTINGS_ID) {
+                OS.KillTimer (hwndMessage, SETTINGS_ID);
+                runSettings ();
+            } else {
+                runTimer (wParam);
+            }
+            break;
+        }
+        default: {
+            if (msg is SWT_TASKBARCREATED) {
+                if (tray !is null) {
+                    TrayItem [] items = tray.items;
+                    for (int i=0; i<items.length; i++) {
+                        TrayItem item = items [i];
+                        if (item !is null) item.recreate ();
+                    }
+                }
+            }
+        }
+    }
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+private static extern(Windows) int monitorEnumFunc (HMONITOR hmonitor, HDC hdc, RECT* lprcMonitor, int dwData) {
+    auto d = cast(Display)cast(void*)dwData;
+    return d.monitorEnumProc( hmonitor, hdc, lprcMonitor );
+}
+int monitorEnumProc (HMONITOR hmonitor, HDC hdc, RECT* lprcMonitor) {
+    if (monitorCount >= monitors.length) {
+        org.eclipse.swt.widgets.Monitor.Monitor[] newMonitors = new org.eclipse.swt.widgets.Monitor.Monitor [monitors.length + 4];
+        System.arraycopy (monitors, 0, newMonitors, 0, monitors.length);
+        monitors = newMonitors;
+    }
+    MONITORINFO lpmi;
+    lpmi.cbSize = MONITORINFO.sizeof;
+    OS.GetMonitorInfo (hmonitor, &lpmi);
+    org.eclipse.swt.widgets.Monitor.Monitor monitor = new org.eclipse.swt.widgets.Monitor.Monitor ();
+    monitor.handle = hmonitor;
+    monitor.x = lpmi.rcMonitor.left;
+    monitor.y = lpmi.rcMonitor.top;
+    monitor.width = lpmi.rcMonitor.right - lpmi.rcMonitor.left;
+    monitor.height = lpmi.rcMonitor.bottom - lpmi.rcMonitor.top;
+    monitor.clientX = lpmi.rcWork.left;
+    monitor.clientY = lpmi.rcWork.top;
+    monitor.clientWidth = lpmi.rcWork.right - lpmi.rcWork.left;
+    monitor.clientHeight = lpmi.rcWork.bottom - lpmi.rcWork.top;
+    monitors [monitorCount++] = monitor;
+    return 1;
+}
+
+private static extern(Windows) int msgFilterProcFunc (int code, uint wParam, int lParam) {
+    Display pThis = Display.getCurrent();
+    return pThis.msgFilterProc( code, wParam, lParam );
+}
+
+int msgFilterProc (int code, int wParam, int lParam) {
+    switch (code) {
+        case OS.MSGF_COMMCTRL_BEGINDRAG: {
+            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);
+                }
+            }
+            break;
+        }
+        /*
+        * Feature in Windows.  For some reason, when the user clicks
+        * a table or tree, the Windows hook WH_MSGFILTER is sent when
+        * an input event from a dialog box, message box, menu, or scroll
+        * bar did not occur, causing async messages to run at the wrong
+        * time.  The fix is to check the message filter code.
+        */
+        case OS.MSGF_DIALOGBOX:
+        case OS.MSGF_MAINLOOP:
+        case OS.MSGF_MENU:
+        case OS.MSGF_MOVE:
+        case OS.MSGF_MESSAGEBOX:
+        case OS.MSGF_NEXTWINDOW:
+        case OS.MSGF_SCROLLBAR:
+        case OS.MSGF_SIZE: {
+            if (runMessages) {
+                *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;
+                    if (!OS.PeekMessage (&msg, null, 0, 0, flags)) {
+                        if (runAsyncMessages (false)) wakeThread ();
+                    }
+                }
+            }
+            break;
+        }
+        default:
+    }
+    return OS.CallNextHookEx (filterHook, code, wParam, lParam);
+}
+
+int numpadKey (int key) {
+    switch (key) {
+        case OS.VK_NUMPAD0: return '0';
+        case OS.VK_NUMPAD1: return '1';
+        case OS.VK_NUMPAD2: return '2';
+        case OS.VK_NUMPAD3: return '3';
+        case OS.VK_NUMPAD4: return '4';
+        case OS.VK_NUMPAD5: return '5';
+        case OS.VK_NUMPAD6: return '6';
+        case OS.VK_NUMPAD7: return '7';
+        case OS.VK_NUMPAD8: return '8';
+        case OS.VK_NUMPAD9: return '9';
+        case OS.VK_MULTIPLY:    return '*';
+        case OS.VK_ADD:         return '+';
+        case OS.VK_SEPARATOR:   return '\0';
+        case OS.VK_SUBTRACT:    return '-';
+        case OS.VK_DECIMAL: return '.';
+        case OS.VK_DIVIDE:      return '/';
+        default:
+    }
+    return 0;
+}
+
+/**
+ * Generate a low level system event.
+ *
+ * <code>post</code> is used to generate low level keyboard
+ * and mouse events. The intent is to enable automated UI
+ * testing by simulating the input from the user.  Most
+ * SWT applications should never need to call this method.
+ * <p>
+ * Note that this operation can fail when the operating system
+ * fails to generate the event for any reason.  For example,
+ * this can happen when there is no such key or mouse button
+ * or when the system event queue is full.
+ * </p>
+ * <p>
+ * <b>Event Types:</b>
+ * <p>KeyDown, KeyUp
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type KeyDown or KeyUp</li>
+ * <p> Either one of:
+ * <li>(in) character a character that corresponds to a keyboard key</li>
+ * <li>(in) keyCode the key code of the key that was typed,
+ *          as defined by the key code constants in class <code>SWT</code></li>
+ * </ul>
+ * <p>MouseDown, MouseUp</p>
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type MouseDown or MouseUp
+ * <li>(in) button the button that is pressed or released
+ * </ul>
+ * <p>MouseMove</p>
+ * <p>The following fields in the <code>Event</code> apply:
+ * <ul>
+ * <li>(in) type MouseMove
+ * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
+ * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
+ * </ul>
+ * </dl>
+ *
+ * @param event the event to be generated
+ *
+ * @return true if the event was generated or false otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the event is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ *
+ */
+public bool post (Event event) {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
+        int type = event.type;
+        switch (type){
+            case SWT.KeyDown:
+            case SWT.KeyUp: {
+            KEYBDINPUT inputs;
+            inputs.wVk = cast(short) untranslateKey (event.keyCode);
+                if (inputs.wVk is 0) {
+                    char key = event.character;
+                    switch (key) {
+                        case SWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
+                        case SWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case SWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
+                        case SWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
+                        case SWT.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 SWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case SWT.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 SWT.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;
+                //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 SWT.MouseDown:
+            case SWT.MouseMove:
+            case SWT.MouseUp:
+            case SWT.MouseWheel: {
+                MOUSEINPUT inputs;
+                if (type is SWT.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 {
+                    if (type is SWT.MouseWheel) {
+                        if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                        inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
+                        switch (event.detail) {
+                            case SWT.SCROLL_PAGE:
+                                inputs.mouseData = event.count * OS.WHEEL_DELTA;
+                                break;
+                            case SWT.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 SWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
+                            case 2: inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
+                            case 3: inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
+                            case 4: {
+                                if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                                inputs.dwFlags = type is SWT.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 SWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                inputs.mouseData = OS.XBUTTON2;
+                                break;
+                            }
+                            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;
+            }
+        default:
+        }
+        return false;
+    }
+}
+
+void postEvent (Event event) {
+    /*
+    * Place the event at the end of the event queue.
+    * This code is always called in the Display's
+    * thread so it must be re-enterant but does not
+    * need to be synchronized.
+    */
+    if (eventQueue is null) eventQueue = new Event [4];
+    int index = 0;
+    int length_ = eventQueue.length;
+    while (index < length_) {
+        if (eventQueue [index] is null) break;
+        index++;
+    }
+    if (index is length_) {
+        Event [] newQueue = new Event [length_ + 4];
+        System.arraycopy (eventQueue, 0, newQueue, 0, length_);
+        eventQueue = newQueue;
+    }
+    eventQueue [index] = event;
+}
+
+/**
+ * Reads an event from the operating system's event queue,
+ * dispatches it appropriately, and returns <code>true</code>
+ * if there is potentially more work to do, or <code>false</code>
+ * if the caller can sleep until another event is placed on
+ * the event queue.
+ * <p>
+ * In addition to checking the system event queue, this method also
+ * checks if any inter-thread messages (created by <code>syncExec()</code>
+ * or <code>asyncExec()</code>) are waiting to be processed, and if
+ * so handles them before returning.
+ * </p>
+ *
+ * @return <code>false</code> if the caller can sleep upon return from this method
+ *
+ * @exception SWTException <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>
+ *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
+ * </ul>
+ *
+ * @see #sleep
+ * @see #wake
+ */
+public bool readAndDispatch () {
+    checkDevice ();
+    lpStartupInfo = null;
+    drawMenuBars ();
+    runPopups ();
+    if (OS.PeekMessage (msg, null, 0, 0, OS.PM_REMOVE)) {
+        if (!filterMessage (msg)) {
+            OS.TranslateMessage (msg);
+            OS.DispatchMessage (msg);
+        }
+        runDeferredEvents ();
+        return true;
+    }
+    return runMessages && runAsyncMessages (false);
+}
+
+static void register (Display display) {
+    static_this();
+    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;
+    }
+}
+
+/**
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the device handle.
+ * <p>
+ * Disposes all shells which are currently open on the display.
+ * After this method has been invoked, all related related shells
+ * will answer <code>true</code> when sent the message
+ * <code>isDisposed()</code>.
+ * </p><p>
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system.  For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in <code>release</code>.  Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by <code>destroy</code>.
+ * </p>
+ * This method is called before <code>destroy</code>.
+ *
+ * @see Device#dispose
+ * @see #destroy
+ */
+override protected void release () {
+    sendEvent (SWT.Dispose, new Event ());
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) {
+        Shell shell = shells [i];
+        if (!shell.isDisposed ()) shell.dispose ();
+    }
+    if (tray !is null) tray.dispose ();
+    tray = null;
+    while (readAndDispatch ()) {}
+    if (disposeList !is null) {
+        for (int i=0; i<disposeList.length; i++) {
+            if (disposeList [i] !is null) disposeList [i].run ();
+        }
+    }
+    disposeList = null;
+    synchronizer.releaseSynchronizer ();
+    synchronizer = null;
+    releaseDisplay ();
+    super.release ();
+}
+
+void releaseDisplay () {
+    if (embeddedHwnd !is null) {
+        OS.PostMessage (embeddedHwnd, SWT_DESTROY, 0, 0);
+    }
+
+    /* Release XP Themes */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (hButtonTheme_ !is null) OS.CloseThemeData (hButtonTheme_);
+        if (hEditTheme_ !is null) OS.CloseThemeData (hEditTheme_);
+        if (hExplorerBarTheme_ !is null) OS.CloseThemeData (hExplorerBarTheme_);
+        if (hScrollBarTheme_ !is null) OS.CloseThemeData (hScrollBarTheme_);
+        if (hTabTheme_ !is null) OS.CloseThemeData (hTabTheme_);
+        hButtonTheme_ = hEditTheme_ = hExplorerBarTheme_ = hScrollBarTheme_ = hTabTheme_ = null;
+    }
+
+    /* Unhook the message hook */
+    static if (!OS.IsWinCE) {
+        if (msgHook !is null) OS.UnhookWindowsHookEx (msgHook);
+        msgHook = null;
+    }
+
+    /* Unhook the filter hook */
+    static if (!OS.IsWinCE) {
+        if (filterHook !is null) OS.UnhookWindowsHookEx (filterHook);
+        filterHook = null;
+        //msgFilterCallback.dispose ();
+        //msgFilterCallback = null;
+        //msgFilterProc_ = 0;
+    }
+
+    /* Unhook the idle hook */
+    static if (!OS.IsWinCE) {
+        if (idleHook !is null) OS.UnhookWindowsHookEx (idleHook);
+        idleHook = null;
+        //foregroundIdleCallback.dispose ();
+        //foregroundIdleCallback = null;
+        //foregroundIdleProc_ = 0;
+    }
+
+    /* Destroy the message only HWND */
+    if (hwndMessage !is null) OS.DestroyWindow (hwndMessage);
+    hwndMessage = null;
+    //messageCallback.dispose ();
+    //messageCallback = null;
+    //messageProc_ = 0;
+
+    /* Unregister the SWT window class */
+    auto hHeap = OS.GetProcessHeap ();
+    auto hInstance = OS.GetModuleHandle (null);
+    OS.UnregisterClass (windowClass_.ptr, hInstance);
+
+    /* Unregister the SWT drop shadow window class */
+    OS.UnregisterClass (windowShadowClass.ptr, hInstance);
+    windowClass_ = windowShadowClass = null;
+    //windowCallback.dispose ();
+    //windowCallback = null;
+    //windowProc_ = 0;
+
+    /* Release the System fonts */
+    if (systemFont !is null) systemFont.dispose ();
+    systemFont = null;
+    lfSystemFont = null;
+
+    /* Release the System Images */
+    if (errorImage !is null) errorImage.dispose ();
+    if (infoImage !is null) infoImage.dispose ();
+    if (questionImage !is null) questionImage.dispose ();
+    if (warningIcon !is null) warningIcon.dispose ();
+    errorImage = infoImage = questionImage = warningIcon = null;
+
+    /* Release Sort Indicators */
+    if (upArrow !is null) upArrow.dispose ();
+    if (downArrow !is null) downArrow.dispose ();
+    upArrow = downArrow = null;
+
+    /* Release the System Cursors */
+    for (int i = 0; i < cursors.length; i++) {
+        if (cursors [i] !is null) cursors [i].dispose ();
+    }
+    cursors = null;
+
+    /* Release Acquired Resources */
+    if (resources !is null) {
+        for (int i=0; i<resources.length; i++) {
+            if (resources [i] !is null) resources [i].dispose ();
+        }
+        resources = null;
+    }
+
+    /* Release Custom Colors for ChooseColor */
+    if (lpCustColors !is null) OS.HeapFree (hHeap, 0, lpCustColors);
+    lpCustColors = null;
+
+    /* Uninitialize OLE */
+    static if (!OS.IsWinCE) OS.OleUninitialize ();
+
+    /* Uninitialize buffered painting */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        OS.BufferedPaintUnInit ();
+    }
+
+    /* Release references */
+    thread = null;
+    msg = null;
+    hookMsg = null;
+    //keyboard = 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) {
+    int i = 0;
+    int length_ = imageList.length;
+    while (i < length_) {
+        if (imageList [i] is list) {
+            if (list.removeRef () > 0) return;
+            list.dispose ();
+            System.arraycopy (imageList, i + 1, imageList, i, --length_ - i);
+            imageList [length_] = null;
+            for (int j=0; j<length_; j++) {
+                if (imageList [j] !is null) return;
+            }
+            imageList = null;
+            return;
+        }
+        i++;
+    }
+}
+
+void releaseToolImageList (ImageList list) {
+    int i = 0;
+    int length_ = toolImageList.length;
+    while (i < length_) {
+        if (toolImageList [i] is list) {
+            if (list.removeRef () > 0) return;
+            list.dispose ();
+            System.arraycopy (toolImageList, i + 1, toolImageList, i, --length_ - i);
+            toolImageList [length_] = null;
+            for (int j=0; j<length_; j++) {
+                if (toolImageList [j] !is null) return;
+            }
+            toolImageList = null;
+            return;
+        }
+        i++;
+    }
+}
+
+void releaseToolHotImageList (ImageList list) {
+    int i = 0;
+    int length_ = toolHotImageList.length;
+    while (i < length_) {
+        if (toolHotImageList [i] is list) {
+            if (list.removeRef () > 0) return;
+            list.dispose ();
+            System.arraycopy (toolHotImageList, i + 1, toolHotImageList, i, --length_ - i);
+            toolHotImageList [length_] = null;
+            for (int j=0; j<length_; j++) {
+                if (toolHotImageList [j] !is null) return;
+            }
+            toolHotImageList = null;
+            return;
+        }
+        i++;
+    }
+}
+
+void releaseToolDisabledImageList (ImageList list) {
+    int i = 0;
+    int length_ = toolDisabledImageList.length;
+    while (i < length_) {
+        if (toolDisabledImageList [i] is list) {
+            if (list.removeRef () > 0) return;
+            list.dispose ();
+            System.arraycopy (toolDisabledImageList, i + 1, toolDisabledImageList, i, --length_ - i);
+            toolDisabledImageList [length_] = null;
+            for (int j=0; j<length_; j++) {
+                if (toolDisabledImageList [j] !is null) return;
+            }
+            toolDisabledImageList = null;
+            return;
+        }
+        i++;
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs anywhere in
+ * a widget. The event type is one of the event constants defined
+ * in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addFilter
+ * @see #addListener
+ *
+ * @since 3.0
+ */
+public void removeFilter (int eventType, Listener listener) {
+    checkDevice ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (filterTable is null) return;
+    filterTable.unhook (eventType, listener);
+    if (filterTable.size () is 0) filterTable = null;
+}
+
+/**
+ * Removes the listener from the collection 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>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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>
+ *
+ * @see Listener
+ * @see SWT
+ * @see #addListener
+ *
+ * @since 2.0
+ */
+public void removeListener (int eventType, Listener listener) {
+    checkDevice ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (eventType, listener);
+}
+
+void removeBar (Menu menu) {
+    if (bars is null) return;
+    for (int i=0; i<bars.length; i++) {
+        if (bars [i] is menu) {
+            bars [i] = null;
+            return;
+        }
+    }
+}
+
+Control removeControl (HANDLE handle) {
+    if (handle is null) return null;
+    lastControl = lastGetControl = null;
+    Control control = null;
+    int index;
+    static if (USE_PROPERTY) {
+        index = cast(int)OS.RemoveProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
+    } else {
+        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;
+    }
+    return control;
+}
+
+void removeMenuItem (MenuItem item) {
+    if (items is null) return;
+    items [item.id - ID_START] = null;
+}
+
+void removePopup (Menu menu) {
+    if (popups is null) return;
+    for (int i=0; i<popups.length; i++) {
+        if (popups [i] is menu) {
+            popups [i] = null;
+            return;
+        }
+    }
+}
+
+bool runAsyncMessages (bool all) {
+    return synchronizer.runAsyncMessages (all);
+}
+
+bool runDeferredEvents () {
+    /*
+    * Run deferred events.  This code is always
+    * called in the Display's thread so it must
+    * be re-enterant but need not be synchronized.
+    */
+    while (eventQueue !is null) {
+
+        /* Take an event off the queue */
+        Event event = eventQueue [0];
+        if (event is null) break;
+        int length_ = eventQueue.length;
+        System.arraycopy (eventQueue, 1, eventQueue, 0, --length_);
+        eventQueue [length_] = null;
+
+        /* Run the event */
+        Widget widget = event.widget;
+        if (widget !is null && !widget.isDisposed ()) {
+            Widget item = event.item;
+            if (item is null || !item.isDisposed ()) {
+                widget.sendEvent (event);
+            }
+        }
+
+        /*
+        * At this point, the event queue could
+        * be null due to a recursive invocation
+        * when running the event.
+        */
+    }
+
+    /* Clear the queue */
+    eventQueue = null;
+    return true;
+}
+
+bool runPopups () {
+    if (popups is null) return false;
+    bool result = false;
+    while (popups !is null) {
+        Menu menu = popups [0];
+        if (menu is null) break;
+        int length_ = popups.length;
+        System.arraycopy (popups, 1, popups, 0, --length_);
+        popups [length_] = null;
+        runDeferredEvents ();
+        if (!menu.isDisposed ()) menu._setVisible (true);
+        result = true;
+    }
+    popups = null;
+    return result;
+}
+
+void runSettings () {
+    Font oldFont = getSystemFont ();
+    saveResources ();
+    updateImages ();
+    sendEvent (SWT.Settings, null);
+    Font newFont = getSystemFont ();
+    bool sameFont = cast(bool)( oldFont ==/*eq*/ newFont );
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) {
+        Shell shell = shells [i];
+        if (!shell.isDisposed ()) {
+            if (!sameFont) {
+                shell.updateFont (oldFont, newFont);
+            }
+            /* This code is intentionally commented */
+            //shell.redraw (true);
+            shell.layout (true, true);
+        }
+    }
+}
+
+bool runTimer (int /*long*/ id) {
+    if (timerList !is null && timerIds !is null) {
+        int index = 0;
+        while (index <timerIds.length) {
+            if (timerIds [index] is id) {
+                OS.KillTimer (hwndMessage, timerIds [index]);
+                timerIds [index] = 0;
+                Runnable runnable = timerList [index];
+                timerList [index] = null;
+                if (runnable !is null) runnable.run ();
+                return true;
+            }
+            index++;
+        }
+    }
+    return false;
+}
+
+void saveResources () {
+    int resourceCount = 0;
+    if (resources is null) {
+        resources = new Resource [RESOURCE_SIZE];
+    } else {
+        resourceCount = resources.length;
+        Resource [] newResources = new Resource [resourceCount + RESOURCE_SIZE];
+        System.arraycopy (resources, 0, newResources, 0, resourceCount);
+        resources = newResources;
+    }
+    if (systemFont !is null) {
+        static if (!OS.IsWinCE) {
+            NONCLIENTMETRICS info;
+            info.cbSize = NONCLIENTMETRICS.sizeof;
+            if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
+                LOGFONT* logFont = &info.lfMessageFont;
+                if (lfSystemFont is null ||
+                    logFont.lfCharSet !is lfSystemFont.lfCharSet ||
+                    logFont.lfHeight !is lfSystemFont.lfHeight ||
+                    logFont.lfWidth !is lfSystemFont.lfWidth ||
+                    logFont.lfEscapement !is lfSystemFont.lfEscapement ||
+                    logFont.lfOrientation !is lfSystemFont.lfOrientation ||
+                    logFont.lfWeight !is lfSystemFont.lfWeight ||
+                    logFont.lfItalic !is lfSystemFont.lfItalic ||
+                    logFont.lfUnderline !is lfSystemFont.lfUnderline ||
+                    logFont.lfStrikeOut !is lfSystemFont.lfStrikeOut ||
+                    logFont.lfCharSet !is lfSystemFont.lfCharSet ||
+                    logFont.lfOutPrecision !is lfSystemFont.lfOutPrecision ||
+                    logFont.lfClipPrecision !is lfSystemFont.lfClipPrecision ||
+                    logFont.lfQuality !is lfSystemFont.lfQuality ||
+                    logFont.lfPitchAndFamily !is lfSystemFont.lfPitchAndFamily ||
+                    getFontName (logFont) !=/*eq*/ getFontName (lfSystemFont)) {
+                        resources [resourceCount++] = systemFont;
+                        lfSystemFont = logFont;
+                        systemFont = null;
+                }
+            }
+        }
+    }
+    if (errorImage !is null) resources [resourceCount++] = errorImage;
+    if (infoImage !is null) resources [resourceCount++] = infoImage;
+    if (questionImage !is null) resources [resourceCount++] = questionImage;
+    if (warningIcon !is null) resources [resourceCount++] = warningIcon;
+    errorImage = infoImage = questionImage = warningIcon = null;
+    for (int i=0; i<cursors.length; i++) {
+        if (cursors [i] !is null) resources [resourceCount++] = cursors [i];
+        cursors [i] = null;
+    }
+    if (resourceCount < RESOURCE_SIZE) {
+        Resource [] newResources = new Resource [resourceCount];
+        System.arraycopy (resources, 0, newResources, 0, resourceCount);
+        resources = newResources;
+    }
+}
+
+void sendEvent (int eventType, Event event) {
+    if (eventTable is null && filterTable is null) {
+        return;
+    }
+    if (event is null) event = new Event ();
+    event.display = this;
+    event.type = eventType;
+    if (event.time is 0) event.time = getLastEventTime ();
+    if (!filterEvent (event)) {
+        if (eventTable !is null) eventTable.sendEvent (event);
+    }
+}
+
+/**
+ * Sets the location of the on-screen pointer relative to the top left corner
+ * of the screen.  <b>Note: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.</b>
+ *
+ * @param x the new x coordinate for the cursor
+ * @param y the new y coordinate for the cursor
+ *
+ * @exception SWTException <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 2.1
+ */
+public void setCursorLocation (int x, int y) {
+    checkDevice ();
+    OS.SetCursorPos (x, y);
+}
+
+/**
+ * Sets the location of the on-screen pointer relative to the top left corner
+ * of the screen.  <b>Note: It is typically considered bad practice for a
+ * program to move the on-screen pointer location.</b>
+ *
+ * @param point new position
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 2.0
+ */
+public void setCursorLocation (Point point) {
+    checkDevice ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setCursorLocation (point.x, point.y);
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given argument.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the display is disposed
+ * of, it is the application's responsibility provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception SWTException <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>
+ *
+ * @see #getData(String)
+ * @see #disposeExec(Runnable)
+ */
+public void setData (String key, Object value) {
+    checkDevice ();
+    // SWT extension: allow null string
+    //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
+
+    if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) {
+        auto data = cast(ValueWrapperBool) value;
+        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) {
+        if (keys is null) return;
+        int index = 0;
+        while (index < keys.length && keys [index]!=/*eq*/key) index++;
+        if (index is keys.length) return;
+        if (keys.length is 1) {
+            keys = null;
+            values = null;
+        } else {
+            String [] newKeys = new String [keys.length - 1];
+            Object [] newValues = new Object [values.length - 1];
+            System.arraycopy (keys, 0, newKeys, 0, index);
+            System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
+            System.arraycopy (values, 0, newValues, 0, index);
+            System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
+            keys = newKeys;
+            values = newValues;
+        }
+        return;
+    }
+
+    /* Add the key/value pair */
+    if (keys is null) {
+        keys.length = 1;
+        values.length = 1;
+        keys[0] = key;
+        values[0] = value;
+        return;
+    }
+    for (int i=0; i<keys.length; i++) {
+        if (keys [i] ==/*eq*/key ) {
+            values [i] = value;
+            return;
+        }
+    }
+    String [] newKeys = new String [keys.length + 1];
+    Object [] newValues = new Object [values.length + 1];
+    System.arraycopy (keys, 0, newKeys, 0, keys.length);
+    System.arraycopy (values, 0, newValues, 0, values.length);
+    newKeys [keys.length] = key;
+    newValues [values.length] = value;
+    keys = newKeys;
+    values = newValues;
+}
+
+/**
+ * Sets the application defined, display specific data
+ * associated with the receiver, to the argument.
+ * The <em>display specific data</em> is a single,
+ * unnamed field that is stored with every display.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the display specific data needs to
+ * be notified when the display is disposed of, it is the
+ * application's responsibility provide a
+ * <code>disposeExec()</code> handler which does so.
+ * </p>
+ *
+ * @param data the new display specific data
+ *
+ * @exception SWTException <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>
+ *
+ * @see #getData()
+ * @see #disposeExec(Runnable)
+ */
+public void setData (Object data) {
+    checkDevice ();
+    this.data = data;
+}
+
+/**
+ * On platforms which support it, sets the application name
+ * to be the argument. On Motif, for example, this can be used
+ * to set the name used for resource lookup.  Specifying
+ * <code>null</code> for the name clears it.
+ *
+ * @param name the new app name or <code>null</code>
+ */
+public static void setAppName (String name) {
+    /* Do nothing */
+}
+
+void setModalDialog (Dialog modalDailog) {
+    this.modalDialog = modalDailog;
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+void setModalShell (Shell shell) {
+    if (modalShells is null) modalShells = new Shell [4];
+    int index = 0, length_ = modalShells.length;
+    while (index < length_) {
+        if (modalShells [index] is shell) return;
+        if (modalShells [index] is null) break;
+        index++;
+    }
+    if (index is length_) {
+        Shell [] newModalShells = new Shell [length_ + 4];
+        System.arraycopy (modalShells, 0, newModalShells, 0, length_);
+        modalShells = newModalShells;
+    }
+    modalShells [index] = shell;
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) shells [i].updateModal ();
+}
+
+/**
+ * Sets the synchronizer used by the display to be
+ * the argument, which can not be null.
+ *
+ * @param synchronizer the new synchronizer for the display (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
+ * </ul>
+ * @exception SWTException <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>
+ *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
+ * </ul>
+ */
+public void setSynchronizer (Synchronizer synchronizer) {
+    checkDevice ();
+    if (synchronizer is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (synchronizer is this.synchronizer) return;
+    Synchronizer oldSynchronizer;
+    synchronized (Device.classinfo) {
+        oldSynchronizer = this.synchronizer;
+        this.synchronizer = synchronizer;
+    }
+    if (oldSynchronizer !is null) {
+        oldSynchronizer.runAsyncMessages(true);
+    }
+}
+
+int shiftedKey (int key) {
+    static if (OS.IsWinCE) return 0;
+
+    /* Clear the virtual keyboard and press the shift key */
+    for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
+    keyboard [OS.VK_SHIFT] |= 0x80;
+
+    /* Translate the key to ASCII or UNICODE using the virtual keyboard */
+    static if (OS.IsUnicode) {
+        wchar result;
+        if (OS.ToUnicode (key, key, keyboard.ptr, &result, 1, 0) is 1) return result;
+    } else {
+        wchar result;
+        if (OS.ToAscii (key, key, keyboard.ptr, &result, 0) is 1) return result;
+    }
+    return 0;
+}
+
+/**
+ * Causes the user-interface thread to <em>sleep</em> (that is,
+ * to be put in a state where it does not consume CPU cycles)
+ * until an event is received or it is otherwise awakened.
+ *
+ * @return <code>true</code> if an event requiring dispatching was placed on the queue.
+ *
+ * @exception SWTException <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>
+ *
+ * @see #wake
+ */
+public bool sleep () {
+    checkDevice ();
+    if (runMessages && getMessageCount () !is 0) return true;
+    static if (OS.IsWinCE) {
+        OS.MsgWaitForMultipleObjectsEx (0, null, OS.INFINITE, OS.QS_ALLINPUT, OS.MWMO_INPUTAVAILABLE);
+        return true;
+    }
+    return cast(bool) OS.WaitMessage ();
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The thread which calls this method
+ * is suspended until the runnable completes.  Specifying <code>null</code>
+ * as the runnable simply wakes the user-interface thread.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param runnable code to run on the user-interface thread or <code>null</code>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #asyncExec
+ */
+public void syncExec (Runnable runnable) {
+    Synchronizer synchronizer;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        synchronizer = this.synchronizer;
+    }
+    synchronizer.syncExec (runnable);
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread after the specified
+ * number of milliseconds have elapsed. If milliseconds is less
+ * than zero, the runnable is not executed.
+ * <p>
+ * Note that at the time the runnable is invoked, widgets
+ * that have the receiver as their display may have been
+ * disposed. Therefore, it is necessary to check for this
+ * case inside the runnable before accessing the widget.
+ * </p>
+ *
+ * @param milliseconds the delay before running the runnable
+ * @param runnable code to run on the user-interface thread
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
+ * </ul>
+ * @exception SWTException <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>
+ *
+ * @see #asyncExec
+ */
+public void timerExec (int milliseconds, Runnable runnable) {
+    checkDevice ();
+    if (runnable is null) error (SWT.ERROR_NULL_ARGUMENT);
+    assert( runnable );
+    if (timerList is null) timerList = new Runnable [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 /*long*/ timerId = 0;
+    if (index !is timerList.length) {
+        timerId = timerIds [index];
+        if (milliseconds < 0) {
+            OS.KillTimer (hwndMessage, timerId);
+            timerList [index] = null;
+            timerIds [index] = 0;
+            return;
+        }
+    } else {
+        if (milliseconds < 0) return;
+        index = 0;
+        while (index < timerList.length) {
+            if (timerList [index] is null) break;
+            index++;
+        }
+        timerId = nextTimerId++;
+        if (index is timerList.length) {
+            Runnable [] newTimerList = new Runnable [timerList.length + 4];
+            SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
+            timerList = newTimerList;
+            int /*long*/ [] newTimerIds = new int /*long*/ [timerIds.length + 4];
+            System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
+            timerIds = newTimerIds;
+        }
+    }
+    int newTimerID = OS.SetTimer (hwndMessage, timerId, milliseconds, null);
+    if (newTimerID !is 0) {
+        timerList [index] = runnable;
+        timerIds [index] = newTimerID;
+    }
+}
+
+bool translateAccelerator (MSG* msg, Control control) {
+    accelKeyHit = true;
+    bool result = control.translateAccelerator (msg);
+    accelKeyHit = false;
+    return result;
+}
+
+static int translateKey (int key) {
+    for (int i=0; i<KeyTable.length; i++) {
+        if (KeyTable [i] [0] is key) return KeyTable [i] [1];
+    }
+    return 0;
+}
+
+bool translateMnemonic (MSG* msg, Control control) {
+    switch (msg.message) {
+        case OS.WM_CHAR:
+        case OS.WM_SYSCHAR:
+            return control.translateMnemonic (msg);
+        default:
+    }
+    return false;
+}
+
+bool translateTraversal (MSG* msg, Control control) {
+    switch (msg.message) {
+        case OS.WM_KEYDOWN:
+            switch (msg.wParam) {
+                case OS.VK_RETURN:
+                case OS.VK_ESCAPE:
+                case OS.VK_TAB:
+                case OS.VK_UP:
+                case OS.VK_DOWN:
+                case OS.VK_LEFT:
+                case OS.VK_RIGHT:
+                case OS.VK_PRIOR:
+                case OS.VK_NEXT:
+                    return control.translateTraversal (msg);
+                default:
+            }
+            break;
+        case OS.WM_SYSKEYDOWN:
+            switch (msg.wParam) {
+                case OS.VK_MENU:
+                    return control.translateTraversal (msg);
+                default:
+            }
+            break;
+        default:
+    }
+    return false;
+}
+
+static int untranslateKey (int key) {
+    for (int i=0; i<KeyTable.length; i++) {
+        if (KeyTable [i] [1] is key) return KeyTable [i] [0];
+    }
+    return 0;
+}
+
+/**
+ * Forces all outstanding paint requests for the display
+ * to be processed before this method returns.
+ *
+ * @exception SWTException <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>
+ *
+ * @see Control#update()
+ */
+public void update() {
+    checkDevice ();
+    /*
+    * Feature in Windows.  When an application does not remove
+    * events from the event queue for some time, Windows assumes
+    * the application is not responding and no longer sends paint
+    * events to the application.  The fix is to detect that the
+    * application is not responding and call PeekMessage() with
+    * PM_REMOVE to tell Windows that the application is ready
+    * to dispatch events.  Note that the message does not have
+    * to be found or dispatched in order to wake Windows up.
+    *
+    * NOTE: This allows other cross thread messages to be delivered,
+    * most notably WM_ACTIVATE.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if (OS.IsHungAppWindow (hwndMessage)) {
+            MSG msg;
+            int flags = OS.PM_REMOVE | OS.PM_NOYIELD;
+            OS.PeekMessage (&msg, hwndMessage, SWT_NULL, SWT_NULL, flags);
+        }
+    }
+    Shell[] shells = getShells ();
+    for (int i=0; i<shells.length; i++) {
+        Shell shell = shells [i];
+        if (!shell.isDisposed ()) shell.update (true);
+    }
+}
+
+void updateImages () {
+    if (upArrow !is null) upArrow.dispose ();
+    if (downArrow !is null) downArrow.dispose ();
+    upArrow = downArrow = null;
+    for (int i=0; i<controlTable.length; i++) {
+        Control control = controlTable [i];
+        if (control !is null) control.updateImages ();
+    }
+}
+
+/**
+ * If the receiver's user-interface thread was <code>sleep</code>ing,
+ * causes it to be awakened and start running again. Note that this
+ * method may be called from any thread.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #sleep
+ */
+public void wake () {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
+        if (thread is Thread.getThis ()) return;
+        wakeThread ();
+    }
+}
+
+void wakeThread () {
+    static if (OS.IsWinCE) {
+        OS.PostMessage (hwndMessage, OS.WM_NULL, 0, 0);
+    } else {
+        OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+    }
+}
+
+/*
+ * Returns a single character, converted from the wide
+ * character set (WCS) used by Java to the specified
+ * multi-byte character set used by the operating system
+ * widgets.
+ *
+ * @param ch the WCS character
+ * @param codePage the code page used to convert the character
+ * @return the MBCS character
+ */
+static int wcsToMbcs (wchar ch, int codePage) {
+    if (OS.IsUnicode) return ch;
+    if (ch <= 0x7F) return ch;
+    wchar[1] wc;
+    wc[0] = ch;
+    auto r = StrToMBCSs( tango.text.convert.Utf.toString(wc), codePage );
+    return r[0];
+}
+
+/*
+ * Returns a single character, converted from the wide
+ * character set (WCS) used by Java to the default
+ * multi-byte character set used by the operating system
+ * widgets.
+ *
+ * @param ch the WCS character
+ * @return the MBCS character
+ */
+static int wcsToMbcs (char ch) {
+    return wcsToMbcs (ch, 0);
+}
+
+private static extern(Windows) int windowProcFunc (HWND hwnd, uint msg, uint wParam, int lParam) {
+    auto d = Display.getCurrent();
+    return d.windowProc( hwnd, msg, wParam, lParam );
+}
+
+int windowProc(){
+    return cast(int)&windowProcFunc;
+}
+
+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, OS.NMLVDISPINFO_sizeof);
+                    if (0 <= plvfi.item.iSubItem && plvfi.item.iSubItem < columnCount) {
+                        if (!columnVisible [plvfi.item.iSubItem]) return 0;
+                    }
+                    break;
+                }
+                default:
+            }
+        }
+    }
+    /*
+    * 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
+    * to the control that is under the cursor.  It seems that
+    * if the control takes some time to respond to the message,
+    * Adobe stops sending them.  The fix is to detect this case
+    * and sleep.
+    *
+    * NOTE: Under normal circumstances, Windows will never send
+    * consecutive WM_NCHITTEST messages to the same control without
+    * another message (normally WM_SETCURSOR) in between.
+    */
+    if (msg is OS.WM_NCHITTEST) {
+        if (hitCount++ >= 1024) {
+            try {Thread.sleep (0.001);} catch (Exception t) {}
+        }
+    } else {
+        hitCount = 0;
+    }
+    if (lastControl !is null && lastHwnd is hwnd) {
+        return lastControl.windowProc (hwnd, msg, wParam, lParam);
+    }
+    int index;
+    static if (USE_PROPERTY) {
+        index = cast(int)OS.GetProp (hwnd, cast(wchar*)SWT_OBJECT_INDEX) - 1;
+    } else {
+        index = OS.GetWindowLongPtr (hwnd, OS.GWLP_USERDATA) - 1;
+    }
+    if (0 <= index && index < controlTable.length) {
+        Control control = controlTable [index];
+        if (control !is null) {
+            lastHwnd = hwnd;
+            lastControl = control;
+            return control.windowProc (hwnd, msg, wParam, lParam);
+        }
+    }
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+static String withCrLf (String string) {
+
+    /* If the string is empty, return the string. */
+    int length_ = string.length;
+    if (length_ is 0) return string;
+
+    /*
+    * Check for an LF or CR/LF and assume the rest of
+    * the string is formated that way.  This will not
+    * work if the string contains mixed delimiters.
+    */
+    int i = string.indexOf ('\n', 0);
+    if (i is -1) return string;
+    if (i > 0 && string.charAt (i - 1) is '\r') {
+        return string;
+    }
+
+    /*
+    * The string is formatted with LF.  Compute the
+    * number of lines and the size of the buffer
+    * needed to hold the result
+    */
+    i++;
+    int count = 1;
+    while (i < length_) {
+        if ((i = string.indexOf ('\n', i)) is -1) break;
+        count++; i++;
+    }
+    count += length_;
+
+    /* Create a new string with the CR/LF line terminator. */
+    i = 0;
+    StringBuffer result = new StringBuffer (count);
+    while (i < length_) {
+        int j = string.indexOf ('\n', i);
+        if (j is -1) j = length_;
+        result.append (string.substring (i, j));
+        if ((i = j) < length_) {
+            result.append ("\r\n"); //$NON-NLS-1$
+            i++;
+        }
+    }
+    return result.toString ();
+}
+
+String windowClass(){
+    return TCHARsToStr( windowClass_ );
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Event.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Event;
+
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Rectangle;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Display;
+
+import tango.text.convert.Format;
+import java.lang.all;
+
+
+/**
+ * Instances of this class provide a description of a particular
+ * event which occurred within SWT. The SWT <em>untyped listener</em>
+ * API uses these instances for all event dispatching.
+ * <p>
+ * Note: For a given event, only the fields which are appropriate
+ * will be filled in. The contents of the fields which are not used
+ * by the event are unspecified.
+ * </p>
+ *
+ * @see Listener
+ * @see org.eclipse.swt.events.TypedEvent
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Listeners</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Event {
+
+    /**
+     * the display where the event occurred
+     *
+     * @since 2.0
+     */
+    public Display display;
+
+    /**
+     * the widget that issued the event
+     */
+    public Widget widget;
+
+    /**
+     * the type of event, as defined by the event type constants
+     * in class <code>SWT</code>
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int type;
+
+    /**
+     * the event specific detail field, as defined by the detail constants
+     * in class <code>SWT</code>
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int detail;
+
+    /**
+     * the item that the event occurred in (can be null)
+     */
+    public Widget item;
+
+    /**
+     * the index of the item where the event occurred
+     *
+     * @since 3.2
+     */
+    public int index;
+
+    /**
+     * the graphics context to use when painting
+     * that is configured to use the colors, font and
+     * damaged region of the control.  It is valid
+     * only during the paint and must not be disposed
+     */
+    public GC gc;
+
+    /**
+     * depending on the event type, the x offset of the bounding
+     * rectangle of the region that requires painting or the
+     * widget-relative, x coordinate of the pointer at the
+     * time the mouse button was pressed or released
+     */
+    public int x;
+
+    /**
+     * depending on the event type, the y offset of the bounding
+     * rectangle of the  region that requires painting or the
+     * widget-relative, y coordinate of the pointer at the
+     * time the mouse button was pressed or released
+     */
+    public int y;
+
+    /**
+     * the width of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int width;
+
+    /**
+     * the height of the bounding rectangle of the
+     * region that requires painting
+     */
+    public int height;
+
+    /**
+     * depending on the event type, the number of following
+     * paint events which are pending which may always be zero
+     * on some platforms or the number of lines or pages to
+     * scroll using the mouse wheel
+     */
+    public int count;
+
+    /**
+     * the time that the event occurred.
+     *
+     * NOTE: This field is an unsigned integer and should
+     * be AND'ed with 0xFFFFFFFFL so that it can be treated
+     * as a signed long.
+     */
+    public int time;
+
+    /**
+     * the button that was pressed or released; 1 for the
+     * first button, 2 for the second button, and 3 for the
+     * third button, etc.
+     */
+    public int button;
+
+    /**
+     * depending on the event, the character represented by the key
+     * that was typed.  This is the final character that results
+     * after all modifiers have been applied.  For example, when the
+     * user types Ctrl+A, the character value is 0x01 (ASCII SOH).
+     * It is important that applications do not attempt to modify the
+     * character value based on a stateMask (such as SWT.CTRL) or the
+     * resulting character will not be correct.
+     */
+    public wchar character = '\0';
+
+    /**
+     * depending on the event, the key code of the key that was typed,
+     * as defined by the key code constants in class <code>SWT</code>.
+     * When the character field of the event is ambiguous, this field
+     * contains the unaffected value of the original character.  For
+     * example, typing Ctrl+M or Enter both result in the character '\r'
+     * but the keyCode field will also contain '\r' when Enter was typed
+     * and 'm' when Ctrl+M was typed.
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int keyCode;
+
+    /**
+     * depending on the event, the state of the keyboard modifier
+     * keys and mouse masks at the time the event was generated.
+     *
+     * @see org.eclipse.swt.SWT
+     */
+    public int stateMask;
+
+    /**
+     * depending on the event, the range of text being modified.
+     * Setting these fields only has effect during ImeComposition 
+     * events.
+     */
+    public int start, end;
+
+    /**
+     * depending on the event, the new text that will be inserted.
+     * Setting this field will change the text that is about to
+     * be inserted or deleted.
+     */
+    public String text;
+
+    /**
+     * depending on the event, a flag indicating whether the operation
+     * should be allowed.  Setting this field to false will cancel the
+     * operation.
+     */
+    public bool doit = true;
+
+    /**
+     * a field for application use
+     */
+    public Object data;
+
+/**
+ * Gets the bounds.
+ *
+ * @return a rectangle that is the bounds.
+ */
+public Rectangle getBounds () {
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Sets the bounds.
+ *
+ * @param rect the new rectangle
+ */
+public void setBounds (Rectangle rect) {
+    this.x = rect.x;
+    this.y = rect.y;
+    this.width = rect.width;
+    this.height = rect.height;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+override public String toString () {
+    return Format( "Event {{type={} {} time={} data={} x={} y={} width={} height={} detail={}}",
+        type, widget, time, data, x, y, width, height, detail );  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/EventTable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.EventTable;
+
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.internal.SWTEventListener;
+import java.lang.System;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.SWTEventListener;
+
+/**
+ * Instances of this class implement a simple
+ * look up mechanism that maps an event type
+ * to a listener.  Multiple listeners for the
+ * same event type are supported.
+ */
+
+class EventTable {
+    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 [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;
+        --index;
+    }
+    index++;
+    if (index is length) {
+        int [] newTypes = new int [length + GROW_SIZE];
+        System.arraycopy (types, 0, newTypes, 0, length);
+        types = newTypes;
+        Listener [] newListeners = new Listener [length + GROW_SIZE];
+        SimpleType!(Listener).arraycopy (listeners, 0, newListeners, 0, length);
+        listeners = newListeners;
+    }
+    types [index] = eventType;
+    listeners [index] = listener;
+}
+
+public bool hooks (int eventType) {
+    if (types is null) return false;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType) return true;
+    }
+    return false;
+}
+
+public void sendEvent (Event event) {
+    if (types is null) return;
+    level += level >= 0 ? 1 : -1;
+    try {
+        for (int i=0; i<types.length; i++) {
+            if (event.type is SWT.None) return;
+            if (types [i] is event.type) {
+                Listener listener = listeners [i];
+                if (listener !is null) listener.handleEvent (event);
+            }
+        }
+    } finally {
+        bool compact = level < 0;
+        level -= level >= 0 ? 1 : -1;
+        if (compact && level is 0) {
+            int index = 0;
+            for (int i=0; i<types.length; i++) {
+                if (types [i] !is 0) {
+                    types [index] = types [i];
+                    listeners [index] = listeners [i];
+                    index++;
+                }
+            }
+            for (int i=index; i<types.length; i++) {
+                types [i] = 0;
+                listeners [i] = null;
+            }
+        }
+    }
+}
+
+public int size () {
+    if (types is null) return 0;
+    int count = 0;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] !is 0) count++;
+    }
+    return count;
+}
+
+void remove (int index) {
+    if (level is 0) {
+        int end = types.length - 1;
+        System.arraycopy (types, index + 1, types, index, end - index);
+        SimpleType!(Listener).arraycopy (listeners, index + 1, listeners, index, end - index);
+        index = end;
+    } else {
+        if (level > 0) level = -level;
+    }
+    types [index] = 0;
+    listeners [index] = null;
+}
+
+public void unhook (int eventType, Listener listener) {
+    if (types is null) return;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType && listeners [i] is listener) {
+            remove (i);
+            return;
+        }
+    }
+}
+
+public void unhook (int eventType, SWTEventListener listener) {
+    if (types is null) return;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType) {
+            if ( auto typedListener = cast(TypedListener) listeners [i] ) {
+                if (typedListener.getEventListener () is listener) {
+                    remove (i);
+                    return;
+                }
+            }
+        }
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ExpandBar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,845 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ExpandBar;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ExpandAdapter;
+import org.eclipse.swt.events.ExpandEvent;
+import org.eclipse.swt.events.ExpandListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Drawable;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ExpandItem;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.ExpandItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class support the layout of selectable
+ * expand bar items.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>ExpandItem</code>.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>V_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Expand, Collapse</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ExpandItem
+ * @see ExpandEvent
+ * @see ExpandListener
+ * @see ExpandAdapter
+ * @see <a href="http://www.eclipse.org/swt/snippets/#expandbar">ExpandBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public class ExpandBar : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.windowProc windowProc;
+
+    ExpandItem[] items;
+    int itemCount;
+    ExpandItem focusItem;
+    int spacing = 4;
+    int yCurrentScroll;
+    HFONT hFont;
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the <code>ExpandListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ExpandListener
+ * @see #removeExpandListener
+ */
+public void addExpandListener (ExpandListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Expand, typedListener);
+    addListener (SWT.Collapse, typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+    style &= ~SWT.H_SCROLL;
+    return style | SWT.NO_BACKGROUND;
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int height = 0, width = 0;
+    if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+        if (itemCount > 0) {
+            auto hDC = OS.GetDC (handle);
+            HTHEME hTheme;
+            if (isAppThemed ()) {
+                hTheme = display.hExplorerBarTheme ();
+            }
+            HFONT hCurrentFont, oldFont;
+            if (hTheme is null) {
+                if (hFont !is null) {
+                    hCurrentFont = hFont;
+                } else {
+                    static if (!OS.IsWinCE) {
+                        NONCLIENTMETRICS info;
+                        info.cbSize = NONCLIENTMETRICS.sizeof;
+                        if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
+                            LOGFONT* logFont = &info.lfCaptionFont;
+                            hCurrentFont = OS.CreateFontIndirect (logFont);
+                        }
+                    }
+                }
+                if (hCurrentFont !is null) {
+                    oldFont = OS.SelectObject (hDC, hCurrentFont);
+                }
+            }
+            height += spacing;
+            for (int i = 0; i < itemCount; i++) {
+                ExpandItem item = items [i];
+                height += item.getHeaderHeight ();
+                if (item.expanded) height += item.height;
+                height += spacing;
+                width = Math.max (width, item.getPreferredWidth (hTheme, hDC));
+            }
+            if (hCurrentFont !is null) {
+                OS.SelectObject (hDC, oldFont);
+                if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont);
+            }
+            OS.ReleaseDC (handle, hDC);
+        }
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    Rectangle trim = computeTrim (0, 0, width, height);
+    return new Point (trim.width, trim.height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~CANVAS;
+    state |= TRACK_MOUSE;
+}
+
+void createItem (ExpandItem item, int style, int index) {
+    if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+    if (itemCount is items.length) {
+        ExpandItem [] newItems = new ExpandItem [itemCount + 4];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    System.arraycopy (items, index, items, index + 1, itemCount - index);
+    items [index] = item;
+    itemCount++;
+    if (focusItem is null) focusItem = item;
+
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    item.width = Math.max (0, rect.right - rect.left - spacing * 2);
+    layoutItems (index, true);
+}
+
+override void createWidget () {
+    super.createWidget ();
+    items = new ExpandItem [4];
+    if (!isAppThemed ()) {
+        backgroundMode = SWT.INHERIT_DEFAULT;
+    }
+}
+
+override int defaultBackground() {
+    if (!isAppThemed ()) {
+        return OS.GetSysColor (OS.COLOR_WINDOW);
+    }
+    return super.defaultBackground();
+}
+
+void destroyItem (ExpandItem item) {
+    int index = 0;
+    while (index < itemCount) {
+        if (items [index] is item) break;
+        index++;
+    }
+    if (index is itemCount) return;
+    if (item is focusItem) {
+        int focusIndex = index > 0 ? index - 1 : 1;
+        if (focusIndex < itemCount) {
+            focusItem = items [focusIndex];
+            focusItem.redraw (true);
+        } else {
+            focusItem = null;
+        }
+    }
+    System.arraycopy (items, index + 1, items, index, --itemCount - index);
+    items [itemCount] = null;
+    item.redraw (true);
+    layoutItems (index, true);
+}
+
+override void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) {
+    RECT rect2;
+    OS.GetClientRect (handle, &rect2);
+    OS.MapWindowPoints (handle, hwnd, cast(POINT*) &rect2, 2);
+    OS.DrawThemeBackground (display.hExplorerBarTheme (), hDC, OS.EBP_NORMALGROUPBACKGROUND, 0, &rect2, null);
+}
+
+void drawWidget (GC gc, RECT* clipRect) {
+    HTHEME hTheme;
+    if (isAppThemed ()) {
+        hTheme = display.hExplorerBarTheme ();
+    }
+    if (hTheme !is null) {
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        OS.DrawThemeBackground (hTheme, gc.handle, OS.EBP_HEADERBACKGROUND, 0, &rect, clipRect);
+    } else {
+        drawBackground (gc.handle);
+    }
+    bool drawFocus = false;
+    if (handle is OS.GetFocus ()) {
+        int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+        drawFocus = (uiState & OS.UISF_HIDEFOCUS) is 0;
+    }
+    HFONT hCurrentFont, oldFont;
+    if (hTheme 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;
+                    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 (hCurrentFont !is null) {
+        OS.SelectObject (gc.handle, oldFont);
+        if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont);
+    }
+}
+
+override Control findBackgroundControl () {
+    Control control = super.findBackgroundControl ();
+    if (!isAppThemed ()) {
+        if (control is null) control = this;
+    }
+    return control;
+}
+
+override Control findThemeControl () {
+    return isAppThemed () ? this : super.findThemeControl ();
+}
+
+int getBandHeight () {
+    if (hFont is null) return ExpandItem.CHEVRON_SIZE;
+    auto hDC = OS.GetDC (handle);
+    auto oldHFont = OS.SelectObject (hDC, hFont);
+    TEXTMETRIC lptm;
+    OS.GetTextMetrics (hDC, &lptm);
+    OS.SelectObject (hDC, oldHFont);
+    OS.ReleaseDC (handle, hDC);
+    return Math.max (ExpandItem.CHEVRON_SIZE, lptm.tmHeight + 4);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 ExpandItem getItem (int index) {
+    checkWidget ();
+    if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return itemCount;
+}
+
+/**
+ * Returns an array of <code>ExpandItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 ExpandItem [] getItems () {
+    checkWidget ();
+    ExpandItem [] result = new ExpandItem [itemCount];
+    System.arraycopy (items, 0, result, 0, itemCount);
+    return result;
+}
+
+/**
+ * Returns the receiver's spacing.
+ *
+ * @return the spacing
+ *
+ * @exception SWTException <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 int getSpacing () {
+    checkWidget ();
+    return spacing;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @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 SWTException <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 int indexOf (ExpandItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    for (int i = 0; i < itemCount; i++) {
+        if (items [i] is item) return i;
+    }
+    return -1;
+}
+
+bool isAppThemed () {
+    if (background !is -1) return false;
+    if (foreground !is -1) return false;
+    if (hFont !is null) return false;
+    return OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ();
+}
+
+void layoutItems (int index, bool setScrollbar_) {
+    if (index < itemCount) {
+        int y = spacing - yCurrentScroll;
+        for (int i = 0; i < index; i++) {
+            ExpandItem item = items [i];
+            if (item.expanded) y += item.height;
+            y += item.getHeaderHeight () + spacing;
+        }
+        for (int i = index; i < itemCount; i++) {
+            ExpandItem item = items [i];
+            item.setBounds (spacing, y, 0, 0, true, false);
+            if (item.expanded) y += item.height;
+            y += item.getHeaderHeight () + spacing;
+        }
+    }
+    if (setScrollbar_) setScrollbar ();
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        for (int i=0; i<items.length; i++) {
+            ExpandItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    focusItem = null;
+    super.releaseChildren (destroy);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ExpandListener
+ * @see #addExpandListener
+ */
+public void removeExpandListener (ExpandListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Expand, listener);
+    eventTable.unhook (SWT.Collapse, listener);
+}
+
+override void setBackgroundPixel (int pixel) {
+    super.setBackgroundPixel (pixel);
+    static if (!OS.IsWinCE) {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+override public void setFont (Font font) {
+    super.setFont (font);
+    hFont = font !is null ? font.handle : null;
+    layoutItems (0, true);
+}
+
+override void setForegroundPixel (int pixel) {
+    super.setForegroundPixel (pixel);
+    static if (!OS.IsWinCE) {
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+}
+
+void setScrollbar () {
+    if (itemCount is 0) return;
+    if ((style & SWT.V_SCROLL) is 0) return;
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    int height = rect.bottom - rect.top;
+    ExpandItem item = items [itemCount - 1];
+    int maxHeight = item.y + getBandHeight () + spacing;
+    if (item.expanded) maxHeight += item.height;
+
+    //claim bottom free space
+    if (yCurrentScroll > 0 && height > maxHeight) {
+        yCurrentScroll = Math.max (0, yCurrentScroll + maxHeight - height);
+        layoutItems (0, false);
+    }
+    maxHeight += yCurrentScroll;
+
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE | OS.SIF_PAGE | OS.SIF_POS;
+    info.nMin = 0;
+    info.nMax = maxHeight;
+    info.nPage = height;
+    info.nPos = Math.min (yCurrentScroll, info.nMax);
+    if (info.nPage !is 0) info.nPage++;
+    OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
+}
+
+/**
+ * Sets the receiver's spacing. Spacing specifies the number of pixels allocated around
+ * each item.
+ * 
+ * @param spacing the spacing around each item
+ *
+ * @exception SWTException <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 setSpacing (int spacing) {
+    checkWidget ();
+    if (spacing < 0) return;
+    if (spacing is this.spacing) return;
+    this.spacing = spacing;
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    int width = Math.max (0, (rect.right - rect.left) - spacing * 2);
+    for (int i = 0; i < itemCount; i++) {
+        ExpandItem item = items[i];
+        if (item.width !is width) item.setBounds (0, 0, width, item.height, false, true);
+    }
+    layoutItems (0, true);
+    OS.InvalidateRect (handle, null, true);
+}
+
+void showItem (ExpandItem item) {
+    Control control = item.control;
+    if (control !is null && !control.isDisposed ()) {
+        control.setVisible (item.expanded);
+    }
+    item.redraw (true);
+    int index = indexOf (item);
+    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 & SWT.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;
+}
+
+override int windowProc () {
+    return cast(int) display.windowProc;
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    if (focusItem is null) return result;
+    switch (wParam) {
+        case OS.VK_SPACE:
+        case OS.VK_RETURN:
+            Event event = new Event ();
+            event.item = focusItem;
+            sendEvent (focusItem.expanded ? SWT.Collapse : SWT.Expand, event);
+            focusItem.expanded = !focusItem.expanded;
+            showItem (focusItem);
+            return LRESULT.ZERO;
+        case OS.VK_UP: {
+            int focusIndex = indexOf (focusItem);
+            if (focusIndex > 0) {
+                focusItem.redraw (true);
+                focusItem = items [focusIndex - 1];
+                focusItem.redraw (true);
+                showFocus (true);
+                return LRESULT.ZERO;
+            }
+            break;
+        }
+        case OS.VK_DOWN: {
+            int focusIndex = indexOf (focusItem);
+            if (focusIndex < itemCount - 1) {
+                focusItem.redraw (true);
+                focusItem = items [focusIndex + 1];
+                focusItem.redraw (true);
+                showFocus (false);
+                return LRESULT.ZERO;
+            }
+            break;
+        }
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+    if (focusItem !is null) focusItem.redraw (true);
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    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);
+        if (hover && focusItem !is item) {
+            focusItem.redraw (true);
+            focusItem = item;
+            focusItem.redraw (true);
+            forceFocus ();
+            break;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    if (focusItem is null) return result;
+    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 ();
+        event.item = focusItem;
+        sendEvent (focusItem.expanded ? SWT.Collapse : SWT.Expand, event);
+        focusItem.expanded = !focusItem.expanded;
+        showItem (focusItem);
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSELEAVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+    if (result !is null) return result;
+    for (int i = 0; i < itemCount; i++) {
+        ExpandItem item = items [i];
+        if (item.hover) {
+            item.hover = false;
+            item.redraw (false);
+            break;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    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);
+        if (item.hover !is hover) {
+            item.hover = hover;
+            item.redraw (false);
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    PAINTSTRUCT ps;
+    GCData data = new GCData ();
+    data.ps = &ps;
+    data.hwnd = handle;
+    GC gc = new_GC (data);
+    if (gc !is null) {
+        int width = ps.rcPaint.right - ps.rcPaint.left;
+        int height = ps.rcPaint.bottom - ps.rcPaint.top;
+        if (width !is 0 && height !is 0) {
+            RECT rect;
+            OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+            drawWidget (gc, &rect);
+            if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+                Event event = new Event ();
+                event.gc = gc;
+                event.x = rect.left;
+                event.y = rect.top;
+                event.width = width;
+                event.height = height;
+                sendEvent (SWT.Paint, event);
+                event.gc = null;
+            }
+        }
+        gc.dispose ();
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    GCData data = new GCData ();
+    data.device = display;
+    data.foreground = getForegroundPixel ();
+    GC gc = GC.win32_new ( cast(Drawable)cast(void*)wParam, data);
+    drawWidget (gc, &rect);
+    gc.dispose ();
+    return result;
+}
+
+override LRESULT WM_SETCURSOR (int wParam, int lParam) {
+    LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+    if (result !is null) return result;
+    int hitTest = cast(short) OS.LOWORD (lParam);
+    if (hitTest is OS.HTCLIENT) {
+        for (int i = 0; i < itemCount; i++) {
+            ExpandItem item = items [i];
+            if (item.hover) {
+                auto hCursor = OS.LoadCursor (null, OS.IDC_HAND);
+                OS.SetCursor (hCursor);
+                return LRESULT.ONE;
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    if (focusItem !is null) focusItem.redraw (true);
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    int width = Math.max (0, (rect.right - rect.left) - spacing * 2);
+    for (int i = 0; i < itemCount; i++) {
+        ExpandItem item = items[i];
+        if (item.width !is width) item.setBounds (0, 0, width, item.height, false, true);
+    }
+    setScrollbar ();
+    OS.InvalidateRect (handle, null, true);
+    return result;
+}
+
+override LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int wParam, int lParam) {
+    LRESULT result = super.wmScroll (bar, true, hwnd, msg, wParam, lParam);
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS;
+    OS.GetScrollInfo (handle, OS.SB_VERT, &info);
+    int updateY = yCurrentScroll - info.nPos;
+    OS.ScrollWindowEx (handle, 0, updateY, null, null, null, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE);
+    yCurrentScroll = info.nPos;
+    if (updateY !is 0) {
+        for (int i = 0; i < itemCount; i++) {
+            items [i].y += updateY;
+        }
+    }
+    return result;
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ExpandItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,506 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ExpandItem;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ExpandBar;
+import org.eclipse.swt.widgets.Item;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a expandable item in a expand bar.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ExpandBar
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.2
+ */
+public class ExpandItem : Item {
+    ExpandBar parent;
+    Control control;
+    bool expanded, hover;
+    int x, y, width, height;
+    int imageHeight, imageWidth;
+    static const int TEXT_INSET = 6;
+    static const int BORDER = 1;
+    static const int CHEVRON_SIZE = 24;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (ExpandBar parent, int style) {
+    this (parent, style, checkNull (parent).getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent, a
+ * style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (ExpandBar parent, int style, int index) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, style, index);
+}
+
+static ExpandBar checkNull (ExpandBar control) {
+    if (control is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return control;
+}
+
+private void drawChevron (HDC hDC, RECT* rect) {
+    HBRUSH oldBrush = OS.SelectObject (hDC, OS.GetSysColorBrush (OS.COLOR_BTNFACE));
+    OS.PatBlt (hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+    OS.SelectObject (hDC, oldBrush);
+    rect.left += 4;
+    rect.top += 4;
+    rect.right -= 4;
+    rect.bottom -= 4;
+    HPEN hPen = OS.CreatePen (OS.PS_SOLID, 1, parent.foreground);
+    HPEN oldPen = OS.SelectObject (hDC, hPen);
+    int [] polyline1, polyline2;
+    if (expanded) {
+        int px = rect.left + 5;
+        int py = rect.top + 7;
+        polyline1 = [
+                px,py, px+1,py, px+1,py-1, px+2,py-1, px+2,py-2, px+3,py-2, px+3,py-3,
+                px+3,py-2, px+4,py-2, px+4,py-1, px+5,py-1, px+5,py, px+7,py];
+        py += 4;
+        polyline2 = [
+                px,py, px+1,py, px+1,py-1, px+2,py-1, px+2,py-2, px+3,py-2, px+3,py-3,
+                px+3,py-2, px+4,py-2, px+4,py-1,  px+5,py-1, px+5,py, px+7,py];
+    } else {
+        int px = rect.left + 5;
+        int py = rect.top + 4;
+        polyline1 = [
+                px,py, px+1,py, px+1,py+1, px+2,py+1, px+2,py+2, px+3,py+2, px+3,py+3,
+                px+3,py+2, px+4,py+2, px+4,py+1,  px+5,py+1, px+5,py, px+7,py];
+        py += 4;
+        polyline2 = [
+                px,py, px+1,py, px+1,py+1, px+2,py+1, px+2,py+2, px+3,py+2, px+3,py+3,
+                px+3,py+2, px+4,py+2, px+4,py+1,  px+5,py+1, px+5,py, px+7,py];
+    }
+    OS.Polyline (hDC, cast(POINT*)polyline1.ptr, polyline1.length / 2);
+    OS.Polyline (hDC, cast(POINT*)polyline2.ptr, polyline2.length / 2);
+    if (hover) {
+        HPEN whitePen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor (OS.COLOR_3DHILIGHT));
+        HPEN darkGrayPen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor (OS.COLOR_3DSHADOW));
+        OS.SelectObject (hDC, whitePen);
+        int [] points1 = [
+                rect.left, rect.bottom,
+                rect.left, rect.top,
+                rect.right, rect.top];
+        OS.Polyline (hDC, cast(POINT*)points1.ptr, points1.length / 2);
+        OS.SelectObject (hDC, darkGrayPen);
+        int [] points2 = [
+                rect.right, rect.top,
+                rect.right, rect.bottom,
+                rect.left, rect.bottom];
+        OS.Polyline (hDC, cast(POINT*)points2.ptr, points2.length / 2);
+        OS.SelectObject (hDC, oldPen);
+        OS.DeleteObject (whitePen);
+        OS.DeleteObject (darkGrayPen);
+    } else {
+        OS.SelectObject (hDC, oldPen);
+    }
+    OS.DeleteObject (hPen);
+}
+
+void drawItem (GC gc, HTHEME hTheme, RECT* clipRect, bool drawFocus) {
+    auto hDC = gc.handle;
+    int headerHeight = parent.getBandHeight ();
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + headerHeight);
+    if (hTheme !is null) {
+        OS.DrawThemeBackground (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, &rect, clipRect);
+    } else {
+        HBRUSH oldBrush = OS.SelectObject (hDC, OS.GetSysColorBrush (OS.COLOR_BTNFACE));
+        OS.PatBlt (hDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, OS.PATCOPY);
+        OS.SelectObject (hDC, oldBrush);
+    }
+    if (image !is null) {
+        rect.left += ExpandItem.TEXT_INSET;
+        if (imageHeight > headerHeight) {
+            gc.drawImage (image, rect.left, rect.top + headerHeight - imageHeight);
+        } else {
+            gc.drawImage (image, rect.left, rect.top + (headerHeight - imageHeight) / 2);
+        }
+        rect.left += imageWidth;
+    }
+    if (text.length > 0) {
+        rect.left += ExpandItem.TEXT_INSET;
+        TCHAR[] buffer = StrToTCHARs ( text/+, parent.getCodePage ()+/ );
+        if (hTheme !is null) {
+            OS.DrawThemeText (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, buffer.ptr, buffer.length, OS.DT_VCENTER | OS.DT_SINGLELINE, 0, &rect);
+        } else {
+            int oldBkMode = OS.SetBkMode (hDC, OS.TRANSPARENT);
+            OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, OS.DT_VCENTER | OS.DT_SINGLELINE);
+            OS.SetBkMode (hDC, oldBkMode);
+        }
+    }
+    int chevronSize = ExpandItem.CHEVRON_SIZE;
+    rect.left = rect.right - chevronSize;
+    rect.top = y + (headerHeight - chevronSize) / 2;
+    rect.bottom = rect.top + chevronSize;
+    if (hTheme !is null) {
+        int partID = expanded ? OS.EBP_NORMALGROUPCOLLAPSE : OS.EBP_NORMALGROUPEXPAND;
+        int stateID = hover ? OS.EBNGC_HOT : OS.EBNGC_NORMAL;
+        OS.DrawThemeBackground (hTheme, hDC, partID, stateID, &rect, clipRect);
+    } else {
+        drawChevron (hDC, &rect);
+    }
+    if (drawFocus) {
+        OS.SetRect (&rect, x + 1, y + 1, x + width - 2, y + headerHeight - 2);
+        OS.DrawFocusRect (hDC, &rect);
+    }
+    if (expanded) {
+        if (!parent.isAppThemed ()) {
+            HPEN pen = OS.CreatePen (OS.PS_SOLID, 1, OS.GetSysColor (OS.COLOR_BTNFACE));
+            HPEN oldPen = OS.SelectObject (hDC, pen);
+            int [] points = [
+                    x, y + headerHeight,
+                    x, y + headerHeight + height,
+                    x + width - 1, y + headerHeight + height,
+                    x + width - 1, y + headerHeight - 1];
+            OS.Polyline (hDC, cast(POINT*) points.ptr, points.length / 2);
+            OS.SelectObject (hDC, oldPen);
+            OS.DeleteObject (pen);
+        }
+    }
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns the control that is shown when the item is expanded.
+ * If no control has been set, return <code>null</code>.
+ *
+ * @return the control
+ *
+ * @exception SWTException <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 Control getControl () {
+    checkWidget ();
+    return control;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is expanded,
+ * and false otherwise.
+ *
+ * @return the expanded state
+ *
+ * @exception SWTException <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 getExpanded () {
+    checkWidget ();
+    return expanded;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header
+ *
+ * @exception SWTException <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 int getHeaderHeight () {
+    checkWidget ();
+    return Math.max (parent.getBandHeight (), imageHeight);
+}
+
+/**
+ * Gets the height of the receiver.
+ *
+ * @return the height
+ *
+ * @exception SWTException <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 int getHeight () {
+    checkWidget ();
+    return height;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>ExpandBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 ExpandBar getParent () {
+    checkWidget ();
+    return parent;
+}
+
+int getPreferredWidth (HTHEME hTheme, HDC hDC) {
+    int width = ExpandItem.TEXT_INSET * 2 + ExpandItem.CHEVRON_SIZE;
+    if (image !is null) {
+        width += ExpandItem.TEXT_INSET + imageWidth;
+    }
+    if (text.length > 0) {
+        RECT rect;
+        TCHAR[] buffer = StrToTCHARs (/+parent.getCodePage (),+/ text);
+        if (hTheme !is null) {
+            OS.GetThemeTextExtent (hTheme, hDC, OS.EBP_NORMALGROUPHEAD, 0, buffer.ptr, buffer.length, OS.DT_SINGLELINE, null, &rect);
+        } else {
+            OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, OS.DT_CALCRECT);
+        }
+        width += (rect.right - rect.left);
+    }
+    return width;
+}
+
+bool isHover (int x, int y) {
+    int bandHeight = parent.getBandHeight ();
+    return this.x < x && x < (this.x + width) && this.y < y && y < (this.y + bandHeight);
+}
+
+void redraw (bool all) {
+    auto parentHandle = parent.handle;
+    int headerHeight = parent.getBandHeight ();
+    RECT rect;
+    int left = all ? x : x + width - headerHeight;
+    OS.SetRect (&rect, left, y, x + width, y + headerHeight);
+    OS.InvalidateRect (parentHandle, &rect, true);
+    if (imageHeight > headerHeight) {
+        OS.SetRect (&rect, x + ExpandItem.TEXT_INSET, y + headerHeight - imageHeight, x + ExpandItem.TEXT_INSET + imageWidth, y);
+        OS.InvalidateRect (parentHandle, &rect, true);
+    }
+    if (!parent.isAppThemed ()) {
+        OS.SetRect (&rect, x, y + headerHeight, x + width, y + headerHeight + height + 1);
+        OS.InvalidateRect (parentHandle, &rect, true);
+    }
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    control = null;
+}
+
+void setBounds (int x, int y, int width, int height, bool move, bool size) {
+    redraw (true);
+    int headerHeight = parent.getBandHeight ();
+    if (move) {
+        if (imageHeight > headerHeight) {
+            y += (imageHeight - headerHeight);
+        }
+        this.x = x;
+        this.y = y;
+        redraw (true);
+    }
+    if (size) {
+        this.width = width;
+        this.height = height;
+        redraw (true);
+    }
+    if (control !is null && !control.isDisposed ()) {
+        if (!parent.isAppThemed ()) {
+            x += BORDER;
+            width = Math.max (0, width - BORDER * 2);
+            height = Math.max (0, height - BORDER);
+        }
+        if (move && size) control.setBounds (x, y + headerHeight, width, height);
+        if (move && !size) control.setLocation (x, y + headerHeight);
+        if (!move && size) control.setSize (width, height);
+    }
+}
+
+/**
+ * Sets the control that is shown when the item is expanded.
+ *
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setControl (Control control) {
+    checkWidget ();
+    if (control !is null) {
+        if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
+    }
+    this.control = control;
+    if (control !is null) {
+        int headerHeight = parent.getBandHeight ();
+        control.setVisible (expanded);
+        if (!parent.isAppThemed ()) {
+            int width = Math.max (0, this.width - BORDER * 2);
+            int height = Math.max (0, this.height - BORDER);
+            control.setBounds (x + BORDER, y + headerHeight, width, height);
+        } else {
+            control.setBounds (x, y + headerHeight, width, height);
+        }
+    }
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ *
+ * @param expanded the new expanded state
+ *
+ * @exception SWTException <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 setExpanded (bool expanded) {
+    checkWidget ();
+    this.expanded = expanded;
+    parent.showItem (this);
+}
+
+/**
+ * Sets the height of the receiver. This is height of the item when it is expanded,
+ * excluding the height of the header.
+ *
+ * @param height the new height
+ *
+ * @exception SWTException <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 setHeight (int height) {
+    checkWidget ();
+    if (height < 0) return;
+    setBounds (0, 0, width, height, false, true);
+    if (expanded) parent.layoutItems (parent.indexOf (this) + 1, true);
+}
+
+override public void setImage (Image image) {
+    super.setImage (image);
+    int oldImageHeight = imageHeight;
+    if (image !is null) {
+        Rectangle bounds = image.getBounds ();
+        imageHeight = bounds.height;
+        imageWidth = bounds.width;
+    } else {
+        imageHeight = imageWidth = 0;
+    }
+    if (oldImageHeight !is imageHeight) {
+        parent.layoutItems (parent.indexOf (this), true);
+    } else {
+        redraw (true);
+    }
+}
+
+override public void setText (String string) {
+    super.setText (string);
+    redraw (true);
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FileDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,625 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.FileDialog;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class allow the user to navigate
+ * the file system and select or enter a file name.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SAVE, OPEN, MULTI</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles SAVE and OPEN may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/snippets/#filedialog">FileDialog snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class FileDialog : Dialog {
+    String [] filterNames;
+    String [] filterExtensions;
+    String [] fileNames;
+    String filterPath = "", fileName = "";
+    int filterIndex = 0;
+    bool overwrite = false;
+    static const String FILTER = "*.*";
+    static int BUFFER_SIZE = 1024 * 32;
+    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.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (parent, style));
+    checkSubclass ();
+}
+
+/**
+ * Returns the path of the first file that was
+ * selected in the dialog relative to the filter path, or an
+ * empty string if no such file has been selected.
+ *
+ * @return the relative path of the file
+ */
+public String getFileName () {
+    return fileName;
+}
+
+/**
+ * Returns a (possibly empty) array with the paths of all files
+ * that were selected in the dialog relative to the filter path.
+ *
+ * @return the relative paths of the files
+ */
+public String [] getFileNames () {
+    return fileNames;
+}
+
+/**
+ * Returns the file extensions which the dialog will
+ * use to filter the files it shows.
+ *
+ * @return the file extensions filter
+ */
+public String [] getFilterExtensions () {
+    return filterExtensions;
+}
+
+/**
+ * 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.
+ *
+ * @return the list of filter names
+ */
+public String [] getFilterNames () {
+    return filterNames;
+}
+
+/**
+ * Returns the directory path that the dialog will use, or an empty
+ * string if this is not set.  File names in this path will appear
+ * in the dialog, filtered according to the filter extensions.
+ *
+ * @return the directory path string
+ *
+ * @see #setFilterExtensions
+ */
+public String getFilterPath () {
+    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:
+            OFNOTIFY* ofn = cast(OFNOTIFY*)lParam;
+            //OS.MoveMemory (ofn, lParam, OFNOTIFY.sizeof);
+            if (ofn.hdr.code is OS.CDN_SELCHANGE) {
+                int lResult = OS.SendMessage (ofn.hdr.hwndFrom, OS.CDM_GETSPEC, 0, 0);
+                if (lResult > 0) {
+                    lResult += OS.MAX_PATH;
+                    OPENFILENAME* lpofn = ofn.lpOFN;
+                    //OS.MoveMemory (lpofn, ofn.lpOFN, OS.OPENFILENAME_sizeof);
+                    if (lpofn.nMaxFile < lResult) {
+                        auto hHeap = OS.GetProcessHeap ();
+                        auto lpstrFile = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, lResult * TCHAR.sizeof);
+                        if (lpstrFile !is null) {
+                            if (lpofn.lpstrFile !is null) OS.HeapFree (hHeap, 0, lpofn.lpstrFile);
+                            lpofn.lpstrFile = lpstrFile;
+                            lpofn.nMaxFile = lResult;
+                            //OS.MoveMemory (ofn.lpOFN, lpofn, OS.OPENFILENAME_sizeof);
+                        }
+                    }
+              }
+          }
+          break;
+        default:
+    }
+    return 0;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a string describing the absolute path of the first selected file,
+ *         or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public String open () {
+    auto hHeap = OS.GetProcessHeap ();
+
+    /* Get the owner HWND for the dialog */
+    HWND hwndOwner;
+    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 & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is SWT.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 = "";
+    /* Use the character encoding for the default locale */
+    TCHAR[] buffer3 = StrToTCHARs (0, title, true);
+    int byteCount3 = buffer3.length * TCHAR.sizeof;
+    auto lpstrTitle = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount3);
+    OS.MoveMemory (lpstrTitle, buffer3.ptr, byteCount3);
+
+    /* Compute filters and copy into lpstrFilter */
+    String strFilter = "";
+    if (filterNames is null) filterNames = null;
+    if (filterExtensions is null) filterExtensions = null;
+    for (int i=0; i<filterExtensions.length; i++) {
+        String filterName = filterExtensions [i];
+        if (i < filterNames.length) filterName = filterNames [i];
+        strFilter = strFilter ~ filterName ~ '\0' ~ filterExtensions [i] ~ '\0';
+    }
+    if (filterExtensions.length is 0) {
+        strFilter = strFilter ~ FILTER ~ '\0' ~ FILTER ~ '\0';
+    }
+    /* Use the character encoding for the default locale */
+    TCHAR[] buffer4 = StrToTCHARs (0, strFilter, true);
+    int byteCount4 = buffer4.length * TCHAR.sizeof;
+    auto lpstrFilter = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount4);
+    OS.MoveMemory (lpstrFilter, buffer4.ptr, byteCount4);
+
+    /* Convert the fileName and filterName to C strings */
+    if (fileName is null) fileName = "";
+    /* Use the character encoding for the default locale */
+    TCHAR[] name = StrToTCHARs (0, fileName, true);
+
+    /*
+    * Copy the name into lpstrFile and ensure that the
+    * last byte is NULL and the buffer does not overrun.
+    */
+    int nMaxFile = OS.MAX_PATH;
+    if ((style & SWT.MULTI) !is 0) nMaxFile = Math.max (nMaxFile, BUFFER_SIZE);
+    int byteCount = nMaxFile * TCHAR.sizeof;
+    auto lpstrFile = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    int byteCountFile = Math.min (name.length * TCHAR.sizeof, byteCount - TCHAR.sizeof);
+    OS.MoveMemory (lpstrFile, name.ptr, byteCountFile);
+
+    /*
+    * Copy the path into lpstrInitialDir and ensure that
+    * the last byte is NULL and the buffer does not overrun.
+    */
+    if (filterPath is null) filterPath = "";
+    /* Use the character encoding for the default locale */
+    TCHAR[] path = StrToTCHARs (0, filterPath.replace ('/', '\\'), true);
+    int byteCount5 = OS.MAX_PATH * TCHAR.sizeof;
+    auto lpstrInitialDir = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount5);
+    int byteCountDir = Math.min (path.length * TCHAR.sizeof, byteCount5 - TCHAR.sizeof);
+    OS.MoveMemory (lpstrInitialDir, path.ptr, byteCountDir);
+
+    /* Create the file dialog struct */
+    OPENFILENAME struct_;
+    struct_.lStructSize = OS.OPENFILENAME_sizeof;
+    struct_.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR;
+    bool save = (style & SWT.SAVE) !is 0;
+    if (save && overwrite) struct_.Flags |= OS.OFN_OVERWRITEPROMPT;
+    if ((style & SWT.MULTI) !is 0) {
+        struct_.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER;
+        if (!OS.IsWinCE && USE_HOOK) {
+            //callback = new Callback (this, "OFNHookProc", 4); //$NON-NLS-1$
+            //int lpfnHook = callback.getAddress ();
+            //if (lpfnHook is 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+            struct_.lCustData = cast(uint) cast(void*) this;
+            struct_.lpfnHook = &OFNHookProc;
+            struct_.Flags |= OS.OFN_ENABLEHOOK;
+        }
+    }
+    struct_.hwndOwner = hwndOwner;
+    struct_.lpstrTitle = lpstrTitle;
+    struct_.lpstrFile = lpstrFile;
+    struct_.nMaxFile = nMaxFile;
+    struct_.lpstrInitialDir = lpstrInitialDir;
+    struct_.lpstrFilter = lpstrFilter;
+    struct_.nFilterIndex = filterIndex is 0 ? filterIndex : filterIndex + 1;
+
+    /*
+    * Set the default extension to an empty string.  If the
+    * user fails to type an extension and this extension is
+    * empty, Windows uses the current value of the filter
+    * extension at the time that the dialog is closed.
+    */
+    TCHAR* lpstrDefExt;
+    if (save) {
+        lpstrDefExt = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+        struct_.lpstrDefExt = lpstrDefExt;
+    }
+
+    /* Make the parent shell be temporary modal */
+    Dialog oldModal = null;
+    Display display = parent.getDisplay ();
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
+    }
+
+    /*
+    * Feature in Windows.  For some reason, the WH_MSGFILTER filter
+    * does not run for GetSaveFileName() or GetOpenFileName().  The
+    * fix is to allow async messages to run in the WH_FOREGROUNDIDLE
+    * hook instead.
+    *
+    * Bug in Windows 98.  For some reason, when certain operating
+    * system calls such as Shell_NotifyIcon(), GetOpenFileName()
+    * and GetSaveFileName() are made during the WH_FOREGROUNDIDLE
+    * hook, Windows hangs.  The fix is to disallow async messages
+    * during WH_FOREGROUNDIDLE.
+    */
+    bool oldRunMessagesInIdle = display.runMessagesInIdle;
+    display.runMessagesInIdle = !OS.IsWin95;
+    /*
+    * Open the dialog.  If the open fails due to an invalid
+    * file name, use an empty file name and open it again.
+    */
+    bool success = cast(bool)( (save) ? OS.GetSaveFileName (&struct_) : OS.GetOpenFileName (&struct_));
+    switch (OS.CommDlgExtendedError ()) {
+        case OS.FNERR_INVALIDFILENAME:
+            OS.MoveMemory (lpstrFile, StrToTCHARz ( "" ), TCHAR.sizeof);
+            success = cast(bool)((save) ? OS.GetSaveFileName (&struct_) : OS.GetOpenFileName (&struct_));
+            break;
+        case OS.FNERR_BUFFERTOOSMALL:
+            USE_HOOK = true;
+            break;
+        default:
+    }
+    display.runMessagesInIdle = oldRunMessagesInIdle;
+
+    /* Clear the temporary dialog modal parent */
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        display.setModalDialog (oldModal);
+    }
+
+    /* Dispose the callback and reassign the buffer */
+    //if (callback !is null) callback.dispose ();
+    lpstrFile = struct_.lpstrFile;
+
+    /* Set the new path, file name and filter */
+    fileNames = null;
+    String fullPath = null;
+    if (success) {
+
+        /* Use the character encoding for the default locale */
+        TCHAR[] buffer = NewTCHARs (0, struct_.nMaxFile);
+        int byteCount1 = buffer.length * TCHAR.sizeof;
+        OS.MoveMemory (buffer.ptr, lpstrFile, byteCount1);
+
+        /*
+        * Bug in WinCE.  For some reason, nFileOffset and nFileExtension
+        * are always zero on WinCE HPC. nFileOffset is always zero on
+        * WinCE PPC when using GetSaveFileName().  nFileOffset is correctly
+        * set on WinCE PPC when using OpenFileName().  The fix is to parse
+        * lpstrFile to calculate nFileOffset.
+        *
+        * Note: WinCE does not support multi-select file dialogs.
+        */
+        int nFileOffset = struct_.nFileOffset;
+        static if (OS.IsWinCE) {
+            if (nFileOffset is 0) {
+                int index = 0;
+                while (index < buffer.length ) {
+                    int ch = buffer[index];
+                    if (ch is 0) break;
+                    if (ch is '\\') nFileOffset = index + 1;
+                    index++;
+                }
+            }
+        }
+        if (nFileOffset > 0) {
+
+            /* Use the character encoding for the default locale */
+            TCHAR[] prefix = NewTCHARs (0, nFileOffset - 1);
+            int byteCount2 = prefix.length * TCHAR.sizeof;
+            OS.MoveMemory (prefix.ptr, lpstrFile, byteCount2);
+            filterPath = TCHARsToStr( prefix );
+
+            /*
+            * Get each file from the buffer.  Files are delimited
+            * by a NULL character with 2 NULL characters at the end.
+            */
+            int count = 0;
+            fileNames = new String[]( (style & SWT.MULTI) !is 0 ? 4 : 1 );
+            int start = nFileOffset;
+            do {
+                int end = start;
+                while (end < buffer.length && buffer[end] !is 0) end++;
+                String string = TCHARsToStr( buffer[ start .. end ] );
+                start = end;
+                if (count is fileNames.length) {
+                    String [] newFileNames = new String[]( fileNames.length + 4 );
+                    System.arraycopy (fileNames, 0, newFileNames, 0, fileNames.length);
+                    fileNames = newFileNames;
+                }
+                fileNames [count++] = string;
+                if ((style & SWT.MULTI) is 0) break;
+                start++;
+            } while (start < buffer.length && buffer[start] !is 0);
+
+            if (fileNames.length > 0) fileName = fileNames  [0];
+            String separator = "";
+            int length_ = filterPath.length;
+            if (length_ > 0 && filterPath[length_ - 1] !is '\\') {
+                separator = "\\";
+            }
+            fullPath = filterPath ~ separator ~ fileName;
+            if (count < fileNames.length) {
+                String [] newFileNames = new String[]( count );
+                System.arraycopy (fileNames, 0, newFileNames, 0, count);
+                fileNames = newFileNames;
+            }
+        }
+        filterIndex = struct_.nFilterIndex - 1;
+    }
+
+    /* Free the memory that was allocated. */
+    OS.HeapFree (hHeap, 0, lpstrFile);
+    OS.HeapFree (hHeap, 0, lpstrFilter);
+    OS.HeapFree (hHeap, 0, lpstrInitialDir);
+    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
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+    /* Answer the full path or null */
+    return fullPath;
+}
+
+/**
+ * Set the initial filename which the dialog will
+ * select by default when opened to the argument,
+ * which may be null.  The name will be prefixed with
+ * the filter path when one is supplied.
+ *
+ * @param string the file name
+ */
+public void setFileName (String string) {
+    fileName = string;
+}
+
+/**
+ * Set the file extensions which the dialog will
+ * use to filter the files it shows to the argument,
+ * which may be null.
+ * <p>
+ * The strings are platform specific. For example, on
+ * some platforms, an extension filter string is typically
+ * of the form "*.extension", where "*.*" matches all files.
+ * For filters with multiple extensions, use semicolon as
+ * a separator, e.g. "*.jpg;*.png".
+ * </p>
+ *
+ * @param extensions the file extension filter
+ *
+ * @see #setFilterNames to specify the user-friendly
+ * names corresponding to the extensions
+ */
+public void setFilterExtensions (String [] extensions) {
+    filterExtensions = 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>
+ * Each name is a user-friendly short description shown for
+ * its corresponding filter. The <code>names</code> array must
+ * be the same length as the <code>extensions</code> array.
+ * </p>
+ *
+ * @param names the list of filter names, or null for no filter names
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterNames (String [] names) {
+    filterNames = names;
+}
+
+/**
+ * Sets the directory path that the dialog will use
+ * to the argument, which may be null. File names in this
+ * path will appear in the dialog, filtered according
+ * to the filter extensions. If the string is null,
+ * then the operating system's default filter path
+ * will be used.
+ * <p>
+ * Note that the path string is platform dependent.
+ * For convenience, either '/' or '\' can be used
+ * as a path separator.
+ * </p>
+ *
+ * @param string the directory path
+ *
+ * @see #setFilterExtensions
+ */
+public void setFilterPath (String string) {
+    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;
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/FontDialog.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,336 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.FontDialog;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class allow the user to select a font
+ * from all available fonts in the system.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class FontDialog : Dialog {
+    FontData fontData;
+    RGB rgb;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (parent, style));
+    checkSubclass ();
+}
+
+/**
+ * Returns a FontData object describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @deprecated use #getFontList ()
+ */
+public FontData getFontData () {
+    return fontData;
+}
+
+/**
+ * Returns a FontData set describing the font that was
+ * selected in the dialog, or null if none is available.
+ *
+ * @return the FontData for the selected font, or null
+ * @since 2.1.1
+ */
+public FontData [] getFontList () {
+    if (fontData is null) return null;
+    FontData [] result = new FontData [1];
+    result [0] = fontData;
+    return result;
+}
+
+/**
+ * Returns an RGB describing the color that was selected
+ * in the dialog, or null if none is available.
+ *
+ * @return the RGB value for the selected color, or null
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public RGB getRGB () {
+    return rgb;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return a FontData object describing the font that was selected,
+ *         or null if the dialog was cancelled or an error occurred
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public FontData open () {
+    static if (OS.IsWinCE) SWT.error (SWT.ERROR_NOT_IMPLEMENTED);
+
+    /* Get the owner HWND for the dialog */
+    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 & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is SWT.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 ();
+    CHOOSEFONT lpcf;
+    lpcf.lStructSize = CHOOSEFONT.sizeof;
+    lpcf.hwndOwner = hwndOwner;
+    lpcf.Flags = OS.CF_SCREENFONTS | OS.CF_EFFECTS;
+    auto lpLogFont = cast(LOGFONT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, LOGFONT.sizeof);
+    if (fontData !is null /+&& fontData.data !is null+/) {
+        LOGFONT logFont = fontData.data;
+        int lfHeight = logFont.lfHeight;
+        auto hDC = OS.GetDC (null);
+        int pixels = -cast(int)(0.5f + (fontData.height * OS.GetDeviceCaps(hDC, OS.LOGPIXELSY) / 72));
+        OS.ReleaseDC (null, hDC);
+        logFont.lfHeight = pixels;
+        lpcf.Flags |= OS.CF_INITTOLOGFONTSTRUCT;
+        OS.MoveMemory (lpLogFont, &logFont, LOGFONT.sizeof);
+        logFont.lfHeight = lfHeight;
+    }
+    lpcf.lpLogFont = lpLogFont;
+    if (rgb !is null) {
+        int red = rgb.red & 0xFF;
+        int green = (rgb.green << 8) & 0xFF00;
+        int blue = (rgb.blue << 16) & 0xFF0000;
+        lpcf.rgbColors = red | green | blue;
+    }
+
+    /* Make the parent shell be temporary modal */
+    Dialog oldModal = null;
+    Display display = null;
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        display = parent.getDisplay ();
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
+    }
+
+    /* Open the dialog */
+    bool success = cast(bool) OS.ChooseFont (&lpcf);
+
+    /* Clear the temporary dialog modal parent */
+    if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+        display.setModalDialog (oldModal);
+    }
+
+    /* Compute the result */
+    if (success) {
+        LOGFONT* logFont = lpLogFont;
+        //OS.MoveMemory (logFont, lpLogFont, LOGFONT.sizeof);
+
+        /*
+         * This will not work on multiple screens or
+         * for printing. Should use DC for the proper device.
+         */
+        auto hDC = OS.GetDC(null);
+        int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY);
+        int pixels = 0;
+        if (logFont.lfHeight > 0) {
+            /*
+             * Feature in Windows. If the lfHeight of the LOGFONT structure
+             * is positive, the lfHeight measures the height of the entire
+             * cell, including internal leading, in logical units. Since the
+             * height of a font in points does not include the internal leading,
+             * we must subtract the internal leading, which requires a TEXTMETRIC,
+             * which in turn requires font creation.
+             */
+            auto hFont = OS.CreateFontIndirect(logFont);
+            auto oldFont = OS.SelectObject(hDC, hFont);
+            TEXTMETRIC lptm ;
+            OS.GetTextMetrics(hDC, &lptm);
+            OS.SelectObject(hDC, oldFont);
+            OS.DeleteObject(hFont);
+            pixels = logFont.lfHeight - lptm.tmInternalLeading;
+        } else {
+            pixels = -logFont.lfHeight;
+        }
+        OS.ReleaseDC(null, hDC);
+
+        float points = pixels * 72f /logPixelsY;
+        fontData = FontData.win32_new (logFont, points);
+        int red = lpcf.rgbColors & 0xFF;
+        int green = (lpcf.rgbColors >> 8) & 0xFF;
+        int blue = (lpcf.rgbColors >> 16) & 0xFF;
+        rgb = new RGB (red, green, blue);
+    }
+
+    /* 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
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+    if (!success) return null;
+    return fontData;
+}
+
+/**
+ * Sets a FontData object describing the font to be
+ * selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the FontData to use initially, or null
+ * @deprecated use #setFontList (FontData [])
+ */
+public void setFontData (FontData fontData) {
+    this.fontData = fontData;
+}
+
+/**
+ * Sets the set of FontData objects describing the font to
+ * be selected by default in the dialog, or null to let
+ * the platform choose one.
+ *
+ * @param fontData the set of FontData objects to use initially, or null
+ *        to let the platform select a default when open() is called
+ *
+ * @see Font#getFontData
+ *
+ * @since 2.1.1
+ */
+public void setFontList (FontData [] fontData) {
+    if (fontData !is null && fontData.length > 0) {
+        this.fontData = fontData [0];
+    } else {
+        this.fontData = null;
+    }
+}
+
+/**
+ * Sets the RGB describing the color to be selected by default
+ * in the dialog, or null to let the platform choose one.
+ *
+ * @param rgb the RGB value to use initially, or null to let
+ *        the platform select a default when open() is called
+ *
+ * @see PaletteData#getRGBs
+ *
+ * @since 2.1
+ */
+public void setRGB (RGB rgb) {
+    this.rgb = rgb;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Group.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,567 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Group;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+import java.lang.all;
+
+/**
+ * Instances of this class provide an etched border
+ * with an optional title.
+ * <p>
+ * Shadow styles are hints and may not be honoured
+ * by the platform.  To create a group with the
+ * default shadow style for the platform, do not
+ * specify a shadow style.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the above styles may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Group : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.windowProc windowProc;
+
+    String text = "";
+    static const int CLIENT_INSET = 3;
+    private static /+const+/ WNDPROC GroupProc;
+    static if( OS.IsWinCE ){
+        static const TCHAR[] GroupClass = "BUTTON\0";
+    }
+    else{
+        static const TCHAR[] GroupClass = "SWT_GROUP\0";
+    }
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            /*
+            * Feature in Windows.  The group box window class
+            * uses the CS_HREDRAW and CS_VREDRAW style bits to
+            * force a full redraw of the control and all children
+            * when resized.  This causes flashing.  The fix is to
+            * register a new window class without these bits and
+            * implement special code that damages only the control.
+            *
+            * Feature in WinCE.  On certain devices, defining
+            * a new window class which looks like BUTTON causes
+            * CreateWindowEx() to crash.  The workaround is to use
+            * the class Button directly.
+            */
+            WNDCLASS lpWndClass;
+            static if (OS.IsWinCE) {
+                OS.GetClassInfo (null, GroupClass.ptr, &lpWndClass);
+                GroupProc = lpWndClass.lpfnWndProc;
+            } else {
+                TCHAR[] WC_BUTTON = "BUTTON\0";
+                OS.GetClassInfo (null, WC_BUTTON.ptr, &lpWndClass);
+                GroupProc = lpWndClass.lpfnWndProc;
+                auto hInstance = OS.GetModuleHandle (null);
+                if (!OS.GetClassInfo (hInstance, GroupClass.ptr, &lpWndClass)) {
+                    auto hHeap = OS.GetProcessHeap ();
+                    lpWndClass.hInstance = hInstance;
+                    lpWndClass.style &= ~(OS.CS_HREDRAW | OS.CS_VREDRAW);
+                    int byteCount = GroupClass.length * TCHAR.sizeof;
+                    auto lpszClassName = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                    OS.MoveMemory (lpszClassName, GroupClass.ptr, byteCount);
+                    lpWndClass.lpszClassName = lpszClassName;
+                    OS.RegisterClass (&lpWndClass);
+                    OS.HeapFree (hHeap, 0, lpszClassName);
+                }
+            }
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SHADOW_ETCHED_IN
+ * @see SWT#SHADOW_ETCHED_OUT
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    /*
+    * Feature in Windows.  When the user clicks on the group
+    * box label, the group box takes focus.  This is unwanted.
+    * The fix is to avoid calling the group box window proc.
+    */
+    switch (msg) {
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONDBLCLK:
+            return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+        default:
+    }
+    return OS.CallWindowProc (GroupProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    style |= SWT.NO_FOCUS;
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    Point size = super.computeSize (wHint, hHint, changed);
+    int length = text.length;
+    if (length !is 0) {
+        /*
+        * Bug in Windows.  When a group control is right-to-left and
+        * is disabled, the first pixel of the text is clipped.  The
+        * fix is to add a space to both sides of the text.  Note that
+        * the work around must run all the time to stop the preferred
+        * size from changing when a group is enabled and disabled.
+        */
+        String string = text;
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+            if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+                string = " " ~ string ~ " ";
+            }
+        }
+        /*
+        * If the group has text, and the text is wider than the
+        * client area, pad the width so the text is not clipped.
+        */
+        TCHAR* buffer = StrToTCHARz (/+getCodePage (),+/ string);
+        HFONT newFont, oldFont;
+        auto hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        RECT rect;
+        int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE;
+        OS.DrawText (hDC, buffer, -1, &rect, flags);
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        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;
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    Rectangle trim = super.computeTrim (x, y, width, height);
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    TEXTMETRIC tm;
+    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 + 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;
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    /*
+    * Bug in Windows.  When a group control is right-to-left and
+    * is disabled, the first pixel of the text is clipped.  The
+    * fix is to add a space to both sides of the text.
+    */
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            String string = enabled || text.length is 0 ? text : " " ~ text ~ " ";
+            TCHAR* buffer = StrToTCHARz (/+getCodePage (),+/ string);
+            OS.SetWindowText (handle, buffer);
+        }
+    }
+}
+
+override public Rectangle getClientArea () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    TEXTMETRIC tm;
+    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;
+    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);
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns the receiver's text, which is the string that the
+ * is used as the <em>title</em>. If the text has not previously
+ * been set, returns an empty string.
+ *
+ * @return the text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    return text;
+}
+
+override bool mnemonicHit (wchar key) {
+    return setFocus ();
+}
+
+override bool mnemonicMatch (wchar key) {
+    wchar mnemonic = findMnemonic (getText ());
+    if (mnemonic is '\0') return false;
+    return CharacterToUpper (key) is CharacterToUpper (mnemonic);
+}
+
+void printWidget (HWND hwnd, GC gc) {
+    /*
+    * 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.
+    */
+    auto hDC = gc.handle;
+    if (!OS.PrintWindow (hwnd, hDC, 0)) {
+        /*
+        * Bug in Windows.  For some reason, WM_PRINT when called
+        * with PRF_CHILDREN will not draw the tool bar divider
+        * for tool bar children that do not have CCS_NODIVIDER.
+        * The fix is to draw the group box and iterate through
+        * the children, drawing each one.
+        */
+        int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND;
+        OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags);
+        int nSavedDC = OS.SaveDC (hDC);
+        Control [] children = _getChildren ();
+        Rectangle rect = getBounds ();
+        OS.IntersectClipRect (hDC, 0, 0, rect.width, rect.height);
+        for (int i=children.length - 1; i>=0; --i) {
+            Point location = children [i].getLocation ();
+            OS.SetWindowOrgEx (hDC, -location.x, -location.y, null);
+            children [i].print (gc);
+        }
+        OS.RestoreDC (hDC, nSavedDC);
+    }
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    text = null;
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    Rectangle oldRect = getClientArea ();
+    super.setFont (font);
+    Rectangle newRect = getClientArea ();
+    if (oldRect!=newRect) sendResize ();
+}
+
+/**
+ * Sets the receiver's text, which is the string that will
+ * be displayed as the receiver's <em>title</em>, to the argument,
+ * which may not be null. The string may include the mnemonic character.
+ * </p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the first child of the group. On most platforms, the
+ * mnemonic appears underlined but may be emphasised in a
+ * platform specific manner.  The mnemonic indicator character
+ * '&amp;' can be escaped by doubling it in the string, causing
+ * a single '&amp;' to be displayed.
+ * </p>
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    text = string;
+    /*
+    * Bug in Windows.  When a group control is right-to-left and
+    * is disabled, the first pixel of the text is clipped.  The
+    * fix is to add a space to both sides of the text.
+    */
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            if (!OS.IsWindowEnabled (handle)) {
+                if (string.length !is 0) string = " " ~ string ~ " ";
+            }
+        }
+    }
+    TCHAR* buffer = StrToTCHARz(/+getCodePage (),+/ string);
+    OS.SetWindowText (handle, buffer);
+}
+
+override int widgetStyle () {
+    /*
+    * Bug in Windows.  When GetDCEx() is called with DCX_INTERSECTUPDATE,
+    * the HDC that is returned does not include the current update region.
+    * This was confirmed under DEBUG Windows when GetDCEx() complained about
+    * invalid flags.  Therefore, it is not easily possible to get an HDC from
+    * outside of WM_PAINT that includes the current damage and clips children.
+    * Because the receiver has children and draws a frame and label, it is
+    * necessary that the receiver always draw clipped, in the current damaged
+    * area.  The fix is to force the receiver to be fully clipped by including
+    * WS_CLIPCHILDREN and WS_CLIPSIBLINGS in the default style bits.
+    */
+    return super.widgetStyle () | OS.BS_GROUPBOX | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
+}
+
+override String windowClass () {
+    return TCHARsToStr( GroupClass );
+}
+
+override int windowProc () {
+    return cast(int) GroupProc;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  Group boxes do not erase
+    * the background before drawing.  The fix is to
+    * fill the background.
+    */
+    drawBackground (cast(HANDLE) wParam);
+    return LRESULT.ONE;
+}
+
+override LRESULT WM_NCHITTEST (int wParam, int lParam) {
+    LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  The window proc for the group box
+    * returns HTTRANSPARENT indicating that mouse messages
+    * should not be delivered to the receiver and any children.
+    * Normally, group boxes in Windows do not have children and
+    * this is the correct behavior for this case.  Because we
+    * allow children, answer HTCLIENT to allow mouse messages
+    * to be delivered to the children.
+    */
+    int /*long*/ code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+    if (code is OS.HTTRANSPARENT) code = OS.HTCLIENT;
+    return new LRESULT (code);
+}
+
+override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  In version 6.00 of COMCTL32.DLL,
+    * every time the mouse moves, the group title redraws.
+    * This only happens when WM_NCHITTEST returns HTCLIENT.
+    * The fix is to avoid calling the group window proc.
+    */
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  In version 6.00 of COMCTL32.DLL,
+    * when WM_PRINTCLIENT is sent from a child BS_GROUP
+    * control to a parent BS_GROUP, the parent BS_GROUP
+    * clears the font from the HDC.  Normally, group boxes
+    * in Windows do not have children so this behavior is
+    * undefined.  When the parent of a BS_GROUP is not a
+    * BS_GROUP, there is no problem.  The fix is to save
+    * and restore the current font.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        auto nSavedDC = OS.SaveDC (cast(HDC)wParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+        OS.RestoreDC (cast(HDC)wParam, nSavedDC);
+        return new LRESULT (code);
+    }
+    return result;
+}
+
+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 group, it sends WM_CTLCOLORBTN to get the foreground
+    * and background.  If drawing happens in WM_CTLCOLORBTN,
+    * it will overwrite the contents of the control.  The
+    * fix is draw the group without drawing the background
+    * and avoid the group window proc.
+    */
+    bool redraw = findImageControl () !is null;
+    if (!redraw) {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                redraw = findThemeControl () !is null;
+            }
+        }
+        if (!redraw) redraw = findBackgroundControl () !is null;
+    }
+    if (redraw) {
+        OS.InvalidateRect (handle, null, false);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+        return new LRESULT (code);
+    }
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Invalidate the portion of the group widget that needs to
+    * be redrawn.  Note that for some reason, invalidating the
+    * group from inside WM_SIZE causes pixel corruption for
+    * radio button children.
+    */
+    static if (OS.IsWinCE) return result;
+    if (!OS.IsWindowVisible (handle)) return result;
+    WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+    //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+    if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) !is 0) {
+        return result;
+    }
+    RECT rect;
+    OS.SetRect (&rect, 0, 0, lpwp.cx, lpwp.cy);
+    OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &rect);
+    int newWidth = rect.right - rect.left;
+    int newHeight = rect.bottom - rect.top;
+    OS.GetClientRect (handle, &rect);
+    int oldWidth = rect.right - rect.left;
+    int oldHeight = rect.bottom - rect.top;
+    if (newWidth is oldWidth && newHeight is oldHeight) {
+        return result;
+    }
+    if (newWidth !is oldWidth) {
+        int left = oldWidth;
+        if (newWidth < oldWidth) left = newWidth;
+        OS.SetRect (&rect, left - CLIENT_INSET, 0, newWidth, newHeight);
+        OS.InvalidateRect (handle, &rect, true);
+    }
+    if (newHeight !is oldHeight) {
+        int bottom = oldHeight;
+        if (newHeight < oldHeight) bottom = newHeight;
+        if (newWidth < oldWidth) oldWidth -= CLIENT_INSET;
+        OS.SetRect (&rect, 0, bottom - CLIENT_INSET, oldWidth, newHeight);
+        OS.InvalidateRect (handle, &rect, true);
+    }
+    return result;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/IME.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,583 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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 org.eclipse.swt.widgets.IME;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.internal.win32.WINTYPES;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent input method editors.
+ * These are typically in-line pre-edit text areas that allow
+ * the user to compose characters from Far Eastern languages
+ * such as Japanese, Chinese or Korean.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>ImeComposition</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @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 () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together 
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a canvas control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Canvas parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    createWidget ();
+}
+
+void createWidget () {
+    text = ""; //$NON-NLS-1$
+    startOffset = -1;
+    if (parent.getIME () is null) {
+        parent.setIME (this);
+    }
+}
+
+/**
+ * Returns the offset of the caret from the start of the document.
+ * The caret is within the current composition.
+ *
+ * @return the caret offset
+ *
+ * @exception SWTException <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 int getCaretOffset () {
+    checkWidget ();
+    return startOffset + caretOffset;
+}
+
+/**
+ * Returns the commit count of the composition.  This is the
+ * number of characters that have been composed.  When the
+ * commit count is equal to the length of the composition
+ * text, then the in-line edit operation is complete.
+ * 
+ * @return the commit count
+ *
+ * @exception SWTException <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 IME#getText
+ */
+public int getCommitCount () {
+    checkWidget ();
+    return commitCount;
+}
+
+/**
+ * Returns the offset of the composition from the start of the document.
+ * This is the start offset of the composition within the document and
+ * in not changed by the input method editor itself during the in-line edit
+ * session.
+ *
+ * @return the offset of the composition
+ *
+ * @exception SWTException <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 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 = new TF_DISPLAYATTRIBUTE();
+                    /* 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)cast(void*)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;
+            default:
+        }
+    }
+    return pda;
+}
+
+/**
+ * Returns the ranges for the style that should be applied during the
+ * in-line edit session.
+ * <p>
+ * The ranges array contains start and end pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] and ends at ranges[n+1] uses the style
+ * at styles[n/2] returned by <code>getStyles()</code>.
+ * </p>
+ * @return the ranges for the styles
+ *
+ * @exception SWTException <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 IME#getStyles
+ */
+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;
+}
+
+/**
+ * Returns the styles for the ranges.
+ * <p>
+ * The ranges array contains start and end pairs.  Each pair refers to
+ * the corresponding style in the styles array.  For example, the pair
+ * that starts at ranges[n] and ends at ranges[n+1] uses the style
+ * at styles[n/2].
+ * </p>
+ * 
+ * @return the ranges for the styles
+ *
+ * @exception SWTException <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 IME#getRanges
+ */
+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;
+}
+
+/**
+ * Returns the composition text.
+ * <p>
+ * The text for an IME is the characters in the widget that
+ * are in the current composition. When the commit count is
+ * equal to the length of the composition text, then the
+ * in-line edit operation is complete.
+ * </p>
+ *
+ * @return the widget text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    return text;
+}
+
+/**
+ * Returns <code>true</code> if the caret should be wide, and
+ * <code>false</code> otherwise.  In some languages, for example
+ * Korean, the caret is typically widened to the width of the
+ * current character in the in-line edit session.
+ * 
+ * @return the wide caret state
+ *
+ * @exception SWTException <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 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 (SWT.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;
+}
+
+/**
+ * Sets the offset of the composition from the start of the document.
+ * This is the start offset of the composition within the document and
+ * in not changed by the input method editor itself during the in-line edit
+ * session but may need to be changed by clients of the IME.  For example,
+ * if during an in-line edit operation, a text editor inserts characters
+ * above the IME, then the IME must be informed that the composition
+ * offset has changed.
+ *
+ * @return the offset of the composition
+ *
+ * @exception SWTException <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 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 = SWT.COMPOSITION_SELECTION;
+                    sendEvent (SWT.ImeComposition, event);
+                    startOffset = event.start;
+                }
+                Event event = new Event ();
+                event.detail = SWT.COMPOSITION_CHANGED;
+                event.start = startOffset;
+                event.end = startOffset + text.length;
+                event.text = text = buffer !is null ? TCHARsToStr(buffer) : "";
+                commitCount = text.length ;
+                sendEvent (SWT.ImeComposition, event);
+                String chars = text;
+                text = ""; //$NON-NLS-1$
+                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+=chars.getRelativeCodePointOffset(i,1)) {
+                        dchar c = chars[ i .. $ ].firstCodePoint();
+                        display.lastAscii = c;
+                        event = new Event ();
+                        event.character = c;
+                        parent.sendEvent (SWT.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;
+                                    default:
+                                }
+                                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;
+                                    default:
+                                }
+                                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;
+                                    default:
+                                }
+                                style.underline = attr.lsStyle !is OS.TF_LS_NONE;
+                                switch (attr.lsStyle) {
+                                    case OS.TF_LS_SQUIGGLE:
+                                        style.underlineStyle = SWT.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 : SWT.UNDERLINE_SINGLE;
+                                        break;
+                                    default:
+                                }
+                            }
+                            delete attr;
+                        }
+                    }
+                }
+            }
+            OS.ImmReleaseContext (hwnd, hIMC);
+        }
+        int end = startOffset + text.length;
+        if (startOffset is -1) {
+            Event event = new Event ();
+            event.detail = SWT.COMPOSITION_SELECTION;
+            sendEvent (SWT.ImeComposition, event);
+            startOffset = event.start;
+            end = event.end;
+        }
+        Event event = new Event ();
+        event.detail = SWT.COMPOSITION_CHANGED;
+        event.start = startOffset;
+        event.end = end;
+        event.text = text = buffer !is null ? TCHARsToStr(buffer) : "";
+        sendEvent (SWT.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 = SWT.COMPOSITION_OFFSET;
+                event.x = OS.GET_X_LPARAM (lParam);
+                event.y = OS.GET_Y_LPARAM (lParam);
+                sendEvent (SWT.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;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Item.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Item;
+
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import java.lang.all;
+
+/**
+ * This class is the abstract superclass of all non-windowed
+ * user interface objects that occur within specific controls.
+ * For example, a tree will contain tree items.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Item : Widget {
+    String text;
+    Image image;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of item to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle
+ */
+public this (Widget parent, int style) {
+    super (parent, style);
+    text = "";
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance,
+ * and the index at which to place it in the items maintained
+ * by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of item to construct
+ * @param index the zero-relative index at which to store the receiver in its parent
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#getStyle
+ */
+public this (Widget parent, int style, int index) {
+    this (parent, style);
+}
+
+override protected void checkSubclass () {
+    /* Do Nothing - Subclassing is allowed */
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget ();
+    return image;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget();
+    return text;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    text = null;
+    image = null;
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image image) {
+    checkWidget ();
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    this.image = image;
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    text = string;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Label.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,714 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Label;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a non-selectable
+ * 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>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SEPARATOR, HORIZONTAL, VERTICAL</dd>
+ * <dd>SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
+ * <dd>CENTER, LEFT, RIGHT, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified.
+ * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified.
+ * Only one of CENTER, LEFT and RIGHT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#label">Label snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Label : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.windowProc windowProc;
+
+    String text = "";
+    Image image;
+    static const int MARGIN = 4;
+    static const bool IMAGE_AND_TEXT = false;
+    private static /+const+/ WNDPROC LabelProc;
+    static const TCHAR[] LabelClass = "STATIC\0";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, LabelClass.ptr, &lpWndClass);
+            LabelProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SEPARATOR
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see SWT#SHADOW_IN
+ * @see SWT#SHADOW_OUT
+ * @see SWT#SHADOW_NONE
+ * @see SWT#CENTER
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    style |= SWT.NO_FOCUS;
+    if ((style & SWT.SEPARATOR) !is 0) {
+        style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0);
+        return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0);
+    }
+    return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0, border = getBorderWidth ();
+    if ((style & SWT.SEPARATOR) !is 0) {
+        int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+        if ((style & SWT.HORIZONTAL) !is 0) {
+            width = DEFAULT_WIDTH;  height = lineWidth * 2;
+        } else {
+            width = lineWidth * 2; height = DEFAULT_HEIGHT;
+        }
+        if (wHint !is SWT.DEFAULT) width = wHint;
+        if (hHint !is SWT.DEFAULT) height = hHint;
+        width += border * 2; height += border * 2;
+        return new Point (width, height);
+    }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    bool drawText = true;
+    bool drawImage = (bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW;
+    if (drawImage) {
+        if (image !is null) {
+            Rectangle rect = image.getBounds();
+            width += rect.width;
+            height += rect.height;
+            if (IMAGE_AND_TEXT) {
+                if (text.length !is 0) width += MARGIN;
+            } else {
+                drawText = false;
+            }
+        }
+    }
+    if (drawText) {
+        auto hDC = OS.GetDC (handle);
+        auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        auto oldFont = OS.SelectObject (hDC, newFont);
+        int length = OS.GetWindowTextLength (handle);
+        if (length is 0) {
+            TEXTMETRIC tm;
+            OS.GetTextMetrics (hDC, &tm);
+            height = Math.max (height, tm.tmHeight);
+        } else {
+            RECT rect;
+            int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
+            if ((style & SWT.WRAP) !is 0 && wHint !is SWT.DEFAULT) {
+                flags |= OS.DT_WORDBREAK;
+                rect.right = Math.max (0, wHint - width);
+            }
+            TCHAR[] buffer = new TCHAR [/+getCodePage (),+/ length + 1];
+            OS.GetWindowText (handle, buffer.ptr, length + 1);
+            OS.DrawText (hDC, buffer.ptr, length, &rect, flags);
+            width += rect.right - rect.left;
+            height = Math.max (height, rect.bottom - rect.top);
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    width += border * 2;
+    height += border * 2;
+    /*
+    * Feature in WinCE PPC.  Text labels have a trim
+    * of one pixel wide on the right and left side.
+    * The fix is to increase the width to include
+    * this trim.
+    */
+    if (OS.IsWinCE && !drawImage) width += 2;
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state |= THEME_BACKGROUND;
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>
+ * unless the receiver is a <code>SEPARATOR</code> label, in
+ * which case, <code>NONE</code> is returned.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <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 int getAlignment () {
+    checkWidget ();
+    if ((style & SWT.SEPARATOR) !is 0) return 0;
+    if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+    if ((style & SWT.CENTER) !is 0) return SWT.CENTER;
+    if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+    return SWT.LEFT;
+}
+
+/**
+ * Returns the receiver's image if it has one, or null
+ * if it does not.
+ *
+ * @return the receiver's image
+ *
+ * @exception SWTException <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 Image getImage () {
+    checkWidget ();
+    return image;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set or if the receiver is
+ * a <code>SEPARATOR</code> label.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    if ((style & SWT.SEPARATOR) !is 0) return "";
+    return text;
+}
+
+override bool mnemonicHit (wchar key) {
+    Composite control = this.parent;
+    while (control !is null) {
+        Control [] children = control._getChildren ();
+        int index = 0;
+        while (index < children.length) {
+            if (children [index] is this) break;
+            index++;
+        }
+        index++;
+        if (index < children.length) {
+            if (children [index].setFocus ()) return true;
+        }
+        control = control.parent;
+    }
+    return false;
+}
+
+override bool mnemonicMatch (wchar key) {
+    wchar mnemonic = findMnemonic (getText ());
+    if (mnemonic is '\0') return false;
+    return CharacterToUpper (key) is CharacterToUpper (mnemonic);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    text = null;
+    image = null;
+}
+
+/**
+ * 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>.  If the receiver is a <code>SEPARATOR</code>
+ * label, the argument is ignored and the alignment is not changed.
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <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 setAlignment (int alignment) {
+    checkWidget ();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return;
+    style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) {
+        bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
+        if ((style & SWT.LEFT) !is 0) {
+            if ((style & SWT.WRAP) !is 0) {
+                bits |= OS.SS_LEFT;
+            } else {
+                bits |= OS.SS_LEFTNOWORDWRAP;
+            }
+        }
+        if ((style & SWT.CENTER) !is 0) bits |= OS.SS_CENTER;
+        if ((style & SWT.RIGHT) !is 0) bits |= OS.SS_RIGHT;
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    }
+    OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * Sets the receiver's image to the argument, which may be
+ * null indicating that no image should be displayed.
+ *
+ * @param image the image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image image) {
+    checkWidget ();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    this.image = image;
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) {
+        bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT);
+        bits |= OS.SS_OWNERDRAW;
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    }
+    OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * This method sets the widget label.  The label may include
+ * the mnemonic character and line delimiters.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, focus is assigned
+ * to the control that follows the label. On most platforms,
+ * the mnemonic appears underlined but may be emphasised in a
+ * platform specific manner.  The mnemonic indicator character
+ * '&amp;' can be escaped by doubling it in the string, causing
+ * a single '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extensions allow null argument
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    /*
+    * Feature in Windows.  For some reason, SetWindowText() for
+    * static controls redraws the control, even when the text has
+    * has not changed.  The fix is to check for this case and do
+    * nothing.
+    */
+    if (string.equals(text)) return;
+    text = string;
+    if (image is null || !IMAGE_AND_TEXT) {
+        int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+        newBits &= ~OS.SS_OWNERDRAW;
+        if ((style & SWT.LEFT) !is 0) {
+            if ((style & SWT.WRAP) !is 0) {
+                newBits |= OS.SS_LEFT;
+            } else {
+                newBits |= OS.SS_LEFTNOWORDWRAP;
+            }
+        }
+        if ((style & SWT.CENTER) !is 0) newBits |= OS.SS_CENTER;
+        if ((style & SWT.RIGHT) !is 0) newBits |= OS.SS_RIGHT;
+        if (oldBits !is newBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+    }
+    string = Display.withCrLf (string);
+    TCHAR* buffer = StrToTCHARz ( getCodePage (), string);
+    OS.SetWindowText (handle, buffer);
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the label uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_ERASEBKGND.
+    */
+    if (OS.COMCTL32_MAJOR < 6) {
+        if (findImageControl () !is null) OS.InvalidateRect (handle, null, true);
+    }
+}
+
+override int widgetExtStyle () {
+    int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
+    if ((style & SWT.BORDER) !is 0) return bits | OS.WS_EX_STATICEDGE;
+    return bits;
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.SS_NOTIFY;
+    if ((style & SWT.SEPARATOR) !is 0) return bits | OS.SS_OWNERDRAW;
+    if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
+        if ((style & SWT.WRAP) !is 0) bits |= OS.SS_EDITCONTROL;
+    }
+    if ((style & SWT.CENTER) !is 0) return bits | OS.SS_CENTER;
+    if ((style & SWT.RIGHT) !is 0) return bits | OS.SS_RIGHT;
+    if ((style & SWT.WRAP) !is 0) return bits | OS.SS_LEFT;
+    return bits | OS.SS_LEFTNOWORDWRAP;
+}
+
+override String windowClass () {
+    return TCHARsToStr( LabelClass );
+}
+
+override int windowProc () {
+    return cast(int) LabelProc;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW) {
+        return LRESULT.ONE;
+    }
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the label uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_ERASEBKGND.
+    */
+    if (OS.COMCTL32_MAJOR < 6) {
+        if (findImageControl () !is null) {
+            drawBackground (cast(HANDLE)wParam);
+            return LRESULT.ONE;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (isDisposed ()) return result;
+    if ((style & SWT.SEPARATOR) !is 0) {
+        OS.InvalidateRect (handle, null, true);
+        return result;
+    }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW) {
+        OS.InvalidateRect (handle, null, true);
+        return result;
+    }
+    /*
+    * Bug in Windows.  For some reason, a label with
+    * style SS_LEFT, SS_CENTER or SS_RIGHT does not
+    * redraw the text in the new position when resized.
+    * Note that SS_LEFTNOWORDWRAP does not have the
+    * problem.  The fix is to force the redraw.
+    */
+    if ((bits & OS.SS_LEFTNOWORDWRAP) !is OS.SS_LEFTNOWORDWRAP) {
+        OS.InvalidateRect (handle, null, true);
+        return result;
+    }
+    return result;
+}
+
+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
+    * foreground and background.  If any drawing happens in
+    * WM_CTLCOLORSTATIC, it overwrites the contents of the control.
+    * The fix is draw the static without drawing the background
+    * and avoid the static window proc.
+    */
+    bool redraw = findImageControl () !is null;
+    if (!redraw) {
+        if ((state & THEME_BACKGROUND) !is 0) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                redraw = findThemeControl () !is null;
+            }
+        }
+    }
+    if (redraw) {
+        OS.InvalidateRect (handle, null, false);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+        return new LRESULT (code);
+    }
+    return result;
+}
+
+override LRESULT wmColorChild (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  For some reason, the HBRUSH that
+    * is returned from WM_CTRLCOLOR is misaligned when
+    * the label uses it to draw.  If the brush is a solid
+    * color, this does not matter.  However, if the brush
+    * contains an image, the image is misaligned.  The
+    * fix is to draw the background in WM_ERASEBKGND.
+    */
+    LRESULT result = super.wmColorChild (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) {
+            if (findImageControl () !is null) {
+                OS.SetBkMode ( cast(HANDLE) wParam, OS.TRANSPARENT);
+                return new LRESULT ( cast(int)OS.GetStockObject (OS.NULL_BRUSH));
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    static if (OS.IsWinCE) {
+        bool drawImage = image !is null;
+        bool drawSeparator = (style & SWT.SEPARATOR) !is 0 && (style & SWT.SHADOW_NONE) is 0;
+        if (drawImage || drawSeparator) {
+            LRESULT result = null;
+            PAINTSTRUCT ps;
+            GCData data = new GCData ();
+            data.ps = &ps;
+            data.hwnd = handle;
+            GC gc = new_GC (data);
+            if (gc !is null) {
+                drawBackground (gc.handle);
+                RECT clientRect;
+                OS.GetClientRect (handle, &clientRect);
+                if (drawSeparator) {
+                    RECT rect;
+                    int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+                    int flags = (style & SWT.SHADOW_IN) !is 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED;
+                    if ((style & SWT.HORIZONTAL) !is 0) {
+                        int bottom = clientRect.top + Math.max (lineWidth * 2, (clientRect.bottom - clientRect.top) / 2);
+                        OS.SetRect (&rect, clientRect.left, clientRect.top, clientRect.right, bottom);
+                        OS.DrawEdge (gc.handle, &rect, flags, OS.BF_BOTTOM);
+                    } else {
+                        int right = clientRect.left + Math.max (lineWidth * 2, (clientRect.right - clientRect.left) / 2);
+                        OS.SetRect (&rect, clientRect.left, clientRect.top, right, clientRect.bottom);
+                        OS.DrawEdge (gc.handle, &rect, flags, OS.BF_RIGHT);
+                    }
+                    result = LRESULT.ONE;
+                }
+                if (drawImage) {
+                    Rectangle imageBounds = image.getBounds ();
+                    int x = 0;
+                    if ((style & SWT.CENTER) !is 0) {
+                        x = Math.max (0, (clientRect.right - imageBounds.width) / 2);
+                    } else {
+                        if ((style & SWT.RIGHT) !is 0) {
+                            x = Math.max (0, (clientRect.right - imageBounds.width));
+                        }
+                    }
+                    gc.drawImage (image, x, Math.max (0, (clientRect.bottom - imageBounds.height) / 2));
+                    result = LRESULT.ONE;
+                }
+                int width = ps.rcPaint.right - ps.rcPaint.left;
+                int height = ps.rcPaint.bottom - ps.rcPaint.top;
+                if (width !is 0 && height !is 0) {
+                    Event event = new Event ();
+                    event.gc = gc;
+                    event.x = ps.rcPaint.left;
+                    event.y = ps.rcPaint.top;
+                    event.width = width;
+                    event.height = height;
+                    sendEvent (SWT.Paint, event);
+                    // widget could be disposed at this point
+                    event.gc = null;
+                }
+                gc.dispose ();
+            }
+            return result;
+        }
+    }
+    return super.WM_PAINT(wParam, lParam);
+}
+
+override LRESULT wmDrawChild (int wParam, int lParam) {
+    DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam;
+    drawBackground (struct_.hDC);
+    if ((style & SWT.SEPARATOR) !is 0) {
+        if ((style & SWT.SHADOW_NONE) !is 0) return null;
+        RECT rect;
+        int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER);
+        int flags = (style & SWT.SHADOW_IN) !is 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED;
+        if ((style & SWT.HORIZONTAL) !is 0) {
+            int bottom = struct_.rcItem.top + Math.max (lineWidth * 2, (struct_.rcItem.bottom - struct_.rcItem.top) / 2);
+            OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, struct_.rcItem.right, bottom);
+            OS.DrawEdge (struct_.hDC, &rect, flags, OS.BF_BOTTOM);
+        } else {
+            int right = struct_.rcItem.left + Math.max (lineWidth * 2, (struct_.rcItem.right - struct_.rcItem.left) / 2);
+            OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, right, struct_.rcItem.bottom);
+            OS.DrawEdge (struct_.hDC, &rect, flags, OS.BF_RIGHT);
+        }
+    } else {
+        int width = struct_.rcItem.right - struct_.rcItem.left;
+        int height = struct_.rcItem.bottom - struct_.rcItem.top;
+        if (width !is 0 && height !is 0) {
+            bool drawImage = image !is null;
+            bool drawText = IMAGE_AND_TEXT && text.length !is 0;
+            int margin = drawText && drawImage ? MARGIN : 0;
+            int imageWidth = 0, imageHeight = 0;
+            if (drawImage) {
+                Rectangle rect = image.getBounds ();
+                imageWidth = rect.width;
+                imageHeight = rect.height;
+            }
+            RECT rect;
+            TCHAR* buffer = null;
+            int textWidth = 0, textHeight = 0, flags = 0;
+            if (drawText) {
+                //rect = new RECT ();
+                flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS;
+                if ((style & SWT.LEFT) !is 0) flags |= OS.DT_LEFT;
+                if ((style & SWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                if ((style & SWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
+                if ((style & SWT.WRAP) !is 0) {
+                    flags |= OS.DT_WORDBREAK;
+                    rect.right = Math.max (0, width - imageWidth - margin);
+                }
+                buffer = StrToTCHARz (/+getCodePage (),+/ text);
+                OS.DrawText (struct_.hDC, buffer, -1, &rect, flags);
+                textWidth = rect.right - rect.left;
+                textHeight = rect.bottom - rect.top;
+            }
+            int x = 0;
+            if ((style & SWT.CENTER) !is 0) {
+                x = Math.max (0, (width - imageWidth - textWidth - margin) / 2);
+            } else {
+                if ((style & SWT.RIGHT) !is 0) {
+                    x = width - imageWidth - textWidth - margin;
+                }
+            }
+            if (drawImage) {
+                GCData data = new GCData();
+                data.device = display;
+                GC gc = GC.win32_new (struct_.hDC, data);
+                Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE);
+                gc.drawImage (image, x, Math.max (0, (height - imageHeight) / 2));
+                if (image !is this.image) image.dispose ();
+                gc.dispose ();
+                x += imageWidth + margin;
+            }
+            if (drawText) {
+                flags &= ~OS.DT_CALCRECT;
+                rect.left = x;
+                rect.right += rect.left;
+                rect.top = Math.max (0, (height - textHeight) / 2);
+                rect.bottom += rect.top;
+                OS.DrawText (struct_.hDC, buffer, -1, &rect, flags);
+            }
+        }
+    }
+    return null;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Layout.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Layout;
+
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A layout controls the position and size
+ * of the children of a composite widget.
+ * This class is the abstract base class for
+ * layouts.
+ *
+ * @see Composite#setLayout(Layout)
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public abstract class Layout {
+
+/**
+ * Computes and returns the size of the specified
+ * composite's client area according to this layout.
+ * <p>
+ * This method computes the size that the client area
+ * of the composite must be in order to position all
+ * children at their preferred size inside the
+ * composite according to the layout algorithm
+ * encoded by this layout.
+ * </p>
+ * <p>
+ * When a width or height hint is supplied, it is
+ * used to constrain the result. For example, if a
+ * width hint is provided that is less than the
+ * width of the client area, the layout may choose
+ * to wrap and increase height, clip, overlap, or
+ * otherwise constrain the children.
+ * </p>
+ *
+ * @param composite a composite widget using this layout
+ * @param wHint width (<code>SWT.DEFAULT</code> for preferred size)
+ * @param hHint height (<code>SWT.DEFAULT</code> for preferred size)
+ * @param flushCache <code>true</code> means flush cached layout values
+ * @return a point containing the computed size (width, height)
+ *
+ * @see #layout
+ * @see Control#getBorderWidth
+ * @see Control#getBounds
+ * @see Control#getSize
+ * @see Control#pack(boolean)
+ * @see "computeTrim, getClientArea for controls that implement them"
+ */
+abstract Point computeSize (Composite composite, int wHint, int hHint, bool flushCache);
+
+/**
+ * Instruct the layout to flush any cached values
+ * associated with the control specified in the argument
+ * <code>control</code>.
+ *
+ * @param control a control managed by this layout
+ * @return true if the Layout has flushed all cached information associated with control
+ *
+ * @since 3.1
+ */
+bool flushCache (Control control) {
+    return false;
+}
+
+/**
+ * Lays out the children of the specified composite
+ * according to this layout.
+ * <p>
+ * This method positions and sizes the children of a
+ * composite using the layout algorithm encoded by this
+ * layout. Children of the composite are positioned in
+ * the client area of the composite. The position of
+ * the composite is not altered by this method.
+ * </p>
+ * <p>
+ * When the flush cache hint is true, the layout is
+ * instructed to flush any cached values associated
+ * with the children. Typically, a layout will cache
+ * the preferred sizes of the children to avoid the
+ * expense of computing these values each time the
+ * widget is laid out.
+ * </p>
+ * <p>
+ * When layout is triggered explicitly by the programmer
+ * the flush cache hint is true. When layout is triggered
+ * by a resize, either caused by the programmer or by the
+ * user, the hint is false.
+ * </p>
+ *
+ * @param composite a composite widget using this layout
+ * @param flushCache <code>true</code> means flush cached layout values
+ */
+abstract void layout (Composite composite, bool flushCache);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Link.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1073 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Link;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.accessibility.ACC;
+import org.eclipse.swt.accessibility.Accessible;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlAdapter;
+import org.eclipse.swt.accessibility.AccessibleControlEvent;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+static import tango.text.Text;
+alias tango.text.Text.Text!(char) StringBuffer;
+
+/**
+ * Instances of this class represent a selectable
+ * user interface object that displays a text with
+ * links.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#link">Link snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.1
+ */
+public class Link : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.windowProc windowProc;
+
+    String text;
+    TextLayout layout;
+    Color linkColor, disabledColor;
+    Point [] offsets;
+    Point selection;
+    String [] ids;
+    int [] mnemonics;
+    int focusIndex, mouseDownIndex;
+    HFONT font;
+    static /+const+/ RGB LINK_FOREGROUND;
+    static /+const+/ WNDPROC LinkProc;
+    static const TCHAR[] LinkClass = OS.WC_LINK;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            LINK_FOREGROUND = new RGB (0, 51, 153);
+            if (OS.COMCTL32_MAJOR >= 6) {
+                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 SWT, 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;
+            }
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, style);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the control is selected by the user.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection, typedListener);
+    addListener (SWT.DefaultSelection, typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    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);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0;
+    if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0;
+    int width, height;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        auto hDC = OS.GetDC (handle);
+        auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        auto oldFont = OS.SelectObject (hDC, newFont);
+        if (text.length > 0) {
+            TCHAR[] buffer = StrToTCHARs (getCodePage (), parse (text));
+            RECT rect;
+            int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+            if (wHint !is SWT.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;
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    } else {
+        int layoutWidth = layout.getWidth ();
+        //TEMPORARY CODE
+        if (wHint is 0) {
+            layout.setWidth (1);
+            Rectangle rect = layout.getBounds ();
+            width = 0;
+            height = rect.height;
+        } else {
+            layout.setWidth (wHint);
+            Rectangle rect = layout.getBounds ();
+            width = rect.width;
+            height = rect.height;
+        }
+        layout.setWidth (layoutWidth);
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2;
+    height += border * 2;
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state |= THEME_BACKGROUND;
+    if (OS.COMCTL32_MAJOR < 6) {
+        layout = new TextLayout (display);
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+            linkColor = Color.win32_new (display, OS.GetSysColor (OS.COLOR_HOTLIGHT));
+        } else {
+            linkColor = new Color (display, LINK_FOREGROUND);
+        }
+        disabledColor = Color.win32_new (display, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+        offsets = new Point [0];
+        ids = new String [0];
+        mnemonics = new int [0];
+        selection = new Point (-1, -1);
+        focusIndex = mouseDownIndex = -1;
+    }
+}
+
+override void createWidget () {
+    super.createWidget ();
+    text = "";
+    if (OS.COMCTL32_MAJOR < 6) {
+        if ((style & SWT.MIRRORED) !is 0) {
+            layout.setOrientation (SWT.RIGHT_TO_LEFT);
+        }
+        initAccessible ();
+    }
+}
+
+void drawWidget (GC gc, RECT* rect) {
+    drawBackground (gc.handle, rect);
+    int selStart = selection.x;
+    int selEnd = selection.y;
+    if (selStart > selEnd) {
+        selStart = selection.y;
+        selEnd = selection.x;
+    }
+    // temporary code to disable text selection
+    selStart = selEnd = -1;
+    if (!OS.IsWindowEnabled (handle)) gc.setForeground (disabledColor);
+    layout.draw (gc, 0, 0, selStart, selEnd, null, null);
+    if (hasFocus () && focusIndex !is -1) {
+        Rectangle [] rects = getRectangles (focusIndex);
+        for (int i = 0; i < rects.length; i++) {
+            Rectangle rectangle = rects [i];
+            gc.drawFocus (rectangle.x, rectangle.y, rectangle.width, rectangle.height);
+        }
+    }
+    if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+        Event event = new Event ();
+        event.gc = gc;
+        event.x = rect.left;
+        event.y = rect.top;
+        event.width = rect.right - rect.left;
+        event.height = rect.bottom - rect.top;
+        sendEvent (SWT.Paint, event);
+        event.gc = null;
+    }
+}
+
+override void enableWidget (bool enabled) {
+    if (OS.COMCTL32_MAJOR >= 6) {
+        LITEM item;
+        item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+        item.stateMask = OS.LIS_ENABLED;
+        item.state = enabled ? OS.LIS_ENABLED : 0;
+        while (OS.SendMessage (handle, OS.LM_SETITEM, 0, &item) !is 0) {
+            item.iLink++;
+        }
+    } else {
+        TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
+        linkStyle.underline = true;
+        for (int i = 0; i < offsets.length; i++) {
+            Point point = offsets [i];
+            layout.setStyle (linkStyle, point.x, point.y);
+        }
+        redraw ();
+    }
+    /*
+    * Feature in Windows.  For some reason, setting
+    * LIS_ENABLED state using LM_SETITEM causes the
+    * SysLink to become enabled.  To be specific,
+    * calling IsWindowEnabled() returns true.  The
+    * fix is disable the SysLink after LM_SETITEM.
+    */
+    super.enableWidget (enabled);
+}
+
+void initAccessible () {
+    Accessible accessible = getAccessible ();
+    accessible.addAccessibleListener (new class() AccessibleAdapter {
+        public void getName (AccessibleEvent e) {
+            e.result = parse (text);
+        }
+    });
+
+    accessible.addAccessibleControlListener (new class() AccessibleControlAdapter {
+        public void getChildAtPoint (AccessibleControlEvent e) {
+            e.childID = ACC.CHILDID_SELF;
+        }
+
+        public void getLocation (AccessibleControlEvent e) {
+            Rectangle rect = display.map (getParent (), null, getBounds ());
+            e.x = rect.x;
+            e.y = rect.y;
+            e.width = rect.width;
+            e.height = rect.height;
+        }
+
+        public void getChildCount (AccessibleControlEvent e) {
+            e.detail = 0;
+        }
+
+        public void getRole (AccessibleControlEvent e) {
+            e.detail = ACC.ROLE_LINK;
+        }
+
+        public void getState (AccessibleControlEvent e) {
+            e.detail = ACC.STATE_FOCUSABLE;
+            if (hasFocus ()) e.detail |= ACC.STATE_FOCUSED;
+        }
+
+        public void getDefaultAction (AccessibleControlEvent e) {
+            e.result = SWT.getMessage ("SWT_Press"); //$NON-NLS-1$
+        }
+
+        public void getSelection (AccessibleControlEvent e) {
+            if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
+        }
+
+        public void getFocus (AccessibleControlEvent e) {
+            if (hasFocus ()) e.childID = ACC.CHILDID_SELF;
+        }
+    });
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+Rectangle [] getRectangles (int linkIndex) {
+    int lineCount = layout.getLineCount ();
+    Rectangle [] rects = new Rectangle [lineCount];
+    int [] lineOffsets = layout.getLineOffsets ();
+    Point point = offsets [linkIndex];
+    int lineStart = 1;
+    while (point.x > lineOffsets [lineStart]) lineStart++;
+    int lineEnd = 1;
+    while (point.y > lineOffsets [lineEnd]) lineEnd++;
+    int index = 0;
+    if (lineStart is lineEnd) {
+        rects [index++] = layout.getBounds (point.x, point.y);
+    } else {
+        rects [index++] = layout.getBounds (point.x, lineOffsets [lineStart]-1);
+        rects [index++] = layout.getBounds (lineOffsets [lineEnd-1], point.y);
+        if (lineEnd - lineStart > 1) {
+            for (int i = lineStart; i < lineEnd - 1; i++) {
+                rects [index++] = layout.getLineBounds (i);
+            }
+        }
+    }
+    if (rects.length !is index) {
+        Rectangle [] tmp = new Rectangle [index];
+        System.arraycopy (rects, 0, tmp, 0, index);
+        rects = tmp;
+    }
+    return rects;
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    return text;
+}
+
+String parse (String string) {
+    int length_ = string.length;
+    offsets = new Point [length_ / 4];
+    ids = new String [length_ / 4];
+    mnemonics = new int [length_ / 4 + 1];
+    StringBuffer result = new StringBuffer ();
+    char [] buffer = new char [length_];
+    string.getChars (0, string.length, buffer, 0);
+    int index = 0, state = 0, linkIndex = 0;
+    int start = 0, tagStart = 0, linkStart = 0, endtagStart = 0, refStart = 0;
+
+    while (index < length_) {
+
+        // instead Character.toLower
+        // only needed for the control symbols, which are always ascii
+        char c = buffer[index];
+        if( c >= 'A' && c <= 'Z' ){
+            c -= ( 'A' - 'a' );
+        }
+
+        // only simple ascii whitespace needed
+        bool isWhitespace(char w ){
+            switch(w){
+                case ' ': return true;
+                default : return false;
+            }
+        }
+
+        switch (state) {
+            case 0:
+                if (c is '<') {
+                    tagStart = index;
+                    state++;
+                }
+                break;
+            case 1:
+                if (c is 'a') state++;
+                break;
+            case 2:
+                switch (c) {
+                    case 'h':
+                        state = 7;
+                        break;
+                    case '>':
+                        linkStart = index  + 1;
+                        state++;
+                        break;
+                    default:
+                        if (isWhitespace(c)) break;
+                        else state = 13;
+                }
+                break;
+            case 3:
+                if (c is '<') {
+                    endtagStart = index;
+                    state++;
+                }
+                break;
+            case 4:
+                state = c is '/' ? state + 1 : 3;
+                break;
+            case 5:
+                state = c is 'a' ? state + 1 : 3;
+                break;
+            case 6:
+                if (c is '>') {
+                    mnemonics [linkIndex] = parseMnemonics (buffer, start, tagStart, result);
+                    int offset = result.length;
+                    parseMnemonics (buffer, linkStart, endtagStart, result);
+                    offsets [linkIndex] = new Point (offset, result.length - 1);
+                    if (ids [linkIndex] is null) {
+                        ids [linkIndex] = buffer[ linkStart .. endtagStart ].dup;
+                    }
+                    linkIndex++;
+                    start = tagStart = linkStart = endtagStart = refStart = index + 1;
+                    state = 0;
+                } else {
+                    state = 3;
+                }
+                break;
+            case 7:
+                state = c is 'r' ? state + 1 : 0;
+                break;
+            case 8:
+                state = c is 'e' ? state + 1 : 0;
+                break;
+            case 9:
+                state = c is 'f' ? state + 1 : 0;
+                break;
+            case 10:
+                state = c is '=' ? state + 1 : 0;
+                break;
+            case 11:
+                if (c is '"') {
+                    state++;
+                    refStart = index + 1;
+                } else {
+                    state = 0;
+                }
+                break;
+            case 12:
+                if (c is '"') {
+                    ids[linkIndex] = buffer[ refStart .. index ].dup;
+                    state = 2;
+                }
+                break;
+            case 13:
+                if (isWhitespace (c)) {
+                    state = 0;
+                } else if (c is '='){
+                    state++;
+                }
+                break;
+            case 14:
+                state = c is '"' ? state + 1 : 0;
+                break;
+            case 15:
+                if (c is '"') state = 2;
+                break;
+            default:
+                state = 0;
+                break;
+        }
+        index++;
+    }
+    if (start < length_) {
+        int tmp = parseMnemonics (buffer, start, tagStart, result);
+        int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length_, result);
+        if (mnemonic is -1) mnemonic = tmp;
+        mnemonics [linkIndex] = mnemonic;
+    } else {
+        mnemonics [linkIndex] = -1;
+    }
+    if (offsets.length !is linkIndex) {
+        Point [] newOffsets = new Point [linkIndex];
+        System.arraycopy (offsets, 0, newOffsets, 0, linkIndex);
+        offsets = newOffsets;
+        String [] newIDs = new String [linkIndex];
+        System.arraycopy (ids, 0, newIDs, 0, linkIndex);
+        ids = newIDs;
+        int [] newMnemonics = new int [linkIndex + 1];
+        System.arraycopy (mnemonics, 0, newMnemonics, 0, linkIndex + 1);
+        mnemonics = newMnemonics;
+    }
+    return result.toString ();
+}
+
+int parseMnemonics (char[] buffer, int start, int end, StringBuffer result) {
+    int mnemonic = -1, index = start;
+    while (index < end) {
+        if (buffer [index] is '&') {
+            if (index + 1 < end && buffer [index + 1] is '&') {
+                result.append (buffer [index]);
+                index++;
+            } else {
+                mnemonic = result.length();
+            }
+        } else {
+            result.append (buffer [index]);
+        }
+        index++;
+    }
+    return mnemonic;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (layout !is null) layout.dispose ();
+    layout = null;
+    if (linkColor !is null) linkColor.dispose ();
+    linkColor = null;
+    disabledColor = null;
+    offsets = null;
+    ids = null;
+    mnemonics = null;
+    text = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+/**
+ * Sets the receiver's text.
+ * <p>
+ * The string can contain both regular text and hyperlinks.  A hyperlink
+ * is delimited by an anchor tag, &lt;A&gt; and &lt;/A&gt;.  Within an
+ * anchor, a single HREF attribute is supported.  When a hyperlink is
+ * selected, the text field of the selection event contains either the
+ * text of the hyperlink or the value of its HREF, if one was specified.
+ * In the rare case of identical hyperlinks within the same string, the
+ * HREF tag can be used to distinguish between them.  The string may
+ * include the mnemonic character and line delimiters.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (string.equals (text)) return;
+    text = string;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        bool enabled = cast(bool) OS.IsWindowEnabled (handle);
+        /*
+        * Bug in Windows.  For some reason, when SetWindowText()
+        * is used to set the text of a link control to the empty
+        * string, the old text remains.  The fix is to set the
+        * text to a space instead.
+        */
+        if (string.length is 0) string = " ";  //$NON-NLS-1$
+        TCHAR* buffer = StrToTCHARz (getCodePage (), string);
+        OS.SetWindowText (handle, buffer);
+        parse (text);
+        enableWidget (enabled);
+    } else {
+        layout.setText (parse (text));
+        focusIndex = offsets.length > 0 ? 0 : -1;
+        selection.x = selection.y = -1;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if (offsets.length > 0) {
+            bits |= OS.WS_TABSTOP;
+        } else {
+            bits &= ~OS.WS_TABSTOP;
+        }
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        bool enabled = cast(bool) OS.IsWindowEnabled (handle);
+        TextStyle linkStyle = new TextStyle (null, enabled ? linkColor : disabledColor, null);
+        linkStyle.underline = true;
+        for (int i = 0; i < offsets.length; i++) {
+            Point point = offsets [i];
+            layout.setStyle (linkStyle, point.x, point.y);
+        }
+        TextStyle mnemonicStyle = new TextStyle (null, null, null);
+        mnemonicStyle.underline = true;
+        for (int i = 0; i < mnemonics.length; i++) {
+            int mnemonic  = mnemonics [i];
+            if (mnemonic !is -1) {
+                layout.setStyle (mnemonicStyle, mnemonic, mnemonic);
+            }
+        }
+        redraw ();
+    }
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle ();
+    return bits | OS.WS_TABSTOP;
+}
+
+override String windowClass () {
+    return OS.COMCTL32_MAJOR >= 6 ? TCHARsToStr(LinkClass) : display.windowClass();
+}
+
+override int windowProc () {
+    return LinkProc !is null ? cast(int)LinkProc : display.windowProc();
+}
+
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+    if (OS.COMCTL32_MAJOR < 6) {
+        if (focusIndex is -1) return result;
+        switch (wParam) {
+            case ' ':
+            case SWT.CR:
+                Event event = new Event ();
+                event.text = ids [focusIndex];
+                sendEvent (SWT.Selection, event);
+                break;
+            case SWT.TAB:
+                bool next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
+                if (next) {
+                    if (focusIndex < offsets.length - 1) {
+                        focusIndex++;
+                        redraw ();
+                    }
+                } else {
+                    if (focusIndex > 0) {
+                        focusIndex--;
+                        redraw ();
+                    }
+                }
+                break;
+            default:
+        }
+    } else {
+        switch (wParam) {
+            case ' ':
+            case SWT.CR:
+            case SWT.TAB:
+                /*
+                * NOTE: Call the window proc with WM_KEYDOWN rather than WM_CHAR
+                * so that the key that was ignored during WM_KEYDOWN is processed.
+                * This allows the application to cancel an operation that is normally
+                * performed in WM_KEYDOWN from WM_CHAR.
+                */
+                int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                return new LRESULT (code);
+            default:
+        }
+
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+    int index, count;
+    int /*long*/ code = 0;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        LITEM item;
+        item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
+        item.stateMask = OS.LIS_FOCUSED;
+        index = 0;
+        while (OS.SendMessage (handle, OS.LM_GETITEM, 0, &item) !is 0) {
+            if ((item.state & OS.LIS_FOCUSED) !is 0) {
+                index = item.iLink;
+            }
+            item.iLink++;
+        }
+        count = item.iLink;
+        code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+    } else {
+        index = focusIndex;
+        count = offsets.length;
+    }
+    if (count is 0) {
+        return new LRESULT (code | OS.DLGC_STATIC);
+    }
+    bool next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
+    if (next && index < count - 1) {
+        return new LRESULT (code | OS.DLGC_WANTTAB);
+    }
+    if (!next && index > 0) {
+        return new LRESULT (code | OS.DLGC_WANTTAB);
+    }
+    return result;
+}
+
+override LRESULT WM_GETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_GETFONT (wParam, lParam);
+    if (result !is null) return result;
+    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);
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        switch (wParam) {
+            case OS.VK_SPACE:
+            case OS.VK_RETURN:
+            case OS.VK_TAB:
+                /*
+                * Ensure that the window proc does not process VK_SPACE,
+                * VK_RETURN or VK_TAB 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;
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) redraw ();
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    if (OS.COMCTL32_MAJOR < 6) {
+        if (focusIndex !is -1) setFocus ();
+        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;
+        selection.x = offset;
+        selection.y = -1;
+        if (oldSelectionX !is -1 && oldSelectionY !is -1) {
+            if (oldSelectionX > oldSelectionY) {
+                int temp = oldSelectionX;
+                oldSelectionX = oldSelectionY;
+                oldSelectionY = temp;
+            }
+            Rectangle rect = layout.getBounds (oldSelectionX, oldSelectionY);
+            redraw (rect.x, rect.y, rect.width, rect.height, false);
+        }
+        for (int j = 0; j < offsets.length; j++) {
+            Rectangle [] rects = getRectangles (j);
+            for (int i = 0; i < rects.length; i++) {
+                Rectangle rect = rects [i];
+                if (rect.contains (x, y)) {
+                    if (j !is focusIndex) {
+                        redraw ();
+                    }
+                    focusIndex = mouseDownIndex = j;
+                    return result;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    if (OS.COMCTL32_MAJOR < 6) {
+        if (mouseDownIndex is -1) return result;
+        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];
+            if (rect.contains (x, y)) {
+                Event event = new Event ();
+                event.text = ids [mouseDownIndex];
+                sendEvent (SWT.Selection, event);
+                break;
+            }
+        }
+    }
+    mouseDownIndex = -1;
+    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 = 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);
+            if (selection.y !is oldSelection) {
+                int newSelection = selection.y;
+                if (oldSelection > newSelection) {
+                    int temp = oldSelection;
+                    oldSelection = newSelection;
+                    newSelection = temp;
+                }
+                Rectangle rect = layout.getBounds (oldSelection, newSelection);
+                redraw (rect.x, rect.y, rect.width, rect.height, false);
+            }
+        } else {
+            for (int j = 0; j < offsets.length; j++) {
+                Rectangle [] rects = getRectangles (j);
+                for (int i = 0; i < rects.length; i++) {
+                    Rectangle rect = rects [i];
+                    if (rect.contains (x, y)) {
+                        setCursor (display.getSystemCursor (SWT.CURSOR_HAND));
+                        return result;
+                    }
+                }
+            }
+            setCursor (null);
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    if (OS.COMCTL32_MAJOR >= 6) {
+        return super.WM_PAINT (wParam, lParam);
+    }
+    PAINTSTRUCT ps;
+    GCData data = new GCData ();
+    data.ps = &ps;
+    data.hwnd = handle;
+    GC gc = new_GC (data);
+    if (gc !is null) {
+        int width = ps.rcPaint.right - ps.rcPaint.left;
+        int height = ps.rcPaint.bottom - ps.rcPaint.top;
+        if (width !is 0 && height !is 0) {
+            RECT rect;
+            OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+            drawWidget (gc, &rect);
+        }
+        gc.dispose ();
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) {
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        GCData data = new GCData ();
+        data.device = display;
+        data.foreground = getForegroundPixel ();
+        GC gc = GC.win32_new (cast(HANDLE)wParam, data);
+        drawWidget (gc, &rect);
+        gc.dispose ();
+    }
+    return result;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) redraw ();
+    return result;
+}
+
+override LRESULT WM_SETFONT (int wParam, int lParam) {
+    if (OS.COMCTL32_MAJOR < 6) {
+        layout.setFont (Font.win32_new (display, cast(HANDLE)wParam));
+    }
+    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) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (OS.COMCTL32_MAJOR < 6) {
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        layout.setWidth (rect.right > 0 ? rect.right : -1);
+        redraw ();
+    }
+    return result;
+}
+
+override LRESULT wmColorChild (int wParam, int lParam) {
+    LRESULT result = super.wmColorChild (wParam, lParam);
+    /*
+    * Feature in Windows.  When a SysLink is disabled, it does
+    * not gray out the non-link portion of the text.  The fix
+    * is to set the text color to the system gray color.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (!OS.IsWindowEnabled (handle)) {
+            OS.SetTextColor (cast(HANDLE)wParam, OS.GetSysColor (OS.COLOR_GRAYTEXT));
+            if (result is null) {
+                int backPixel = getBackgroundPixel ();
+                OS.SetBkColor (cast(HANDLE)wParam, backPixel);
+                auto hBrush = findBrush (backPixel, OS.BS_SOLID);
+                return new LRESULT ( cast(int) hBrush);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    if (OS.COMCTL32_MAJOR >= 6) {
+        switch (hdr.code) {
+            case OS.NM_RETURN:
+            case OS.NM_CLICK:
+                NMLINK* item = cast(NMLINK*)lParam;
+                //OS.MoveMemory (item, lParam, NMLINK.sizeof);
+                Event event = new Event ();
+                event.text = ids [item.item.iLink];
+                sendEvent (SWT.Selection, event);
+                break;
+            default:
+        }
+    }
+    return super.wmNotifyChild (hdr, wParam, lParam);
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/List.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1732 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.List;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface
+ * object that displays a list of strings and issues notification
+ * when a string is selected.  A list may be single or multi select.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SINGLE, MULTI</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of SINGLE and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#list">List snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class List : Scrollable {
+
+    alias Scrollable.computeSize computeSize;
+    alias Scrollable.windowProc windowProc;
+
+    static const int INSET = 3;
+    private static /+const+/ WNDPROC ListProc;
+    static const TCHAR[] ListClass = "LISTBOX";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ListClass.ptr, &lpWndClass);
+            ListProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+/**
+ * Adds the argument to the end of the receiver's list.
+ *
+ * @param string the new item
+ *
+ * @exception SWTException <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 #add(String,int)
+ */
+public void add (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TCHAR* buffer = StrToTCHARz ( getCodePage (), string);
+    int result = OS.SendMessage (handle, OS.LB_ADDSTRING, 0, buffer);
+    if (result is OS.LB_ERR) error (SWT.ERROR_ITEM_NOT_ADDED);
+    if (result is OS.LB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+/**
+ * Adds the argument to the receiver's list at the given
+ * zero-relative index.
+ * <p>
+ * Note: To add an item at the end of the list, use the
+ * result of calling <code>getItemCount()</code> as the
+ * index or use <code>add(String)</code>.
+ * </p>
+ *
+ * @param string the new item
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 #add(String)
+ */
+public void add (String string, int index) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (index is -1) error (SWT.ERROR_INVALID_RANGE);
+    TCHAR* buffer = StrToTCHARz(getCodePage (), string);
+    int result = OS.SendMessage (handle, OS.LB_INSERTSTRING, index, buffer);
+    if (result is OS.LB_ERRSPACE) error (SWT.ERROR_ITEM_NOT_ADDED);
+    if (result is OS.LB_ERR) {
+        int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+        if (0 <= index && index <= count) {
+            error (SWT.ERROR_ITEM_NOT_ADDED);
+        } else {
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+    }
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the selection changes.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    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;
+        }
+        default:
+    }
+    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;
+        }
+        default:
+    }
+    return code;
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if (wHint is SWT.DEFAULT) {
+        if ((style & SWT.H_SCROLL) !is 0) {
+            width = OS.SendMessage (handle, OS.LB_GETHORIZONTALEXTENT, 0, 0);
+            width -= INSET;
+        } else {
+            int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+            HFONT newFont, oldFont;
+            auto hDC = OS.GetDC (handle);
+            newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+            if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+            RECT rect;
+            int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+            int cp = getCodePage ();
+            TCHAR[] buffer = NewTCHARs (cp, 64 + 1);
+            for (int i=0; i<count; i++) {
+                int length = OS.SendMessage (handle, OS.LB_GETTEXTLEN, i, 0);
+                if (length !is OS.LB_ERR) {
+                    if (length + 1 > buffer.length) {
+                        buffer = NewTCHARs (cp, length + 1);
+                    }
+                    int result = OS.SendMessage (handle, OS.LB_GETTEXT, i, buffer.ptr);
+                    if (result !is OS.LB_ERR) {
+                        OS.DrawText (hDC, buffer.ptr, length, &rect, flags);
+                        width = Math.max (width, rect.right - rect.left);
+                    }
+                }
+            }
+            if (newFont !is null) OS.SelectObject (hDC, oldFont);
+            OS.ReleaseDC (handle, hDC);
+        }
+    }
+    if (hHint is SWT.DEFAULT) {
+        int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+        int itemHeight = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+        height = count * itemHeight;
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2 + INSET;
+    height += border * 2;
+    if ((style & SWT.V_SCROLL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    }
+    return new Point (width, height);
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected.  If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception SWTException <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 deselect (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (indices.length is 0) return;
+    if ((style & SWT.SINGLE) !is 0) {
+        int oldIndex = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (oldIndex is OS.LB_ERR) return;
+        for (int i=0; i<indices.length; i++) {
+            if (oldIndex is indices [i]) {
+                OS.SendMessage (handle, OS.LB_SETCURSEL, -1, 0);
+                return;
+            }
+        }
+        return;
+    }
+    for (int i=0; i<indices.length; i++) {
+        int index = indices [i];
+        if (index !is -1) {
+            OS.SendMessage (handle, OS.LB_SETSEL, 0, index);
+        }
+    }
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException <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 deselect (int index) {
+    checkWidget ();
+    if (index is -1) return;
+    if ((style & SWT.SINGLE) !is 0) {
+        int oldIndex = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (oldIndex is OS.LB_ERR) return;
+        if (oldIndex is index) OS.SendMessage (handle, OS.LB_SETCURSEL, -1, 0);
+        return;
+    }
+    OS.SendMessage (handle, OS.LB_SETSEL, 0, index);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected.  If the item at the index
+ * was not selected, it remains deselected.  The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @exception SWTException <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 deselect (int start, int end) {
+    checkWidget ();
+    if (start > end) return;
+    if ((style & SWT.SINGLE) !is 0) {
+        int oldIndex = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (oldIndex is OS.LB_ERR) return;
+        if (start <= oldIndex && oldIndex <= end) {
+            OS.SendMessage (handle, OS.LB_SETCURSEL, -1, 0);
+        }
+        return;
+    }
+    /*
+    * Ensure that at least one item is contained in
+    * the range from start to end.  Note that when
+    * start = end, LB_SELITEMRANGEEX deselects the
+    * item.
+    */
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (start < 0 && end < 0) return;
+    if (start >= count && end >= count) return;
+    start = Math.min (count - 1, Math.max (0, start));
+    end = Math.min (count - 1, Math.max (0, end));
+    OS.SendMessage (handle, OS.LB_SELITEMRANGEEX, end, start);
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @exception SWTException <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 deselectAll () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        OS.SendMessage (handle, OS.LB_SETCURSEL, -1, 0);
+    } else {
+        OS.SendMessage (handle, OS.LB_SETSEL, 0, -1);
+    }
+}
+
+/**
+ * Returns the zero-relative index of the item which currently
+ * has the focus in the receiver, or -1 if no item has focus.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException <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 int getFocusIndex () {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+    if (result is 0) {
+        int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+        if (count is 0) return -1;
+    }
+    return result;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 String getItem (int index) {
+    checkWidget ();
+    int length_ = OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+    if (length_ !is OS.LB_ERR) {
+        TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
+        int result = OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer.ptr);
+        if (result !is OS.LB_ERR) return TCHARsToStr( buffer[0 .. length_] );
+    }
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (0 <= index && index < count) error (SWT.ERROR_CANNOT_GET_ITEM);
+    error (SWT.ERROR_INVALID_RANGE);
+    return "";
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (result is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_COUNT);
+    return result;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the list.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException <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 int getItemHeight () {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+    if (result is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_ITEM_HEIGHT);
+    return result;
+}
+
+/**
+ * Returns a (possibly empty) array of <code>String</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver's list
+ *
+ * @exception SWTException <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 String [] getItems () {
+    checkWidget ();
+    int count = getItemCount ();
+    String [] result = new String [count];
+    for (int i=0; i<count; i++) result [i] = getItem (i);
+    return result;
+}
+
+/**
+ * Returns an array of <code>String</code>s that are currently
+ * selected in the receiver.  The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @exception SWTException <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 String [] getSelection () {
+    checkWidget ();
+    int [] indices = getSelectionIndices ();
+    String [] result = new String [indices.length];
+    for (int i=0; i<indices.length; i++) {
+        result [i] = getItem (indices [i]);
+    }
+    return result;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @exception SWTException <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 int getSelectionCount () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        int result = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (result is OS.LB_ERR) return 0;
+        return 1;
+    }
+    int result = OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+    if (result is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_COUNT);
+    return result;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item or -1
+ *
+ * @exception SWTException <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 int getSelectionIndex () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        return OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+    }
+    int count = OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+    if (count is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    if (count is 0) return -1;
+    int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+    int result = OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+    if (result is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    if (result !is 0) return index;
+    int buffer;
+    result = OS.SendMessage (handle, OS.LB_GETSELITEMS, 1, &buffer);
+    if (result !is 1) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    return buffer;
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver.  The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return the array of indices of the selected items
+ *
+ * @exception SWTException <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 int [] getSelectionIndices () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        int result = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (result is OS.LB_ERR) return new int [0];
+        return [result];
+    }
+    int length = OS.SendMessage (handle, OS.LB_GETSELCOUNT, 0, 0);
+    if (length is OS.LB_ERR) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    int [] indices = new int [length];
+    int result = OS.SendMessage (handle, OS.LB_GETSELITEMS, length, indices.ptr);
+    if (result !is length) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    return indices;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @exception SWTException <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 int getTopIndex () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+}
+
+/**
+ * Gets the index of an item.
+ * <p>
+ * The list is searched starting at 0 until an
+ * item is found that is equal to the search item.
+ * If no item is found, -1 is returned.  Indexing
+ * is zero based.
+ *
+ * @param string the search item
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string) {
+    return indexOf (string, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the given,
+ * zero-relative index until an item is found that is equal
+ * to the argument, and returns the index of that item. If
+ * no item is found or the starting index is out of range,
+ * returns -1.
+ *
+ * @param string the search item
+ * @param start the zero-relative index at which to start the search
+ * @return the index of the item
+ *
+ * @exception SWTException <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 int indexOf (String string, int start) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+
+    /*
+    * Bug in Windows.  For some reason, LB_FINDSTRINGEXACT
+    * will not find empty strings even though it is legal
+    * to insert an empty string into a list.  The fix is
+    * to search the list, an item at a time.
+    */
+    if (string.length is 0) {
+        int count = getItemCount ();
+        for (int i=start; i<count; i++) {
+            if (string ==/*eq*/ getItem (i)) return i;
+        }
+        return -1;
+    }
+
+    /* Use LB_FINDSTRINGEXACT to search for the item */
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (!(0 <= start && start < count)) return -1;
+    int index = start - 1, last;
+    TCHAR* buffer = StrToTCHARz (getCodePage (), string );
+    do {
+        index = OS.SendMessage (handle, OS.LB_FINDSTRINGEXACT, last = index, buffer);
+        if (index is OS.LB_ERR || index <= last) return -1;
+    } while (string !=/*eq*/ getItem (index));
+    return index;
+}
+
+/**
+ * Returns <code>true</code> if the item is selected,
+ * and <code>false</code> otherwise.  Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the selection state of the item at the index
+ *
+ * @exception SWTException <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 isSelected (int index) {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+    return (result !is 0) && (result !is OS.LB_ERR);
+}
+
+/**
+ * Removes the items from the receiver at the given
+ * zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (indices.length is 0) return;
+    int [] newIndices = new int [indices.length];
+    System.arraycopy (indices, 0, newIndices, 0, indices.length);
+    sort (newIndices);
+    int start = newIndices [newIndices.length - 1], end = newIndices [0];
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    RECT rect;
+    HDC hDC;
+    HFONT oldFont, newFont;
+    int newWidth = 0;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        //rect = new RECT ();
+        hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    }
+    int cp = getCodePage ();
+    int i = 0, topCount = 0, last = -1;
+    while (i < newIndices.length) {
+        int index = newIndices [i];
+        if (index !is last) {
+            TCHAR[] buffer = null;
+            if ((style & SWT.H_SCROLL) !is 0) {
+                int length = OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+                if (length is OS.LB_ERR) break;
+                buffer = NewTCHARs (cp, length + 1);
+                int result = OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer.ptr);
+                if (result is OS.LB_ERR) break;
+            }
+            int result = OS.SendMessage (handle, OS.LB_DELETESTRING, index, 0);
+            if (result is OS.LB_ERR) break;
+            if ((style & SWT.H_SCROLL) !is 0) {
+                int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+                OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+                newWidth = Math.max (newWidth, rect.right - rect.left);
+            }
+            if (index < topIndex) topCount++;
+            last = index;
+        }
+        i++;
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        setScrollWidth (newWidth, false);
+    }
+    if (topCount > 0) {
+        topIndex -= topCount;
+        OS.SendMessage (handle, OS.LB_SETTOPINDEX, topIndex, 0);
+    }
+    if (i < newIndices.length) error (SWT.ERROR_ITEM_NOT_REMOVED);
+}
+
+/**
+ * Removes the item from the receiver at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int index) {
+    checkWidget ();
+    TCHAR[] buffer = null;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        int length = OS.SendMessage (handle, OS.LB_GETTEXTLEN, index, 0);
+        if (length is OS.LB_ERR) {
+            int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+            if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+        buffer = NewTCHARs (getCodePage (), length + 1);
+        int result = OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer.ptr);
+        if (result is OS.LB_ERR) {
+            int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+            if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+    }
+    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    int result = OS.SendMessage (handle, OS.LB_DELETESTRING, index, 0);
+    if (result is OS.LB_ERR) {
+        int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+        if (0 <= index && index < count) error (SWT.ERROR_ITEM_NOT_REMOVED);
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth (buffer.ptr, false);
+    if (index < topIndex) {
+        OS.SendMessage (handle, OS.LB_SETTOPINDEX, topIndex - 1, 0);
+    }
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int start, int end) {
+    checkWidget ();
+    if (start > end) return;
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    if (start is 0 && end is count - 1) {
+        removeAll ();
+        return;
+    }
+    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    RECT rect;
+    HDC hDC;
+    HFONT oldFont, newFont;
+    int newWidth = 0;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        //rect = new RECT ();
+        hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    }
+    int cp = getCodePage ();
+    int index = start;
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    while (index <= end) {
+        TCHAR[] buffer = null;
+        if ((style & SWT.H_SCROLL) !is 0) {
+            int length = OS.SendMessage (handle, OS.LB_GETTEXTLEN, start, 0);
+            if (length is OS.LB_ERR) break;
+            buffer = NewTCHARs (cp, length + 1);
+            int result = OS.SendMessage (handle, OS.LB_GETTEXT, start, buffer.ptr);
+            if (result is OS.LB_ERR) break;
+        }
+        int result = OS.SendMessage (handle, OS.LB_DELETESTRING, start, 0);
+        if (result is OS.LB_ERR) break;
+        if ((style & SWT.H_SCROLL) !is 0) {
+            OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+            newWidth = Math.max (newWidth, rect.right - rect.left);
+        }
+        index++;
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        setScrollWidth (newWidth, false);
+    }
+    if (end < topIndex) {
+        topIndex -= end - start + 1;
+        OS.SendMessage (handle, OS.LB_SETTOPINDEX, topIndex, 0);
+    }
+    if (index <= end) error (SWT.ERROR_ITEM_NOT_REMOVED);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * until an item is found that is equal to the argument,
+ * and removes that item from the list.
+ *
+ * @param string the item to remove
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the string is not found in the list</li>
+ * </ul>
+ * @exception SWTException <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 remove (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int index = indexOf (string, 0);
+    if (index is -1) error (SWT.ERROR_INVALID_ARGUMENT);
+    remove (index);
+}
+
+/**
+ * Removes all of the items from the receiver.
+ * <p>
+ * @exception SWTException <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 removeAll () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.LB_RESETCONTENT, 0, 0);
+    if ((style & SWT.H_SCROLL) !is 0) {
+        OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, 0, 0);
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception SWTException <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 List#setSelection(int[])
+ */
+public void select (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int length = indices.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    select (indices, false);
+}
+
+void select (int [] indices, bool scroll) {
+    int i = 0;
+    while (i < indices.length) {
+        int index = indices [i];
+        if (index !is -1) {
+            select (index, false);
+        }
+        i++;
+    }
+    if (scroll) showSelection ();
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver's
+ * list.  If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 select (int index) {
+    checkWidget ();
+    select (index, false);
+}
+
+void select (int index, bool scroll) {
+    if (index < 0) return;
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (index >= count) return;
+    if (scroll) {
+        if ((style & SWT.SINGLE) !is 0) {
+            OS.SendMessage (handle, OS.LB_SETCURSEL, index, 0);
+        } else {
+            OS.SendMessage (handle, OS.LB_SETSEL, 1, index);
+        }
+        return;
+    }
+    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    RECT itemRect, selectedRect;
+    bool selectedRectNull = true;
+    OS.SendMessage (handle, OS.LB_GETITEMRECT, index, &itemRect);
+    bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+    if (redraw) {
+        OS.UpdateWindow (handle);
+        OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    int focusIndex = -1;
+    if ((style & SWT.SINGLE) !is 0) {
+        int oldIndex = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+        if (oldIndex !is -1) {
+            //selectedRect = new RECT ();
+            selectedRectNull = false;
+            OS.SendMessage (handle, OS.LB_GETITEMRECT, oldIndex, &selectedRect);
+        }
+        OS.SendMessage (handle, OS.LB_SETCURSEL, index, 0);
+    } else {
+        focusIndex = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+        OS.SendMessage (handle, OS.LB_SETSEL, 1, index);
+    }
+    if ((style & SWT.MULTI) !is 0) {
+        if (focusIndex !is -1) {
+            OS.SendMessage (handle, OS.LB_SETCARETINDEX, focusIndex, 0);
+        }
+    }
+    OS.SendMessage (handle, OS.LB_SETTOPINDEX, topIndex, 0);
+    if (redraw) {
+        OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.ValidateRect (handle, null);
+        OS.InvalidateRect (handle, &itemRect, true);
+        if (!selectedRectNull) {
+            OS.InvalidateRect (handle, &selectedRect, true);
+        }
+    }
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException <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 List#setSelection(int,int)
+ */
+public void select (int start, int end) {
+    checkWidget ();
+    if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (count is 0 || start >= count) return;
+    start = Math.max (0, start);
+    end = Math.min (end, count - 1);
+    if ((style & SWT.SINGLE) !is 0) {
+        select (start, false);
+    } else {
+        select (start, end, false);
+    }
+}
+
+void select (int start, int end, bool scroll) {
+    /*
+    * Note that when start = end, LB_SELITEMRANGEEX
+    * deselects the item.
+    */
+    if (start is end) {
+        select (start, scroll);
+        return;
+    }
+    OS.SendMessage (handle, OS.LB_SELITEMRANGEEX, start, end);
+    if (scroll) showSelection ();
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ *
+ * @exception SWTException <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 selectAll () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) return;
+    OS.SendMessage (handle, OS.LB_SETSEL, 1, -1);
+}
+
+void setFocusIndex (int index) {
+//  checkWidget ();
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) return;
+    OS.SendMessage (handle, OS.LB_SETCARETINDEX, index, 0);
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    super.setFont (font);
+    if ((style & SWT.H_SCROLL) !is 0) setScrollWidth ();
+}
+
+/**
+ * Sets the text of the item in the receiver's list at the given
+ * zero-relative index to the string argument.
+ *
+ * @param index the index for the item
+ * @param string the new text for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 setItem (int index, String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int topIndex = getTopIndex ();
+    bool isSelected = isSelected (index);
+    remove (index);
+    add (string, index);
+    if (isSelected) select (index, false);
+    setTopIndex (topIndex);
+}
+
+/**
+ * Sets the receiver's items to be the given array of items.
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if an item in the items array is null</li>
+ * </ul>
+ * @exception SWTException <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 setItems (String [] items) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    // SWT extension: allow null item strings
+    //for (int i=0; i<items.length; i++) {
+    //    if (items [i] is null) error (SWT.ERROR_INVALID_ARGUMENT);
+    //}
+    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);
+    }
+    RECT rect;
+    HDC hDC;
+    HFONT oldFont, newFont;
+    int newWidth = 0;
+    if ((style & SWT.H_SCROLL) !is 0) {
+        //rect = new RECT ();
+        hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, 0, 0);
+    }
+    int length = items.length;
+    OS.SendMessage (handle, OS.LB_RESETCONTENT, 0, 0);
+    OS.SendMessage (handle, OS.LB_INITSTORAGE, length, length * 32);
+    int index = 0;
+    int cp = getCodePage ();
+    while (index < length) {
+        String string = items [index];
+        TCHAR* buffer = StrToTCHARz (cp, string);
+        int result = OS.SendMessage (handle, OS.LB_ADDSTRING, 0, buffer);
+        if (result is OS.LB_ERR || result is OS.LB_ERRSPACE) break;
+        if ((style & SWT.H_SCROLL) !is 0) {
+            int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+            OS.DrawText (hDC, buffer, -1, &rect, flags);
+            newWidth = Math.max (newWidth, rect.right - rect.left);
+        }
+        index++;
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+        OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, newWidth + INSET, 0);
+    }
+    if (redraw) {
+        OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+        /*
+        * This code is intentionally commented.  The window proc
+        * for the list box implements WM_SETREDRAW to invalidate
+        * and erase the widget.  This is undocumented behavior.
+        * The commented code below shows what is actually happening
+        * and reminds us that we are relying on this undocumented
+        * behavior.
+        */
+//      int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+//      OS.RedrawWindow (handle, null, 0, flags);
+    }
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+    if (index < items.length) error (SWT.ERROR_ITEM_NOT_ADDED);
+}
+
+void setScrollWidth () {
+    int newWidth = 0;
+    RECT rect;
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    int cp = getCodePage ();
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    for (int i=0; i<count; i++) {
+        int length = OS.SendMessage (handle, OS.LB_GETTEXTLEN, i, 0);
+        if (length !is OS.LB_ERR) {
+            TCHAR[] buffer = NewTCHARs (cp, length + 1 );
+            int result = OS.SendMessage (handle, OS.LB_GETTEXT, i, buffer.ptr);
+            if (result !is OS.LB_ERR) {
+                OS.DrawText (hDC, buffer.ptr, -1, &rect, flags);
+                newWidth = Math.max (newWidth, rect.right - rect.left);
+            }
+        }
+    }
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, newWidth + INSET, 0);
+}
+
+void setScrollWidth (TCHAR* buffer, bool grow) {
+    RECT rect;
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    OS.DrawText (hDC, buffer, -1, &rect, flags);
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    setScrollWidth (rect.right - rect.left, grow);
+}
+
+void setScrollWidth (int newWidth, bool grow) {
+    newWidth += INSET;
+    int width = OS.SendMessage (handle, OS.LB_GETHORIZONTALEXTENT, 0, 0);
+    if (grow) {
+        if (newWidth <= width) return;
+        OS.SendMessage (handle, OS.LB_SETHORIZONTALEXTENT, newWidth, 0);
+    } else {
+        if (newWidth < width) return;
+        setScrollWidth ();
+    }
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception SWTException <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 List#deselectAll()
+ * @see List#select(int[])
+ */
+public void setSelection(int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    deselectAll ();
+    int length = indices.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    select (indices, true);
+    if ((style & SWT.MULTI) !is 0) {
+        int focusIndex = indices [0];
+        if (focusIndex >= 0) setFocusIndex (focusIndex);
+    }
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ *
+ * @param items the array of items
+ *
+ * @exception SWTException <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 List#deselectAll()
+ * @see List#select(int[])
+ * @see List#setSelection(int[])
+ */
+public void setSelection (String [] items) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    deselectAll ();
+    int length = items.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    int focusIndex = -1;
+    for (int i=length-1; i>=0; --i) {
+        String string = items [i];
+        int index = 0;
+        if (string !is null) {
+            int localFocus = -1;
+            while ((index = indexOf (string, index)) !is -1) {
+                if (localFocus is -1) localFocus = index;
+                select (index, false);
+                if ((style & SWT.SINGLE) !is 0 && isSelected (index)) {
+                    showSelection ();
+                    return;
+                }
+                index++;
+            }
+            if (localFocus !is -1) focusIndex = localFocus;
+        }
+    }
+    if ((style & SWT.MULTI) !is 0) {
+        if (focusIndex >= 0) setFocusIndex (focusIndex);
+    }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new item is selected.
+ * Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 List#deselectAll()
+ * @see List#select(int)
+ */
+public void setSelection (int index) {
+    checkWidget ();
+    deselectAll ();
+    select (index, true);
+    if ((style & SWT.MULTI) !is 0) {
+        if (index >= 0) setFocusIndex (index);
+    }
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @exception SWTException <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 List#deselectAll()
+ * @see List#select(int,int)
+ */
+public void setSelection (int start, int end) {
+    checkWidget ();
+    deselectAll ();
+    if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (count is 0 || start >= count) return;
+    start = Math.max (0, start);
+    end = Math.min (end, count - 1);
+    if ((style & SWT.SINGLE) !is 0) {
+        select (start, true);
+    } else {
+        select (start, end, true);
+        setFocusIndex (start);
+    }
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException <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 setTopIndex (int index) {
+    checkWidget ();
+    int result = OS.SendMessage (handle, OS.LB_SETTOPINDEX, index, 0);
+    if (result is OS.LB_ERR) {
+        int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+        index = Math.min (count - 1, Math.max (0, index));
+        OS.SendMessage (handle, OS.LB_SETTOPINDEX, index, 0);
+    }
+}
+
+/**
+ * Shows the selection.  If the selection is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException <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 showSelection () {
+    checkWidget ();
+    int index;
+    if ((style & SWT.SINGLE) !is 0) {
+        index = OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+    } else {
+        int indices;
+        int result = OS.SendMessage (handle, OS.LB_GETSELITEMS, 1, &indices);
+        index = indices;
+        if (result !is 1) index = -1;
+    }
+    if (index is -1) return;
+    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+    if (count is 0) return;
+    int height = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+    forceResize ();
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    int visibleCount = Math.max (rect.bottom / height, 1);
+    int bottomIndex = Math.min (topIndex + visibleCount, count) - 1;
+    if (topIndex <= index && index <= bottomIndex) return;
+    int newTop = Math.min (Math.max (index - (visibleCount / 2), 0), count - 1);
+    OS.SendMessage (handle, OS.LB_SETTOPINDEX, newTop, 0);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.LBS_NOTIFY | OS.LBS_NOINTEGRALHEIGHT;
+    if ((style & SWT.SINGLE) !is 0) return bits;
+    if ((style & SWT.MULTI) !is 0) {
+        if ((style & SWT.SIMPLE) !is 0) return bits | OS.LBS_MULTIPLESEL;
+        return bits | OS.LBS_EXTENDEDSEL;
+    }
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARsToStr( ListClass );
+}
+
+override int windowProc () {
+    return cast(int) ListProc;
+}
+
+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 (SWT.Selection);
+                    return LRESULT.ZERO;
+                }
+                default:
+            }
+        }
+    }
+    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;
+                }
+                default:
+            }
+            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
+    * when their is white space at the bottom of the control.
+    * The fix is to detect when the top index has changed and
+    * redraw the control.
+    *
+    * Bug in Windows.  If the receiver is scrolled horizontally
+    * and is resized, the list does not redraw properly.  The fix
+    * is to redraw the control when the horizontal scroll bar is
+    * not at the beginning.
+    */
+    int oldIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (!isDisposed ()) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_POS;
+        if (OS.GetScrollInfo (handle, OS.SB_HORZ, &info)) {
+            if (info.nPos !is 0) OS.InvalidateRect (handle, null, true);
+        }
+        int newIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+        if (oldIndex !is newIndex) OS.InvalidateRect (handle, null, true);
+    }
+    return result;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    int code = OS.HIWORD (wParam);
+    switch (code) {
+        case OS.LBN_SELCHANGE:
+            postEvent (SWT.Selection);
+            break;
+        case OS.LBN_DBLCLK:
+            postEvent (SWT.DefaultSelection);
+            break;
+        default:
+    }
+    return super.wmCommandChild (wParam, lParam);
+}
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Listener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Listener;
+
+import org.eclipse.swt.widgets.Event;
+
+import tango.core.Traits;
+import tango.core.Tuple;
+
+/**
+ * Implementers of <code>Listener</code> provide a simple
+ * <code>handleEvent()</code> method that is used internally
+ * by SWT to dispatch events.
+ * <p>
+ * After creating an instance of a class that implements this interface
+ * it can be added to a widget using the
+ * <code>addListener(int eventType, Listener handler)</code> method and
+ * removed using the
+ * <code>removeListener (int eventType, Listener handler)</code> method.
+ * When the specified event occurs, <code>handleEvent(...)</code> will
+ * be sent to the instance.
+ * </p>
+ * <p>
+ * Classes which implement this interface are described within SWT as
+ * providing the <em>untyped listener</em> API. Typically, widgets will
+ * also provide a higher-level <em>typed listener</em> API, that is based
+ * on the standard <code>java.util.EventListener</code> pattern.
+ * </p>
+ * <p>
+ * Note that, since all internal SWT event dispatching is based on untyped
+ * listeners, it is simple to build subsets of SWT for use on memory
+ * constrained, small footprint devices, by removing the classes and
+ * methods which implement the typed listener API.
+ * </p>
+ *
+ * @see Widget#addListener
+ * @see java.util.EventListener
+ * @see org.eclipse.swt.events
+ */
+public interface Listener {
+
+/**
+ * Sent when an event that the receiver has registered for occurs.
+ *
+ * @param event the event which occurred
+ */
+void handleEvent (Event event);
+}
+
+
+/// Helper class for the dgListener template function
+private class _DgListenerT(Dg,T...) : Listener {
+
+    alias ParameterTupleOf!(Dg) DgArgs;
+    static assert( is(DgArgs == Tuple!(Event,T)),
+                "Delegate args not correct: delegate args: ("~DgArgs.stringof~") vs. passed args: ("~Tuple!(Event,T).stringof~")" );
+
+    Dg dg;
+    T  t;
+
+    private this( Dg dg, T t ){
+        this.dg = dg;
+        static if( T.length > 0 ){
+            this.t = t;
+        }
+    }
+
+    void handleEvent( Event e ){
+        dg(e,t);
+    }
+}
+
+/++
+ + dgListener creates a class implementing the Listener interface and delegating the call to
+ + handleEvent to the users delegate. This template function will store also additional parameters.
+ +
+ + Examle of usage:
+ + ---
+ + void handleTextEvent (Event e, int inset ) {
+ +     // ...
+ + }
+ + text.addListener (SWT.FocusOut, dgListener( &handleTextEvent, inset ));
+ + ---
+ +/
+Listener dgListener( Dg, T... )( Dg dg, T args ){
+    return new _DgListenerT!( Dg, T )( dg, args );
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Menu.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1584 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Menu;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are user interface objects that contain
+ * menu items.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BAR, DROP_DOWN, POP_UP, NO_RADIO_GROUP</dd>
+ * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Help, Hide, Show </dd>
+ * </dl>
+ * <p>
+ * Note: Only one of BAR, DROP_DOWN and POP_UP may be specified.
+ * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#menu">Menu snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Menu : Widget {
+    /**
+     * the handle to the OS resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HMENU handle;
+
+    int x, y;
+    HBRUSH hBrush;
+    HWND hwndCB;
+    int id0, id1;
+    int foreground = -1, background = -1;
+    Image backgroundImage;
+    bool hasLocation;
+    MenuItem cascade;
+    Decorations parent;
+    ImageList imageList;
+
+    /* Resource ID for SHMENUBARINFO */
+    static const int ID_PPC = 100;
+
+    /* SmartPhone SoftKeyBar resource ids */
+    static const int ID_SPMM = 102;
+    static const int ID_SPBM = 103;
+    static const int ID_SPMB = 104;
+    static const int ID_SPBB = 105;
+    static const int ID_SPSOFTKEY0 = 106;
+    static const int ID_SPSOFTKEY1 = 107;
+
+/**
+ * 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)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#POP_UP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Control parent) {
+    this (checkNull (parent).menuShell (), SWT.POP_UP);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Decorations</code>) and a style value
+ * describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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)
+ * @param style the style of menu to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BAR
+ * @see SWT#DROP_DOWN
+ * @see SWT#POP_UP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Decorations parent, int style) {
+    this (parent, checkStyle (style), null);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (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)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Menu parentMenu) {
+    this (checkNull (parentMenu).parent, SWT.DROP_DOWN);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (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)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (MenuItem parentItem) {
+    this (checkNull (parentItem).parent);
+}
+
+this (Decorations parent, int style, HWND handle) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    this.handle = handle;
+    /*
+    * Bug in IBM JVM 1.3.1.  For some reason, when the checkOrientation() is
+    * called from createWidget(), the JVM issues this error:
+    *
+    * JVM Exception 0x2 (subcode 0x0) occurred in thread "main" (TID:0x9F19D8)
+    *
+    * In addition, on Windows XP, a dialog appears with following error message,
+    * indicating that the problem may be in the JIT:
+    *
+    * AppName: java.exe  AppVer: 0.0.0.0     ModName: jitc.dll
+    * ModVer: 0.0.0.0    Offset: 000b6912
+    *
+    * The fix is to call checkOrientation() from here.
+    */
+    checkOrientation (parent);
+    createWidget ();
+}
+
+void _setVisible (bool visible) {
+    if ((style & (SWT.BAR | SWT.DROP_DOWN)) !is 0) return;
+    auto hwndParent = parent.handle;
+    if (visible) {
+        int flags = OS.TPM_LEFTBUTTON;
+        if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) flags |= OS.TPM_RIGHTBUTTON;
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) flags |= OS.TPM_RIGHTALIGN;
+        if ((parent.style & SWT.MIRRORED) !is 0) {
+            flags &= ~OS.TPM_RIGHTALIGN;
+            if ((style & SWT.LEFT_TO_RIGHT) !is 0) flags |= OS.TPM_RIGHTALIGN;
+        }
+        int nX = x, nY = y;
+        if (!hasLocation) {
+            int pos = OS.GetMessagePos ();
+            nX = OS.GET_X_LPARAM (pos);
+            nY = OS.GET_Y_LPARAM (pos);
+        }
+        /*
+        * Feature in Windows.  It is legal use TrackPopupMenu()
+        * to display an empty menu as long as menu items are added
+        * inside of WM_INITPOPUPMENU.  If no items are added, then
+        * TrackPopupMenu() fails and does not send an indication
+        * 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=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, OS.MAKEWPARAM (0, 0xFFFF), 0);
+        }
+    } else {
+        OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0);
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when help events are generated for the control,
+ * by sending it one of the messages defined in the
+ * <code>HelpListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when menus are hidden or shown, by sending it
+ * one of the messages defined in the <code>MenuListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuListener
+ * @see #removeMenuListener
+ */
+public void addMenuListener (MenuListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Hide,typedListener);
+    addListener (SWT.Show,typedListener);
+}
+
+static Control checkNull (Control control) {
+    if (control is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return control;
+}
+
+static Menu checkNull (Menu menu) {
+    if (menu is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return menu;
+}
+
+static MenuItem checkNull (MenuItem item) {
+    if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return item;
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.POP_UP, SWT.BAR, SWT.DROP_DOWN, 0, 0, 0);
+}
+
+void createHandle () {
+    if (handle !is null) return;
+    if ((style & SWT.BAR) !is 0) {
+        static if( OS.IsWinCE ) if (OS.IsPPC) {
+            auto hwndShell = parent.handle;
+            SHMENUBARINFO mbi;
+            mbi.cbSize = SHMENUBARINFO.sizeof;
+            mbi.hwndParent = hwndShell;
+            mbi.dwFlags = OS.SHCMBF_HIDDEN;
+            mbi.nToolBarId = ID_PPC;
+            mbi.hInstRes = OS.GetLibraryHandle ();
+            bool success = cast(bool) OS.SHCreateMenuBar (&mbi);
+            hwndCB = mbi.hwndMB;
+            if (!success) error (SWT.ERROR_NO_HANDLES);
+            /* Remove the item from the resource file */
+            OS.SendMessage (hwndCB, OS.TB_DELETEBUTTON, 0, 0);
+            return;
+        }
+        /*
+        * Note in WinCE SmartPhone.  The SoftBar contains only 2 items.
+        * An item can either be a menu or a button.
+        * SWT.BAR: creates a SoftBar with 2 menus
+        * SWT.BAR | SWT.BUTTON1: creates a SoftBar with 1 button
+        *    for button1, and a menu for button2
+        * SWT.BAR | SWT.BUTTON1 | SWT.BUTTON2: creates a SoftBar with
+        *    2 buttons
+        */
+        static if (OS.IsSP) {
+            /* Determine type of menubar */
+            int nToolBarId;
+            if ((style & SWT.BUTTON1) !is 0) {
+                nToolBarId = ((style & SWT.BUTTON2) !is 0) ? ID_SPBB : ID_SPBM;
+            } else {
+                nToolBarId = ((style & SWT.BUTTON2) !is 0) ? ID_SPMB : ID_SPMM;
+            }
+
+            /* Create SHMENUBAR */
+            SHMENUBARINFO mbi;
+            mbi.cbSize = SHMENUBARINFO.sizeof;
+            mbi.hwndParent = parent.handle;
+            mbi.dwFlags = OS.SHCMBF_HIDDEN;
+            mbi.nToolBarId = nToolBarId; /* as defined in .rc file */
+            mbi.hInstRes = OS.GetLibraryHandle ();
+            if (!OS.SHCreateMenuBar (&mbi)) error (SWT.ERROR_NO_HANDLES);
+            hwndCB = mbi.hwndMB;
+
+            /*
+            * Feature on WinCE SmartPhone.  The SHCMBF_HIDDEN flag causes the
+            * SHMENUBAR to not be drawn. However the keyboard events still go
+            * through it.  The workaround is to also hide the SHMENUBAR with
+            * ShowWindow ().
+            */
+            OS.ShowWindow (hwndCB, OS.SW_HIDE);
+
+            TBBUTTONINFO info = new TBBUTTONINFO ();
+            info.cbSize = TBBUTTONINFO.sizeof;
+            info.dwMask = OS.TBIF_COMMAND;
+            MenuItem item;
+
+            /* Set first item */
+            if (nToolBarId is ID_SPMM || nToolBarId is ID_SPMB) {
+                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, SWT.DROP_DOWN, hMenu);
+                item = new MenuItem (this, menu, SWT.CASCADE, 0);
+            } else {
+                item = new MenuItem (this, null, SWT.PUSH, 0);
+            }
+            info.idCommand = id0 = item.id;
+            OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, ID_SPSOFTKEY0, info);
+
+            /* Set second item */
+            if (nToolBarId is ID_SPMM || nToolBarId is ID_SPBM) {
+                int /*long*/ hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY1);
+                OS.RemoveMenu (hMenu, 0, OS.MF_BYPOSITION);
+                Menu menu = new Menu (parent, SWT.DROP_DOWN, hMenu);
+                item = new MenuItem (this, menu, SWT.CASCADE, 1);
+            } else {
+                item = new MenuItem (this, null, SWT.PUSH, 1);
+            }
+            info.idCommand = id1 = item.id;
+            OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, ID_SPSOFTKEY1, info);
+
+            /*
+            * Override the Back key.  For some reason, the owner of the menubar
+            * must be a Dialog or it won't receive the WM_HOTKEY message.  As
+            * a result, Shell on WinCE SP must use the class Dialog.
+            */
+            int dwMask = OS.SHMBOF_NODEFAULT | OS.SHMBOF_NOTIFY;
+            int /*long*/ lParam = OS.MAKELPARAM (dwMask, dwMask);
+            OS.SendMessage (hwndCB, OS.SHCMBM_OVERRIDEKEY, OS.VK_ESCAPE, lParam);
+            return;
+        }
+        handle = OS.CreateMenu ();
+        if (handle is null) error (SWT.ERROR_NO_HANDLES);
+        static if (OS.IsHPC) {
+            auto hwndShell = parent.handle;
+            hwndCB = OS.CommandBar_Create (OS.GetModuleHandle (null), hwndShell, 1);
+            if (hwndCB is null) error (SWT.ERROR_NO_HANDLES);
+            OS.CommandBar_Show (hwndCB, false);
+            OS.CommandBar_InsertMenubarEx (hwndCB, 0, handle, 0);
+            /*
+            * The command bar hosts the 'close' button when the window does not
+            * have a caption.
+            */
+            if ((parent.style & SWT.CLOSE) !is 0 && (parent.style & SWT.TITLE) is 0) {
+                OS.CommandBar_AddAdornments (hwndCB, 0, 0);
+            }
+        }
+    } else {
+        handle = OS.CreatePopupMenu ();
+        if (handle is null) error (SWT.ERROR_NO_HANDLES);
+    }
+}
+
+void createItem (MenuItem item, int index) {
+    int count = GetMenuItemCount (handle);
+    if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+    display.addMenuItem (item);
+    bool success = false;
+    if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+        if (OS.IsSP) return;
+        TBBUTTON lpButton;
+        lpButton.idCommand = item.id;
+        lpButton.fsStyle = cast(byte) OS.TBSTYLE_AUTOSIZE;
+        if ((item.style & SWT.CASCADE) !is 0) lpButton.fsStyle |= OS.TBSTYLE_DROPDOWN | 0x80;
+        if ((item.style & SWT.SEPARATOR) !is 0) lpButton.fsStyle = cast(byte) OS.BTNS_SEP;
+        lpButton.fsState = cast(byte) OS.TBSTATE_ENABLED;
+        lpButton.iBitmap = OS.I_IMAGENONE;
+        success = OS.SendMessage (hwndCB, OS.TB_INSERTBUTTON, index, &lpButton) !is 0;
+    } else {
+        static if (OS.IsWinCE) {
+            int uFlags = OS.MF_BYPOSITION;
+            TCHAR lpNewItem = null;
+            if ((item.style & SWT.SEPARATOR) !is 0) {
+                uFlags |= OS.MF_SEPARATOR;
+            } else {
+                lpNewItem = new TCHAR (0, " ", true);
+            }
+            success = OS.InsertMenu (handle, index, uFlags, item.id, lpNewItem);
+            if (success) {
+                MENUITEMINFO info = new MENUITEMINFO ();
+                info.cbSize = OS.MENUITEMINFO_sizeof;
+                info.fMask = OS.MIIM_DATA;
+                info.dwItemData = item.id;
+                success = OS.SetMenuItemInfo (handle, index, true, info);
+            }
+        } else {
+            /*
+            * Bug in Windows.  For some reason, when InsertMenuItem()
+            * is used to insert an item without text, it is not possible
+            * to use SetMenuItemInfo() to set the text at a later time.
+            * The fix is to insert the item with some text.
+            *
+            * Feature in Windows.  When an empty string is used instead
+            * of a space and InsertMenuItem() is used to set a submenu
+            * before setting text to a non-empty string, the menu item
+            * becomes unexpectedly disabled.  The fix is to insert a
+            * space.
+            */
+            auto hHeap = OS.GetProcessHeap ();
+            TCHAR[] buffer = StrToTCHARs (0, " \0");
+            int byteCount = (buffer.length-1) * TCHAR.sizeof;
+            auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (pszText, buffer.ptr, byteCount);
+            MENUITEMINFO info;
+            info.cbSize = OS.MENUITEMINFO_sizeof;
+            info.fMask = OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_DATA;
+            info.wID = item.id;
+            info.dwItemData = item.id;
+            info.fType = item.widgetStyle ();
+            info.dwTypeData = pszText;
+            success = cast(bool) OS.InsertMenuItem (handle, index, true, &info);
+            if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+        }
+    }
+    if (!success) {
+        display.removeMenuItem (item);
+        error (SWT.ERROR_ITEM_NOT_ADDED);
+    }
+    redraw ();
+}
+
+void createWidget () {
+    /*
+    * Bug in IBM JVM 1.3.1.  For some reason, when the following code is called
+    * from this method, the JVM issues this error:
+    *
+    * JVM Exception 0x2 (subcode 0x0) occurred in thread "main" (TID:0x9F19D8)
+    *
+    * In addition, on Windows XP, a dialog appears with following error message,
+    * indicating that the problem may be in the JIT:
+    *
+    * AppName: java.exe  AppVer: 0.0.0.0     ModName: jitc.dll
+    * ModVer: 0.0.0.0    Offset: 000b6912
+    *
+    * The fix is to move the code to the caller of this method.
+    */
+//  checkOrientation (parent);
+    createHandle ();
+    parent.addMenu (this);
+}
+
+int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_MENU);
+}
+
+int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_MENUTEXT);
+}
+
+void destroyAccelerators () {
+    parent.destroyAccelerators ();
+}
+
+void destroyItem (MenuItem item) {
+    static if (OS.IsWinCE) {
+        if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+            if (OS.IsSP) {
+                redraw();
+                return;
+            }
+            int index = OS.SendMessage (hwndCB, OS.TB_COMMANDTOINDEX, item.id, 0);
+            if (OS.SendMessage (hwndCB, OS.TB_DELETEBUTTON, index, 0) is 0) {
+                error (SWT.ERROR_ITEM_NOT_REMOVED);
+            }
+            int count = OS.SendMessage (hwndCB, OS.TB_BUTTONCOUNT, 0, 0);
+            if (count is 0) {
+                if (imageList !is null) {
+                    OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
+                    display.releaseImageList (imageList);
+                    imageList = null;
+                }
+            }
+        } else {
+            int index = 0;
+            MENUITEMINFO info;
+            info.cbSize = OS.MENUITEMINFO_sizeof;
+            info.fMask = OS.MIIM_DATA;
+            while (OS.GetMenuItemInfo (handle, index, true, &info)) {
+                if (info.dwItemData is item.id) break;
+                index++;
+            }
+            if (info.dwItemData !is item.id) {
+                error (SWT.ERROR_ITEM_NOT_REMOVED);
+            }
+            if (!OS.DeleteMenu (handle, index, OS.MF_BYPOSITION)) {
+                error (SWT.ERROR_ITEM_NOT_REMOVED);
+            }
+        }
+    } else {
+        if (!OS.DeleteMenu (handle, item.id, OS.MF_BYCOMMAND)) {
+            error (SWT.ERROR_ITEM_NOT_REMOVED);
+        }
+    }
+    redraw ();
+}
+
+override void destroyWidget () {
+    MenuItem cascade = this.cascade;
+    HMENU hMenu = handle;
+    HWND hCB = hwndCB;
+    releaseHandle ();
+    static if (OS.IsWinCE) {
+        if( hCB !is null ){
+            OS.CommandBar_Destroy (hCB);
+        }
+    } else {
+        if (cascade !is null) {
+            if (!OS.IsSP) cascade.setMenu (null, true);
+        } else {
+            if (hMenu !is null) OS.DestroyMenu (hMenu);
+        }
+    }
+}
+
+void fixMenus (Decorations newParent) {
+    MenuItem [] items = getItems ();
+    for (int i=0; i<items.length; i++) {
+        items [i].fixMenus (newParent);
+    }
+    parent.removeMenu (this);
+    newParent.addMenu (this);
+    this.parent = newParent;
+}
+
+/**
+ * Returns the receiver's background color.
+ *
+ * @return the background color
+ *
+ * @exception SWTException <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*/ Color getBackground () {
+    checkWidget ();
+    return Color.win32_new (display, background !is -1 ? background : defaultBackground ());
+}
+
+/**
+ * Returns the receiver's background image.
+ *
+ * @return the background image
+ *
+ * @exception SWTException <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*/ Image getBackgroundImage () {
+    checkWidget ();
+    return backgroundImage;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null),
+ * unless the receiver is a menu or a shell. In this case, the
+ * location is relative to the display.
+ * <p>
+ * Note that the bounds of a menu or menu item are undefined when
+ * the menu is not visible.  This is because most platforms compute
+ * the bounds of a menu dynamically just before it is displayed.
+ * </p>
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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.1
+ */
+/*public*/ Rectangle getBounds () {
+    checkWidget ();
+    static if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0);
+    if ((style & SWT.BAR) !is 0) {
+        if (parent.menuBar !is this) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        auto hwndShell = parent.handle;
+        MENUBARINFO info;
+        info.cbSize = MENUBARINFO.sizeof;
+        if (OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 0, &info)) {
+            int width = info.rcBar.right - info.rcBar.left;
+            int height = info.rcBar.bottom - info.rcBar.top;
+            return new Rectangle (info.rcBar.left, info.rcBar.top, width, height);
+        }
+    } else {
+        int count = GetMenuItemCount (handle);
+        if (count !is 0) {
+            RECT rect1;
+            if (OS.GetMenuItemRect (null, handle, 0, &rect1)) {
+                RECT rect2;
+                if (OS.GetMenuItemRect (null, handle, count - 1, &rect2)) {
+                    int x = rect1.left - 2, y = rect1.top - 2;
+                    int width = (rect2.right - rect2.left) + 4;
+                    int height = (rect2.bottom - rect1.top) + 4;
+                    return new Rectangle (x, y, width, height);
+                }
+            }
+        }
+    }
+    return new Rectangle (0, 0, 0, 0);
+}
+
+/**
+ * Returns the default menu item or null if none has
+ * been previously set.
+ *
+ * @return the default menu item.
+ *
+ * </ul>
+ * @exception SWTException <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 MenuItem getDefaultItem () {
+    checkWidget ();
+    static if (OS.IsWinCE) return null;
+    int id = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+    if (id is -1) return null;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    info.fMask = OS.MIIM_ID;
+    if (OS.GetMenuItemInfo (handle, id, false, &info)) {
+        return display.getMenuItem (info.wID);
+    }
+    return null;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #isEnabled
+ */
+public bool getEnabled () {
+    checkWidget ();
+    return (state & DISABLED) is 0;
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException <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*/ Color getForeground () {
+    checkWidget ();
+    return Color.win32_new (display, foreground !is -1 ? foreground : defaultForeground ());
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 MenuItem getItem (int index) {
+    checkWidget ();
+    int id = 0;
+    if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+        static if (OS.IsPPC) {
+            TBBUTTON lpButton;
+            int result = OS.SendMessage (hwndCB, OS.TB_GETBUTTON, index, &lpButton);
+            if (result is 0) error (SWT.ERROR_CANNOT_GET_ITEM);
+            id = lpButton.idCommand;
+        }
+        if (OS.IsSP) {
+            if (!(0 <= index && index <= 1)) error (SWT.ERROR_CANNOT_GET_ITEM);
+            id = index is 0 ? id0 : id1;
+        }
+    } else {
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        info.fMask = OS.MIIM_DATA;
+        if (!OS.GetMenuItemInfo (handle, index, true, &info)) {
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+        id = info.dwItemData;
+    }
+    return display.getMenuItem (id);
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return GetMenuItemCount (handle);
+}
+
+/**
+ * Returns a (possibly empty) array of <code>MenuItem</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 MenuItem [] getItems () {
+    checkWidget ();
+    if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+        if (OS.IsSP) {
+            MenuItem [] result = new MenuItem [2];
+            result[0] = display.getMenuItem (id0);
+            result[1] = display.getMenuItem (id1);
+            return result;
+        }
+        int count = OS.SendMessage (hwndCB, OS.TB_BUTTONCOUNT, 0, 0);
+        TBBUTTON lpButton;
+        MenuItem [] result = new MenuItem [count];
+        for (int i=0; i<count; i++) {
+            OS.SendMessage (hwndCB, OS.TB_GETBUTTON, i, &lpButton);
+            result [i] = display.getMenuItem (lpButton.idCommand);
+        }
+        return result;
+    }
+    int index = 0, count = 0;
+    int length = OS.IsWinCE ? 4 : OS.GetMenuItemCount (handle);
+    MenuItem [] items = new MenuItem [length];
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    info.fMask = OS.MIIM_DATA;
+    while (OS.GetMenuItemInfo (handle, index, true, &info)) {
+        if (count is items.length) {
+            MenuItem [] newItems = new MenuItem [count + 4];
+            System.arraycopy (items, 0, newItems, 0, count);
+            items = newItems;
+        }
+        MenuItem item = display.getMenuItem (info.dwItemData);
+        if (item !is null) items [count++] = item;
+        index++;
+    }
+    if (count is items.length) return items;
+    MenuItem [] result = new MenuItem [count];
+    System.arraycopy (items, 0, result, 0, count);
+    return result;
+}
+
+int GetMenuItemCount (HANDLE handle) {
+    static if (OS.IsWinCE) {
+        if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+            return OS.IsSP ? 2 : OS.SendMessage (hwndCB, OS.TB_BUTTONCOUNT, 0, 0);
+        }
+        int count = 0;
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        while (OS.GetMenuItemInfo (handle, count, true, &info)) count++;
+        return count;
+    }
+    return OS.GetMenuItemCount (handle);
+}
+
+override String getNameText () {
+    String result = "";
+    MenuItem [] items = getItems ();
+    int length_ = items.length;
+    if (length_ > 0) {
+        for (int i=0; i<length_-1; i++) {
+            result = result ~ items [i].getNameText() ~ ", ";
+        }
+        result = result ~ items [length_-1].getNameText ();
+    }
+    return result;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Decorations</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Decorations getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>MenuItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException <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 MenuItem getParentItem () {
+    checkWidget ();
+    return cascade;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>Menu</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException <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 Menu getParentMenu () {
+    checkWidget ();
+    if (cascade !is null) return cascade.parent;
+    return null;
+}
+
+/**
+ * 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
+ * of other shells.
+ *
+ * @return the receiver's shell
+ *
+ * @exception SWTException <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 #getParent
+ */
+public Shell getShell () {
+    checkWidget ();
+    return parent.getShell ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver 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 visibility state
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget ();
+    if ((style & SWT.BAR) !is 0) {
+        return this is parent.menuShell ().menuBar;
+    }
+    if ((style & SWT.POP_UP) !is 0) {
+        Menu [] popups = display.popups;
+        if (popups is null) return false;
+        for (int i=0; i<popups.length; i++) {
+            if (popups [i] is this) return true;
+        }
+    }
+    Shell shell = getShell ();
+    Menu menu = shell.activeMenu;
+    while (menu !is null && menu !is this) {
+        menu = menu.getParentMenu ();
+    }
+    return this is menu;
+}
+
+int imageIndex (Image image) {
+    if (hwndCB is null || image is null) return OS.I_IMAGENONE;
+    if (imageList is null) {
+        Rectangle bounds = image.getBounds ();
+        imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+        int index = imageList.add (image);
+        HANDLE hImageList = imageList.getHandle ();
+        OS.SendMessage (hwndCB, OS.TB_SETIMAGELIST, 0, hImageList);
+        return index;
+    }
+    int index = imageList.indexOf (image);
+    if (index is -1) {
+        index = imageList.add (image);
+    } else {
+        imageList.put (index, image);
+    }
+    return index;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (MenuItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    if (item.parent !is this) return -1;
+    if ((OS.IsPPC || OS.IsSP) && hwndCB !is null) {
+        if (OS.IsPPC) {
+            return OS.SendMessage (hwndCB, OS.TB_COMMANDTOINDEX, item.id, 0);
+        }
+        if (OS.IsSP) {
+            if (item.id is id0) return 0;
+            if (item.id is id1) return 1;
+            return -1;
+        }
+    }
+    int index = 0;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    info.fMask = OS.MIIM_DATA;
+    while (OS.GetMenuItemInfo (handle, index, true, &info)) {
+        if (info.dwItemData is item.id) return index;
+        index++;
+    }
+    return -1;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled menu is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #getEnabled
+ */
+public bool isEnabled () {
+    checkWidget ();
+    Menu parentMenu = getParentMenu ();
+    if (parentMenu is null) {
+        return getEnabled () && parent.isEnabled ();
+    }
+    return getEnabled () && parentMenu.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException <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 #getVisible
+ */
+public bool isVisible () {
+    checkWidget ();
+    return getVisible ();
+}
+
+void redraw () {
+    if (!isVisible ()) return;
+    if ((style & SWT.BAR) !is 0) {
+        display.addBar (this);
+    } else {
+        update ();
+    }
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    handle = null;
+    cascade = null;
+}
+
+override void releaseChildren (bool destroy) {
+    MenuItem [] items = getItems ();
+    for (int i=0; i<items.length; i++) {
+        MenuItem item = items [i];
+        if (item !is null && !item.isDisposed ()) {
+            if (OS.IsPPC && hwndCB !is null) {
+                item.dispose ();
+            } else {
+                item.release (false);
+            }
+        }
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if ((style & SWT.BAR) !is 0) {
+        display.removeBar (this);
+        if (this is parent.menuBar) {
+            parent.setMenuBar (null);
+        }
+    } else {
+        if ((style & SWT.POP_UP) !is 0) {
+            display.removePopup (this);
+        }
+    }
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    backgroundImage = null;
+    if (hBrush is null) OS.DeleteObject (hBrush);
+    hBrush = null;
+    if (OS.IsPPC && hwndCB !is null) {
+        if (imageList !is null) {
+            OS.SendMessage (hwndCB, OS.TB_SETIMAGELIST, 0, 0);
+            display.releaseToolImageList (imageList);
+            imageList = null;
+        }
+    }
+    if (parent !is null) parent.removeMenu (this);
+    parent = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Help, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the menu events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuListener
+ * @see #addMenuListener
+ */
+public void removeMenuListener (MenuListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Hide, listener);
+    eventTable.unhook (SWT.Show, listener);
+}
+
+/**
+ * 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.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setBackground (Color color) {
+    checkWidget ();
+    int pixel = -1;
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        pixel = color.handle;
+    }
+    if (pixel is background) return;
+    background = pixel;
+    updateBackground ();
+}
+
+/**
+ * Sets the receiver's background image to the image specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.  The background image is tiled to fill
+ * the available space.
+ *
+ * @param image the new image (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
+ * </ul>
+ * @exception SWTException <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 setBackgroundImage (Image image) {
+    checkWidget ();
+    if (image !is null) {
+        if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (image.type !is SWT.BITMAP) error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    if (backgroundImage is image) return;
+    backgroundImage = image;
+    updateBackground ();
+}
+
+/**
+ * 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.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setForeground (Color color) {
+    checkWidget ();
+    int pixel = -1;
+    if (color !is null) {
+        if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+        pixel = color.handle;
+    }
+    if (pixel is foreground) return;
+    foreground = pixel;
+    updateForeground ();
+}
+
+/**
+ * Sets the default menu item to the argument or removes
+ * the default emphasis when the argument is <code>null</code>.
+ *
+ * @param item the default menu item or null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the menu item has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setDefaultItem (MenuItem item) {
+    checkWidget ();
+    int newID = -1;
+    if (item !is null) {
+        if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+        if (item.parent !is this) return;
+        newID = item.id;
+    }
+    static if (OS.IsWinCE) return;
+    int oldID = OS.GetMenuDefaultItem (handle, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+    if (newID is oldID) return;
+    OS.SetMenuDefaultItem (handle, newID, OS.MF_BYCOMMAND);
+    redraw ();
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled menu is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <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 setEnabled (bool enabled) {
+    checkWidget ();
+    state &= ~DISABLED;
+    if (!enabled) state |= DISABLED;
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the arguments which are relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p><p>
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ * </p>
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException <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 setLocation (int x, int y) {
+    checkWidget ();
+    if ((style & (SWT.BAR | SWT.DROP_DOWN)) !is 0) return;
+    this.x = x;
+    this.y = y;
+    hasLocation = true;
+}
+
+/**
+ * Sets the location of the receiver, which must be a popup,
+ * to the point specified by the argument which is relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p><p>
+ * Note that the platform window manager ultimately has control
+ * over the location of popup menus.
+ * </p>
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 2.1
+ */
+public void setLocation (Point location) {
+    checkWidget ();
+    if (location is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    setLocation (location.x, location.y);
+}
+
+/**
+ * Marks the receiver 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 SWTException <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 setVisible (bool visible) {
+    checkWidget ();
+    if ((style & (SWT.BAR | SWT.DROP_DOWN)) !is 0) return;
+    if (visible) {
+        display.addPopup (this);
+    } else {
+        display.removePopup (this);
+        _setVisible (false);
+    }
+}
+
+void update () {
+    if (OS.IsPPC || OS.IsSP) return;
+    static if (OS.IsHPC) {
+        /*
+        * Each time a menu has been modified, the command menu bar
+        * must be redrawn or it won't update properly.  For example,
+        * a submenu will not drop down.
+        */
+        Menu menuBar = parent.menuBar;
+        if (menuBar !is null) {
+            Menu menu = this;
+            while (menu !is null && menu !is menuBar) {
+                menu = menu.getParentMenu ();
+            }
+            if (menu is menuBar) {
+                OS.CommandBar_DrawMenuBar (menuBar.hwndCB, 0);
+                OS.CommandBar_Show (menuBar.hwndCB, true);
+            }
+        }
+        return;
+    }
+    static if (OS.IsWinCE) return;
+    if ((style & SWT.BAR) !is 0) {
+        if (this is parent.menuBar) OS.DrawMenuBar (parent.handle);
+        return;
+    }
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+        return;
+    }
+    bool hasCheck = false, hasImage = false;
+    MenuItem [] items = getItems ();
+    for (int i=0; i<items.length; i++) {
+        MenuItem item = items [i];
+        if (item.image !is null) {
+            hasImage = true;
+            if (hasCheck) break;
+        }
+        if ((item.style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+            hasCheck = true;
+            if ( hasImage) break;
+        }
+    }
+
+    /*
+    * Bug in Windows.  If a menu contains items that have
+    * images and can be checked, Windows does not include
+    * the width of the image and the width of the check when
+    * computing the width of the menu.  When the longest item
+    * does not have an image, the label and the accelerator
+    * text can overlap.  The fix is to use SetMenuItemInfo()
+    * to indicate that all items have a bitmap and then include
+    * the width of the widest bitmap in WM_MEASURECHILD.
+    *
+    * NOTE:  This work around causes problems on Windows 98.
+    * Under certain circumstances that have yet to be isolated,
+    * some menus can become huge and blank.  For now, do not
+    * run the code on Windows 98.
+    *
+    * NOTE:  This work around doesn't run on Vista because
+    * WM_MEASURECHILD and WM_DRAWITEM cause Vista to lose
+    * the menu theme.
+    */
+    if (!OS.IsWin95) {
+        if (OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            MENUITEMINFO info;
+            info.cbSize = OS.MENUITEMINFO_sizeof;
+            info.fMask = OS.MIIM_BITMAP;
+            for (int i=0; i<items.length; i++) {
+                MenuItem item = items [i];
+                if ((style & SWT.SEPARATOR) is 0) {
+                    if (item.image is null || foreground !is -1) {
+                        info.hbmpItem = hasImage || foreground !is -1 ? OS.HBMMENU_CALLBACK : null;
+                        OS.SetMenuItemInfo (handle, item.id, false, &info);
+                    }
+                }
+            }
+        }
+    }
+
+    /* Update the menu to hide or show the space for bitmaps */
+    MENUINFO lpcmi;
+    lpcmi.cbSize = MENUINFO.sizeof;
+    lpcmi.fMask = OS.MIM_STYLE;
+    OS.GetMenuInfo (handle, &lpcmi);
+    if (hasImage && !hasCheck) {
+        lpcmi.dwStyle |= OS.MNS_CHECKORBMP;
+    } else {
+        lpcmi.dwStyle &= ~OS.MNS_CHECKORBMP;
+    }
+    OS.SetMenuInfo (handle, &lpcmi);
+}
+
+void updateBackground () {
+    if (hBrush is null) OS.DeleteObject (hBrush);
+    hBrush = null;
+    if (backgroundImage !is null) {
+        hBrush = OS.CreatePatternBrush (backgroundImage.handle);
+    } else {
+        if (background !is -1) hBrush = OS.CreateSolidBrush (background);
+    }
+    MENUINFO lpcmi;
+    lpcmi.cbSize = MENUINFO.sizeof;
+    lpcmi.fMask = OS.MIM_BACKGROUND;
+    lpcmi.hbrBack = hBrush;
+    OS.SetMenuInfo (handle, &lpcmi);
+}
+
+void updateForeground () {
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    int index = 0;
+    while (OS.GetMenuItemInfo (handle, index, true, &info)) {
+        info.fMask = OS.MIIM_BITMAP;
+        info.hbmpItem = OS.HBMMENU_CALLBACK;
+        OS.SetMenuItemInfo (handle, index, true, &info);
+        index++;
+    }
+    redraw ();
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/MenuItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1213 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.MenuItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ArmListener;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that issues notification when pressed and released.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>CHECK, CASCADE, PUSH, RADIO, SEPARATOR</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Arm, Help, Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles CHECK, CASCADE, PUSH, RADIO and SEPARATOR
+ * may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class MenuItem : Item {
+    Menu parent, menu;
+    HBITMAP hBitmap;
+    int id, accelerator;
+    /*
+    * Feature in Windows.  On Windows 98, it is necessary
+    * to add 4 pixels to the width of the image or the image
+    * and text are too close.  On other Windows platforms,
+    * this causes the text of the longest item to touch the
+    * accelerator text.  The fix is to use smaller margins
+    * everywhere but on Windows 98.
+    */
+    private static int MARGIN_WIDTH_;
+    public static int MARGIN_WIDTH(){
+        assert( static_this_completed );
+        return MARGIN_WIDTH_;
+    }
+    private static int MARGIN_HEIGHT_;
+    public static int MARGIN_HEIGHT(){
+        assert( static_this_completed );
+        return MARGIN_HEIGHT_;
+    }
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            MARGIN_WIDTH_ = OS.IsWin95 ? 2 : 1;
+            MARGIN_HEIGHT_ = OS.IsWin95 ? 2 : 1;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Menu</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a menu control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Menu parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Menu</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a menu 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#CHECK
+ * @see SWT#CASCADE
+ * @see SWT#PUSH
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Menu parent, int style, int index) {
+    static_this();
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+this (Menu parent, Menu menu, int style, int index) {
+    static_this();
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    this.menu = menu;
+    if (menu !is null) menu.cascade = this;
+    display.addMenuItem (this);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the arm events are generated for the control, by sending
+ * it one of the messages defined in the <code>ArmListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ArmListener
+ * @see #removeArmListener
+ */
+public void addArmListener (ArmListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Arm, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the help events are generated for the control, by sending
+ * it one of the messages defined in the <code>HelpListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #removeHelpListener
+ */
+public void addHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Help, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the menu item is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the stateMask field of the event object is valid.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the menu item is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.CASCADE, 0);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+bool fillAccel (ACCEL* accel) {
+    accel.cmd = accel.key = accel.fVirt = 0;
+    if (accelerator is 0 || !getEnabled ()) return false;
+    if ((accelerator & SWT.COMMAND) !is 0) return false;
+    int fVirt = OS.FVIRTKEY;
+    int key = accelerator & SWT.KEY_MASK;
+    auto vKey = Display.untranslateKey (key);
+    if (vKey !is 0) {
+        key = vKey;
+    } else {
+        switch (key) {
+            /*
+            * Bug in Windows.  For some reason, VkKeyScan
+            * fails to map ESC to VK_ESCAPE and DEL to
+            * VK_DELETE.  The fix is to map these keys
+            * as a special case.
+            */
+            case 27: key = OS.VK_ESCAPE; break;
+            case 127: key = OS.VK_DELETE; break;
+            default: {
+                key = Display.wcsToMbcs (cast(char) key);
+                if (key is 0) return false;
+                static if (OS.IsWinCE) {
+                    key = cast(int) OS.CharUpper (cast(TCHAR*) key);
+                } else {
+                    vKey = OS.VkKeyScan (cast(TCHAR) key) & 0xFF;
+                    if (vKey is -1) {
+                        fVirt = 0;
+                    } else {
+                        key = vKey;
+                    }
+                }
+            }
+        }
+    }
+    accel.key = cast(short) key;
+    accel.cmd = cast(short) id;
+    accel.fVirt = cast(byte) fVirt;
+    if ((accelerator & SWT.ALT) !is 0) accel.fVirt |= OS.FALT;
+    if ((accelerator & SWT.SHIFT) !is 0) accel.fVirt |= OS.FSHIFT;
+    if ((accelerator & SWT.CONTROL) !is 0) accel.fVirt |= OS.FCONTROL;
+    return true;
+}
+
+void fixMenus (Decorations newParent) {
+    if (menu !is null) menu.fixMenus (newParent);
+}
+
+/**
+ * Returns the widget accelerator.  An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @return the accelerator or 0
+ *
+ * </ul>
+ * @exception SWTException <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 int getAccelerator () {
+    checkWidget ();
+    return accelerator;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent (or its display if its parent is null).
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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.1
+ */
+/*public*/ Rectangle getBounds () {
+    checkWidget ();
+    static if (OS.IsWinCE) return new Rectangle (0, 0, 0, 0);
+    int index = parent.indexOf (this);
+    if (index is -1) return new Rectangle (0, 0, 0, 0);
+    if ((parent.style & SWT.BAR) !is 0) {
+        Decorations shell = parent.parent;
+        if (shell.menuBar !is parent) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        auto hwndShell = shell.handle;
+        MENUBARINFO info1;
+        info1.cbSize = MENUBARINFO.sizeof;
+        if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, 1, &info1)) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        MENUBARINFO info2;
+        info2.cbSize = MENUBARINFO.sizeof;
+        if (!OS.GetMenuBarInfo (hwndShell, OS.OBJID_MENU, index + 1, &info2)) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        int x = info2.rcBar.left - info1.rcBar.left;
+        int y = info2.rcBar.top - info1.rcBar.top;
+        int width = info2.rcBar.right - info2.rcBar.left;
+        int height = info2.rcBar.bottom - info2.rcBar.top;
+        return new Rectangle (x, y, width, height);
+    } else {
+        auto hMenu = parent.handle;
+        RECT rect1;
+        if (!OS.GetMenuItemRect (null, hMenu, 0, &rect1)) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        RECT rect2;
+        if (!OS.GetMenuItemRect (null, hMenu, index, &rect2)) {
+            return new Rectangle (0, 0, 0, 0);
+        }
+        int x = rect2.left - rect1.left + 2;
+        int y = rect2.top - rect1.top + 2;
+        int width = rect2.right - rect2.left;
+        int height = rect2.bottom - rect2.top;
+        return new Rectangle (x, y, width, height);
+    }
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #isEnabled
+ */
+public bool getEnabled () {
+    checkWidget ();
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
+        auto hwndCB = parent.hwndCB;
+        TBBUTTONINFO info;
+        info.cbSize = TBBUTTONINFO.sizeof;
+        info.dwMask = OS.TBIF_STATE;
+        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 & SWT.SEPARATOR) !is 0) {
+        return (state & DISABLED) is 0;
+    }
+    auto hMenu = parent.handle;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    info.fMask = OS.MIIM_STATE;
+    bool success;
+    static if (OS.IsWinCE) {
+        int index = parent.indexOf (this);
+        if (index is -1) error (SWT.ERROR_CANNOT_GET_ENABLED);
+        success = cast(bool) OS.GetMenuItemInfo (hMenu, index, true, &info);
+    } else {
+        success = cast(bool) OS.GetMenuItemInfo (hMenu, id, false, &info);
+    }
+    if (!success) error (SWT.ERROR_CANNOT_GET_ENABLED);
+    return (info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) is 0;
+}
+
+/**
+ * Returns the receiver's cascade menu if it has one or null
+ * if it does not. Only <code>CASCADE</code> menu items can have
+ * a pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ *
+ * @return the receiver's menu
+ *
+ * @exception SWTException <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>
+ */
+override public Menu getMenu () {
+    checkWidget ();
+    return menu;
+}
+
+override String getNameText () {
+    if ((style & SWT.SEPARATOR) !is 0) return "|";
+    return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Menu</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Menu getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked.
+ *
+ * @return the selection state
+ *
+ * @exception SWTException <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 getSelection () {
+    checkWidget ();
+    if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return false;
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) return false;
+    auto hMenu = parent.handle;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    info.fMask = OS.MIIM_STATE;
+    bool success = cast(bool) OS.GetMenuItemInfo (hMenu, id, false, &info);
+    if (!success) error (SWT.ERROR_CANNOT_GET_SELECTION);
+    return (info.fState & OS.MFS_CHECKED) !is 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled menu item is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #getEnabled
+ */
+public bool isEnabled () {
+    return getEnabled () && parent.isEnabled ();
+}
+
+override void releaseChildren (bool destroy) {
+    if (menu !is null) {
+        menu.release (false);
+        menu = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+    id = -1;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (menu !is null) menu.dispose ();
+    menu = null;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (hBitmap !is null) OS.DeleteObject (hBitmap);
+    hBitmap = null;
+    if (accelerator !is 0) {
+        parent.destroyAccelerators ();
+    }
+    accelerator = 0;
+    display.removeMenuItem (this);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the arm events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ArmListener
+ * @see #addArmListener
+ */
+public void removeArmListener (ArmListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Arm, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the help events are generated for the control.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 HelpListener
+ * @see #addHelpListener
+ */
+public void removeHelpListener (HelpListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Help, listener);
+}
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void selectRadio () {
+    int index = 0;
+    MenuItem [] items = parent.getItems ();
+    while (index < items.length && items [index] !is this) index++;
+    int i = index - 1;
+    while (i >= 0 && items [i].setRadioSelection (false)) --i;
+    int j = index + 1;
+    while (j < items.length && items [j].setRadioSelection (false)) j++;
+    setSelection (true);
+}
+
+/**
+ * Sets the widget accelerator.  An accelerator is the bit-wise
+ * OR of zero or more modifier masks and a key. Examples:
+ * <code>SWT.MOD1 | SWT.MOD2 | 'T', SWT.MOD3 | SWT.F2</code>.
+ * <code>SWT.CONTROL | SWT.SHIFT | 'T', SWT.ALT | SWT.F2</code>.
+ * The default value is zero, indicating that the menu item does
+ * not have an accelerator.
+ *
+ * @param accelerator an integer that is the bit-wise OR of masks and a key
+ *
+ * </ul>
+ * @exception SWTException <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 setAccelerator (int accelerator) {
+    checkWidget ();
+    if (this.accelerator is accelerator) return;
+    this.accelerator = accelerator;
+    parent.destroyAccelerators ();
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled menu item is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <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 setEnabled (bool enabled) {
+    checkWidget ();
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
+        auto hwndCB = parent.hwndCB;
+        TBBUTTONINFO info;
+        info.cbSize = TBBUTTONINFO.sizeof;
+        info.dwMask = OS.TBIF_STATE;
+        OS.SendMessage (hwndCB, OS.TB_GETBUTTONINFO, id, &info);
+        info.fsState &= ~OS.TBSTATE_ENABLED;
+        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 & SWT.SEPARATOR) !is 0) {
+            if (enabled) {
+                state &= ~DISABLED;
+            } else {
+                state |= DISABLED;
+            }
+        }
+        auto hMenu = parent.handle;
+        static if (OS.IsWinCE) {
+            int index = parent.indexOf (this);
+            if (index is -1) return;
+            int uEnable = OS.MF_BYPOSITION | (enabled ? OS.MF_ENABLED : OS.MF_GRAYED);
+            OS.EnableMenuItem (hMenu, index, uEnable);
+        } else {
+            MENUITEMINFO info;
+            info.cbSize = OS.MENUITEMINFO_sizeof;
+            info.fMask = OS.MIIM_STATE;
+            bool success = cast(bool) OS.GetMenuItemInfo (hMenu, id, false, &info);
+            if (!success) error (SWT.ERROR_CANNOT_SET_ENABLED);
+            int bits = OS.MFS_DISABLED | OS.MFS_GRAYED;
+            if (enabled) {
+                if ((info.fState & bits) is 0) return;
+                info.fState &= ~bits;
+            } else {
+                if ((info.fState & bits) is bits) return;
+                info.fState |= bits;
+            }
+            success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
+            if (!success) {
+                /*
+                * Bug in Windows.  For some reason SetMenuItemInfo(),
+                * returns a fail code when setting the enabled or
+                * selected state of a default item, but sets the
+                * state anyway.  The fix is to ignore the error.
+                *
+                * NOTE:  This only happens on Vista.
+                */
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                    success = id is OS.GetMenuDefaultItem (hMenu, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+                }
+                if (!success) error (SWT.ERROR_CANNOT_SET_ENABLED);
+            }
+        }
+    }
+    parent.destroyAccelerators ();
+    parent.redraw ();
+}
+
+/**
+ * Sets the image the receiver will display to the argument.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept (for example, Windows NT).
+ * </p>
+ *
+ * @param image the image to display
+ *
+ * @exception SWTException <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>
+ */
+override public void setImage (Image image) {
+    checkWidget ();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    super.setImage (image);
+    static if (OS.IsWinCE) {
+        if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
+            int /*long*/ hwndCB = parent.hwndCB;
+            TBBUTTONINFO info;
+            info.cbSize = TBBUTTONINFO.sizeof;
+            info.dwMask = OS.TBIF_IMAGE;
+            info.iImage = parent.imageIndex (image);
+            OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, id, &info);
+        }
+        return;
+    }
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
+    MENUITEMINFO info;
+    info.cbSize = OS.MENUITEMINFO_sizeof;
+    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)) {
+            if (hBitmap !is null) OS.DeleteObject (hBitmap);
+            info.hbmpItem = hBitmap = image !is null ? Display.create32bitDIB (image) : null;
+        } else {
+            info.hbmpItem = OS.HBMMENU_CALLBACK;
+        }
+    }
+    auto hMenu = parent.handle;
+    OS.SetMenuItemInfo (hMenu, id, false, &info);
+    parent.redraw ();
+}
+
+/**
+ * Sets the receiver's pull down menu to the argument.
+ * Only <code>CASCADE</code> menu items can have a
+ * pull down menu. The sequence of key strokes, button presses
+ * and/or button releases that are used to request a pull down
+ * menu is platform specific.
+ * <p>
+ * Note: Disposing of a menu item that has a pull down menu
+ * will dispose of the menu.  To avoid this behavior, set the
+ * menu to null before the menu item is disposed.
+ * </p>
+ *
+ * @param menu the new pull down menu
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_MENU_NOT_DROP_DOWN - if the menu is not a drop down menu</li>
+ *    <li>ERROR_MENUITEM_NOT_CASCADE - if the menu item is not a <code>CASCADE</code></li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setMenu (Menu menu) {
+    checkWidget ();
+
+    /* Check to make sure the new menu is valid */
+    if ((style & SWT.CASCADE) is 0) {
+        error (SWT.ERROR_MENUITEM_NOT_CASCADE);
+    }
+    if (menu !is null) {
+        if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+        if ((menu.style & SWT.DROP_DOWN) is 0) {
+            error (SWT.ERROR_MENU_NOT_DROP_DOWN);
+        }
+        if (menu.parent !is parent.parent) {
+            error (SWT.ERROR_INVALID_PARENT);
+        }
+    }
+    setMenu (menu, false);
+}
+
+void setMenu (Menu menu, bool dispose) {
+
+    /* Assign the new menu */
+    Menu oldMenu = this.menu;
+    if (oldMenu is menu) return;
+    if (oldMenu !is null) oldMenu.cascade = null;
+    this.menu = menu;
+
+    /* Assign the new menu in the OS */
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
+        if (OS.IsPPC) {
+            HWND hwndCB = parent.hwndCB;
+            HMENU hMenu = menu is null ? null : menu.handle;
+            OS.SendMessage (hwndCB, OS.SHCMBM_SETSUBMENU, id, hMenu);
+        }
+        if (OS.IsSP) error (SWT.ERROR_CANNOT_SET_MENU);
+    } else {
+        HMENU hMenu = parent.handle;
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        info.fMask = OS.MIIM_DATA;
+        int index = 0;
+        while (OS.GetMenuItemInfo (hMenu, index, true, &info)) {
+            if (info.dwItemData is id) break;
+            index++;
+        }
+        if (info.dwItemData !is id) return;
+        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 use MIIM_BITMAP and MIIM_STRING.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+            info.fMask |= OS.MIIM_BITMAP | OS.MIIM_STRING;
+        } else {
+            info.fMask |= OS.MIIM_TYPE;
+        }
+        info.dwTypeData = pszText;
+        info.cch = cch;
+        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;
+        }
+        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
+            * state and submenu.  The fix is to use InsertMenu() to insert
+            * the item, SetMenuItemInfo() to set the string and EnableMenuItem()
+            * and CheckMenuItem() to set the state.
+            */
+            int /*long*/ uIDNewItem = id;
+            int uFlags = OS.MF_BYPOSITION;
+            if (menu !is null) {
+                uFlags |= OS.MF_POPUP;
+                uIDNewItem = cast(int)menu.handle;
+            }
+            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) !is 0;
+                if ((info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) !is 0) {
+                    OS.EnableMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_GRAYED);
+                }
+                if ((info.fState & OS.MFS_CHECKED) !is 0) {
+                    OS.CheckMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_CHECKED);
+                }
+            }
+        } else {
+            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);
+        if (!success) error (SWT.ERROR_CANNOT_SET_MENU);
+    }
+    parent.destroyAccelerators ();
+}
+
+bool setRadioSelection (bool value) {
+    if ((style & SWT.RADIO) is 0) return false;
+    if (getSelection () !is value) {
+        setSelection (value);
+        postEvent (SWT.Selection);
+    }
+    return true;
+}
+
+/**
+ * Sets the selection state of the receiver.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked.
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException <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 setSelection (bool selected) {
+    checkWidget ();
+    if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return;
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) return;
+    auto hMenu = parent.handle;
+    if (OS.IsWinCE) {
+        int index = parent.indexOf (this);
+        if (index is -1) return;
+        int uCheck = OS.MF_BYPOSITION | (selected ? OS.MF_CHECKED : OS.MF_UNCHECKED);
+        OS.CheckMenuItem (hMenu, index, uCheck);
+    } else {
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        info.fMask = OS.MIIM_STATE;
+        bool success = cast(bool) OS.GetMenuItemInfo (hMenu, id, false, &info);
+        if (!success) error (SWT.ERROR_CANNOT_SET_SELECTION);
+        info.fState &= ~OS.MFS_CHECKED;
+        if (selected) info.fState |= OS.MFS_CHECKED;
+        success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
+        if (!success) {
+            /*
+            * Bug in Windows.  For some reason SetMenuItemInfo(),
+            * returns a fail code when setting the enabled or
+            * selected state of a default item, but sets the
+            * state anyway.  The fix is to ignore the error.
+            *
+            * NOTE:  This only happens on Vista.
+            */
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                success = id is OS.GetMenuDefaultItem (hMenu, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED);
+            }
+            if (!success) error (SWT.ERROR_CANNOT_SET_SELECTION);
+        }
+    }
+    parent.redraw ();
+}
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character and accelerator text.
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner.  The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ * <p>
+ * Accelerator text is indicated by the '\t' character.
+ * On platforms that support accelerator text, the text
+ * that follows the '\t' character is displayed to the user,
+ * typically indicating the key stroke that will cause
+ * the item to become selected.  On most platforms, the
+ * accelerator text appears right aligned in the menu.
+ * Setting the accelerator text does not install the
+ * accelerator key sequence. The accelerator key sequence
+ * is installed using #setAccelerator.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 #setAccelerator
+ */
+override public void setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (text==/*eq*/string ) return;
+    super.setText (string);
+    auto hHeap = OS.GetProcessHeap ();
+    TCHAR* pszText;
+    bool success = false;
+    if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
+        /*
+        * Bug in WinCE PPC.  Tool items on the menubar don't resize
+        * correctly when the character '&' is used (even when it
+        * is a sequence '&&').  The fix is to remove all '&' from
+        * the string.
+        */
+        if (string.indexOf ('&') !is -1) {
+            int length_ = string.length;
+            char[] text = new char [length_];
+            string.getChars( 0, length_, text, 0);
+            int i = 0, j = 0;
+            for (i=0; i<length_; i++) {
+                if (text[i] !is '&') text [j++] = text [i];
+            }
+            if (j < i) string = text[ 0 .. j ].dup;
+        }
+        /* 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);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+        auto hwndCB = parent.hwndCB;
+        TBBUTTONINFO info2;
+        info2.cbSize = TBBUTTONINFO.sizeof;
+        info2.dwMask = OS.TBIF_TEXT;
+        info2.pszText = pszText;
+        success = OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, id, &info2) !is 0;
+    } else {
+        MENUITEMINFO info;
+        info.cbSize = OS.MENUITEMINFO_sizeof;
+        auto hMenu = parent.handle;
+
+        /* 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);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+        /*
+        * 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)) {
+            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 (SWT.ERROR_CANNOT_SET_TEXT);
+    parent.redraw ();
+}
+
+int widgetStyle () {
+    int bits = 0;
+    Decorations shell = parent.parent;
+    if ((shell.style & SWT.MIRRORED) !is 0) {
+        if ((parent.style & SWT.LEFT_TO_RIGHT) !is 0) {
+            bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+        }
+    } else {
+        if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) {
+            bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER;
+        }
+    }
+    if ((style & SWT.SEPARATOR) !is 0) return bits | OS.MFT_SEPARATOR;
+    if ((style & SWT.RADIO) !is 0) return bits | OS.MFT_RADIOCHECK;
+    return bits | OS.MFT_STRING;
+}
+
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
+    if ((style & SWT.CHECK) !is 0) {
+        setSelection (!getSelection ());
+    } else {
+        if ((style & SWT.RADIO) !is 0) {
+            if ((parent.getStyle () & SWT.NO_RADIO_GROUP) !is 0) {
+                setSelection (!getSelection ());
+            } else {
+                selectRadio ();
+            }
+        }
+    }
+    Event event = new Event ();
+    setInputState (event, SWT.Selection);
+    postEvent (SWT.Selection, event);
+    return null;
+}
+
+LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) {
+    DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam;
+    //OS.MoveMemory (struct_, lParam, DRAWITEMSTRUCT.sizeof);
+    if (image !is null) {
+        GCData data = new GCData();
+        data.device = display;
+        GC gc = GC.win32_new (struct_.hDC, data);
+        /*
+        * Bug in Windows.  When a bitmap is included in the
+        * menu bar, the HDC seems to already include the left
+        * coordinate.  The fix is to ignore this value when
+        * the item is in a menu bar.
+        */
+        int x = (parent.style & SWT.BAR) !is 0 ? MARGIN_WIDTH * 2 : struct_.rcItem.left;
+        Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE);
+        gc.drawImage (image, x, struct_.rcItem.top + MARGIN_HEIGHT);
+        if (this.image !is image) image.dispose ();
+        gc.dispose ();
+    }
+    if (parent.foreground !is -1) OS.SetTextColor (struct_.hDC, parent.foreground);
+    return null;
+}
+
+LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) {
+    MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;
+    //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof);
+    int width = 0, height = 0;
+    if (image !is null) {
+        Rectangle rect = image.getBounds ();
+        width = rect.width;
+        height = rect.height;
+    } else {
+        /*
+        * Bug in Windows.  If a menu contains items that have
+        * images and can be checked, Windows does not include
+        * the width of the image and the width of the check when
+        * computing the width of the menu.  When the longest item
+        * does not have an image, the label and the accelerator
+        * text can overlap.  The fix is to use SetMenuItemInfo()
+        * to indicate that all items have a bitmap and then include
+        * the width of the widest bitmap in WM_MEASURECHILD.
+        */
+        MENUINFO lpcmi;
+        lpcmi.cbSize = MENUINFO.sizeof;
+        lpcmi.fMask = OS.MIM_STYLE;
+        auto hMenu = parent.handle;
+        OS.GetMenuInfo (hMenu, &lpcmi);
+        if ((lpcmi.dwStyle & OS.MNS_CHECKORBMP) is 0) {
+            MenuItem [] items = parent.getItems ();
+            for (int i=0; i<items.length; i++) {
+                MenuItem item = items [i];
+                if (item.image !is null) {
+                    Rectangle rect = item.image.getBounds ();
+                    width = Math.max (width, rect.width);
+                }
+            }
+        }
+    }
+    if (width !is 0 || height !is 0) {
+        struct_.itemWidth = width + MARGIN_WIDTH * 2;
+        struct_.itemHeight = height + MARGIN_HEIGHT * 2;
+        //OS.MoveMemory (lParam, struct_, MEASUREITEMSTRUCT.sizeof);
+    }
+    return null;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/MessageBox.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.MessageBox;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Display;
+import java.lang.all;
+
+/**
+ * Instances of this class are used to inform or warn the user.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>ICON_ERROR, ICON_INFORMATION, ICON_QUESTION, ICON_WARNING, ICON_WORKING</dd>
+ * <dd>OK, OK | CANCEL</dd>
+ * <dd>YES | NO, YES | NO | CANCEL</dd>
+ * <dd>RETRY | CANCEL</dd>
+ * <dd>ABORT | RETRY | IGNORE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION, ICON_QUESTION,
+ * ICON_WARNING and ICON_WORKING may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample, Dialog tab</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public  class MessageBox : Dialog {
+
+    alias Dialog.checkStyle checkStyle;
+
+    String message = "";
+    private bool allowNullParent = false;
+
+/**
+ * Constructs a new instance of this class given only its parent.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, SWT.OK | SWT.ICON_INFORMATION | SWT.APPLICATION_MODAL);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of dialog to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (parent, checkStyle (style)));
+    checkSubclass ();
+}
+
+/++
+ + SWT extension, a MessageBox with no parent
+ +/
+public this (int style) {
+    allowNullParent = true;
+    this( null, style );
+}
+// PORT
+// actually, the parent can be null
+override void checkParent (Shell parent){
+    if( !allowNullParent ){
+        super.checkParent( parent );
+    }
+}
+
+static int checkStyle (int style) {
+    int mask = (SWT.YES | SWT.NO | SWT.OK | SWT.CANCEL | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
+    int bits = style & mask;
+    if (bits is SWT.OK || bits is SWT.CANCEL || bits is (SWT.OK | SWT.CANCEL)) return style;
+    if (bits is SWT.YES || bits is SWT.NO || bits is (SWT.YES | SWT.NO) || bits is (SWT.YES | SWT.NO | SWT.CANCEL)) return style;
+    if (bits is (SWT.RETRY | SWT.CANCEL) || bits is (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) return style;
+    style = (style & ~mask) | SWT.OK;
+    return style;
+}
+
+/**
+ * Returns the dialog's message, or an empty string if it does not have one.
+ * The message is a description of the purpose for which the dialog was opened.
+ * This message will be visible in the dialog while it is open.
+ *
+ * @return the message
+ */
+public String getMessage () {
+    return message;
+}
+
+/**
+ * Makes the dialog visible and brings it to the front
+ * of the display.
+ *
+ * @return the ID of the button that was selected to dismiss the
+ *         message box (e.g. SWT.OK, SWT.CANCEL, etc.)
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the dialog has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li>
+ * </ul>
+ */
+public int open () {
+
+    /* Compute the MessageBox style */
+    int buttonBits = 0;
+    if ((style & SWT.OK) is SWT.OK) buttonBits = OS.MB_OK;
+    if ((style & (SWT.OK | SWT.CANCEL)) is (SWT.OK | SWT.CANCEL)) buttonBits = OS.MB_OKCANCEL;
+    if ((style & (SWT.YES | SWT.NO)) is (SWT.YES | SWT.NO)) buttonBits = OS.MB_YESNO;
+    if ((style & (SWT.YES | SWT.NO | SWT.CANCEL)) is (SWT.YES | SWT.NO | SWT.CANCEL)) buttonBits = OS.MB_YESNOCANCEL;
+    if ((style & (SWT.RETRY | SWT.CANCEL)) is (SWT.RETRY | SWT.CANCEL)) buttonBits = OS.MB_RETRYCANCEL;
+    if ((style & (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) is (SWT.ABORT | SWT.RETRY | SWT.IGNORE)) buttonBits = OS.MB_ABORTRETRYIGNORE;
+    if (buttonBits is 0) buttonBits = OS.MB_OK;
+
+    int iconBits = 0;
+    if ((style & SWT.ICON_ERROR) !is 0) iconBits = OS.MB_ICONERROR;
+    if ((style & SWT.ICON_INFORMATION) !is 0) iconBits = OS.MB_ICONINFORMATION;
+    if ((style & SWT.ICON_QUESTION) !is 0) iconBits = OS.MB_ICONQUESTION;
+    if ((style & SWT.ICON_WARNING) !is 0) iconBits = OS.MB_ICONWARNING;
+    if ((style & SWT.ICON_WORKING) !is 0) iconBits = OS.MB_ICONINFORMATION;
+
+    /* Only MB_APPLMODAL is supported on WinCE */
+    int modalBits = 0;
+    static if (OS.IsWinCE) {
+        if ((style & (SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+            modalBits = OS.MB_APPLMODAL;
+        }
+    } else {
+        if ((style & SWT.PRIMARY_MODAL) !is 0) modalBits = OS.MB_APPLMODAL;
+        if ((style & SWT.APPLICATION_MODAL) !is 0) modalBits = OS.MB_TASKMODAL;
+        if ((style & SWT.SYSTEM_MODAL) !is 0) modalBits = OS.MB_SYSTEMMODAL;
+    }
+
+    int bits = buttonBits | iconBits | modalBits;
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) bits |= OS.MB_RTLREADING | OS.MB_RIGHT;
+    if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) is 0) {
+        if (parent !is null && (parent.style & SWT.MIRRORED) !is 0) {
+            bits |= OS.MB_RTLREADING | OS.MB_RIGHT;
+        }
+    }
+
+    /*
+    * Feature in Windows.  System modal is not supported
+    * on Windows 95 and NT.  The fix is to convert system
+    * modal to task modal.
+    */
+    if ((bits & OS.MB_SYSTEMMODAL) !is 0) {
+        bits |= OS.MB_TASKMODAL;
+        bits &= ~OS.MB_SYSTEMMODAL;
+        /* Force a system modal message box to the front */
+        bits |= OS.MB_TOPMOST;
+    }
+
+    /*
+    * Feature in Windows.  In order for MB_TASKMODAL to work,
+    * the parent HWND of the MessageBox () call must be NULL.
+    * If the parent is not NULL, MB_TASKMODAL behaves the
+    * same as MB_APPLMODAL.  The fix to set the parent HWND
+    * anyway and not rely on MB_MODAL to work by making the
+    * parent be temporarily modal.
+    */
+    HWND hwndOwner = parent !is null ? parent.handle : 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.getModalDialog ();
+        display.setModalDialog (this);
+    }
+
+    /* Open the message box */
+    /* Use the character encoding for the default locale */
+    TCHAR[] buffer1 = StrToTCHARs (0, message, true);
+    TCHAR[] buffer2 = StrToTCHARs (0, title, true);
+    int code = OS.MessageBox (hwndOwner, buffer1.ptr, buffer2.ptr, bits);
+
+    /* Clear the temporarily dialog modal parent */
+    if ((bits & OS.MB_TASKMODAL) !is 0) {
+        display.setModalDialog (oldModal);
+    }
+
+    /*
+    * This code is intentionally commented.  On some
+    * platforms, the owner window is repainted right
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
+
+    /* Compute and return the result */
+    if (code !is 0) {
+        int type = bits & 0x0F;
+        if (type is OS.MB_OK) return SWT.OK;
+        if (type is OS.MB_OKCANCEL) {
+            return (code is OS.IDOK) ? SWT.OK : SWT.CANCEL;
+        }
+        if (type is OS.MB_YESNO) {
+            return (code is OS.IDYES) ? SWT.YES : SWT.NO;
+        }
+        if (type is OS.MB_YESNOCANCEL) {
+            if (code is OS.IDYES) return SWT.YES;
+            if (code is OS.IDNO) return SWT.NO;
+            return SWT.CANCEL;
+        }
+        if (type is OS.MB_RETRYCANCEL) {
+            return (code is OS.IDRETRY) ? SWT.RETRY : SWT.CANCEL;
+        }
+        if (type is OS.MB_ABORTRETRYIGNORE) {
+            if (code is OS.IDRETRY) return SWT.RETRY;
+            if (code is OS.IDABORT) return SWT.ABORT;
+            return SWT.IGNORE;
+        }
+    }
+    return SWT.CANCEL;
+}
+
+/**
+ * Sets the dialog's message, which is a description of
+ * the purpose for which it was opened. This message will be
+ * visible on the dialog while it is open.
+ *
+ * @param string the message
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
+ * </ul>
+ */
+public void setMessage (String string) {
+    if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    message = string;
+}
+
+/++
+ + SWT extension
+ +/
+public static int showMessageBox(String str, String title, Shell shell, int style) {
+    MessageBox msgBox = (shell is null ) ? new MessageBox( style ) : new MessageBox(shell, style);
+    msgBox.setMessage(str);
+    if(title !is null){
+        msgBox.setText(title);
+    }
+    return msgBox.open();
+}
+
+/// SWT extension
+public static int showInfo(String str, String title = null, Shell shell = null) {
+    return showMessageBox( str, title, shell, SWT.OK | SWT.ICON_INFORMATION );
+}
+/// SWT extension
+alias showInfo showInformation;
+
+/// SWT extension
+public static int showWarning(String str, String title = null, Shell shell = null) {
+    return showMessageBox( str, title, shell, SWT.OK | SWT.ICON_WARNING );
+}
+/// SWT extension
+public static int showError(String str, String title = null, Shell shell = null) {
+    return showMessageBox( str, title, shell, SWT.OK | SWT.ICON_ERROR );
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Monitor.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Monitor;
+
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.WINTYPES;
+
+/**
+ * Instances of this class are descriptions of monitors.
+ *
+ * @see Display
+ * @see <a href="http://www.eclipse.org/swt/snippets/#monitor">Monitor snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public final class Monitor {
+    HMONITOR handle;
+    int x, y, width, height;
+    int clientX, clientY, clientWidth, clientHeight;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Compares the argument to the receiver, and returns true
+ * if they represent the <em>same</em> object using a class
+ * specific comparison.
+ *
+ * @param object the object to compare with this object
+ * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
+ *
+ * @see #hashCode()
+ */
+public override int opEquals (Object object) {
+    if (object is this) return true;
+    if ( auto mon = cast(org.eclipse.swt.widgets.Monitor.Monitor)object ){
+       return handle is mon.handle;
+    }
+    return false;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its device. Note that on multi-monitor systems the
+ * origin can be negative.
+ *
+ * @return the receiver's bounding rectangle
+ */
+public Rectangle getBounds () {
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ */
+public Rectangle getClientArea () {
+    return new Rectangle (clientX, clientY, clientWidth, clientHeight);
+}
+
+/**
+ * Returns an integer hash code for the receiver. Any two
+ * objects that return <code>true</code> when passed to
+ * <code>equals</code> must return the same value for this
+ * method.
+ *
+ * @return the receiver's hash
+ *
+ * @see #equals(Object)
+ */
+public override hash_t toHash() {
+    return cast(hash_t)handle;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ProgressBar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,483 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ProgressBar;
+
+import org.eclipse.swt.widgets.Control;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+
+import java.lang.all;
+
+/**
+ * Instances of the receiver represent an unselectable
+ * user interface object that is used to display progress,
+ * typically in the form of a bar.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>SMOOTH, HORIZONTAL, VERTICAL, INDETERMINATE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#progressbar">ProgressBar snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class ProgressBar : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.windowProc windowProc;
+
+    static const int DELAY = 100;
+    static const int TIMER_ID = 100;
+    static const int MINIMUM_WIDTH = 100;
+    private static /+const+/ WNDPROC ProgressBarProc;
+    static const TCHAR[] ProgressBarClass = OS.PROGRESS_CLASS;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ProgressBarClass.ptr, &lpWndClass);
+            ProgressBarProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The progress bar 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 SWT, 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 = (ProgressBarClass.length+1) * TCHAR.sizeof;
+            TCHAR* lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, ProgressBarClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SMOOTH
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc (ProgressBarProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    style |= SWT.NO_FOCUS;
+    return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int border = getBorderWidth ();
+    int width = border * 2, height = border * 2;
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    } else {
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+        height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint + (border * 2);
+    if (hHint !is SWT.DEFAULT) height = hHint + (border * 2);
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    startTimer ();
+}
+
+override int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <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 int getMaximum () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.PBM_GETRANGE, 0, 0);
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <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 int getMinimum () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.PBM_GETRANGE, 1, 0);
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <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 int getSelection () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.PBM_GETPOS, 0, 0);
+}
+
+/**
+ * Returns the state of the receiver. The value will be one of:
+ * <ul>
+ *  <li>{@link SWT#NORMAL}</li>
+ *  <li>{@link SWT#ERROR}</li>
+ *  <li>{@link SWT#PAUSED}</li>
+ * </ul>
+ *
+ * @return the state
+ *
+ * @exception SWTException <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 SWT.NORMAL;
+            case OS.PBST_ERROR: return SWT.ERROR;
+            case OS.PBST_PAUSED: return SWT.PAUSED;
+            default:
+        }
+    }
+    return SWT.NORMAL;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    stopTimer ();
+}
+
+void startTimer () {
+    if ((style & SWT.INDETERMINATE) !is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if (OS.COMCTL32_MAJOR < 6 || (bits & OS.PBS_MARQUEE) is 0) {
+            OS.SetTimer (handle, TIMER_ID, DELAY, null);
+        } else {
+            OS.SendMessage (handle, OS.PBM_SETMARQUEE, 1, DELAY);
+        }
+    }
+}
+
+void stopTimer () {
+    if ((style & SWT.INDETERMINATE) !is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if (OS.COMCTL32_MAJOR < 6 || (bits & OS.PBS_MARQUEE) is 0) {
+            OS.KillTimer (handle, TIMER_ID);
+        } else {
+            OS.SendMessage (handle, OS.PBM_SETMARQUEE, 0, 0);
+        }
+    }
+}
+
+override void setBackgroundPixel (int pixel) {
+    if (pixel is -1) pixel = OS.CLR_DEFAULT;
+    OS.SendMessage (handle, OS.PBM_SETBKCOLOR, 0, pixel);
+}
+
+override void setForegroundPixel (int pixel) {
+    if (pixel is -1) pixel = OS.CLR_DEFAULT;
+    OS.SendMessage (handle, OS.PBM_SETBARCOLOR, 0, pixel);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow.  This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value.  If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException <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 setMaximum (int value) {
+    checkWidget ();
+    int minimum = OS.SendMessage (handle, OS.PBM_GETRANGE, 1, 0);
+    if (0 <= minimum && minimum < value) {
+        OS.SendMessage (handle, OS.PBM_SETRANGE32, minimum, value);
+    }
+}
+
+/**
+ * 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
+ * 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
+ *
+ * @exception SWTException <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 setMinimum (int value) {
+    checkWidget ();
+    int maximum = OS.SendMessage (handle, OS.PBM_GETRANGE, 0, 0);
+    if (0 <= value && value < maximum) {
+        OS.SendMessage (handle, OS.PBM_SETRANGE32, value, maximum);
+    }
+}
+
+/**
+ * Sets the single 'selection' that is the receiver's
+ * position to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <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 setSelection (int value) {
+    checkWidget ();
+    /*
+    * Feature in Vista.  When the progress bar is not in
+    * a normal state, PBM_SETPOS does not set the position
+    * of the bar when the selection is equal to the minimum.
+    * 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;
+    bool fixSelection = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        int /*long*/ minumum = OS.SendMessage (handle, OS.PBM_GETRANGE, 1, 0);
+        int /*long*/ selection = OS.SendMessage (handle, OS.PBM_GETPOS, 0, 0);
+        if (selection is minumum) {
+            fixSelection = true;
+            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)) {
+        if (fixSelection) OS.SendMessage (handle, OS.PBM_SETSTATE, state, 0);
+    }
+}
+
+/**
+ * Sets the state of the receiver. The state must be one of these values:
+ * <ul>
+ *  <li>{@link SWT#NORMAL}</li>
+ *  <li>{@link SWT#ERROR}</li>
+ *  <li>{@link SWT#PAUSED}</li>
+ * </ul>
+ *
+ * @param state the new state
+ *
+ * @exception SWTException <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 SWT.NORMAL:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_NORMAL, 0);
+                break;
+            case SWT.ERROR:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_ERROR, 0);
+                break;
+            case SWT.PAUSED:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_PAUSED, 0);
+                break;
+            default:
+        }
+    }
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle ();
+    if ((style & SWT.SMOOTH) !is 0) bits |= OS.PBS_SMOOTH;
+    if ((style & SWT.VERTICAL) !is 0) bits |= OS.PBS_VERTICAL;
+    if ((style & SWT.INDETERMINATE) !is 0) bits |= OS.PBS_MARQUEE;
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARsToStr( ProgressBarClass );
+}
+
+override int windowProc () {
+    return cast(int) ProgressBarProc;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  The progress bar does
+    * not implement WM_GETDLGCODE.  As a result,
+    * a progress bar takes focus and takes part
+    * in tab traversal.  This behavior, while
+    * unspecified, is unwanted.  The fix is to
+    * implement WM_GETDLGCODE to behave like a
+    * STATIC control.
+    */
+    return new LRESULT (OS.DLGC_STATIC);
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  When a progress bar with the style
+    * PBS_MARQUEE becomes too small, the animation (currently
+    * a small bar moving from right to left) does not have
+    * enough space to draw.  The result is that the progress
+    * bar does not appear to be moving.  The fix is to detect
+    * this case, clear the PBS_MARQUEE style and emulate the
+    * animation using PBM_STEPIT.
+    *
+    * NOTE:  This only happens on Window XP.
+    */
+    if ((style & SWT.INDETERMINATE) !is 0) {
+        if (OS.COMCTL32_MAJOR >= 6) {
+            forceResize ();
+            RECT rect;
+            OS.GetClientRect (handle, &rect);
+            int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            int newBits = oldBits;
+            if (rect.right - rect.left < MINIMUM_WIDTH) {
+                newBits &= ~OS.PBS_MARQUEE;
+            } else {
+                newBits |= OS.PBS_MARQUEE;
+            }
+            if (newBits !is oldBits) {
+                stopTimer ();
+                OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+                startTimer ();
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_TIMER (int wParam, int lParam) {
+    LRESULT result = super.WM_TIMER (wParam, lParam);
+    if (result !is null) return result;
+    if ((style & SWT.INDETERMINATE) !is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if (OS.COMCTL32_MAJOR < 6 || (bits & OS.PBS_MARQUEE) is 0) {
+            if (wParam is TIMER_ID) {
+                OS.SendMessage (handle, OS.PBM_STEPIT, 0, 0);
+            }
+        }
+    }
+    return result;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/RunnableLock.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.RunnableLock;
+
+import tango.core.Thread;
+import java.lang.Runnable;
+import tango.core.Exception;
+import tango.core.sync.Condition;
+import tango.core.sync.Mutex;
+
+/**
+ * Instances of this class are used to ensure that an
+ * application cannot interfere with the locking mechanism
+ * used to implement asynchronous and synchronous communication
+ * between widgets and background threads.
+ */
+
+class RunnableLock : Mutex {
+    Runnable runnable;
+    Thread thread;
+    Exception throwable;
+    Condition cond;
+
+this (Runnable runnable) {
+    this.runnable = runnable;
+    this.cond = new Condition(this);
+}
+
+bool done () {
+    return runnable is null || throwable !is null;
+}
+
+void run () {
+    if (runnable !is null) runnable.run ();
+    runnable = null;
+}
+
+void notifyAll(){
+    cond.notifyAll();
+}
+void wait(){
+    cond.wait();
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Sash.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Sash;
+
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of the receiver represent a selectable user interface object
+ * that allows the user to drag a rubber banded outline of the sash within
+ * the parent control.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL, SMOOTH</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#sash">Sash snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Sash : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.windowProc windowProc;
+
+    bool dragging;
+    int startX, startY, lastX, lastY;
+    const static int INCREMENT = 1;
+    const static int PAGE_INCREMENT = 9;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the x, y, width, and height fields of the event object are valid.
+ * If the receiver is being dragged, the event object detail field contains the value <code>SWT.DRAG</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state |= THEME_BACKGROUND;
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int border = getBorderWidth ();
+    int width = border * 2, height = border * 2;
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        width += DEFAULT_WIDTH;  height += 3;
+    } else {
+        width += 3; height += DEFAULT_HEIGHT;
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint + (border * 2);
+    if (hHint !is SWT.DEFAULT) height = hHint + (border * 2);
+    return new Point (width, height);
+}
+
+void drawBand (int x, int y, int width, int height) {
+    if ((style & SWT.SMOOTH) !is 0) return;
+    HWND hwndTrack = parent.handle;
+    byte [] bits = [-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0];
+    auto stippleBitmap = OS.CreateBitmap (8, 8, 1, 1, bits.ptr);
+    auto stippleBrush = OS.CreatePatternBrush (stippleBitmap);
+    auto hDC = OS.GetDCEx (hwndTrack, null, OS.DCX_CACHE);
+    auto oldBrush = OS.SelectObject (hDC, stippleBrush);
+    OS.PatBlt (hDC, x, y, width, height, OS.PATINVERT);
+    OS.SelectObject (hDC, oldBrush);
+    OS.ReleaseDC (hwndTrack, hDC);
+    OS.DeleteObject (stippleBrush);
+    OS.DeleteObject (stippleBitmap);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+override String windowClass () {
+    return display.windowClass();
+}
+
+override int windowProc () {
+    return display.windowProc();
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    super.WM_ERASEBKGND (wParam, lParam);
+    drawBackground (cast(HANDLE) wParam);
+    return LRESULT.ONE;
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    switch (wParam) {
+        case OS.VK_LEFT:
+        case OS.VK_RIGHT:
+        case OS.VK_UP:
+        case OS.VK_DOWN:
+
+            /* Calculate the new x or y position */
+            if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return result;
+            int step = OS.GetKeyState (OS.VK_CONTROL) < 0 ? INCREMENT : PAGE_INCREMENT;
+            POINT pt;
+            if ((style & SWT.VERTICAL) !is 0) {
+                if (wParam is OS.VK_UP || wParam is OS.VK_DOWN) break;
+                pt.x = wParam is OS.VK_LEFT ? -step : step;
+            } else {
+                if (wParam is OS.VK_LEFT || wParam is OS.VK_RIGHT) break;
+                pt.y = wParam is OS.VK_UP ? -step : step;
+            }
+            auto hwndTrack = parent.handle;
+            OS.MapWindowPoints (handle, hwndTrack, &pt, 1);
+            RECT rect, clientRect;
+            OS.GetWindowRect (handle, &rect);
+            int width = rect.right - rect.left;
+            int height = rect.bottom - rect.top;
+            OS.GetClientRect (hwndTrack, &clientRect);
+            int clientWidth = clientRect.right - clientRect.left;
+            int clientHeight = clientRect.bottom - clientRect.top;
+            int newX = lastX, newY = lastY;
+            if ((style & SWT.VERTICAL) !is 0) {
+                newX = Math.min (Math.max (0, pt.x - startX), clientWidth - width);
+            } else {
+                newY = Math.min (Math.max (0, pt.y - startY), clientHeight - height);
+            }
+            if (newX is lastX && newY is lastY) return result;
+
+            /* Update the pointer position */
+            POINT cursorPt;
+            cursorPt.x = pt.x;  cursorPt.y = pt.y;
+            OS.ClientToScreen (hwndTrack, &cursorPt);
+            if ((style & SWT.VERTICAL) !is 0) {
+                cursorPt.y += height / 2;
+            }
+            else {
+                cursorPt.x += width / 2;
+            }
+            OS.SetCursorPos (cursorPt.x, cursorPt.y);
+
+            Event event = new Event ();
+            event.x = newX;
+            event.y = newY;
+            event.width = width;
+            event.height = height;
+            sendEvent (SWT.Selection, event);
+            if (isDisposed ()) return LRESULT.ZERO;
+            if (event.doit) {
+                if ((style & SWT.SMOOTH) !is 0) {
+                    setBounds (event.x, event.y, width, height);
+                }
+            }
+            return result;
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    return new LRESULT (OS.DLGC_STATIC);
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+
+    /* Compute the banding rectangle */
+    auto hwndTrack = parent.handle;
+    POINT pt;
+    OS.POINTSTOPOINT (pt, lParam);
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    OS.MapWindowPoints (handle, null, &pt, 1);
+    startX = pt.x - rect.left;
+    startY = pt.y - rect.top;
+    OS.MapWindowPoints (null, hwndTrack, cast(POINT*) &rect, 2);
+    lastX = rect.left;
+    lastY = rect.top;
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+
+    /* The event must be sent because doit flag is used */
+    Event event = new Event ();
+    event.x = lastX;
+    event.y = lastY;
+    event.width = width;
+    event.height = height;
+    if ((style & SWT.SMOOTH) is 0) {
+        event.detail = SWT.DRAG;
+    }
+    sendEvent (SWT.Selection, event);
+    if (isDisposed ()) return LRESULT.ZERO;
+
+    /* Draw the banding rectangle */
+    if (event.doit) {
+        dragging = true;
+        lastX = event.x;
+        lastY = event.y;
+        menuShell ().bringToTop ();
+        if (isDisposed ()) return LRESULT.ZERO;
+        static if (OS.IsWinCE) {
+            OS.UpdateWindow (hwndTrack);
+        } else {
+            int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (hwndTrack, null, null, flags);
+        }
+        drawBand (event.x, event.y, width, height);
+        if ((style & SWT.SMOOTH) !is 0) {
+            setBounds (event.x, event.y, width, height);
+            // widget could be disposed at this point
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+    LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+
+    /* Compute the banding rectangle */
+    if (!dragging) return result;
+    dragging = false;
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+
+    /* The event must be sent because doit flag is used */
+    Event event = new Event ();
+    event.x = lastX;
+    event.y = lastY;
+    event.width = width;
+    event.height = height;
+    drawBand (event.x, event.y, width, height);
+    sendEvent (SWT.Selection, event);
+    if (isDisposed ()) return result;
+    if (event.doit) {
+        if ((style & SWT.SMOOTH) !is 0) {
+            setBounds (event.x, event.y, width, height);
+            // widget could be disposed at this point
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+    if (result !is null) return result;
+    if (!dragging || (wParam & OS.MK_LBUTTON) is 0) return result;
+
+    /* Compute the banding rectangle */
+    POINT pt;
+    OS.POINTSTOPOINT (pt, lParam);
+    auto hwndTrack = parent.handle;
+    OS.MapWindowPoints (handle, hwndTrack, &pt, 1);
+    RECT rect, clientRect;
+    OS.GetWindowRect (handle, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    OS.GetClientRect (hwndTrack, &clientRect);
+    int newX = lastX, newY = lastY;
+    if ((style & SWT.VERTICAL) !is 0) {
+        int clientWidth = clientRect.right - clientRect.left;
+        newX = Math.min (Math.max (0, pt.x - startX), clientWidth - width);
+    } else {
+        int clientHeight = clientRect.bottom - clientRect.top;
+        newY = Math.min (Math.max (0, pt.y - startY), clientHeight - height);
+    }
+    if (newX is lastX && newY is lastY) return result;
+    drawBand (lastX, lastY, width, height);
+
+    /* The event must be sent because doit flag is used */
+    Event event = new Event ();
+    event.x = newX;
+    event.y = newY;
+    event.width = width;
+    event.height = height;
+    if ((style & SWT.SMOOTH) is 0) {
+        event.detail = SWT.DRAG;
+    }
+    sendEvent (SWT.Selection, event);
+    if (isDisposed ()) return LRESULT.ZERO;
+    if (event.doit) {
+        lastX = event.x;
+        lastY = event.y;
+    }
+    static if (OS.IsWinCE) {
+        OS.UpdateWindow (hwndTrack);
+    } else {
+        int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (hwndTrack, null, null, flags);
+    }
+    drawBand (lastX, lastY, width, height);
+    if ((style & SWT.SMOOTH) !is 0) {
+        setBounds (lastX, lastY, width, height);
+        // widget could be disposed at this point
+    }
+    return result;
+}
+
+override LRESULT WM_SETCURSOR (int wParam, int lParam) {
+    LRESULT result = super.WM_SETCURSOR (wParam, lParam);
+    if (result !is null) return result;
+    int hitTest = cast(short) OS.LOWORD (lParam);
+    if (hitTest is OS.HTCLIENT) {
+        HCURSOR hCursor;
+        if ((style & SWT.HORIZONTAL) !is 0) {
+            hCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENS);
+        } else {
+            hCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZEWE);
+        }
+        OS.SetCursor (hCursor);
+        return LRESULT.ONE;
+    }
+    return result;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Scale.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Scale;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of the receiver represent a selectable user
+ * interface object that present a range of continuous
+ * numeric values.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#scale">Scale snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Scale : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.setBackgroundImage setBackgroundImage;
+    alias Control.windowProc windowProc;
+
+    bool ignoreResize, ignoreSelection;
+    private static /+const+/ WNDPROC TrackBarProc;
+    static const TCHAR[] TrackBarClass = OS.TRACKBAR_CLASS;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, TrackBarClass.ptr, &lpWndClass);
+            TrackBarProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The track bar 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 SWT, 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 = (TrackBarClass.length+1) * TCHAR.sizeof;
+            auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, TrackBarClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the user changes the receiver's value.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc (TrackBarProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int border = getBorderWidth ();
+    int width = border * 2, height = border * 2;
+    RECT rect;
+    OS.SendMessage (handle, OS.TBM_GETTHUMBRECT, 0, &rect);
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
+        int scrollY = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+        height += (rect.top * 2) + scrollY + (scrollY / 3);
+    } else {
+        int scrollX = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+        width += (rect.left * 2) + scrollX + (scrollX / 3);
+        height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint + (border * 2);
+    if (hHint !is SWT.DEFAULT) height = hHint + (border * 2);
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state |= THEME_BACKGROUND | DRAW_BACKGROUND;
+    OS.SendMessage (handle, OS.TBM_SETRANGEMAX, 0, 100);
+    OS.SendMessage (handle, OS.TBM_SETPAGESIZE, 0, 10);
+    OS.SendMessage (handle, OS.TBM_SETTICFREQ, 10, 0);
+}
+
+override int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_BTNFACE);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <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 int getIncrement () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TBM_GETLINESIZE, 0, 0);
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <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 int getMaximum () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <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 int getMinimum () {
+    checkWidget ();
+    return cast(int)OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <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 int getPageIncrement () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TBM_GETPAGESIZE, 0, 0);
+}
+
+/**
+ * Returns the 'selection', which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <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 int getSelection () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+override void setBackgroundImage (HBITMAP hImage) {
+    super.setBackgroundImage (hImage);
+    /*
+    * Bug in Windows.  Changing the background color of the Scale
+    * widget and calling InvalidateRect() still draws with the old
+    * color.  The fix is to send a fake WM_SIZE event to cause
+    * it to redraw with the new background color.
+    */
+    ignoreResize = true;
+    OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
+    ignoreResize = false;
+}
+
+override void setBackgroundPixel (int pixel) {
+    super.setBackgroundPixel (pixel);
+    /*
+    * Bug in Windows.  Changing the background color of the Scale
+    * widget and calling InvalidateRect() still draws with the old
+    * color.  The fix is to send a fake WM_SIZE event to cause
+    * it to redraw with the new background color.
+    */
+    ignoreResize = true;
+    OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
+    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
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param increment the new increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setIncrement (int increment) {
+    checkWidget ();
+    if (increment < 1) return;
+    int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+    int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
+    if (increment > maximum - minimum) return;
+    OS.SendMessage (handle, OS.TBM_SETLINESIZE, 0, increment);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow.  This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value.  If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException <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 setMaximum (int value) {
+    checkWidget ();
+    int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+    if (0 <= minimum && minimum < value) {
+        OS.SendMessage (handle, OS.TBM_SETRANGEMAX, 1, value);
+    }
+}
+
+/**
+ * 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
+ * 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
+ *
+ * @exception SWTException <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 setMinimum (int value) {
+    checkWidget ();
+    int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
+    if (0 <= value && value < maximum) {
+        OS.SendMessage (handle, OS.TBM_SETRANGEMIN, 1, value);
+    }
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param pageIncrement the page increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setPageIncrement (int pageIncrement) {
+    checkWidget ();
+    if (pageIncrement < 1) return;
+    int minimum = OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+    int maximum = OS.SendMessage (handle, OS.TBM_GETRANGEMAX, 0, 0);
+    if (pageIncrement > maximum - minimum) return;
+    OS.SendMessage (handle, OS.TBM_SETPAGESIZE, 0, pageIncrement);
+    OS.SendMessage (handle, OS.TBM_SETTICFREQ, pageIncrement, 0);
+}
+
+/**
+ * Sets the 'selection', which is the receiver's value,
+ * to the argument which must be greater than or equal to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <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 setSelection (int value) {
+    checkWidget ();
+    OS.SendMessage (handle, OS.TBM_SETPOS, 1, value);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.WS_TABSTOP | OS.TBS_BOTH | OS.TBS_AUTOTICKS;
+    if ((style & SWT.HORIZONTAL) !is 0) return bits | OS.TBS_HORZ | OS.TBS_DOWNISLEFT;
+    return bits | OS.TBS_VERT;
+}
+
+override String windowClass () {
+    return TCHARsToStr(TrackBarClass);
+}
+
+override int windowProc () {
+    return cast(int) TrackBarProc;
+}
+
+override LRESULT WM_MOUSEWHEEL (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 (SWT.Selection);
+        // widget could be disposed at this point
+    }
+    return new LRESULT (code);
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  For some reason, when WM_CTLCOLORSTATIC
+    * is used to implement transparency and returns a NULL brush,
+    * Windows doesn't always draw the track bar.  It seems that
+    * it is drawn correctly the first time.  It is possible that
+    * Windows double buffers the control and the double buffer
+    * strategy fails when WM_CTLCOLORSTATIC returns unexpected
+    * results.  The fix is to send a fake WM_SIZE to force it
+    * to redraw every time there is a WM_PAINT.
+    */
+    bool fixPaint = findBackgroundControl () !is null;
+    if (!fixPaint) {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            Control control = findThemeControl ();
+            fixPaint = control !is null;
+        }
+    }
+    if (fixPaint) {
+        bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+        ignoreResize = true;
+        OS.SendMessage (handle, OS.WM_SIZE, 0, 0);
+        ignoreResize = false;
+        if (redraw) {
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, null, false);
+        }
+    }
+    return super.WM_PAINT (wParam, lParam);
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    if (ignoreResize) return null;
+    return super.WM_SIZE (wParam, lParam);
+}
+
+override LRESULT wmScrollChild (int wParam, int lParam) {
+
+    /* Do nothing when scrolling is ending */
+    int code = OS.LOWORD (wParam);
+    switch (code) {
+        case OS.TB_ENDTRACK:
+        case OS.TB_THUMBPOSITION:
+            return null;
+        default:
+    }
+
+    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 = SWT.HOME;  break;
+//          case OS.TB_BOTTOM:      event.detail = SWT.END;  break;
+//          case OS.TB_LINEDOWN:    event.detail = SWT.ARROW_DOWN;  break;
+//          case OS.TB_LINEUP:      event.detail = SWT.ARROW_UP;  break;
+//          case OS.TB_PAGEDOWN:    event.detail = SWT.PAGE_DOWN;  break;
+//          case OS.TB_PAGEUP:      event.detail = SWT.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 (SWT.Selection, event);
+        // widget could be disposed at this point
+    }
+    return null;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ScrollBar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,965 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ScrollBar;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Scrollable;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ * <p>
+ * At any given moment, a given scroll bar will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the scroll bar represents (that is, between its
+ * <em>minimum</em> and <em>maximum</em> values).
+ * </p><p>
+ * Typically, scroll bars will be made up of five areas:
+ * <ol>
+ * <li>an arrow button for decrementing the value</li>
+ * <li>a page decrement area for decrementing the value by a larger amount</li>
+ * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
+ * <li>a page increment area for incrementing the value by a larger amount</li>
+ * <li>an arrow button for incrementing the value</li>
+ * </ol>
+ * Based on their style, scroll bars are either <code>HORIZONTAL</code>
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or <code>VERTICAL</code>
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ * </p><p>
+ * On some platforms, the size of the scroll bar's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the scroll bar will not change.
+ * </p><p>
+ * Scroll bars are created by specifying either <code>H_SCROLL</code>,
+ * <code>V_SCROLL</code> or both when creating a <code>Scrollable</code>.
+ * They are accessed from the <code>Scrollable</code> using
+ * <code>getHorizontalBar</code> and <code>getVerticalBar</code>.
+ * </p><p>
+ * Note: Scroll bars are not Controls.  On some platforms, scroll bars
+ * that appear as part of some standard controls such as a text or list
+ * have no operating system resources and are not children of the control.
+ * For this reason, scroll bars are treated specially.  To create a control
+ * that looks like a scroll bar but has operating system resources, use
+ * <code>Slider</code>.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see Slider
+ * @see Scrollable
+ * @see Scrollable#getHorizontalBar
+ * @see Scrollable#getVerticalBar
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class ScrollBar : Widget {
+    Scrollable parent;
+    int increment, pageIncrement;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+this (Scrollable parent, int style) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
+ * <code>SWT.NONE</code> - for the end of a drag.
+ * <code>SWT.DRAG</code>.
+ * <code>SWT.HOME</code>.
+ * <code>SWT.END</code>.
+ * <code>SWT.ARROW_DOWN</code>.
+ * <code>SWT.ARROW_UP</code>.
+ * <code>SWT.PAGE_DOWN</code>.
+ * <code>SWT.PAGE_UP</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's value
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+void createWidget () {
+    increment = 1;
+    pageIncrement = 10;
+    /*
+    * Do not set the initial values of the maximum
+    * or the thumb.  These values normally default
+    * to 100 and 10 but may have been set already
+    * by the widget that owns the scroll bar.  For
+    * example, a scroll bar that is created for a
+    * list widget, setting these defaults would
+    * override the initial values provided by the
+    * list widget.
+    */
+}
+
+override void destroyWidget () {
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    static if (OS.IsWinCE) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+        info.nPage = 101;
+        info.nMax = 100;
+        info.nMin = 0;
+        OS.SetScrollInfo (hwnd, type, &info, true);
+    } else {
+        OS.ShowScrollBar (hwnd, type, false);
+    }
+    parent.destroyScrollBar (style);
+    releaseHandle ();
+    //This code is intentionally commented
+    //parent.sendEvent (SWT.Resize);
+}
+
+Rectangle getBounds () {
+//  checkWidget ();
+    parent.forceResize ();
+    RECT rect;
+    OS.GetClientRect (parent.scrolledHandle (), &rect);
+    int x = 0, y = 0, width, height;
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        y = rect.bottom - rect.top;
+        width = rect.right - rect.left;
+        height = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    } else {
+        x = rect.right - rect.left;
+        width = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+        height = rect.bottom - rect.top;
+    }
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #isEnabled
+ */
+public bool getEnabled () {
+    checkWidget();
+    return (state & DISABLED) is 0;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <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 int getIncrement () {
+    checkWidget();
+    return increment;
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <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 int getMaximum () {
+    checkWidget();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    OS.GetScrollInfo (hwnd, type, &info);
+    return info.nMax;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <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 int getMinimum () {
+    checkWidget();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    OS.GetScrollInfo (hwnd, type, &info);
+    return info.nMin;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <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 int getPageIncrement () {
+    checkWidget();
+    return pageIncrement;
+}
+
+/**
+ * Returns the receiver's parent, which must be a Scrollable.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Scrollable getParent () {
+    checkWidget();
+    return parent;
+}
+
+/**
+ * Returns the single 'selection' that is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <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 int getSelection () {
+    checkWidget();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    OS.GetScrollInfo (hwnd, type, &info);
+    return info.nPos;
+}
+
+/**
+ * Returns a point describing the receiver's size. The
+ * x coordinate of the result is the width of the receiver.
+ * The y coordinate of the result is the height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException <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 Point getSize () {
+    checkWidget();
+    parent.forceResize ();
+    RECT rect;
+    OS.GetClientRect (parent.scrolledHandle (), &rect);
+    int width, height;
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        width = rect.right - rect.left;
+        height = OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    } else {
+        width = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+        height = rect.bottom - rect.top;
+    }
+    return new Point (width, height);
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @exception SWTException <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 ScrollBar
+ */
+public int getThumb () {
+    checkWidget();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_PAGE;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    OS.GetScrollInfo (hwnd, type, &info);
+    if (info.nPage !is 0) --info.nPage;
+    return info.nPage;
+}
+
+/**
+ * Returns <code>true</code> if the receiver 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 visibility state
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        SCROLLBARINFO psbi;
+        psbi.cbSize = SCROLLBARINFO.sizeof;
+        int idObject = (style & SWT.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;
+}
+
+HWND hwndScrollBar () {
+    return parent.scrolledHandle ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled control is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #getEnabled
+ */
+public bool isEnabled () {
+    checkWidget();
+    return getEnabled () && parent.isEnabled ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException <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 #getVisible
+ */
+public bool isVisible () {
+    checkWidget();
+    return getVisible () && parent.isVisible ();
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (parent.horizontalBar is this) parent.horizontalBar = null;
+    if (parent.verticalBar is this) parent.verticalBar = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+int scrollBarType () {
+    return (style & SWT.VERTICAL) !is 0 ? OS.SB_VERT : OS.SB_HORZ;
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <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 setEnabled (bool enabled) {
+    checkWidget();
+    /*
+    * This line is intentionally commented.  Currently
+    * always show scrollbar as being enabled and visible.
+    */
+//  if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+    static if (!OS.IsWinCE) {
+        auto hwnd = hwndScrollBar ();
+        auto type = scrollBarType ();
+        int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH;
+        OS.EnableScrollBar (hwnd, type, flags);
+        if (enabled) {
+            state &= ~DISABLED;
+        } else {
+            state |= DISABLED;
+        }
+    }
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setIncrement (int value) {
+    checkWidget();
+    if (value < 1) return;
+    increment = value;
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum
+ *
+ * @exception SWTException <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 setMaximum (int value) {
+    checkWidget();
+    if (value < 0) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (hwnd, type, &info);
+    if (value - info.nMin - info.nPage < 1) return;
+    info.nMax = value;
+    SetScrollInfo (hwnd, type, &info, true);
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @exception SWTException <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 setMinimum (int value) {
+    checkWidget();
+    if (value < 0) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (hwnd, type, &info);
+    if (info.nMax - value - info.nPage < 1) return;
+    info.nMin = value;
+    SetScrollInfo (hwnd, type, &info, true);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setPageIncrement (int value) {
+    checkWidget();
+    if (value < 1) return;
+    pageIncrement = value;
+}
+
+bool SetScrollInfo (HWND hwnd, int flags, SCROLLINFO* info, bool fRedraw) {
+    /*
+    * Bug in Windows.  For some reason, when SetScrollInfo()
+    * is used with SIF_POS and the scroll bar is hidden,
+    * the opposite scroll bar is incorrectly made visible
+    * so that the next time the parent is resized (or another
+    * scroll bar operation is performed), the opposite scroll
+    * bar draws.  The fix is to hide both scroll bars.
+    */
+    bool barVisible = false;
+    bool visible = getVisible ();
+
+    /*
+    * This line is intentionally commented.  Currently
+    * always show scrollbar as being enabled and visible.
+    */
+//  if (OS.IsWinCE) error (SWT.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;
+            default:
+        }
+        barVisible = bar !is null && bar.getVisible ();
+    }
+    if (!visible || (state & DISABLED) !is 0) fRedraw = false;
+    bool result = cast(bool) OS.SetScrollInfo (hwnd, flags, info, fRedraw);
+
+    /*
+    * Bug in Windows.  For some reason, when the widget
+    * is a standard scroll bar, and SetScrollInfo() is
+    * called with SIF_RANGE or SIF_PAGE, the widget is
+    * incorrectly made visible so that the next time the
+    * parent is resized (or another scroll bar operation
+    * is performed), the scroll bar draws.  The fix is
+    * to hide the scroll bar (again) when already hidden.
+    */
+    if (!visible) {
+        /*
+        * This line is intentionally commented.  Currently
+        * always show scrollbar as being enabled and visible.
+        */
+//      if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+        if (!OS.IsWinCE) {
+            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);
+        }
+    }
+
+    /*
+    * Feature in Windows.  Using SIF_DISABLENOSCROLL,
+    * SetScrollInfo () can change enabled and disabled
+    * state of the scroll bar causing a scroll bar that
+    * was disabled by the application to become enabled.
+    * The fix is to disable the scroll bar (again) when
+    * the application has disabled the scroll bar.
+    */
+    if ((state & DISABLED) !is 0) {
+        /*
+        * This line is intentionally commented.  Currently
+        * always show scrollbar as being enabled and visible.
+        */
+//      if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+        if (!OS.IsWinCE) {
+            OS.EnableScrollBar (hwnd, flags, OS.ESB_DISABLE_BOTH);
+        }
+    }
+    return result;
+}
+
+/**
+ * Sets the single <em>selection</em> that is the receiver's
+ * value to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param selection the new selection (must be zero or greater)
+ *
+ * @exception SWTException <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 setSelection (int selection) {
+    checkWidget();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    info.fMask = OS.SIF_POS;
+    info.nPos = selection;
+    SetScrollInfo (hwnd, type, &info, true);
+}
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.  This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @exception SWTException <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 setThumb (int value) {
+    checkWidget();
+    if (value < 1) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    info.fMask = OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (hwnd, type, &info);
+    info.nPage = value;
+    if (info.nPage !is 0) info.nPage++;
+    SetScrollInfo (hwnd, type, &info, true);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException <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 setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+    checkWidget();
+    if (minimum < 0) return;
+    if (maximum < 0) return;
+    if (thumb < 1) return;
+    if (increment < 1) return;
+    if (pageIncrement < 1) return;
+    this.increment = increment;
+    this.pageIncrement = pageIncrement;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS | OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    info.nPos = selection;
+    info.nMin = minimum;
+    info.nMax = maximum;
+    info.nPage = thumb;
+    if (info.nPage !is 0) info.nPage++;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    SetScrollInfo (hwnd, type, &info, true);
+}
+
+/**
+ * Marks the receiver 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 SWTException <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 setVisible (bool visible) {
+    checkWidget();
+    if (visible is getVisible ()) return;
+
+    /*
+    * On Windows CE, use SIF_DISABLENOSCROLL to show and
+    * hide the scroll bar when the page size is equal to
+    * the range.
+    */
+    static if (OS.IsWinCE) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        auto hwnd = hwndScrollBar ();
+        auto type = scrollBarType ();
+        info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+        if (visible) info.fMask |= OS.SIF_DISABLENOSCROLL;
+        OS.GetScrollInfo (hwnd, type, &info);
+        if (info.nPage is info.nMax - info.nMin + 1) {
+            /*
+            * Bug in Windows.  When the only changed flag to
+            * SetScrollInfo () is OS.SIF_DISABLENOSCROLL,
+            * Windows does not update the scroll bar state.
+            * The fix is to increase and then decrease the
+            * maximum, causing Windows to honour the flag.
+            */
+            int max = info.nMax;
+            info.nMax++;
+            OS.SetScrollInfo (hwnd, type, &info, false);
+            info.nMax = max;
+            OS.SetScrollInfo (hwnd, type, &info, true);
+        } else {
+            /*
+            * This line is intentionally commented.  Currently
+            * always show scrollbar as being enabled and visible.
+            */
+//          if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED);
+        }
+        return;
+    }
+
+    /*
+    * Set the state bits before calling ShowScrollBar ()
+    * because hiding and showing the scroll bar can cause
+    * WM_SIZE messages when the client area is resized.
+    * Setting the state before the call means that code
+    * that runs during WM_SIZE that queries the visibility
+    * of the scroll bar will get the correct value.
+    */
+    state = visible ? state & ~HIDDEN : state | HIDDEN;
+    auto hwnd = hwndScrollBar ();
+    auto type = scrollBarType ();
+    if (OS.ShowScrollBar (hwnd, type, visible)) {
+        /*
+        * Bug in Windows.  For some reason, when the widget
+        * is a standard scroll bar, and SetScrollInfo () is
+        * called with SIF_RANGE or SIF_PAGE while the widget
+        * is not visible, the widget is incorrectly disabled
+        * even though the values for SIF_RANGE and SIF_PAGE,
+        * when set for a visible scroll bar would not disable
+        * the scroll bar.  The fix is to enable the scroll bar
+        * when not disabled by the application and the current
+        * scroll bar ranges would cause the scroll bar to be
+        * enabled had they been set when the scroll bar was
+        * visible.
+        */
+        if ((state & DISABLED) is 0) {
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+            OS.GetScrollInfo (hwnd, type, &info);
+            if (info.nMax - info.nMin - info.nPage >= 0) {
+                OS.EnableScrollBar (hwnd, type, OS.ESB_ENABLE_BOTH);
+            }
+        }
+        sendEvent (visible ? SWT.Show : SWT.Hide);
+        // widget could be disposed at this point
+    }
+}
+
+LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) {
+
+    /* Do nothing when scrolling is ending */
+    int code = OS.LOWORD (wParam);
+    if (code is OS.SB_ENDSCROLL) return null;
+
+    /*
+    * 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.
+    */
+    Event event = new Event ();
+    switch (code) {
+        case OS.SB_THUMBPOSITION:   event.detail = SWT.NONE;  break;
+        case OS.SB_THUMBTRACK:      event.detail = SWT.DRAG;  break;
+        case OS.SB_TOP:             event.detail = SWT.HOME;  break;
+        case OS.SB_BOTTOM:          event.detail = SWT.END;  break;
+        case OS.SB_LINEDOWN:        event.detail = SWT.ARROW_DOWN;  break;
+        case OS.SB_LINEUP:          event.detail = SWT.ARROW_UP;  break;
+        case OS.SB_PAGEDOWN:        event.detail = SWT.PAGE_DOWN;  break;
+        case OS.SB_PAGEUP:          event.detail = SWT.PAGE_UP;  break;
+        default:
+    }
+    sendEvent (SWT.Selection, event);
+    // the widget could be destroyed at this point
+    return null;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Scrollable.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,508 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Scrollable;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+
+import org.eclipse.swt.graphics.Rectangle;
+
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Widget;
+
+import java.lang.all;
+
+/**
+ * This class is the abstract superclass of all classes which
+ * represent controls that have standard scroll bars.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>H_SCROLL, V_SCROLL</dd>
+ * <dt><b>Events:</b>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Scrollable : Control {
+
+    alias Control.windowProc windowProc;
+
+    ScrollBar horizontalBar, verticalBar;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#H_SCROLL
+ * @see SWT#V_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, style);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+/**
+ * Given a desired <em>client area</em> for the receiver
+ * (as described by the arguments), returns the bounding
+ * rectangle which would be required to produce that client
+ * area.
+ * <p>
+ * In other words, it returns a rectangle such that, if the
+ * receiver's bounds were set to that rectangle, the area
+ * of the receiver which is capable of displaying data
+ * (that is, not covered by the "trimmings") would be the
+ * rectangle described by the arguments (relative to the
+ * receiver's parent).
+ * </p>
+ *
+ * @param x the desired x coordinate of the client area
+ * @param y the desired y coordinate of the client area
+ * @param width the desired width of the client area
+ * @param height the desired height of the client area
+ * @return the required bounds to produce the given client area
+ *
+ * @exception SWTException <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 #getClientArea
+ */
+public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    auto scrolledHandle_ = scrolledHandle ();
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    int bits1 = OS.GetWindowLong (scrolledHandle_, OS.GWL_STYLE);
+    int bits2 = OS.GetWindowLong (scrolledHandle_, OS.GWL_EXSTYLE);
+    OS.AdjustWindowRectEx (&rect, bits1, false, bits2);
+    if (horizontalBar !is null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    if (verticalBar !is null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+    int nWidth = rect.right - rect.left, nHeight = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, nWidth, nHeight);
+}
+
+ScrollBar createScrollBar (int type) {
+    ScrollBar bar = new ScrollBar (this, type);
+    if ((state & CANVAS) !is 0) {
+        bar.setMaximum (100);
+        bar.setThumb (10);
+    }
+    return bar;
+}
+
+override void createWidget () {
+    super.createWidget ();
+    if ((style & SWT.H_SCROLL) !is 0) horizontalBar = createScrollBar (SWT.H_SCROLL);
+    if ((style & SWT.V_SCROLL) !is 0) verticalBar = createScrollBar (SWT.V_SCROLL);
+}
+
+void destroyScrollBar (int type) {
+    auto hwnd = scrolledHandle ();
+    int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+    if ((type & SWT.HORIZONTAL) !is 0) {
+        style &= ~SWT.H_SCROLL;
+        bits &= ~OS.WS_HSCROLL;
+    }
+    if ((type & SWT.VERTICAL) !is 0) {
+        style &= ~SWT.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,
+ * not covered by the "trimmings").
+ *
+ * @return the client area
+ *
+ * @exception SWTException <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 #computeTrim
+ */
+public Rectangle getClientArea () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    auto scrolledHandle_ = scrolledHandle ();
+    OS.GetClientRect (scrolledHandle_, &rect);
+    int x = rect.left, y = rect.top;
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    if (scrolledHandle_ !is handle) {
+        OS.GetClientRect (handle, &rect);
+        OS.MapWindowPoints(handle, scrolledHandle_, cast(POINT*)&rect, 2);
+        x = -rect.left;
+        y = -rect.top;
+    }
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Returns the receiver's horizontal scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the horizontal scroll bar (or null)
+ *
+ * @exception SWTException <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 ScrollBar getHorizontalBar () {
+    checkWidget ();
+    return horizontalBar;
+}
+
+/**
+ * Returns the receiver's vertical scroll bar if it has
+ * one, and null if it does not.
+ *
+ * @return the vertical scroll bar (or null)
+ *
+ * @exception SWTException <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 ScrollBar getVerticalBar () {
+    checkWidget ();
+    return verticalBar;
+}
+
+override void releaseChildren (bool destroy) {
+    if (horizontalBar !is null) {
+        horizontalBar.release (false);
+        horizontalBar = null;
+    }
+    if (verticalBar !is null) {
+        verticalBar.release (false);
+        verticalBar = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+HANDLE scrolledHandle () {
+    return handle;
+}
+
+override int widgetExtStyle () {
+    return super.widgetExtStyle ();
+    /*
+    * This code is intentionally commented.  In future,
+    * we may wish to support different standard Windows
+    * edge styles.  The issue here is that not all of
+    * these styles are available on the other platforms
+    * this would need to be a hint.
+    */
+//  if ((style & SWT.BORDER) !is 0) return OS.WS_EX_CLIENTEDGE;
+//  if ((style & SWT.SHADOW_IN) !is 0) return OS.WS_EX_STATICEDGE;
+//  return super.widgetExtStyle ();
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.WS_TABSTOP;
+    if ((style & SWT.H_SCROLL) !is 0) bits |= OS.WS_HSCROLL;
+    if ((style & SWT.V_SCROLL) !is 0) bits |= OS.WS_VSCROLL;
+    return bits;
+}
+
+override String windowClass () {
+    return display.windowClass();
+}
+
+override int windowProc () {
+    return display.windowProc;
+}
+
+override LRESULT WM_HSCROLL (int wParam, int lParam) {
+    LRESULT result = super.WM_HSCROLL (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Bug on WinCE.  lParam should be NULL when the message is not sent
+    * by a scroll bar control, but it contains the handle to the window.
+    * When the message is sent by a scroll bar control, it correctly
+    * contains the handle to the scroll bar.  The fix is to check for
+    * both.
+    */
+    if (horizontalBar !is null && (lParam is 0 || lParam is cast(int)handle)) {
+        return wmScroll (horizontalBar, (state & CANVAS) !is 0, handle, OS.WM_HSCROLL, wParam, lParam);
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
+    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.
+    */
+    if ((state & CANVAS) !is 0) {
+        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;
+        if (msg is 0) return result;
+        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 {
+            int code = 0;
+            if (pageScroll) {
+                code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP;
+            } else {
+                code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP;
+                if (msg is OS.WM_VSCROLL) delta *= linesToScroll;
+            }
+            /* 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;
+    }
+
+    /*
+    * When the native widget scrolls inside WM_MOUSEWHEEL, it
+    * may or may not send a WM_VSCROLL or WM_HSCROLL to do the
+    * actual scrolling.  This depends on the implementation of
+    * each native widget.  In order to ensure that application
+    * code is notified when the scroll bar moves, compare the
+    * scroll bar position before and after the WM_MOUSEWHEEL.
+    * If the native control sends a WM_VSCROLL or WM_HSCROLL,
+    * then the application has already been notified.  If not
+    * explicitly send the event.
+    */
+    int vPosition = verticalBar is null ? 0 : verticalBar.getSelection ();
+    int hPosition = horizontalBar is null ? 0 : horizontalBar.getSelection ();
+    int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
+    if (verticalBar !is null) {
+        int position = verticalBar.getSelection ();
+        if (position !is vPosition) {
+            Event event = new Event ();
+            event.detail = position < vPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
+            verticalBar.sendEvent (SWT.Selection, event);
+        }
+    }
+    if (horizontalBar !is null) {
+        int position = horizontalBar.getSelection ();
+        if (position !is hPosition) {
+            Event event = new Event ();
+            event.detail = position < hPosition ? SWT.PAGE_UP : SWT.PAGE_DOWN;
+            horizontalBar.sendEvent (SWT.Selection, event);
+        }
+    }
+    return new LRESULT (code);
+}
+
+override LRESULT WM_SIZE (int wParam, int 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;
+    return new LRESULT (code);
+}
+
+override LRESULT WM_VSCROLL (int wParam, int lParam) {
+    LRESULT result = super.WM_VSCROLL (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug on WinCE.  lParam should be NULL when the message is not sent
+    * by a scroll bar control, but it contains the handle to the window.
+    * When the message is sent by a scroll bar control, it correctly
+    * contains the handle to the scroll bar.  The fix is to check for
+    * both.
+    */
+    if (verticalBar !is null && (lParam is 0 || lParam is cast(int)handle)) {
+        return wmScroll (verticalBar, (state & CANVAS) !is 0, handle, OS.WM_VSCROLL, wParam, lParam);
+    }
+    return result;
+}
+
+override 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 & SWT.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;
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE;
+        OS.GetScrollInfo (hwnd, type, &info);
+        info.fMask = OS.SIF_POS;
+        int code = OS.LOWORD (wParam);
+        switch (code) {
+            case OS.SB_ENDSCROLL:  return null;
+            case OS.SB_THUMBPOSITION:
+            case OS.SB_THUMBTRACK:
+                /*
+                * Note: On WinCE, the value in SB_THUMBPOSITION is relative to nMin.
+                * Same for SB_THUMBPOSITION 'except' for the very first thumb track
+                * message which has the actual value of nMin. This is a problem when
+                * nMin is not zero.
+                */
+                info.nPos = info.nTrackPos;
+                break;
+            case OS.SB_TOP:
+                info.nPos = info.nMin;
+                break;
+            case OS.SB_BOTTOM:
+                info.nPos = info.nMax;
+                break;
+            case OS.SB_LINEDOWN:
+                info.nPos += bar.getIncrement ();
+                break;
+            case OS.SB_LINEUP:
+                int increment = bar.getIncrement ();
+                info.nPos = Math.max (info.nMin, info.nPos - increment);
+                break;
+            case OS.SB_PAGEDOWN:
+                info.nPos += bar.getPageIncrement ();
+                break;
+            case OS.SB_PAGEUP:
+                int pageIncrement = bar.getPageIncrement ();
+                info.nPos = Math.max (info.nMin, info.nPos - pageIncrement);
+                break;
+            default:
+        }
+        OS.SetScrollInfo (hwnd, type, &info, true);
+    } else {
+        int /*long*/ code = callWindowProc (hwnd, msg, wParam, lParam);
+        result = code is 0 ? LRESULT.ZERO : new LRESULT (code);
+    }
+    bar.wmScrollChild (wParam, lParam);
+    return result;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Shell.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2503 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ShellListener;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Decorations;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolTip;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent the "windows"
+ * which the desktop or "window manager" is managing.
+ * Instances that do not have a parent (that is, they
+ * are built using the constructor, which takes a
+ * <code>Display</code> as the argument) are described
+ * as <em>top level</em> shells. Instances that do have
+ * a parent are described as <em>secondary</em> or
+ * <em>dialog</em> shells.
+ * <p>
+ * Instances are always displayed in one of the maximized,
+ * minimized or normal states:
+ * <ul>
+ * <li>
+ * When an instance is marked as <em>maximized</em>, the
+ * window manager will typically resize it to fill the
+ * entire visible area of the display, and the instance
+ * is usually put in a state where it can not be resized
+ * (even if it has style <code>RESIZE</code>) until it is
+ * no longer maximized.
+ * </li><li>
+ * When an instance is in the <em>normal</em> state (neither
+ * maximized or minimized), its appearance is controlled by
+ * the style constants which were specified when it was created
+ * and the restrictions of the window manager (see below).
+ * </li><li>
+ * When an instance has been marked as <em>minimized</em>,
+ * its contents (client area) will usually not be visible,
+ * and depending on the window manager, it may be
+ * "iconified" (that is, replaced on the desktop by a small
+ * simplified representation of itself), relocated to a
+ * distinguished area of the screen, or hidden. Combinations
+ * of these changes are also possible.
+ * </li>
+ * </ul>
+ * </p><p>
+ * The <em>modality</em> of an instance may be specified using
+ * style bits. The modality style bits are used to determine
+ * whether input is blocked for other shells on the display.
+ * The <code>PRIMARY_MODAL</code> style allows an instance to block
+ * input to its parent. The <code>APPLICATION_MODAL</code> style
+ * allows an instance to block input to every other shell in the
+ * display. The <code>SYSTEM_MODAL</code> style allows an instance
+ * to block input to all shells, including shells belonging to
+ * different applications.
+ * </p><p>
+ * Note: The styles supported by this class are treated
+ * as <em>HINT</em>s, since the window manager for the
+ * desktop on which the instance is visible has ultimate
+ * control over the appearance and behavior of decorations
+ * and modality. For example, some window managers only
+ * support resizable windows and will always assume the
+ * RESIZE style, even if it is not set. In addition, if a
+ * modality style is not supported, it is "upgraded" to a
+ * more restrictive modality style that is supported. For
+ * example, if <code>PRIMARY_MODAL</code> is not supported,
+ * it would be upgraded to <code>APPLICATION_MODAL</code>.
+ * A modality style may also be "downgraded" to a less
+ * restrictive style. For example, most operating systems
+ * no longer support <code>SYSTEM_MODAL</code> because
+ * it can freeze up the desktop, so this is typically
+ * downgraded to <code>APPLICATION_MODAL</code>.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
+ * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
+ * </dl>
+ * Class <code>SWT</code> provides two "convenience constants"
+ * for the most commonly required style combinations:
+ * <dl>
+ * <dt><code>SHELL_TRIM</code></dt>
+ * <dd>
+ * the result of combining the constants which are required
+ * to produce a typical application top level shell: (that
+ * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
+ * </dd>
+ * <dt><code>DIALOG_TRIM</code></dt>
+ * <dd>
+ * the result of combining the constants which are required
+ * to produce a typical application dialog shell: (that
+ * is, <code>TITLE | CLOSE | BORDER</code>)
+ * </dd>
+ * </dl>
+ * </p>
+ * <p>
+ * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
+ * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is not intended to be subclassed.
+ * </p>
+ *
+ * @see Decorations
+ * @see SWT
+ * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Shell : Decorations {
+
+    alias Decorations.setBounds setBounds;
+    alias Decorations.setParent setParent;
+    alias Decorations.setToolTipText setToolTipText;
+
+    Menu activeMenu;
+    ToolTip [] toolTips;
+    HIMC hIMC;
+    HWND hwndMDIClient_;
+    TCHAR* lpstrTip;
+    HANDLE toolTipHandle_;
+    HANDLE balloonTipHandle_;
+    int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
+    HBRUSH [] brushes;
+    bool showWithParent, fullScreen, wasMaximized;
+    String toolTitle, balloonTitle;
+    HICON toolIcon;
+    HICON balloonIcon;
+    WNDPROC windowProc_;
+    Control lastActive;
+    static if( OS.IsWinCE ){
+        SHACTIVATEINFO psai;
+    }
+    static /+const+/ WNDPROC ToolTipProc;
+    static /+const+/ WNDPROC DialogProc;
+    static if( OS.IsWinCE ){
+        static const TCHAR[] DialogClass = "Dialog\0"w;
+    }
+    else{
+        static const TCHAR[] DialogClass = "#32770\0"w;
+    }
+    const static int [] SYSTEM_COLORS = [
+        OS.COLOR_BTNFACE,
+        OS.COLOR_WINDOW,
+        OS.COLOR_BTNTEXT,
+        OS.COLOR_WINDOWTEXT,
+        OS.COLOR_HIGHLIGHT,
+        OS.COLOR_SCROLLBAR,
+    ];
+    final static int BRUSHES_SIZE = 32;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, DialogClass.ptr, &lpWndClass);
+            DialogProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class. This is equivalent
+ * to calling <code>Shell((Display) null)</code>.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this () {
+    this (cast(Display) null);
+}
+
+/**
+ * Constructs a new instance of this class given only the style
+ * value describing its behavior and appearance. This is equivalent
+ * to calling <code>Shell((Display) null, style)</code>.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param style the style of control to construct
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public this (int style) {
+    this (cast(Display) null, style);
+}
+
+/**
+ * Constructs a new instance of this class given only the display
+ * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
+ * <p>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the shell on
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Display display) {
+    this (display, OS.IsWinCE ? SWT.NONE : SWT.SHELL_TRIM);
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on and a style value describing its behavior
+ * and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the shell on
+ * @param style the style of control to construct
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public this (Display display, int style) {
+    this (display, null, style, null, false);
+}
+
+this (Display display, Shell parent, int style, HWND handle, bool embedded) {
+    static_this();
+    super ();
+    checkSubclass ();
+    if (display is null) display = Display.getCurrent ();
+    if (display is null) display = Display.getDefault ();
+    if (!display.isValidThread ()) {
+        error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    }
+    if (parent !is null && parent.isDisposed ()) {
+        error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    this.style = checkStyle (style);
+    this.parent = parent;
+    this.display = display;
+    this.handle = handle;
+    if (handle !is null && !embedded) {
+        state |= FOREIGN_HANDLE;
+    }
+    createWidget ();
+}
+
+/**
+ * Constructs a new instance of this class given only its
+ * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
+ * <p>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+public this (Shell parent) {
+    this (parent, OS.IsWinCE ? SWT.NONE : SWT.DIALOG_TRIM);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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>
+ * Note: Currently, null can be passed in for the parent.
+ * This has the effect of creating the shell on the currently active
+ * display if there is one. If there is no current display, the
+ * shell is created on a "default" display. <b>Passing in null as
+ * the parent is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param parent a shell which will be the parent of the new instance
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#BORDER
+ * @see SWT#CLOSE
+ * @see SWT#MIN
+ * @see SWT#MAX
+ * @see SWT#RESIZE
+ * @see SWT#TITLE
+ * @see SWT#NO_TRIM
+ * @see SWT#SHELL_TRIM
+ * @see SWT#DIALOG_TRIM
+ * @see SWT#ON_TOP
+ * @see SWT#TOOL
+ * @see SWT#MODELESS
+ * @see SWT#PRIMARY_MODAL
+ * @see SWT#APPLICATION_MODAL
+ * @see SWT#SYSTEM_MODAL
+ */
+public this (Shell parent, int style) {
+    this (parent !is null ? parent.display : null, parent, style, null, false);
+}
+
+/**
+ * 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
+ * can be shared within the packages provided by SWT. 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
+ */
+public static Shell win32_new (Display display, HWND handle) {
+    return new Shell (display, null, SWT.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 SWT. 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, SWT.NO_TRIM, handle, false);
+}
+
+static int checkStyle (int style) {
+    style = Decorations.checkStyle (style);
+    style &= ~SWT.TRANSPARENT;
+    int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
+    int bits = style & ~mask;
+    if ((style & SWT.SYSTEM_MODAL) !is 0) return bits | SWT.SYSTEM_MODAL;
+    if ((style & SWT.APPLICATION_MODAL) !is 0) return bits | SWT.APPLICATION_MODAL;
+    if ((style & SWT.PRIMARY_MODAL) !is 0) return bits | SWT.PRIMARY_MODAL;
+    return bits;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when operations are performed on the receiver,
+ * by sending the listener one of the messages defined in the
+ * <code>ShellListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ShellListener
+ * @see #removeShellListener
+ */
+public void addShellListener (ShellListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Close,typedListener);
+    addListener (SWT.Iconify,typedListener);
+    addListener (SWT.Deiconify,typedListener);
+    addListener (SWT.Activate, typedListener);
+    addListener (SWT.Deactivate, typedListener);
+}
+
+HANDLE balloonTipHandle () {
+    if (balloonTipHandle_ is null) createBalloonTipHandle ();
+    return balloonTipHandle_;
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwnd is toolTipHandle_ || hwnd is balloonTipHandle_) {
+        return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
+    }
+    if (hwndMDIClient_ !is null) {
+        return OS.DefFrameProc (hwnd, hwndMDIClient_, msg, wParam, lParam);
+    }
+    if (windowProc_ !is null) {
+        return OS.CallWindowProc (windowProc_, hwnd, msg, wParam, lParam);
+    }
+    if ((style & SWT.TOOL) !is 0) {
+        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+        if ((style & trim) is 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+    }
+    if (parent !is null) {
+        switch (msg) {
+            case OS.WM_KILLFOCUS:
+            case OS.WM_SETFOCUS:
+                return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+            default:
+        }
+        return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
+    }
+    return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+}
+
+/**
+ * Requests that the window manager close the receiver in
+ * the same way it would be closed when the user clicks on
+ * the "close box" or performs some other platform specific
+ * key or mouse combination that indicates the window
+ * should be removed.
+ *
+ * @exception SWTException <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 SWT#Close
+ * @see #dispose
+ */
+public void close () {
+    checkWidget ();
+    closeWidget ();
+}
+
+void createBalloonTipHandle () {
+    balloonTipHandle_ = OS.CreateWindowEx (
+        0,
+        OS.TOOLTIPS_CLASS.ptr,
+        null,
+        OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
+        OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+        handle,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (balloonTipHandle_ is null) error (SWT.ERROR_NO_HANDLES);
+    if (ToolTipProc is null) {
+        ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC);
+    }
+    /*
+    * 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 (balloonTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    display.addControl (balloonTipHandle_, this);
+    OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, display.windowProc);
+}
+
+override void createHandle () {
+    bool embedded = handle !is null && (state & FOREIGN_HANDLE) is 0;
+
+    /*
+    * On Windows 98 and NT, setting a window to be the
+    * top most window using HWND_TOPMOST can result in a
+    * parent dialog shell being moved behind its parent
+    * if the dialog has a sibling that is currently on top
+    * This only occurs using SetWindowPos (), not when the
+    * handle is created.
+    */
+    /*
+    * The following code is intentionally commented.
+    */
+//  if ((style & SWT.ON_TOP) !is 0) display.lockActiveWindow = true;
+    if (handle is null || embedded) {
+        super.createHandle ();
+    } else {
+        state |= CANVAS;
+        if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+            state |= THEME_BACKGROUND;
+        }
+        windowProc_ = cast(WNDPROC) OS.GetWindowLong (handle, OS.GWL_WNDPROC);
+    }
+
+    /*
+    * The following code is intentionally commented.
+    */
+//  if ((style & SWT.ON_TOP) !is 0)  display.lockActiveWindow = false;
+
+    if (!embedded) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
+        static if (!OS.IsWinCE) bits |= OS.WS_POPUP;
+        if ((style & SWT.TITLE) !is 0) bits |= OS.WS_CAPTION;
+        if ((style & SWT.NO_TRIM) is 0) {
+            if ((style & (SWT.BORDER | SWT.RESIZE)) is 0) bits |= OS.WS_BORDER;
+        }
+        /*
+        * Bug in Windows.  When the WS_CAPTION bits are cleared using
+        * SetWindowLong(), Windows does not resize the client area of
+        * the window to get rid of the caption until the first resize.
+        * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force
+        * the frame to be redrawn and resized.
+        */
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+        SetWindowPos (handle, null, 0, 0, 0, 0, flags);
+        static if (OS.IsWinCE) _setMaximized (true);
+        static if (OS.IsPPC) {
+            psai = new SHACTIVATEINFO ();
+            psai.cbSize = SHACTIVATEINFO.sizeof;
+        }
+    }
+    if (OS.IsDBLocale) {
+        hIMC = OS.ImmCreateContext ();
+        if (hIMC !is null) OS.ImmAssociateContext (handle, hIMC);
+    }
+}
+
+void createToolTip (ToolTip toolTip) {
+    int id = 0;
+    if (toolTips is null) toolTips = new ToolTip [4];
+    while (id < toolTips.length && toolTips [id] !is null) id++;
+    if (id is toolTips.length) {
+        ToolTip [] newToolTips = new ToolTip [toolTips.length + 4];
+        System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length);
+        toolTips = newToolTips;
+    }
+    toolTips [id] = toolTip;
+    toolTip.id = id + Display.ID_START;
+    static if (OS.IsWinCE) return;
+    TOOLINFO lpti;
+    lpti.cbSize = OS.TOOLINFO_sizeof;
+    lpti.hwnd = handle;
+    lpti.uId = toolTip.id;
+    lpti.uFlags = OS.TTF_TRACK;
+    lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+    OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, &lpti);
+}
+
+void createToolTipHandle () {
+    toolTipHandle_ = OS.CreateWindowEx (
+        0,
+        OS.TOOLTIPS_CLASS.ptr,
+        null,
+        OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
+        OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+        handle,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (toolTipHandle_ is null) error (SWT.ERROR_NO_HANDLES);
+    if (ToolTipProc is null) {
+        ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC);
+    }
+    /*
+    * 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 (toolTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    display.addControl (toolTipHandle_, this);
+    OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, display.windowProc);
+}
+
+override void deregister () {
+    super.deregister ();
+    if (toolTipHandle_ !is null) display.removeControl (toolTipHandle_);
+    if (balloonTipHandle_ !is null) display.removeControl (balloonTipHandle_);
+}
+
+void destroyToolTip (ToolTip toolTip) {
+    if (toolTips is null) return;
+    toolTips [toolTip.id - Display.ID_START] = null;
+    static if (OS.IsWinCE) return;
+    if (balloonTipHandle_ !is null) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        lpti.uId = toolTip.id;
+        lpti.hwnd = handle;
+        OS.SendMessage (balloonTipHandle_, OS.TTM_DELTOOL, 0, &lpti);
+    }
+    toolTip.id = -1;
+}
+
+override void destroyWidget () {
+    fixActiveShell ();
+    super.destroyWidget ();
+}
+
+override public void dispose () {
+    /*
+    * This code is intentionally commented.  On some
+    * platforms, the owner window is repainted right
+    * away when a dialog window exits.  This behavior
+    * is currently unspecified.
+    */
+//  /*
+//  * Note:  It is valid to attempt to dispose a widget
+//  * more than once.  If this happens, fail silently.
+//  */
+//  if (!isValidWidget ()) return;
+//  if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+//  Display oldDisplay = display;
+    super.dispose ();
+    // widget is disposed at this point
+//  if (oldDisplay !is null) oldDisplay.update ();
+}
+
+override void enableWidget (bool enabled) {
+    if (enabled) {
+        state &= ~DISABLED;
+    } else {
+        state |= DISABLED;
+    }
+    if (Display.TrimEnabled) {
+        if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
+    } else {
+        OS.EnableWindow (handle, enabled);
+    }
+}
+
+override HBRUSH findBrush (int value, int lbStyle) {
+    if (lbStyle is OS.BS_SOLID) {
+        for (int i=0; i<SYSTEM_COLORS.length; i++) {
+            if (value is OS.GetSysColor (SYSTEM_COLORS [i])) {
+                return OS.GetSysColorBrush (SYSTEM_COLORS [i]);
+            }
+        }
+    }
+    if (brushes is null) brushes = new HBRUSH [BRUSHES_SIZE];
+    LOGBRUSH logBrush;
+    for (int i=0; i<brushes.length; i++) {
+        HBRUSH hBrush = brushes [i];
+        if (hBrush is null) break;
+        OS.GetObject (hBrush, LOGBRUSH.sizeof, &logBrush);
+        switch (logBrush.lbStyle) {
+            case OS.BS_SOLID:
+                if (lbStyle is OS.BS_SOLID) {
+                    if (logBrush.lbColor is value) return hBrush;
+                }
+                break;
+            case OS.BS_PATTERN:
+                if (lbStyle is OS.BS_PATTERN) {
+                    if (logBrush.lbHatch is value) return hBrush;
+                }
+                break;
+            default:
+        }
+    }
+    int length_ = brushes.length;
+    HBRUSH hBrush = brushes [--length_];
+    if (hBrush !is null) OS.DeleteObject (hBrush);
+    System.arraycopy (brushes, 0, brushes, 1, length_);
+    switch (lbStyle) {
+        case OS.BS_SOLID:
+            hBrush = OS.CreateSolidBrush (value);
+            break;
+        case OS.BS_PATTERN:
+            hBrush = OS.CreatePatternBrush ( cast(HBITMAP) value);
+            break;
+        default:
+    }
+    return brushes [0] = hBrush;
+}
+
+override Control findBackgroundControl () {
+    return background !is -1 || backgroundImage !is null ? this : null;
+}
+
+override Cursor findCursor () {
+    return cursor;
+}
+
+override Control findThemeControl () {
+    return null;
+}
+
+ToolTip findToolTip (int id) {
+    if (toolTips is null) return null;
+    id = id - Display.ID_START;
+    return 0 <= id && id < toolTips.length ? toolTips [id] : null;
+}
+
+void fixActiveShell () {
+    /*
+    * Feature in Windows.  When the active shell is disposed
+    * or hidden, Windows normally makes the parent shell active
+    * and assigns focus.  This does not happen when the parent
+    * shell is disabled.  Instead, Windows assigns focus to the
+    * next shell on the desktop (possibly a shell in another
+    * application).  The fix is to activate the disabled parent
+    * shell before disposing or hiding the active shell.
+    */
+    auto hwndParent = OS.GetParent (handle);
+    if (hwndParent !is null && handle is OS.GetActiveWindow ()) {
+        if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) {
+            OS.SetActiveWindow (hwndParent);
+        }
+    }
+}
+
+void fixShell (Shell newShell, Control control) {
+    if (this is newShell) return;
+    if (control is lastActive) setActiveControl (null);
+    String toolTipText = control.toolTipText_;
+    if (toolTipText !is null) {
+        control.setToolTipText (this, null);
+        control.setToolTipText (newShell, toolTipText);
+    }
+}
+
+void fixToolTip () {
+    /*
+    * Bug in Windows.  On XP, when a tooltip is
+    * hidden due to a time out or mouse press,
+    * the tooltip remains active although no
+    * longer visible and won't show again until
+    * another tooltip becomes active.  If there
+    * is only one tooltip in the window,  it will
+    * never show again.  The fix is to remove the
+    * current tooltip and add it again every time
+    * the mouse leaves the control.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (toolTipHandle_ is null) return;
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        if (OS.SendMessage (toolTipHandle_, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+            if ((lpti.uFlags & OS.TTF_IDISHWND) !is 0) {
+                OS.SendMessage (toolTipHandle_, OS.TTM_DELTOOL, 0, &lpti);
+                OS.SendMessage (toolTipHandle_, OS.TTM_ADDTOOL, 0, &lpti);
+            }
+        }
+    }
+}
+
+/**
+ * If the receiver is visible, moves it to the top of the
+ * drawing order for the display on which it was created
+ * (so that all other shells on that display, which are not
+ * the receiver's children will be drawn behind it) and forces
+ * the window manager to make the shell active.
+ *
+ * @exception SWTException <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 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void forceActive () {
+    checkWidget ();
+    if(!isVisible()) return;
+    OS.SetForegroundWindow (handle);
+}
+
+override void forceResize () {
+    /* Do nothing */
+}
+
+/**
+ * Returns the receiver's alpha value. The alpha value
+ * is between 0 (transparent) and 255 (opaque).
+ *
+ * @return the alpha value
+ *
+ * @exception SWTException <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) {
+        if (OS.IsIconic (handle)) return super.getBounds ();
+    }
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+ToolTip getCurrentToolTip () {
+    if (toolTipHandle_ !is null) {
+        ToolTip tip = getCurrentToolTip (toolTipHandle_);
+        if (tip !is null) return tip;
+    }
+    if (balloonTipHandle_ !is null) {
+        ToolTip tip = getCurrentToolTip (balloonTipHandle_);
+        if (tip !is null) return tip;
+    }
+    return null;
+}
+
+ToolTip getCurrentToolTip (HWND hwndToolTip) {
+    if (hwndToolTip is null) return null;
+    if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+            if ((lpti.uFlags & OS.TTF_IDISHWND) is 0) return findToolTip (lpti.uId);
+        }
+    }
+    return null;
+}
+
+override public bool getEnabled () {
+    checkWidget ();
+    return (state & DISABLED) is 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is currently
+ * in fullscreen state, and false otherwise.
+ * <p>
+ *
+ * @return the fullscreen state
+ *
+ * @exception SWTException <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
+ * <code>SWT</code>:
+ * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
+ * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
+ *
+ * @return the IME mode
+ *
+ * @exception SWTException <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 SWT
+ */
+public int getImeInputMode () {
+    checkWidget ();
+    if (!OS.IsDBLocale) return 0;
+    auto hIMC = OS.ImmGetContext (handle);
+    uint lpfdwConversion, lpfdwSentence;
+    bool open = cast(bool) OS.ImmGetOpenStatus (hIMC);
+    if (open) open = cast(bool) OS.ImmGetConversionStatus (hIMC, &lpfdwConversion, &lpfdwSentence);
+    OS.ImmReleaseContext (handle, hIMC);
+    if (!open) return SWT.NONE;
+    int result = 0;
+    if ((lpfdwConversion & OS.IME_CMODE_ROMAN) !is 0) result |= SWT.ROMAN;
+    if ((lpfdwConversion & OS.IME_CMODE_FULLSHAPE) !is 0) result |= SWT.DBCS;
+    if ((lpfdwConversion & OS.IME_CMODE_KATAKANA) !is 0) return result | SWT.PHONETIC;
+    if ((lpfdwConversion & OS.IME_CMODE_NATIVE) !is 0) return result | SWT.NATIVE;
+    return result | SWT.ALPHA;
+}
+
+override public Point getLocation () {
+    checkWidget ();
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) {
+            return super.getLocation ();
+        }
+    }
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    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.
+ * The y coordinate of the result is the minimum height of the
+ * receiver.
+ *
+ * @return the receiver's size
+ *
+ * @exception SWTException <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.1
+ */
+public Point getMinimumSize () {
+    checkWidget ();
+    int width = Math.max (0, minWidth);
+    int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+    if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) {
+        width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+    }
+    int height = Math.max (0, minHeight);
+    if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) {
+        if ((style & SWT.RESIZE) !is 0) {
+            height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+        } else {
+            RECT rect;
+            int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+            OS.AdjustWindowRectEx (&rect, bits1, false, bits2);
+            height = Math.max (height, rect.bottom - rect.top);
+        }
+    }
+    return new Point (width,  height);
+}
+
+/**
+ * Returns the region that defines the shape of the shell,
+ * or null if the shell has the default shape.
+ *
+ * @return the region that defines the shape of the shell (or null)
+ *
+ * @exception SWTException <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.0
+ *
+ */
+public Region getRegion () {
+    /* This method is needed for the @since 3.0 Javadoc */
+    checkWidget ();
+    return region;
+}
+
+override public Shell getShell () {
+    checkWidget ();
+    return this;
+}
+
+override public Point getSize () {
+    checkWidget ();
+    static if (!OS.IsWinCE) {
+        if (OS.IsIconic (handle)) return super.getSize ();
+    }
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    return new Point (width, height);
+}
+
+/**
+ * Returns an array containing all shells which are
+ * descendants of the receiver.
+ * <p>
+ * @return the dialog shells
+ *
+ * @exception SWTException <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 Shell [] getShells () {
+    checkWidget ();
+    int count = 0;
+    Shell [] shells = display.getShells ();
+    for (int i=0; i<shells.length; i++) {
+        Control shell = shells [i];
+        do {
+            shell = shell.parent;
+        } while (shell !is null && shell !is this);
+        if (shell is this) count++;
+    }
+    int index = 0;
+    Shell [] result = new Shell [count];
+    for (int i=0; i<shells.length; i++) {
+        Control shell = shells [i];
+        do {
+            shell = shell.parent;
+        } while (shell !is null && shell !is this);
+        if (shell is this) {
+            result [index++] = shells [i];
+        }
+    }
+    return result;
+}
+
+override Composite findDeferredControl () {
+    return layoutCount > 0 ? this : null;
+}
+
+override public bool isEnabled () {
+    checkWidget ();
+    return getEnabled ();
+}
+
+override public bool isVisible () {
+    checkWidget ();
+    return getVisible ();
+}
+
+HWND hwndMDIClient () {
+    if (hwndMDIClient_ is null) {
+        int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
+        hwndMDIClient_ = OS.CreateWindowEx (
+            0,
+            StrToTCHARz("MDICLIENT"),
+            null,
+            widgetStyle,
+            0, 0, 0, 0,
+            handle,
+            null,
+            OS.GetModuleHandle (null),
+            new CREATESTRUCT ());
+//      OS.ShowWindow (hwndMDIClient_, OS.SW_SHOW);
+    }
+    return hwndMDIClient_;
+}
+
+/**
+ * Moves the receiver to the top of the drawing order for
+ * the display on which it was created (so that all other
+ * shells on that display, which are not the receiver's
+ * children will be drawn behind it), marks it visible,
+ * sets the focus and asks the window manager to make the
+ * shell active.
+ *
+ * @exception SWTException <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 Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#setActive
+ * @see Shell#forceActive
+ */
+public void open () {
+    checkWidget ();
+    STARTUPINFO* lpStartUpInfo = Display.lpStartupInfo;
+    if (lpStartUpInfo is null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) is 0) {
+        bringToTop ();
+        if (isDisposed ()) return;
+    }
+    /*
+    * Feature on WinCE PPC.  A new application becomes
+    * the foreground application only if it has at least
+    * one visible window before the event loop is started.
+    * The workaround is to explicitly force the shell to
+    * be the foreground window.
+    */
+    static if (OS.IsWinCE) OS.SetForegroundWindow (handle);
+    OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+    setVisible (true);
+    if (isDisposed ()) return;
+    /*
+    * Bug in Windows XP.  Despite the fact that an icon has been
+    * set for a window, the task bar displays the wrong icon the
+    * first time the window is made visible with ShowWindow() after
+    * a call to BringToTop(), when a long time elapses between the
+    * ShowWindow() and the time the event queue is read.  The icon
+    * in the window trimming is correct but the one in the task
+    * bar does not get updated.  The fix is to call PeekMessage()
+    * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond
+    * to a cross thread WM_GETICON.
+    *
+    * NOTE: This allows other cross thread messages to be delivered,
+    * most notably WM_ACTIVATE.
+    */
+    MSG msg;
+    int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
+    OS.PeekMessage (&msg, null, 0, 0, flags);
+    if (!restoreFocus () && !traverseGroup (true)) setFocus ();
+}
+
+public bool print (GC gc) {
+    checkWidget ();
+    if (gc is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    return false;
+}
+
+override void register () {
+    super.register ();
+    if (toolTipHandle_ !is null) display.addControl (toolTipHandle_, this);
+    if (balloonTipHandle_ !is null) display.addControl (balloonTipHandle_, this);
+}
+
+void releaseBrushes () {
+    if (brushes !is null) {
+        for (int i=0; i<brushes.length; i++) {
+            if (brushes [i] !is null) OS.DeleteObject (brushes [i]);
+        }
+    }
+    brushes = null;
+}
+
+override void releaseChildren (bool destroy) {
+    Shell [] shells = getShells ();
+    for (int i=0; i<shells.length; i++) {
+        Shell shell = shells [i];
+        if (shell !is null && !shell.isDisposed ()) {
+            shell.release (false);
+        }
+    }
+    if (toolTips !is null) {
+        for (int i=0; i<toolTips.length; i++) {
+            ToolTip toolTip = toolTips [i];
+            if (toolTip !is null && !toolTip.isDisposed ()) {
+                toolTip.release (false);
+            }
+        }
+    }
+    toolTips = null;
+    super.releaseChildren (destroy);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    hwndMDIClient_ = null;
+}
+
+override void releaseParent () {
+    /* Do nothing */
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    releaseBrushes ();
+    activeMenu = null;
+    display.clearModal (this);
+    if (lpstrTip !is null) {
+        auto hHeap = OS.GetProcessHeap ();
+        OS.HeapFree (hHeap, 0, lpstrTip);
+    }
+    lpstrTip = null;
+    toolTipHandle_ = balloonTipHandle_ = null;
+    if (OS.IsDBLocale) {
+        if (hIMC !is null) OS.ImmDestroyContext (hIMC);
+    }
+    lastActive = null;
+    toolTitle = balloonTitle = null;
+}
+
+override void removeMenu (Menu menu) {
+    super.removeMenu (menu);
+    if (menu is activeMenu) activeMenu = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when operations are performed on the receiver.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ShellListener
+ * @see #addShellListener
+ */
+public void removeShellListener (ShellListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Close, listener);
+    eventTable.unhook (SWT.Iconify,listener);
+    eventTable.unhook (SWT.Deiconify,listener);
+    eventTable.unhook (SWT.Activate, listener);
+    eventTable.unhook (SWT.Deactivate, listener);
+}
+
+LRESULT selectPalette (HPALETTE hPalette) {
+    auto hDC = OS.GetDC (handle);
+    auto hOld = OS.SelectPalette (hDC, hPalette, false);
+    int result = OS.RealizePalette (hDC);
+    if (result > 0) {
+        OS.InvalidateRect (handle, null, true);
+    } else {
+        OS.SelectPalette (hDC, hOld, true);
+        OS.RealizePalette (hDC);
+    }
+    OS.ReleaseDC (handle, hDC);
+    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
+ * (so that all other shells on that display, which are not
+ * the receiver's children will be drawn behind it) and asks
+ * the window manager to make the shell active
+ *
+ * @exception SWTException <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 2.0
+ * @see Control#moveAbove
+ * @see Control#setFocus
+ * @see Control#setVisible
+ * @see Display#getActiveShell
+ * @see Decorations#setDefaultButton(Button)
+ * @see Shell#open
+ * @see Shell#setActive
+ */
+public void setActive () {
+    checkWidget ();
+    if (!isVisible ()) return;
+    bringToTop ();
+    // widget could be disposed at this point
+}
+
+void setActiveControl (Control control) {
+    if (control !is null && control.isDisposed ()) control = null;
+    if (lastActive !is null && lastActive.isDisposed ()) lastActive = null;
+    if (lastActive is control) return;
+
+    /*
+    * Compute the list of controls to be activated and
+    * deactivated by finding the first common parent
+    * control.
+    */
+    Control [] activate = (control is null) ? new Control [0] : control.getPath ();
+    Control [] deactivate = (lastActive is null) ? new Control [0] : lastActive.getPath ();
+    lastActive = control;
+    int index = 0, length = Math.min (activate.length, deactivate.length);
+    while (index < length) {
+        if (activate [index] !is deactivate [index]) break;
+        index++;
+    }
+
+    /*
+    * It is possible (but unlikely), that application
+    * code could have destroyed some of the widgets. If
+    * this happens, keep processing those widgets that
+    * are not disposed.
+    */
+    for (int i=deactivate.length-1; i>=index; --i) {
+        if (!deactivate [i].isDisposed ()) {
+            deactivate [i].sendEvent (SWT.Deactivate);
+        }
+    }
+    for (int i=activate.length-1; i>=index; --i) {
+        if (!activate [i].isDisposed ()) {
+            activate [i].sendEvent (SWT.Activate);
+        }
+    }
+}
+
+/**
+ * Sets the receiver's alpha value which must be
+ * between 0 (transparent) and 255 (opaque).
+ * <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 SWTException <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);
+}
+
+override public void setEnabled (bool enabled) {
+    checkWidget ();
+    if (((state & DISABLED) is 0) is enabled) return;
+    super.setEnabled (enabled);
+    if (enabled && handle is OS.GetActiveWindow ()) {
+        if (!restoreFocus ()) traverseGroup (true);
+    }
+}
+
+/**
+ * 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 SWTException <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 = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.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>SWT</code>:
+ * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
+ * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
+ *
+ * @param mode the new IME mode
+ *
+ * @exception SWTException <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 SWT
+ */
+public void setImeInputMode (int mode) {
+    checkWidget ();
+    if (!OS.IsDBLocale) return;
+    bool imeOn = mode !is SWT.NONE;
+    auto hIMC = OS.ImmGetContext (handle);
+    OS.ImmSetOpenStatus (hIMC, imeOn);
+    if (imeOn) {
+        uint lpfdwConversion, lpfdwSentence;
+        if (OS.ImmGetConversionStatus (hIMC, &lpfdwConversion, &lpfdwSentence)) {
+            int newBits = 0;
+            int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
+            if ((mode & SWT.PHONETIC) !is 0) {
+                newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
+                oldBits = 0;
+            } else {
+                if ((mode & SWT.NATIVE) !is 0) {
+                    newBits = OS.IME_CMODE_NATIVE;
+                    oldBits = OS.IME_CMODE_KATAKANA;
+                }
+            }
+            if ((mode & (SWT.DBCS | SWT.NATIVE)) !is 0) {
+                newBits |= OS.IME_CMODE_FULLSHAPE;
+            } else {
+                oldBits |= OS.IME_CMODE_FULLSHAPE;
+            }
+            if ((mode & SWT.ROMAN) !is 0) {
+                newBits |= OS.IME_CMODE_ROMAN;
+            } else {
+                oldBits |= OS.IME_CMODE_ROMAN;
+            }
+            lpfdwConversion |= newBits;
+            lpfdwConversion &= ~oldBits;
+            OS.ImmSetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
+        }
+    }
+    OS.ImmReleaseContext (handle, hIMC);
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the arguments.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param width the new minimum width for the receiver
+ * @param height the new minimum height for the receiver
+ *
+ * @exception SWTException <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.1
+ */
+public void setMinimumSize (int width, int height) {
+    checkWidget ();
+    int widthLimit = 0, heightLimit = 0;
+    int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+    if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) {
+        widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
+        if ((style & SWT.RESIZE) !is 0) {
+            heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
+        } else {
+            RECT rect;
+            int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+            OS.AdjustWindowRectEx (&rect, bits1, false, bits2);
+            heightLimit = rect.bottom - rect.top;
+        }
+    }
+    minWidth = Math.max (widthLimit, width);
+    minHeight = Math.max (heightLimit, height);
+    Point size = getSize ();
+    int newWidth = Math.max (size.x, minWidth);
+    int newHeight = Math.max (size.y, minHeight);
+    if (minWidth <= widthLimit) minWidth = SWT.DEFAULT;
+    if (minHeight <= heightLimit) minHeight = SWT.DEFAULT;
+    if (newWidth !is size.x || newHeight !is size.y) setSize (newWidth, newHeight);
+}
+
+/**
+ * Sets the receiver's minimum size to the size specified by the argument.
+ * If the new minimum size is larger than the current size of the receiver,
+ * the receiver is resized to the new minimum size.
+ *
+ * @param size the new minimum size for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void setMinimumSize (Point size) {
+    checkWidget ();
+    if (size is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setMinimumSize (size.x, size.y);
+}
+
+void setItemEnabled (int cmd, bool enabled) {
+    auto hMenu = OS.GetSystemMenu (handle, false);
+    if (hMenu is null) return;
+    int flags = OS.MF_ENABLED;
+    if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED;
+    OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags);
+}
+
+override void setParent () {
+    /* Do nothing.  Not necessary for Shells */
+}
+
+/**
+ * Sets the shape of the shell to the region specified
+ * by the argument.  When the argument is null, the
+ * default shape of the shell is restored.  The shell
+ * must be created with the style SWT.NO_TRIM in order
+ * to specify a region.
+ *
+ * @param region the region that defines the shape of the shell (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ *
+ */
+public void setRegion (Region region) {
+    checkWidget ();
+    if ((style & SWT.NO_TRIM) is 0) return;
+    super.setRegion (region);
+}
+
+void setToolTipText (HWND hwnd, String text) {
+    static if (OS.IsWinCE) return;
+    TOOLINFO lpti;
+    lpti.cbSize = OS.TOOLINFO_sizeof;
+    lpti.hwnd = handle;
+    lpti.uId = cast(uint) hwnd;
+    auto hwndToolTip = toolTipHandle ();
+    if (text is null) {
+        OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, cast(int)&lpti);
+    } else {
+        if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, cast(int)&lpti) !is 0) {
+            OS.SendMessage (hwndToolTip, OS.TTM_UPDATE, 0, 0);
+        } else {
+            lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS;
+            lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+            OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, cast(int)&lpti);
+        }
+    }
+}
+
+void setToolTipText (NMTTDISPINFO* lpnmtdi, CHAR [] buffer) {
+    /*
+    * Ensure that the current position of the mouse
+    * is inside the client area of the shell.  This
+    * prevents tool tips from popping up over the
+    * shell trimmings.
+    */
+    if (!hasCursor ()) return;
+    auto hHeap = OS.GetProcessHeap ();
+    if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip);
+    int byteCount = buffer.length;
+    lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    OS.MoveMemory (lpstrTip, buffer.ptr, byteCount);
+    lpnmtdi.lpszText = lpstrTip;
+}
+
+void setToolTipText (NMTTDISPINFO* lpnmtdi, WCHAR [] buffer) {
+    /*
+    * Ensure that the current position of the mouse
+    * is inside the client area of the shell.  This
+    * prevents tool tips from popping up over the
+    * shell trimmings.
+    */
+    if (!hasCursor ()) return;
+    auto hHeap = OS.GetProcessHeap ();
+    if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip);
+    int byteCount = buffer.length * 2;
+    lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+    OS.MoveMemory (lpstrTip, buffer.ptr, byteCount);
+    lpnmtdi.lpszText = lpstrTip;
+}
+
+void setToolTipTitle (HWND hwndToolTip, String text, HICON icon) {
+    /*
+    * Bug in Windows.  For some reason, when TTM_SETTITLE
+    * is used to set the title of a tool tip, Windows leaks
+    * GDI objects.  This happens even when TTM_SETTITLE is
+    * called with TTI_NONE and NULL.  The documentation
+    * states that Windows copies the icon and that the
+    * programmer must free the copy but does not provide
+    * API to get the icon.  For example, when TTM_SETTITLE
+    * is called with ICON_ERROR, when TTM_GETTITLE is used
+    * to query the title and the icon, the uTitleBitmap
+    * field in the TTGETTITLE struct is zero.  The fix
+    * is to remember these values, only set them when then
+    * change and leak less.
+    *
+    * NOTE:  This only happens on Vista.
+    */
+    if (hwndToolTip !is toolTipHandle_ && hwndToolTip !is balloonTipHandle_) {
+        return;
+    }
+    if (hwndToolTip is toolTipHandle_) {
+        if (text is toolTitle || (toolTitle !is null && toolTitle.equals (text) )) {
+            if (icon is toolIcon) return;
+        }
+        toolTitle = text;
+        toolIcon = icon;
+    } else {
+        if (hwndToolTip is balloonTipHandle_) {
+            if (text is balloonTitle || (balloonTitle !is null && balloonTitle.equals (text))) {
+                if (icon is toolIcon) return;
+            }
+            balloonTitle = text;
+            balloonIcon = icon;
+        }
+    }
+    if (text !is null) {
+        static if( OS.IsUnicode ){
+            TCHAR* pszTitle = StrToTCHARz( text);
+        }
+        else {
+            TCHAR* pszTitle = StrToTCHARz( text, getCodePage ());
+        }
+        OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, cast(int)pszTitle);
+    } else {
+        OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
+    }
+}
+
+override public void setVisible (bool visible) {
+    checkWidget ();
+    /*
+    * Feature in Windows.  When ShowWindow() is called used to hide
+    * a window, Windows attempts to give focus to the parent. If the
+    * parent is disabled by EnableWindow(), focus is assigned to
+    * another windows on the desktop.  This means that if you hide
+    * a modal window before the parent is enabled, the parent will
+    * not come to the front.  The fix is to change the modal state
+    * before hiding or showing a window so that this does not occur.
+    */
+    int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
+    if ((style & mask) !is 0) {
+        if (visible) {
+            display.setModalShell (this);
+            if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) {
+                display.setModalDialog (null);
+            }
+            Control control = display._getFocusControl ();
+            if (control !is null && !control.isActive ()) {
+                bringToTop ();
+                if (isDisposed ()) return;
+            }
+            auto hwndShell = OS.GetActiveWindow ();
+            if (hwndShell is null) {
+                if (parent !is null) hwndShell = parent.handle;
+            }
+            if (hwndShell !is null) {
+                OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
+            }
+            OS.ReleaseCapture ();
+        } else {
+            display.clearModal (this);
+        }
+    } else {
+        updateModal ();
+    }
+
+    /*
+    * Bug in Windows.  Calling ShowOwnedPopups() to hide the
+    * child windows of a hidden window causes the application
+    * to be deactivated.  The fix is to call ShowOwnedPopups()
+    * to hide children before hiding the parent.
+    */
+    if (showWithParent && !visible) {
+        static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, false);
+    }
+    if (!visible) fixActiveShell ();
+    super.setVisible (visible);
+    if (isDisposed ()) return;
+    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) {
+        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 /*long*/ newProc = display.windowProc;
+        if (toolTipHandle_ !is null) {
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, newProc);
+        }
+        if (balloonTipHandle_ !is null) {
+            OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, newProc);
+        }
+    }
+}
+
+HANDLE toolTipHandle () {
+    if (toolTipHandle_ is null) createToolTipHandle ();
+    return toolTipHandle_;
+}
+
+override bool translateAccelerator (MSG* msg) {
+    if (!isEnabled () || !isActive ()) return false;
+    if (menuBar !is null && !menuBar.isEnabled ()) return false;
+    return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
+}
+
+override bool traverseEscape () {
+    if (parent is null) return false;
+    if (!isVisible () || !isEnabled ()) return false;
+    close ();
+    return true;
+}
+
+override void unsubclass () {
+    super.unsubclass ();
+    if (ToolTipProc !is null) {
+        if (toolTipHandle_ !is null) {
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc);
+        }
+        if (toolTipHandle_ !is null) {
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc);
+        }
+    }
+}
+
+void updateModal () {
+    if (Display.TrimEnabled) {
+        setItemEnabled (OS.SC_CLOSE, isActive ());
+    } else {
+        OS.EnableWindow (handle, isActive ());
+    }
+}
+
+override CREATESTRUCT* widgetCreateStruct () {
+    return null;
+}
+
+override HWND widgetParent () {
+    if (handle !is null) return handle;
+    return parent !is null ? parent.handle : null;
+}
+
+override int widgetExtStyle () {
+    int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
+    if ((style & SWT.TOOL) !is 0) bits |= OS.WS_EX_TOOLWINDOW;
+
+    /*
+    * Feature in Windows.  When a window that does not have a parent
+    * is created, it is automatically added to the Windows Task Bar,
+    * even when it has no title.  The fix is to use WS_EX_TOOLWINDOW
+    * which does not cause the window to appear in the Task Bar.
+    */
+    static if (!OS.IsWinCE) {
+        if (parent is null) {
+            if ((style & SWT.ON_TOP) !is 0) {
+                int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+                if ((style & SWT.NO_TRIM) !is 0 || (style & trim) is 0) {
+                    bits |= OS.WS_EX_TOOLWINDOW;
+                }
+            }
+        }
+    }
+
+    /*
+    * Bug in Windows 98 and NT.  Creating a window with the
+    * WS_EX_TOPMOST extended style can result in a dialog shell
+    * being moved behind its parent.  The exact case where this
+    * happens is a shell with two dialog shell children where
+    * each dialog child has another hidden dialog child with
+    * the WS_EX_TOPMOST extended style.  Clicking on either of
+    * the visible dialogs causes them to become active but move
+    * to the back, behind the parent shell.  The fix is to
+    * disallow the WS_EX_TOPMOST extended style on Windows 98
+    * and NT.
+    */
+    if (parent !is null) {
+        if (OS.IsWin95) return bits;
+        if (OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+            return bits;
+        }
+    }
+    if ((style & SWT.ON_TOP) !is 0) bits |= OS.WS_EX_TOPMOST;
+    return bits;
+}
+
+override String windowClass () {
+    static if (OS.IsSP) return DialogClass;
+    if ((style & SWT.TOOL) !is 0) {
+        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+        if ((style & trim) is 0) return TCHARsToStr( display.windowShadowClass );
+    }
+    return parent !is null ? TCHARzToStr(DialogClass.ptr) : super.windowClass ();
+}
+
+override int windowProc () {
+    if (windowProc_ !is null) return cast(int) windowProc_;
+    static if (OS.IsSP) return cast(int) DialogProc;
+    if ((style & SWT.TOOL) !is 0) {
+        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
+        if ((style & trim) is 0) return super.windowProc ();
+    }
+    return parent !is null ? cast(int) DialogProc : super.windowProc ();
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwnd is toolTipHandle_ || hwnd is balloonTipHandle_) {
+        switch (msg) {
+            case OS.WM_TIMER: {
+                if (wParam !is ToolTip.TIMER_ID) break;
+                ToolTip tip = getCurrentToolTip (hwnd);
+                if (tip !is null && tip.autoHide) {
+                    tip.setVisible (false);
+                }
+                break;
+            }
+            case OS.WM_LBUTTONDOWN: {
+                ToolTip tip = getCurrentToolTip (hwnd);
+                if (tip !is null) {
+                    tip.setVisible (false);
+                    tip.postEvent (SWT.Selection);
+                }
+                break;
+            }
+            default:
+        }
+        return callWindowProc (hwnd, msg, wParam, lParam);
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle ();
+    if (handle !is null) return bits | OS.WS_CHILD;
+    bits &= ~OS.WS_CHILD;
+    /*
+    * Feature in WinCE.  Calling CreateWindowEx () with WS_OVERLAPPED
+    * and a parent window causes the new window to become a WS_CHILD of
+    * the parent instead of a dialog child.  The fix is to use WS_POPUP
+    * for a window with a parent.
+    *
+    * Feature in WinCE PPC.  A window without a parent with WS_POPUP
+    * always shows on top of the Pocket PC 'Today Screen'. The fix
+    * is to not set WS_POPUP for a window without a parent on WinCE
+    * devices.
+    *
+    * NOTE: WS_POPUP causes CreateWindowEx () to ignore CW_USEDEFAULT
+    * and causes the default window location and size to be zero.
+    */
+    static if (OS.IsWinCE) {
+        if (OS.IsSP) return bits | OS.WS_POPUP;
+        return parent is null ? bits : bits | OS.WS_POPUP;
+    }
+
+    /*
+    * Use WS_OVERLAPPED for all windows, either dialog or top level
+    * so that CreateWindowEx () will respect CW_USEDEFAULT and set
+    * the default window location and size.
+    *
+    * NOTE:  When a WS_OVERLAPPED window is created, Windows gives
+    * the new window WS_CAPTION style bits.  These two constants are
+    * as follows:
+    *
+    *   WS_OVERLAPPED = 0
+    *   WS_CAPTION = WS_BORDER | WS_DLGFRAME
+    *
+    */
+    return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION;
+}
+
+override LRESULT WM_ACTIVATE (int wParam, int lParam) {
+    static if (OS.IsPPC) {
+        /*
+        * Note: this does not work when we get WM_ACTIVATE prior
+        * to adding a listener.
+        */
+        if (hooks (SWT.HardKeyDown) || hooks (SWT.HardKeyUp)) {
+            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 (OS.LOWORD (wParam) !is 0) {
+            OS.SHSipPreference (handle, psai.fSipUp is 0 ? OS.SIP_DOWN : OS.SIP_UP);
+        }
+    }
+
+    /*
+    * 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 commit the composition
+    * string.
+    */
+    if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        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 (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);
+        }
+    }
+    return parent !is null ? LRESULT.ZERO : result;
+}
+
+override LRESULT WM_COMMAND (int wParam, int lParam) {
+    static if (OS.IsPPC) {
+        /*
+        * Note in WinCE PPC:  Close the Shell when the "Done Button" has
+        * been pressed. lParam is either 0 (PocketPC 2002) or the handle
+        * to the Shell (PocketPC).
+        */
+        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;
+        }
+    }
+    /*
+    * Feature in Windows.  On PPC, the menu is not actually an HMENU.
+    * By observation, it is a tool bar that is configured to look like
+    * a menu.  Therefore, when the PPC menu sends WM_COMMAND messages,
+    * lParam is not zero because the WM_COMMAND was not sent from a menu.
+    * Sub menu item events originate from the menu bar.  Top menu items
+    * events originate from a tool bar.  The fix is to detect the source
+    * of the WM_COMMAND and set lParam to zero to pretend that the message
+    * came from a real Windows menu, not a tool bar.
+    */
+    static if (OS.IsPPC || OS.IsSP) {
+        if (menuBar !is null) {
+            auto hwndCB = menuBar.hwndCB;
+            if (lParam !is 0 && hwndCB !is null) {
+                if (lParam is hwndCB) {
+                    return super.WM_COMMAND (wParam, 0);
+                } else {
+                    int /*long*/ hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD);
+                    if (lParam is hwndChild) return super.WM_COMMAND (wParam, 0);
+                }
+            }
+        }
+    }
+    return super.WM_COMMAND (wParam, lParam);
+}
+
+override LRESULT WM_DESTROY (int wParam, int lParam) {
+    LRESULT result = super.WM_DESTROY (wParam, lParam);
+    /*
+    * When the shell is a WS_CHILD window of a non-SWT
+    * window, the destroy code does not get called because
+    * the non-SWT window does not call dispose ().  Instead,
+    * the destroy code is called here in WM_DESTROY.
+    */
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.WS_CHILD) !is 0) {
+        releaseParent ();
+        release (false);
+    }
+    return result;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  When a shell is resized by dragging
+    * the resize handles, Windows temporarily fills in black
+    * rectangles where the new contents of the shell should
+    * draw.  The fix is to always draw the background of shells.
+    *
+    * NOTE: This only happens on Vista.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        drawBackground (cast(HDC)wParam);
+        return LRESULT.ONE;
+    }
+    return result;
+}
+
+override LRESULT WM_ENTERIDLE (int wParam, int lParam) {
+    LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
+    if (result !is null) return result;
+    if (display.runMessages) {
+        if (display.runAsyncMessages (false)) display.wakeThread ();
+    }
+    return result;
+}
+
+override LRESULT WM_GETMINMAXINFO (int wParam, int lParam) {
+    LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
+    if (result !is null) return result;
+    if (minWidth !is SWT.DEFAULT || minHeight !is SWT.DEFAULT) {
+        MINMAXINFO* info = cast(MINMAXINFO*)lParam;
+        //OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
+        if (minWidth !is SWT.DEFAULT) info.ptMinTrackSize.x = minWidth;
+        if (minHeight !is SWT.DEFAULT) info.ptMinTrackSize.y = minHeight;
+        //OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
+        return LRESULT.ZERO;
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Check for WM_MOUSEACTIVATE when an MDI shell is active
+    * and stop the normal shell activation but allow the mouse
+    * down to be delivered.
+    */
+    int hittest = cast(short) OS.LOWORD (lParam);
+    switch (hittest) {
+        case OS.HTERROR:
+        case OS.HTTRANSPARENT:
+        case OS.HTNOWHERE:
+            break;
+        default: {
+            Control control = display._getFocusControl ();
+            if (control !is null) {
+                Decorations decorations = control.menuShell ();
+                if (decorations.getShell () is this && decorations !is this) {
+                    display.ignoreRestoreFocus = true;
+                    display.lastHittest = hittest;
+                    display.lastHittestControl = null;
+                    if (hittest is OS.HTMENU || hittest is OS.HTSYSMENU) {
+                        display.lastHittestControl = control;
+                        return null;
+                    }
+                    if (OS.IsWin95 && hittest is OS.HTCAPTION) {
+                        display.lastHittestControl = control;
+                    }
+                    return new LRESULT (OS.MA_NOACTIVATE);
+                }
+            }
+        }
+    }
+    if (hittest is OS.HTMENU) return null;
+
+    /*
+    * Get the current location of the cursor,
+    * not the location of the cursor when the
+    * WM_MOUSEACTIVATE was generated.  This is
+    * strictly incorrect but is necessary in
+    * order to support Activate and Deactivate
+    * events for embedded widgets that have
+    * their own event loop.  In that case, the
+    * cursor location reported by GetMessagePos()
+    * is the one for our event loop, not the
+    * embedded widget's event loop.
+    */
+    POINT pt;
+    if (!OS.GetCursorPos (&pt)) {
+        int pos = OS.GetMessagePos ();
+        OS.POINTSTOPOINT (pt, pos);
+    }
+    auto hwnd = OS.WindowFromPoint (pt);
+    if (hwnd is null) return null;
+    Control control = display.findControl (hwnd);
+
+    /*
+    * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS,
+    * do not activate the shell when the user clicks on the
+    * the client area or on the border or a control within the
+    * shell that does not take focus.
+    */
+    if (control !is null && (control.state & CANVAS) !is 0) {
+        if ((control.style & SWT.NO_FOCUS) !is 0) {
+            int bits = SWT.ON_TOP | SWT.NO_FOCUS;
+            if ((style & bits) is bits) {
+                if (hittest is OS.HTBORDER || hittest is OS.HTCLIENT) {
+                    return new LRESULT (OS.MA_NOACTIVATE);
+                }
+            }
+        }
+    }
+
+    int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam);
+    setActiveControl (control);
+    return new LRESULT (code);
+}
+
+override LRESULT WM_MOVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOVE (wParam, lParam);
+    if (result !is null) return result;
+    ToolTip tip = getCurrentToolTip ();
+    if (tip !is null) tip.setVisible (false);
+    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 /*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 /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+        if (hittest is OS.HTMENU) hittest = OS.HTBORDER;
+        return new LRESULT (hittest);
+    }
+    return null;
+}
+
+override LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * When the normal activation was interrupted in WM_MOUSEACTIVATE
+    * because the active shell was an MDI shell, set the active window
+    * to the top level shell but lock the active window and stop focus
+    * changes.  This allows the user to interact the top level shell
+    * in the normal manner.
+    */
+    if (!display.ignoreRestoreFocus) return result;
+    Display display = this.display;
+    HWND hwndActive;
+    bool fixActive = OS.IsWin95 && display.lastHittest is OS.HTCAPTION;
+    if (fixActive) hwndActive = OS.SetActiveWindow (handle);
+    display.lockActiveWindow = true;
+    int /*long*/ code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
+    display.lockActiveWindow = false;
+    if (fixActive) OS.SetActiveWindow (hwndActive);
+    Control focusControl = display.lastHittestControl;
+    if (focusControl !is null && !focusControl.isDisposed ()) {
+        focusControl.setFocus ();
+    }
+    display.lastHittestControl = null;
+    display.ignoreRestoreFocus = false;
+    return new LRESULT (code);
+}
+
+override LRESULT WM_PALETTECHANGED (int wParam, int lParam) {
+    if ( cast(HANDLE)wParam !is handle) {
+        auto hPalette = display.hPalette;
+        if (hPalette !is null) return selectPalette (hPalette);
+    }
+    return super.WM_PALETTECHANGED (wParam, lParam);
+}
+
+override LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) {
+    auto hPalette = display.hPalette;
+    if (hPalette !is null) return selectPalette (hPalette);
+    return super.WM_QUERYNEWPALETTE (wParam, lParam);
+}
+
+override LRESULT WM_SETCURSOR (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the shell is disabled
+    * by a Windows standard dialog (like a MessageBox
+    * or FileDialog), clicking in the shell does not
+    * bring the shell or the dialog to the front. The
+    * fix is to detect this case and bring the shell
+    * forward.
+    */
+    int msg = OS.HIWORD (lParam);
+    if (msg is OS.WM_LBUTTONDOWN) {
+        if (!Display.TrimEnabled) {
+            Shell modalShell = display.getModalShell ();
+            if (modalShell !is null && !isActive ()) {
+                auto hwndModal = modalShell.handle;
+                if (OS.IsWindowEnabled (hwndModal)) {
+                    OS.SetActiveWindow (hwndModal);
+                }
+            }
+        }
+        if (!OS.IsWindowEnabled (handle)) {
+            static if (!OS.IsWinCE) {
+                auto hwndPopup = OS.GetLastActivePopup (handle);
+                if (hwndPopup !is null && hwndPopup !is handle) {
+                    if (display.getControl (hwndPopup) is null) {
+                        if (OS.IsWindowEnabled (hwndPopup)) {
+                            OS.SetActiveWindow (hwndPopup);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    /*
+    * When the shell that contains a cursor is disabled,
+    * WM_SETCURSOR is called with HTERROR.  Normally,
+    * when a control is disabled, the parent will get
+    * mouse and cursor events.  In the case of a disabled
+    * shell, there is no enabled parent.  In order to
+    * show the cursor when a shell is disabled, it is
+    * necessary to override WM_SETCURSOR when called
+    * with HTERROR to set the cursor but only when the
+    * mouse is in the client area of the shell.
+    */
+    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 ();
+                OS.POINTSTOPOINT (pt, pos);
+                OS.ScreenToClient (handle, &pt);
+                RECT rect;
+                OS.GetClientRect (handle, &rect);
+                if (OS.PtInRect (&rect, pt)) {
+                    OS.SetCursor (cursor.handle);
+                    switch (msg) {
+                        case OS.WM_LBUTTONDOWN:
+                        case OS.WM_RBUTTONDOWN:
+                        case OS.WM_MBUTTONDOWN:
+                        case OS.WM_XBUTTONDOWN:
+                            OS.MessageBeep (OS.MB_OK);
+                        default:
+                    }
+                    return LRESULT.ONE;
+                }
+            }
+        }
+    }
+    return super.WM_SETCURSOR (wParam, lParam);
+}
+
+override LRESULT WM_SETTINGCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SETTINGCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    static if (OS.IsPPC) {
+        if (wParam is OS.SPI_SETSIPINFO) {
+            /*
+            * The SIP is in a new state.  Cache its new value.
+            * Resize the Shell if it has the style SWT.RESIZE.
+            * Note that SHHandleWMSettingChange resizes the
+            * Shell and also updates the cached state.
+            */
+            if ((style & SWT.RESIZE) !is 0) {
+                OS.SHHandleWMSettingChange (handle, wParam, lParam, psai);
+                return LRESULT.ZERO;
+            } else {
+                SIPINFO pSipInfo;
+                pSipInfo.cbSize = SIPINFO.sizeof;
+                OS.SipGetInfo (&pSipInfo);
+                psai.fSipUp = pSipInfo.fdwFlags & OS.SIPF_ON;
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SHOWWINDOW (int wParam, int lParam) {
+    LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  If the shell is hidden while the parent
+    * is iconic,  Windows shows the shell when the parent is
+    * deiconified.  This does not happen if the shell is hidden
+    * while the parent is not an icon.  The fix is to track
+    * visible state for the shell and refuse to show the shell
+    * when the parent is shown.
+    */
+    if (lParam is OS.SW_PARENTOPENING) {
+        Control control = this;
+        while (control !is null) {
+            Shell shell = control.getShell ();
+            if (!shell.showWithParent) return LRESULT.ZERO;
+            control = control.parent;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  When the last visible window in
+    * a process minimized, Windows swaps out the memory for
+    * the process.  The assumption is that the user can no
+    * longer interact with the window, so the memory can be
+    * released to other applications.  However, for programs
+    * that use a lot of memory, swapping the memory back in
+    * can take a long time, sometimes minutes.  The fix is
+    * to intercept WM_SYSCOMMAND looking for SC_MINIMIZE
+    * and use ShowWindow() with SW_SHOWMINIMIZED to minimize
+    * the window, rather than running the default window proc.
+    *
+    * NOTE:  The default window proc activates the next
+    * top-level window in the Z-order while ShowWindow()
+    * with SW_SHOWMINIMIZED does not.  There is no fix for
+    * this at this time.
+    */
+    if (OS.IsWinNT) {
+        int cmd = wParam & 0xFFF0;
+        switch (cmd) {
+            case OS.SC_MINIMIZE:
+                long memory = RuntimeTotalMemory ();
+                if (memory >= 32 * 1024 * 1024) {
+                    OS.ShowWindow (handle, OS.SW_SHOWMINIMIZED);
+                    return LRESULT.ZERO;
+                }
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
+    if (result !is null) return result;
+    auto lpwp = cast(WINDOWPOS*)lParam;
+    //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+    if ((lpwp.flags & OS.SWP_NOSIZE) is 0) {
+        lpwp.cx = Math.max (lpwp.cx, minWidth);
+        int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
+        if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) {
+            lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
+        }
+        lpwp.cy = Math.max (lpwp.cy, minHeight);
+        if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) {
+            if ((style & SWT.RESIZE) !is 0) {
+                lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
+            } else {
+                RECT rect;
+                int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+                OS.AdjustWindowRectEx (&rect, bits1, false, bits2);
+                lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top);
+            }
+        }
+        //OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
+    }
+    return result;
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Slider.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,817 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Slider;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class are selectable user interface
+ * objects that represent a range of positive, numeric values.
+ * <p>
+ * At any given moment, a given slider will have a
+ * single 'selection' that is considered to be its
+ * value, which is constrained to be within the range of
+ * values the slider represents (that is, between its
+ * <em>minimum</em> and <em>maximum</em> values).
+ * </p><p>
+ * Typically, sliders will be made up of five areas:
+ * <ol>
+ * <li>an arrow button for decrementing the value</li>
+ * <li>a page decrement area for decrementing the value by a larger amount</li>
+ * <li>a <em>thumb</em> for modifying the value by mouse dragging</li>
+ * <li>a page increment area for incrementing the value by a larger amount</li>
+ * <li>an arrow button for incrementing the value</li>
+ * </ol>
+ * Based on their style, sliders are either <code>HORIZONTAL</code>
+ * (which have a left facing button for decrementing the value and a
+ * right facing button for incrementing it) or <code>VERTICAL</code>
+ * (which have an upward facing button for decrementing the value
+ * and a downward facing buttons for incrementing it).
+ * </p><p>
+ * On some platforms, the size of the slider's thumb can be
+ * varied relative to the magnitude of the range of values it
+ * represents (that is, relative to the difference between its
+ * maximum and minimum values). Typically, this is used to
+ * indicate some proportional value such as the ratio of the
+ * visible area of a document to the total amount of space that
+ * it would take to display it. SWT supports setting the thumb
+ * size even if the underlying platform does not, but in this
+ * case the appearance of the slider will not change.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>HORIZONTAL, VERTICAL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see ScrollBar
+ * @see <a href="http://www.eclipse.org/swt/snippets/#slider">Slider snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Slider : Control {
+
+    alias Control.computeSize computeSize;
+    alias Control.setBounds setBounds;
+    alias Control.windowProc windowProc;
+
+    int increment, pageIncrement;
+    bool ignoreFocus;
+    static /+const+/ WNDPROC ScrollBarProc;
+    static const TCHAR[] ScrollBarClass = "SCROLLBAR";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ScrollBarClass.ptr, &lpWndClass);
+            ScrollBarProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#HORIZONTAL
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's value, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the event object detail field contains one of the following values:
+ * <code>SWT.NONE</code> - for the end of a drag.
+ * <code>SWT.DRAG</code>.
+ * <code>SWT.HOME</code>.
+ * <code>SWT.END</code>.
+ * <code>SWT.ARROW_DOWN</code>.
+ * <code>SWT.ARROW_UP</code>.
+ * <code>SWT.PAGE_DOWN</code>.
+ * <code>SWT.PAGE_UP</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's value
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    /*
+    * Feature in Windows.  Windows runs a modal message
+    * loop when the user drags a scroll bar.  This means
+    * that mouse down events won't get delivered until
+    * after the loop finishes.  The fix is to run any
+    * deferred messages, including mouse down messages
+    * before calling the scroll bar window proc.
+    */
+    switch (msg) {
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONDBLCLK:
+            display.runDeferredEvents ();
+        default:
+    }
+    return OS.CallWindowProc (ScrollBarProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int border = getBorderWidth ();
+    int width = border * 2, height = border * 2;
+    if ((style & SWT.HORIZONTAL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXHSCROLL) * 10;
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    } else {
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+        height += OS.GetSystemMetrics (OS.SM_CYVSCROLL) * 10;
+    }
+    if (wHint !is SWT.DEFAULT) width = wHint + (border * 2);
+    if (hHint !is SWT.DEFAULT) height = hHint + (border * 2);
+    return new Point (width, height);
+}
+
+override void createWidget () {
+    super.createWidget ();
+    increment = 1;
+    pageIncrement = 10;
+    /*
+    * Set the initial values of the maximum
+    * to 100 and the thumb to 10.  Note that
+    * info.nPage needs to be 11 in order to
+    * get a thumb that is 10.
+    */
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_ALL;
+    info.nMax = 100;
+    info.nPage = 11;
+    OS.SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_SCROLLBAR);
+}
+
+override int defaultForeground () {
+    return OS.GetSysColor (OS.COLOR_BTNFACE);
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    static if (!OS.IsWinCE) {
+        int flags = enabled ? OS.ESB_ENABLE_BOTH : OS.ESB_DISABLE_BOTH;
+        OS.EnableScrollBar (handle, OS.SB_CTL, flags);
+    }
+    if (enabled) {
+        state &= ~DISABLED;
+    } else {
+        state |= DISABLED;
+    }
+}
+
+override public bool getEnabled () {
+    checkWidget ();
+    return (state & DISABLED) is 0;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <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 int getIncrement () {
+    checkWidget ();
+    return increment;
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <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 int getMaximum () {
+    checkWidget ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    return info.nMax;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <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 int getMinimum () {
+    checkWidget ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    return info.nMin;
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <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 int getPageIncrement () {
+    checkWidget ();
+    return pageIncrement;
+}
+
+/**
+ * Returns the 'selection', which is the receiver's value.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <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 int getSelection () {
+    checkWidget ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    return info.nPos;
+}
+
+/**
+ * Returns the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.
+ *
+ * @return the thumb value
+ *
+ * @exception SWTException <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 int getThumb () {
+    checkWidget ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_PAGE;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    if (info.nPage !is 0) --info.nPage;
+    return info.nPage;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's value.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+override void setBounds (int x, int y, int width, int height, int flags) {
+    super.setBounds (x, y, width, height, flags);
+    /*
+    * Bug in Windows.  If the scroll bar is resized when it has focus,
+    * the flashing cursor that is used to show that the scroll bar has
+    * focus is not moved.  The fix is to send a fake WM_SETFOCUS to
+    * get the scroll bar to recompute the size of the flashing cursor.
+    */
+    if (OS.GetFocus () is handle) {
+        ignoreFocus = true;
+        OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
+        ignoreFocus = false;
+    }
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down (or right/left) arrows
+ * are pressed to the argument, which must be at least
+ * one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setIncrement (int value) {
+    checkWidget ();
+    if (value < 1) return;
+    increment = value;
+}
+
+/**
+ * Sets the maximum. If this value is negative or less than or
+ * equal to the minimum, the value is ignored. If necessary, first
+ * the thumb and then the selection are adjusted to fit within the
+ * new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException <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 setMaximum (int value) {
+    checkWidget ();
+    if (value < 0) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    if (value - info.nMin - info.nPage < 1) return;
+    info.nMax = value;
+    SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+/**
+ * Sets the minimum value. If this value is negative or greater
+ * than or equal to the maximum, the value is ignored. If necessary,
+ * first the thumb and then the selection are adjusted to fit within
+ * the new range.
+ *
+ * @param value the new minimum
+ *
+ * @exception SWTException <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 setMinimum (int value) {
+    checkWidget ();
+    if (value < 0) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    if (info.nMax - value - info.nPage < 1) return;
+    info.nMin = value;
+    SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the page increment/decrement areas
+ * are selected to the argument, which must be at least
+ * one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setPageIncrement (int value) {
+    checkWidget ();
+    if (value < 1) return;
+    pageIncrement = value;
+}
+
+bool SetScrollInfo (HWND hwnd, int flags, SCROLLINFO* info, bool fRedraw) {
+    /*
+    * Feature in Windows.  Using SIF_DISABLENOSCROLL,
+    * SetScrollInfo () can change enabled and disabled
+    * state of the scroll bar causing a scroll bar that
+    * was disabled by the application to become enabled.
+    * The fix is to disable the scroll bar (again) when
+    * the application has disabled the scroll bar.
+    */
+    if ((state & DISABLED) !is 0) fRedraw = false;
+    bool result = cast(bool) OS.SetScrollInfo (hwnd, flags, info, fRedraw);
+    if ((state & DISABLED) !is 0) {
+        OS.EnableWindow (handle, false);
+        static if (!OS.IsWinCE) {
+            OS.EnableScrollBar (handle, OS.SB_CTL, OS.ESB_DISABLE_BOTH);
+        }
+    }
+
+    /*
+    * Bug in Windows.  If the thumb is resized when it has focus,
+    * the flashing cursor that is used to show that the scroll bar
+    * has focus is not moved.  The fix is to send a fake WM_SETFOCUS
+    * to get the scroll bar to recompute the size of the flashing
+    * cursor.
+    */
+    if (OS.GetFocus () is handle) {
+        ignoreFocus = true;
+        OS.SendMessage (handle, OS.WM_SETFOCUS, 0, 0);
+        ignoreFocus = false;
+    }
+    return result;
+}
+
+/**
+ * Sets the 'selection', which is the receiver's
+ * value, to the argument which must be greater than or equal
+ * to zero.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <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 setSelection (int value) {
+    checkWidget ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS;
+    info.nPos = value;
+    SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+/**
+ * Sets the size of the receiver's thumb relative to the
+ * difference between its maximum and minimum values.  This new
+ * value will be ignored if it is less than one, and will be
+ * clamped if it exceeds the receiver's current range.
+ *
+ * @param value the new thumb value, which must be at least one and not
+ * larger than the size of the current range
+ *
+ * @exception SWTException <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 setThumb (int value) {
+    checkWidget ();
+    if (value < 1) return;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    info.nPage = value;
+    if (info.nPage !is 0) info.nPage++;
+    SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, thumb, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param thumb the new thumb value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException <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 setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
+    checkWidget ();
+    if (minimum < 0) return;
+    if (maximum < 0) return;
+    if (thumb < 1) return;
+    if (increment < 1) return;
+    if (pageIncrement < 1) return;
+    this.increment = increment;
+    this.pageIncrement = pageIncrement;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_POS | OS.SIF_PAGE | OS.SIF_RANGE | OS.SIF_DISABLENOSCROLL;
+    info.nPos = selection;
+    info.nMin = minimum;
+    info.nMax = maximum;
+    info.nPage = thumb;
+    if (info.nPage !is 0) info.nPage++;
+    SetScrollInfo (handle, OS.SB_CTL, &info, true);
+}
+
+override int widgetExtStyle () {
+    /*
+    * Bug in Windows.  If a scroll bar control is given a border,
+    * dragging the scroll bar thumb eats away parts of the border
+    * while the thumb is dragged.  The fix is to clear border for
+    * all scroll bars.
+    */
+    int bits = super.widgetExtStyle ();
+    if ((style & SWT.BORDER) !is 0) bits &= ~OS.WS_EX_CLIENTEDGE;
+    return bits;
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.WS_TABSTOP;
+    /*
+    * Bug in Windows.  If a scroll bar control is given a border,
+    * dragging the scroll bar thumb eats away parts of the border
+    * while the thumb is dragged.  The fix is to clear WS_BORDER.
+    */
+    if ((style & SWT.BORDER) !is 0) bits &= ~OS.WS_BORDER;
+    if ((style & SWT.HORIZONTAL) !is 0) return bits | OS.SBS_HORZ;
+    return bits | OS.SBS_VERT;
+}
+
+override String windowClass () {
+    return TCHARsToStr(ScrollBarClass);
+}
+
+override int windowProc () {
+    return cast(int) ScrollBarProc;
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    if ((style & SWT.VERTICAL) !is 0) return result;
+    /*
+    * Bug in Windows.  When a horizontal scroll bar is mirrored,
+    * the native control does not correctly swap the arrow keys.
+    * The fix is to swap them before calling the scroll bar window
+    * proc.
+    *
+    * NOTE: This fix is not ideal.  It breaks when the bug is fixed
+    * in the operating system.
+    */
+    if ((style & SWT.MIRRORED) !is 0) {
+        switch (wParam) {
+            case OS.VK_LEFT:
+            case OS.VK_RIGHT: {
+                int key = wParam is OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT;
+                int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
+                return new LRESULT (code);
+            }
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  Windows uses the WS_TABSTOP
+    * style for the scroll bar to decide that focus
+    * should be set during WM_LBUTTONDBLCLK.  This is
+    * not the desired behavior.  The fix is to clear
+    * and restore WS_TABSTOP so that Windows will not
+    * assign focus.
+    */
+    int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    int newBits = oldBits & ~OS.WS_TABSTOP;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+    LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
+    if (isDisposed ()) return LRESULT.ZERO;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
+    if (result is LRESULT.ZERO) return result;
+
+    /*
+    * Feature in Windows.  Windows runs a modal message loop
+    * when the user drags a scroll bar that terminates when
+    * it sees an WM_LBUTTONUP.  Unfortunately the WM_LBUTTONUP
+    * is consumed.  The fix is to send a fake mouse up and
+    * release the automatic capture.
+    */
+    static if (!OS.IsWinCE) {
+        if (OS.GetCapture () is handle) OS.ReleaseCapture ();
+        if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
+            return LRESULT.ZERO;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  Windows uses the WS_TABSTOP
+    * style for the scroll bar to decide that focus
+    * should be set during WM_LBUTTONDOWN.  This is
+    * not the desired behavior.  The fix is to clear
+    * and restore WS_TABSTOP so that Windows will not
+    * assign focus.
+    */
+    int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    int newBits = oldBits & ~OS.WS_TABSTOP;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+    LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+    if (isDisposed ()) return LRESULT.ZERO;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
+    if (result is LRESULT.ZERO) return result;
+
+    /*
+    * Feature in Windows.  Windows runs a modal message loop
+    * when the user drags a scroll bar that terminates when
+    * it sees an WM_LBUTTONUP.  Unfortunately the WM_LBUTTONUP
+    * is consumed.  The fix is to send a fake mouse up and
+    * release the automatic capture.
+    */
+    static if (!OS.IsWinCE) {
+        if (OS.GetCapture () is handle) OS.ReleaseCapture ();
+        if (!sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam)) {
+            return LRESULT.ONE;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    if (ignoreFocus) return null;
+    return super.WM_SETFOCUS (wParam, lParam);
+}
+
+override LRESULT wmScrollChild (int wParam, int lParam) {
+
+    /* Do nothing when scrolling is ending */
+    int code = OS.LOWORD (wParam);
+    if (code is OS.SB_ENDSCROLL) return null;
+
+    /* Move the thumb */
+    Event event = new Event ();
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE;
+    OS.GetScrollInfo (handle, OS.SB_CTL, &info);
+    info.fMask = OS.SIF_POS;
+    switch (code) {
+        case OS.SB_THUMBPOSITION:
+            event.detail = SWT.NONE;
+            info.nPos = info.nTrackPos;
+            break;
+        case OS.SB_THUMBTRACK:
+            event.detail = SWT.DRAG;
+            info.nPos = info.nTrackPos;
+            break;
+        case OS.SB_TOP:
+            event.detail = SWT.HOME;
+            info.nPos = info.nMin;
+            break;
+        case OS.SB_BOTTOM:
+            event.detail = SWT.END;
+            info.nPos = info.nMax;
+            break;
+        case OS.SB_LINEDOWN:
+            event.detail = SWT.ARROW_DOWN;
+            info.nPos += increment;
+            break;
+        case OS.SB_LINEUP:
+            event.detail = SWT.ARROW_UP;
+            info.nPos = Math.max (info.nMin, info.nPos - increment);
+            break;
+        case OS.SB_PAGEDOWN:
+            event.detail = SWT.PAGE_DOWN;
+            info.nPos += pageIncrement;
+            break;
+        case OS.SB_PAGEUP:
+            event.detail = SWT.PAGE_UP;
+            info.nPos = Math.max (info.nMin, info.nPos - pageIncrement);
+            break;
+        default:
+    }
+    OS.SetScrollInfo (handle, OS.SB_CTL, &info, true);
+
+    /*
+    * Feature in Windows.  Windows runs a modal message
+    * loop when the user drags a scroll bar.  This means
+    * that selection event must be sent because WM_HSCROLL
+    * and WM_VSCROLL are sent from the modal message loop
+    * so that they are delivered during inside the loop.
+    */
+    sendEvent (SWT.Selection, event);
+    // the widget could be destroyed at this point
+    return null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Spinner.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1505 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Spinner;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+
+
+import java.lang.all;
+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
+ * objects that allow the user to enter and modify numeric
+ * values.
+ * <p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to add children to it, or set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, Modify, Verify</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#spinner">Spinner snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.1
+ */
+public class Spinner : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.sendKeyEvent sendKeyEvent;
+    alias Composite.setBackgroundImage setBackgroundImage;
+    alias Composite.setToolTipText setToolTipText;
+    alias Composite.windowProc windowProc;
+
+    HWND hwndText, hwndUpDown;
+    bool ignoreModify;
+    int pageIncrement, digits;
+    static /+const+/ WNDPROC EditProc;
+    static const TCHAR[] EditClass = "EDIT";
+    static /+const+/ WNDPROC UpDownProc;
+    static const TCHAR[] UpDownClass = OS.UPDOWN_CLASS;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, EditClass.ptr, &lpWndClass);
+            EditProc = lpWndClass.lpfnWndProc;
+            OS.GetClassInfo (null, UpDownClass.ptr, &lpWndClass);
+            UpDownProc = lpWndClass.lpfnWndProc;
+            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
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwnd is hwndText) {
+        return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+    }
+    if (hwnd is hwndUpDown) {
+        return OS.CallWindowProc (UpDownProc, hwnd, msg, wParam, lParam);
+    }
+    return OS.DefWindowProc (handle, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+override bool checkHandle (HWND hwnd) {
+    return hwnd is handle || hwnd is hwndText || hwnd is hwndUpDown;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+    auto hInstance = OS.GetModuleHandle (null);
+    int textExStyle = (style & SWT.BORDER) !is 0 ? OS.WS_EX_CLIENTEDGE : 0;
+    int textStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.ES_AUTOHSCROLL | OS.WS_CLIPSIBLINGS;
+    if ((style & SWT.READ_ONLY) !is 0) textStyle |= OS.ES_READONLY;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) textExStyle |= OS.WS_EX_LAYOUTRTL;
+    }
+    hwndText = OS.CreateWindowEx (
+        textExStyle,
+        EditClass.ptr,
+        null,
+        textStyle,
+        0, 0, 0, 0,
+        handle,
+        null,
+        hInstance,
+        null);
+    if (hwndText is null) error (SWT.ERROR_NO_HANDLES);
+    OS.SetWindowLongPtr (hwndText, OS.GWLP_ID, cast(LONG_PTR)hwndText);
+    int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY;
+    if ((style & SWT.WRAP) !is 0) upDownStyle |= OS.UDS_WRAP;
+    if ((style & SWT.BORDER) !is 0) {
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+            upDownStyle |= OS.UDS_ALIGNLEFT;
+        } else {
+            upDownStyle |= OS.UDS_ALIGNRIGHT;
+        }
+    }
+    hwndUpDown = OS.CreateWindowEx (
+        0,
+        UpDownClass.ptr,
+        null,
+        upDownStyle,
+        0, 0, 0, 0,
+        handle,
+        null,
+        hInstance,
+        null);
+    if (hwndUpDown is null) error (SWT.ERROR_NO_HANDLES);
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+    SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags);
+    OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_ID, cast(LONG_PTR)hwndUpDown);
+    if (OS.IsDBLocale) {
+        auto hIMC = OS.ImmGetContext (handle);
+        OS.ImmAssociateContext (hwndText, hIMC);
+        OS.ImmAssociateContext (hwndUpDown, hIMC);
+        OS.ImmReleaseContext (handle, hIMC);
+    }
+    OS.SendMessage (hwndUpDown, OS.UDM_SETRANGE32, 0, 100);
+    OS.SendMessage (hwndUpDown, OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, 0);
+    pageIncrement = 10;
+    digits = 0;
+    TCHAR* buffer = StrToTCHARz (getCodePage (), "0");
+    OS.SetWindowText (hwndText, buffer);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is not called for texts.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #removeVerifyListener
+ */
+void addVerifyListener (VerifyListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Verify, typedListener);
+}
+
+override HWND borderHandle () {
+    return hwndText;
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+        HFONT newFont, oldFont;
+        auto hDC = OS.GetDC (hwndText);
+        newFont = cast(HFONT) OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        TEXTMETRIC tm;
+        OS.GetTextMetrics (hDC, &tm);
+        height = tm.tmHeight;
+        RECT rect;
+        int max;
+        OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, &max);
+        String string = .toString( max );
+        if (digits > 0) {
+            StringBuffer buffer = new StringBuffer ();
+            buffer.append (string);
+            buffer.append (getDecimalSeparator ());
+            int count = digits - string.length;
+            while (count >= 0) {
+                buffer.append ("0");
+                count--;
+            }
+            string = buffer.toString ();
+        }
+        TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
+        int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+        OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
+        width = rect.right - rect.left;
+        if (newFont !is null ) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (hwndText, hDC);
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    Rectangle trim = computeTrim (0, 0, width, height);
+    if (hHint is SWT.DEFAULT) {
+        int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL) + 2 * getBorderWidth ();
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            upDownHeight += (style & SWT.BORDER) !is 0 ? 1 : 3;
+        }
+        trim.height = Math.max (trim.height, upDownHeight);
+    }
+    return new Point (trim.width, trim.height);
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+
+    /* Get the trim of the text control */
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    int bits0 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
+    int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
+    OS.AdjustWindowRectEx (&rect, bits0, false, bits1);
+    width = rect.right - rect.left;
+    height = rect.bottom - rect.top;
+
+    /*
+    * The preferred height of a single-line text widget
+    * has been hand-crafted to be the same height as
+    * the single-line text widget in an editable combo
+    * box.
+    */
+    int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+    x -= OS.LOWORD (margins);
+    width += OS.LOWORD (margins) + OS.HIWORD (margins);
+    if ((style & SWT.BORDER) !is 0) {
+        x -= 1;
+        y -= 1;
+        width += 2;
+        height += 2;
+    }
+    width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+    return new Rectangle (x, y, width, height);
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 copy () {
+    checkWidget ();
+    OS.SendMessage (hwndText, OS.WM_COPY, 0, 0);
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @exception SWTException <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 cut () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (hwndText, OS.WM_CUT, 0, 0);
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    OS.EnableWindow (hwndText, enabled);
+    OS.EnableWindow (hwndUpDown, enabled);
+}
+
+override void deregister () {
+    super.deregister ();
+    display.removeControl (hwndText);
+    display.removeControl (hwndUpDown);
+}
+
+override bool hasFocus () {
+    auto hwndFocus = OS.GetFocus ();
+    if (hwndFocus is handle) return true;
+    if (hwndFocus is hwndText) return true;
+    if (hwndFocus is hwndUpDown) return true;
+    return false;
+}
+
+/**
+ * Returns the number of decimal places used by the receiver.
+ *
+ * @return the digits
+ *
+ * @exception SWTException <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 int getDigits () {
+    checkWidget ();
+    return digits;
+}
+
+String getDecimalSeparator () {
+    TCHAR[] tchar = NewTCHARs (getCodePage (), 4);
+    int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SDECIMAL, tchar.ptr, 4);
+    return size !is 0 ? TCHARsToStr( tchar[0 .. size-1] ) : ".";
+}
+
+/**
+ * Returns the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed.
+ *
+ * @return the increment
+ *
+ * @exception SWTException <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 int getIncrement () {
+    checkWidget ();
+    UDACCEL udaccel;
+    OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, &udaccel);
+    return udaccel.nInc;
+}
+
+/**
+ * Returns the maximum value which the receiver will allow.
+ *
+ * @return the maximum
+ *
+ * @exception SWTException <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 int getMaximum () {
+    checkWidget ();
+    int max;
+    OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, &max);
+    return max;
+}
+
+/**
+ * Returns the minimum value which the receiver will allow.
+ *
+ * @return the minimum
+ *
+ * @exception SWTException <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 int getMinimum () {
+    checkWidget ();
+    int min;
+    OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null);
+    return min;
+}
+
+/**
+ * Returns the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed.
+ *
+ * @return the page increment
+ *
+ * @exception SWTException <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 int getPageIncrement () {
+    checkWidget ();
+    return pageIncrement;
+}
+
+/**
+ * Returns the <em>selection</em>, which is the receiver's position.
+ *
+ * @return the selection
+ *
+ * @exception SWTException <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 int getSelection () {
+    checkWidget ();
+    static if (OS.IsWinCE) {
+        return OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+    } else {
+        return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+    }
+}
+
+int getSelectionText (bool [] parseFail) {
+    int length_ = OS.GetWindowTextLength (hwndText);
+    TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
+    OS.GetWindowText (hwndText, buffer.ptr, length_ + 1);
+    String string = TCHARsToStr( buffer[ 0 .. length_] );
+    try {
+        int value;
+        if (digits > 0) {
+            String decimalSeparator = getDecimalSeparator ();
+            int index = string.indexOf (decimalSeparator);
+            if (index !is -1)  {
+                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);
+                } else {
+                    int i = digits - decimalPart.length;
+                    for (int j = 0; j < i; j++) {
+                        decimalPart = decimalPart ~ "0";
+                    }
+                }
+                int wholeValue = Integer.parseInt (wholePart);
+                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);
+        }
+        int max, min;
+        OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, &max);
+        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 SWTException <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 SWTException <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;
+    int mbcsSize = OS.GetWindowTextLengthA (hwndText);
+    if (mbcsSize is 0) return 0;
+    if (mbcsPos >= mbcsSize) return mbcsSize;
+    CHAR [] buffer = new CHAR [mbcsSize + 1];
+    OS.GetWindowTextA (hwndText, buffer.ptr, mbcsSize + 1);
+    return OS.MultiByteToWideChar (getCodePage (), OS.MB_PRECOMPOSED, buffer.ptr, mbcsPos, null, 0);
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 paste () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (hwndText, OS.WM_PASTE, 0, 0);
+}
+
+override void register () {
+    super.register ();
+    display.addControl (hwndText, this);
+    display.addControl (hwndUpDown, this);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    hwndText = hwndUpDown = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #addVerifyListener
+ */
+void removeVerifyListener (VerifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Verify, listener);
+}
+
+override bool sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+    if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+        return false;
+    }
+    if ((style & SWT.READ_ONLY) !is 0) return true;
+    if (type !is SWT.KeyDown) return true;
+    if (msg !is OS.WM_CHAR && msg !is OS.WM_KEYDOWN && msg !is OS.WM_IME_CHAR) {
+        return true;
+    }
+    if (event.character is 0) return true;
+//  if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
+    char key = event.character;
+    int stateMask = event.stateMask;
+
+    /*
+    * Disable all magic keys that could modify the text
+    * and don't send events when Alt, Shift or Ctrl is
+    * pressed.
+    */
+    switch (msg) {
+        case OS.WM_CHAR:
+            if (key !is 0x08 && key !is 0x7F && key !is '\r' && key !is '\t' && key !is '\n') break;
+            // FALL THROUGH
+        case OS.WM_KEYDOWN:
+            if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) !is 0) return false;
+            break;
+        default:
+    }
+
+    /*
+    * If the left button is down, the text widget refuses the character.
+    */
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+        return true;
+    }
+
+    /* Verify the character */
+    String oldText = "";
+    int start, end;
+    OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+    switch (key) {
+        case 0x08:  /* Bs */
+            if (start is end) {
+                if (start is 0) return true;
+                start = start - 1;
+                if (!OS.IsUnicode && OS.IsDBLocale) {
+                    int newStart, newEnd;
+                    OS.SendMessage (hwndText, OS.EM_SETSEL, start, end);
+                    OS.SendMessage (hwndText, OS.EM_GETSEL, &newStart, &newEnd);
+                    if (start !is newStart) start = start - 1;
+                }
+                start = Math.max (start, 0);
+            }
+            break;
+        case 0x7F:  /* Del */
+            if (start is end) {
+                int length_ = OS.GetWindowTextLength (hwndText);
+                if (start is length_) return true;
+                end = end + 1;
+                if (!OS.IsUnicode && OS.IsDBLocale) {
+                    int newStart, newEnd;
+                    OS.SendMessage (hwndText, OS.EM_SETSEL, start, end);
+                    OS.SendMessage (hwndText, OS.EM_GETSEL, &newStart, &newEnd);
+                    if (end !is newEnd) end = end + 1;
+                }
+                end = Math.min (end, length_);
+            }
+            break;
+        case '\r':  /* Return */
+            return true;
+        default:    /* Tab and other characters */
+            if (key !is '\t' && key < 0x20) return true;
+            oldText = [key];
+            break;
+    }
+    String newText = verifyText (oldText, start, end, event);
+    if (newText is null) return false;
+    if (newText is oldText) return true;
+    TCHAR* buffer = StrToTCHARz (getCodePage (), newText);
+    OS.SendMessage (hwndText, OS.EM_SETSEL, start, end);
+    OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
+    return false;
+}
+
+override void setBackgroundImage (HBITMAP hBitmap) {
+    super.setBackgroundImage (hBitmap);
+    OS.InvalidateRect (hwndText, null, true);
+}
+
+override void setBackgroundPixel (int pixel) {
+    super.setBackgroundPixel (pixel);
+    OS.InvalidateRect (hwndText, null, true);
+}
+
+/**
+ * Sets the number of decimal places used by the receiver.
+ * <p>
+ * The digit setting is used to allow for floating point values in the receiver.
+ * For example, to set the selection to a floating point value of 1.37 call setDigits() with
+ * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value
+ * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all
+ * numeric APIs.
+ * </p>
+ *
+ * @param value the new digits (must be greater than or equal to zero)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the value is less than zero</li>
+ * </ul>
+ * @exception SWTException <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 setDigits (int value) {
+    checkWidget ();
+    if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (value is this.digits) return;
+    this.digits = value;
+    int pos;
+    static if (OS.IsWinCE) {
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+    } else {
+        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+    }
+    setSelection (pos, false, true, false);
+}
+
+override void setForegroundPixel (int pixel) {
+    super.setForegroundPixel (pixel);
+    OS.InvalidateRect (hwndText, null, true);
+}
+
+/**
+ * Sets the amount that the receiver's value will be
+ * modified by when the up/down arrows are pressed to
+ * the argument, which must be at least one.
+ *
+ * @param value the new increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setIncrement (int value) {
+    checkWidget ();
+    if (value < 1) return;
+    auto hHeap = OS.GetProcessHeap ();
+    int count = OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 0, cast(UDACCEL*)null);
+    auto udaccels = cast(UDACCEL*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, UDACCEL.sizeof * count);
+    OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, count, udaccels);
+    int first = -1;
+    UDACCEL udaccel;
+    for (int i = 0; i < count; i++) {
+        void* offset = udaccels + i;
+        OS.MoveMemory (&udaccel, offset, UDACCEL.sizeof);
+        if (first is -1) first = udaccel.nInc;
+        udaccel.nInc  =  udaccel.nInc * value / first;
+        OS.MoveMemory (offset, &udaccel, UDACCEL.sizeof);
+    }
+    OS.SendMessage (hwndUpDown, OS.UDM_SETACCEL, count, udaccels);
+    OS.HeapFree (hHeap, 0, udaccels);
+}
+
+/**
+ * Sets the maximum value that the receiver will allow.  This new
+ * value will be ignored if it is not greater than the receiver's current
+ * minimum value.  If the new maximum is applied then the receiver's
+ * selection value will be adjusted if necessary to fall within its new range.
+ *
+ * @param value the new maximum, which must be greater than the current minimum
+ *
+ * @exception SWTException <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 setMaximum (int value) {
+    checkWidget ();
+    int min;
+    OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null);
+    if (value <= min) return;
+    int pos;
+    static if (OS.IsWinCE) {
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+    } else {
+        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+    }
+    OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, min, value);
+    if (pos > value) setSelection (value, true, true, false);
+}
+
+/**
+ * Sets the minimum value that the receiver will allow.  This new
+ * 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 less than the current maximum
+ *
+ * @exception SWTException <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 setMinimum (int value) {
+    checkWidget ();
+    int max;
+    OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, &max);
+    if (value >= max) return;
+    int pos;
+    static if (OS.IsWinCE) {
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+    } else {
+        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+    }
+    OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, value, max);
+    if (pos < value) setSelection (value, true, true, false);
+}
+
+/**
+ * Sets the amount that the receiver's position will be
+ * modified by when the page up/down keys are pressed
+ * to the argument, which must be at least one.
+ *
+ * @param value the page increment (must be greater than zero)
+ *
+ * @exception SWTException <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 setPageIncrement (int value) {
+    checkWidget ();
+    if (value < 1) return;
+    pageIncrement = value;
+}
+
+/**
+ * Sets the <em>selection</em>, which is the receiver's
+ * position, to the argument. If the argument is not within
+ * the range specified by minimum and maximum, it will be
+ * adjusted to fall within this range.
+ *
+ * @param value the new selection (must be zero or greater)
+ *
+ * @exception SWTException <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 setSelection (int value) {
+    checkWidget ();
+    int max, min;
+    OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, &max);
+    value = Math.min (Math.max (min, value), max );
+    setSelection (value, true, true, false);
+}
+
+void setSelection (int value, bool setPos, bool setText, bool notify) {
+    if (setPos) {
+        OS.SendMessage (hwndUpDown , OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, value);
+    }
+    if (setText) {
+        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);
+                buffer.append (string.substring (index));
+            } else {
+                buffer.append ("0");
+                buffer.append (decimalSeparator);
+                while (index++ < 0) buffer.append ("0");
+                buffer.append (string);
+            }
+            string = buffer.toString ();
+        }
+        if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+            int length_ = OS.GetWindowTextLength (hwndText);
+            string = verifyText (string, 0, length_, null);
+            if (string is null) return;
+        }
+        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 (SWT.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 SWTException <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 (SWT.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);
+}
+
+/**
+ * Sets the receiver's selection, minimum value, maximum
+ * value, digits, increment and page increment all at once.
+ * <p>
+ * Note: This is similar to setting the values individually
+ * using the appropriate methods, but may be implemented in a
+ * more efficient fashion on some platforms.
+ * </p>
+ *
+ * @param selection the new selection value
+ * @param minimum the new minimum value
+ * @param maximum the new maximum value
+ * @param digits the new digits value
+ * @param increment the new increment value
+ * @param pageIncrement the new pageIncrement value
+ *
+ * @exception SWTException <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.2
+ */
+public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
+    checkWidget ();
+    if (maximum <= minimum) return;
+    if (digits < 0) return;
+    if (increment < 1) return;
+    if (pageIncrement < 1) return;
+    selection = Math.min (Math.max (minimum, selection), maximum);
+    setIncrement (increment);
+    this.pageIncrement = pageIncrement;
+    this.digits = digits;
+    OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, minimum, maximum);
+    setSelection (selection, true, true, false);
+}
+
+override void subclass () {
+    super.subclass ();
+    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.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) {
+    Event event = new Event ();
+    event.text = string;
+    event.start = start;
+    event.end = end;
+    if (keyEvent !is null) {
+        event.character = keyEvent.character;
+        event.keyCode = keyEvent.keyCode;
+        event.stateMask = keyEvent.stateMask;
+    }
+    int index = 0;
+    if (digits > 0) {
+        String decimalSeparator = getDecimalSeparator ();
+        index = string.indexOf (decimalSeparator);
+        if (index !is -1) {
+            string = string.substring (0, index) ~ string.substring (index + 1);
+        }
+        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++;
+    }
+    event.doit = index is string.length ;
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        event.start = mbcsToWcsPos (start);
+        event.end = mbcsToWcsPos (end);
+    }
+    sendEvent (SWT.Verify, event);
+    if (!event.doit || isDisposed ()) return null;
+    return event.text;
+}
+
+override int widgetExtStyle () {
+    return super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (hwnd is hwndText || hwnd is hwndUpDown) {
+        LRESULT result = null;
+        switch (msg) {
+            /* Keyboard messages */
+            case OS.WM_CHAR:        result = wmChar (hwnd, wParam, lParam); break;
+            case OS.WM_IME_CHAR:    result = wmIMEChar (hwnd, wParam, lParam); break;
+            case OS.WM_KEYDOWN:     result = wmKeyDown (hwnd, wParam, lParam); break;
+            case OS.WM_KEYUP:       result = wmKeyUp (hwnd, wParam, lParam); break;
+            case OS.WM_SYSCHAR:     result = wmSysChar (hwnd, wParam, lParam); break;
+            case OS.WM_SYSKEYDOWN:  result = wmSysKeyDown (hwnd, wParam, lParam); break;
+            case OS.WM_SYSKEYUP:    result = wmSysKeyUp (hwnd, wParam, lParam); break;
+
+            /* Mouse Messages */
+            case OS.WM_CAPTURECHANGED:  result = wmCaptureChanged (hwnd, wParam, lParam); break;
+            case OS.WM_LBUTTONDBLCLK:   result = wmLButtonDblClk (hwnd, wParam, lParam); break;
+            case OS.WM_LBUTTONDOWN:     result = wmLButtonDown (hwnd, wParam, lParam); break;
+            case OS.WM_LBUTTONUP:       result = wmLButtonUp (hwnd, wParam, lParam); break;
+            case OS.WM_MBUTTONDBLCLK:   result = wmMButtonDblClk (hwnd, wParam, lParam); break;
+            case OS.WM_MBUTTONDOWN:     result = wmMButtonDown (hwnd, wParam, lParam); break;
+            case OS.WM_MBUTTONUP:       result = wmMButtonUp (hwnd, wParam, lParam); break;
+            case OS.WM_MOUSEHOVER:      result = wmMouseHover (hwnd, wParam, lParam); break;
+            case OS.WM_MOUSELEAVE:      result = wmMouseLeave (hwnd, wParam, lParam); break;
+            case OS.WM_MOUSEMOVE:       result = wmMouseMove (hwnd, wParam, lParam); break;
+//          case OS.WM_MOUSEWHEEL:      result = wmMouseWheel (hwnd, wParam, lParam); break;
+            case OS.WM_RBUTTONDBLCLK:   result = wmRButtonDblClk (hwnd, wParam, lParam); break;
+            case OS.WM_RBUTTONDOWN:     result = wmRButtonDown (hwnd, wParam, lParam); break;
+            case OS.WM_RBUTTONUP:       result = wmRButtonUp (hwnd, wParam, lParam); break;
+            case OS.WM_XBUTTONDBLCLK:   result = wmXButtonDblClk (hwnd, wParam, lParam); break;
+            case OS.WM_XBUTTONDOWN:     result = wmXButtonDown (hwnd, wParam, lParam); break;
+            case OS.WM_XBUTTONUP:       result = wmXButtonUp (hwnd, wParam, lParam); break;
+
+            /* Focus Messages */
+            case OS.WM_SETFOCUS:        result = wmSetFocus (hwnd, wParam, lParam); break;
+            case OS.WM_KILLFOCUS:       result = wmKillFocus (hwnd, wParam, lParam); break;
+
+            /* Paint messages */
+            case OS.WM_PAINT:           result = wmPaint (hwnd, wParam, lParam); break;
+            case OS.WM_PRINT:           result = wmPrint (hwnd, wParam, lParam); break;
+
+            /* Menu messages */
+            case OS.WM_CONTEXTMENU:     result = wmContextMenu (hwnd, wParam, lParam); break;
+
+            /* Clipboard messages */
+            case OS.WM_CLEAR:
+            case OS.WM_CUT:
+            case OS.WM_PASTE:
+            case OS.WM_UNDO:
+            case OS.EM_UNDO:
+                if (hwnd is hwndText) {
+                    result = wmClipboard (hwnd, msg, wParam, lParam);
+                }
+                break;
+            default:
+        }
+        if (result !is null) return result.value;
+        return callWindowProc (hwnd, msg, wParam, lParam);
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    super.WM_ERASEBKGND (wParam, lParam);
+    drawBackground (cast(HANDLE)wParam);
+    return LRESULT.ONE;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    return null;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    OS.SetFocus (hwndText);
+    OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+    return null;
+}
+
+override LRESULT WM_SETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFONT (wParam, lParam);
+    if (result !is null) return result;
+    OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam);
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (isDisposed ()) return result;
+    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);
+    int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
+    SetWindowPos (hwndText, null, 0, 0, textWidth + border, height, flags);
+    SetWindowPos (hwndUpDown, null, textWidth, 0, upDownWidth, height, flags);
+    return result;
+}
+
+override LRESULT wmChar (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = super.wmChar (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  For some reason, when the
+    * widget is a single line text widget, when the
+    * user presses tab, return or escape, Windows beeps.
+    * The fix is to look for these keys and not call
+    * the window proc.
+    */
+    switch (wParam) {
+        case SWT.CR:
+            postEvent (SWT.DefaultSelection);
+            // FALL THROUGH
+        case SWT.TAB:
+        case SWT.ESC: return LRESULT.ZERO;
+        default:
+    }
+    return result;
+}
+
+LRESULT wmClipboard (HWND hwndText, int msg, int wParam, int lParam) {
+    if ((style & SWT.READ_ONLY) !is 0) return null;
+//  if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+    bool call = false;
+    int start, end;
+    String newText = null;
+    switch (msg) {
+        case OS.WM_CLEAR:
+        case OS.WM_CUT:
+            OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+            if (start !is end) {
+                newText = "";
+                call = true;
+            }
+            break;
+        case OS.WM_PASTE:
+            OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+            newText = getClipboardText ();
+            break;
+        case OS.EM_UNDO:
+        case OS.WM_UNDO:
+            if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) !is 0) {
+                ignoreModify = true;
+                OS.SendMessage (hwndText, OS.EM_GETSEL, &start, &end);
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                int length_ = OS.GetWindowTextLength (hwndText);
+                int newStart, newEnd;
+                OS.SendMessage (hwndText, OS.EM_GETSEL, &newStart, &newEnd);
+                if (length_ !is 0 && newStart !is newEnd ) {
+                    TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
+                    OS.GetWindowText (hwndText, buffer.ptr, length_ + 1);
+                    newText = TCHARsToStr( buffer[ newStart .. newEnd ] );
+                } else {
+                    newText = "";
+                }
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+                ignoreModify = false;
+            }
+            break;
+        default:
+    }
+    if (newText !is null) {
+        String oldText = newText;
+        newText = verifyText (newText, start, end, null);
+        if (newText is null) return LRESULT.ZERO;
+        if ( newText !=/*eq*/ oldText ) {
+            if (call) {
+                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
+            }
+            TCHAR[] buffer = StrToTCHARs (getCodePage (), newText, true);
+            if (msg is OS.WM_SETTEXT) {
+                auto hHeap = OS.GetProcessHeap ();
+                int byteCount = buffer.length * TCHAR.sizeof;
+                auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+                OS.MoveMemory (pszText, buffer.ptr, byteCount);
+                int code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, cast(int) pszText);
+                OS.HeapFree (hHeap, 0, pszText);
+                return new LRESULT (code);
+            } else {
+                OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer.ptr);
+                return LRESULT.ZERO;
+            }
+        }
+    }
+    return null;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    int code = OS.HIWORD (wParam);
+    switch (code) {
+        case OS.EN_CHANGE:
+            if (ignoreModify) break;
+            bool [] parseFail = new bool [1];
+            int value = getSelectionText (parseFail);
+            if (!parseFail [0]) {
+                int pos;
+                static if (OS.IsWinCE) {
+                    pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+                } else {
+                    pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+                }
+                if (pos !is value) setSelection (value, true, false, true);
+            }
+            sendEvent (SWT.Modify);
+            if (isDisposed ()) return LRESULT.ZERO;
+            break;
+        default:
+    }
+    return super.wmCommandChild (wParam, lParam);
+}
+
+override LRESULT wmKeyDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+    if (result !is null) return result;
+
+    /* Increment the value */
+    UDACCEL udaccel;
+    OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, &udaccel);
+    int delta = 0;
+    switch (wParam) {
+        case OS.VK_UP: delta = udaccel.nInc; break;
+        case OS.VK_DOWN: delta = -udaccel.nInc; break;
+        case OS.VK_PRIOR: delta = pageIncrement; break;
+        case OS.VK_NEXT: delta = -pageIncrement; break;
+        default:
+    }
+    if (delta !is 0) {
+        bool [1] parseFail;
+        int value = getSelectionText (parseFail);
+        if (parseFail [0]) {
+            static if (OS.IsWinCE) {
+                value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+            } else {
+                value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+            }
+        }
+        int newValue = value + delta;
+        int max, min;
+        OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, &max);
+        if ((style & SWT.WRAP) !is 0) {
+            if (newValue < min ) newValue = max;
+            if (newValue > max ) newValue = min;
+        }
+        newValue = Math.min (Math.max (min , newValue), max );
+        if (value !is newValue) setSelection (newValue, true, true, true);
+    }
+
+    /*  Stop the edit control from moving the caret */
+    switch (wParam) {
+        case OS.VK_UP:
+        case OS.VK_DOWN:
+            return LRESULT.ZERO;
+        default:
+    }
+    return result;
+}
+
+override LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) {
+    bool [1] parseFail;
+    int value = getSelectionText (parseFail);
+    if (parseFail [0]) {
+        static if (OS.IsWinCE) {
+            value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
+        } else {
+            value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
+        }
+        setSelection (value, false, true, false);
+    }
+    return super.wmKillFocus (hwnd, wParam, lParam);
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    switch (hdr.code) {
+        case OS.UDN_DELTAPOS:
+            NMUPDOWN* lpnmud = cast(NMUPDOWN*)lParam;
+            //OS.MoveMemory (lpnmud, lParam, NMUPDOWN.sizeof);
+            int value = lpnmud.iPos + lpnmud.iDelta;
+            int max, min;
+            OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, &max);
+            if ((style & SWT.WRAP) !is 0) {
+                if (value < min ) value = max ;
+                if (value > max ) value = min ;
+            }
+            /*
+            * The SWT.Modify event is sent after the widget has been
+            * updated with the new state.  Rather than allowing
+            * the default updown window proc to set the value
+            * when the user clicks on the updown control, set
+            * the value explicitly and stop the window proc
+            * from running.
+            */
+            value = Math.min (Math.max (min , value), max );
+            if (value !is lpnmud.iPos) {
+                setSelection (value, true, true, true);
+            }
+            return LRESULT.ONE;
+        default:
+    }
+    return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+override LRESULT wmScrollChild (int wParam, int lParam) {
+    int code = OS.LOWORD (wParam);
+    switch (code) {
+        case OS.SB_THUMBPOSITION:
+            postEvent (SWT.Selection);
+            break;
+        default:
+    }
+    return super.wmScrollChild (wParam, lParam);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Synchronizer.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Synchronizer;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.RunnableLock;
+import java.lang.Runnable;
+import java.lang.System;
+import org.eclipse.swt.internal.Compatibility;
+
+import org.eclipse.swt.SWT;
+import tango.core.Thread;
+import org.eclipse.swt.graphics.Device;
+import tango.core.Exception;
+
+/**
+ * Instances of this class provide synchronization support
+ * for displays. A default instance is created automatically
+ * for each display, and this instance is sufficient for almost
+ * all applications.
+ * <p>
+ * <b>IMPORTANT:</b> Typical application code <em>never</em>
+ * needs to deal with this class. It is provided only to
+ * allow applications which require non-standard
+ * synchronization behavior to plug in the support they
+ * require. <em>Subclasses which override the methods in
+ * this class must ensure that the superclass methods are
+ * invoked in their implementations</em>
+ * </p>
+ *
+ * @see Display#setSynchronizer
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Synchronizer {
+    Display display;
+    int messageCount;
+    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 (SWT.getPlatform ());
+
+/**
+ * Constructs a new instance of this class.
+ *
+ * @param display the display to create the synchronizer on
+ */
+public this (Display display) {
+    this.display = display;
+    messageLock = new Object ();
+}
+
+void addLast (RunnableLock lock) {
+    bool wake = false;
+    synchronized (messageLock) {
+        if (messages is null) messages = new RunnableLock [GROW_SIZE];
+        if (messageCount is messages.length) {
+            RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE];
+            System.arraycopy (messages, 0, newMessages, 0, messageCount);
+            messages = newMessages;
+        }
+        messages [messageCount++] = lock;
+        wake = messageCount is 1;
+    }
+    if (wake) display.wakeThread ();
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The caller of this method continues
+ * to run in parallel, and is not notified when the
+ * runnable has completed.
+ *
+ * @param runnable code to run on the user-interface thread.
+ *
+ * @see #syncExec
+ */
+public void asyncExec (Runnable runnable) {
+    if (runnable is null) {
+        //TEMPORARY CODE
+        if (!IS_CARBON) {
+            display.wake ();
+            return;
+        }
+    }
+    addLast (new RunnableLock (runnable));
+}
+
+int getMessageCount () {
+    synchronized (messageLock) {
+        return messageCount;
+    }
+}
+
+void releaseSynchronizer () {
+    display = null;
+    messages = null;
+    messageLock = null;
+    syncThread = null;
+}
+
+RunnableLock removeFirst () {
+    synchronized (messageLock) {
+        if (messageCount is 0) return null;
+        RunnableLock lock = messages [0];
+        System.arraycopy (messages, 1, messages, 0, --messageCount);
+        messages [messageCount] = null;
+        if (messageCount is 0) {
+            if (messages.length > MESSAGE_LIMIT) messages = null;
+        }
+        return lock;
+    }
+}
+
+bool runAsyncMessages () {
+    return runAsyncMessages (false);
+}
+
+bool runAsyncMessages (bool all) {
+    bool run = false;
+    do {
+        RunnableLock lock = removeFirst ();
+        if (lock is null) return run;
+        run = true;
+        synchronized (lock) {
+            syncThread = lock.thread;
+            try {
+                lock.run ();
+            } catch (Exception t) {
+                lock.throwable = t;
+                SWT.error (SWT.ERROR_FAILED_EXEC, t);
+            } finally {
+                syncThread = null;
+                lock.notifyAll ();
+            }
+        }
+    } while (all);
+    return run;
+}
+
+/**
+ * Causes the <code>run()</code> method of the runnable to
+ * be invoked by the user-interface thread at the next
+ * reasonable opportunity. The thread which calls this method
+ * is suspended until the runnable completes.
+ *
+ * @param runnable code to run on the user-interface thread.
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
+ * </ul>
+ *
+ * @see #asyncExec
+ */
+public void syncExec (Runnable runnable) {
+    RunnableLock lock = null;
+    synchronized (Device.classinfo) {
+        if (display is null || display.isDisposed ()) SWT.error (SWT.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;
+    }
+    synchronized (lock) {
+        bool interrupted = false;
+        while (!lock.done ()) {
+            try {
+                lock.wait ();
+            } catch (SyncException e) {
+                interrupted = true;
+            }
+        }
+        if (interrupted) {
+            Compatibility.interrupt();
+        }
+        if (lock.throwable !is null) {
+            SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable);
+        }
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TabFolder.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1039 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TabFolder;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Control;
+
+import java.lang.all;
+
+/**
+ * Instances of this class implement the notebook user interface
+ * metaphor.  It allows the user to select a notebook page from
+ * set of pages.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TabItem</code>.
+ * <code>Control</code> children are created and then set into a
+ * tab item using <code>TabItem#setControl</code>.
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * it does not make sense to set a layout on it.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>TOP, BOTTOM</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles TOP and BOTTOM may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tabfolder">TabFolder, TabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TabFolder : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.windowProc windowProc;
+
+    TabItem [] items;
+    ImageList imageList;
+    private static /+const+/ WNDPROC TabFolderProc;
+    static const TCHAR[] TabFolderClass = OS.WC_TABCONTROL;
+
+    /*
+    * These are the undocumented control id's for the children of
+    * a tab control.  Since there are no constants for these values,
+    * they may change with different versions of Windows.
+    */
+    static const int ID_UPDOWN = 1;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, TabFolderClass.ptr, &lpWndClass);
+            TabFolderProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The tab control window class
+            * uses the CS_HREDRAW and CS_VREDRAW style bits to
+            * force a full redraw of the control and all children
+            * when resized.  This causes flashing.  The fix is to
+            * register a new window class without these bits and
+            * implement special code that damages only the exposed
+            * area.
+            *
+            * 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 SWT, 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_HREDRAW | OS.CS_VREDRAW | OS.CS_GLOBALCLASS);
+            int byteCount = (TabFolderClass.length+1) * TCHAR.sizeof;
+            auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, TabFolderClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener(SWT.Selection,typedListener);
+    addListener(SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    return OS.CallWindowProc (TabFolderProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    /*
+    * When the SWT.TOP style has not been set, force the
+    * tabs to be on the bottom for tab folders on PPC.
+    */
+    if (OS.IsPPC) {
+        if ((style & SWT.TOP) is 0) style |= SWT.BOTTOM;
+    }
+    style = checkBits (style, SWT.TOP, SWT.BOTTOM, 0, 0, 0, 0);
+
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    Point size = super.computeSize (wHint, hHint, changed);
+    RECT insetRect, itemRect;
+    OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 0, &insetRect);
+    int width = insetRect.left - insetRect.right;
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    if (count !is 0) {
+        OS.SendMessage (handle, OS.TCM_GETITEMRECT, count - 1, &itemRect);
+        width = Math.max (width, itemRect.right - insetRect.right);
+    }
+    RECT rect;
+    OS.SetRect (&rect, 0, 0, width, size.y);
+    OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 1, &rect);
+    int border = getBorderWidth ();
+    rect.left -= border;  rect.right += border;
+    width = rect.right - rect.left;
+    size.x = Math.max (width, size.x);
+    return size;
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    RECT rect;
+    OS.SetRect (&rect, x, y, x + width, y + height);
+    OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 1, &rect);
+    int border = getBorderWidth ();
+    rect.left -= border;  rect.right += border;
+    rect.top -= border;  rect.bottom += border;
+    int newWidth = rect.right - rect.left;
+    int newHeight = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, newWidth, newHeight);
+}
+
+void createItem (TabItem item, int index) {
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+    if (count is items.length) {
+        TabItem [] newItems = new TabItem [items.length + 4];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    TCITEM tcItem;
+    if (OS.SendMessage (handle, OS.TCM_INSERTITEM, index, &tcItem) is -1) {
+        error (SWT.ERROR_ITEM_NOT_ADDED);
+    }
+    System.arraycopy (items, index, items, index + 1, count - index);
+    items [index] = item;
+
+    /*
+    * Send a selection event when the item that is added becomes
+    * the new selection.  This only happens when the first item
+    * is added.
+    */
+    if (count is 0) {
+        Event event = new Event ();
+        event.item = items [0];
+        sendEvent (SWT.Selection, event);
+        // the widget could be destroyed at this point
+    }
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    /* Enable the flat look for tab folders on PPC */
+    if (OS.IsPPC) {
+        OS.SendMessage (handle, OS.CCM_SETVERSION, 0x020c /*COMCTL32_VERSION*/, 0);
+    }
+
+    /*
+    * 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.
+    */
+    auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
+    OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+}
+
+override void createWidget () {
+    super.createWidget ();
+    items = new TabItem [4];
+}
+
+void destroyItem (TabItem item) {
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    int index = 0;
+    while (index < count) {
+        if (items [index] is item) break;
+        index++;
+    }
+    if (index is count) return;
+    int selectionIndex = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+    if (OS.SendMessage (handle, OS.TCM_DELETEITEM, index, 0) is 0) {
+        error (SWT.ERROR_ITEM_NOT_REMOVED);
+    }
+    System.arraycopy (items, index + 1, items, index, --count - index);
+    items [count] = null;
+    if (count is 0) {
+        if (imageList !is null) {
+            OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, 0);
+            display.releaseImageList (imageList);
+        }
+        imageList = null;
+        items = new TabItem [4];
+    }
+    if (count > 0 && index is selectionIndex) {
+        setSelection (Math.max (0, selectionIndex - 1), true);
+    }
+}
+
+override void drawThemeBackground (HDC hDC, HWND hwnd, RECT* rect) {
+    RECT rect2;
+    OS.GetClientRect (handle, &rect2);
+    OS.MapWindowPoints (handle, hwnd, cast(POINT*) &rect2, 2);
+    RECT dummy;
+    if (OS.IntersectRect (&dummy, &rect2, rect)) {
+        OS.DrawThemeBackground (display.hTabTheme (), hDC, OS.TABP_BODY, 0, &rect2, null);
+    }
+}
+
+override Control findThemeControl () {
+    /* It is not possible to change the background of this control */
+    return this;
+}
+
+override public Rectangle getClientArea () {
+    checkWidget ();
+    forceResize ();
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 0, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 TabItem getItem (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+
+/**
+ * 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 SWTException <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 (SWT.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
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+}
+
+/**
+ * Returns an array of <code>TabItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 TabItem [] getItems () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    TabItem [] result = new TabItem [count];
+    System.arraycopy (items, 0, result, 0, count);
+    return result;
+}
+
+/**
+ * Returns an array of <code>TabItem</code>s that are currently
+ * selected in the receiver. An empty array indicates that no
+ * items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @exception SWTException <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 TabItem [] getSelection () {
+    checkWidget ();
+    int index = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+    if (index is -1) return new TabItem [0];
+    return [ items [index] ];
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException <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 int getSelectionIndex () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+}
+
+int imageIndex (Image image) {
+    if (image is null) return OS.I_IMAGENONE;
+    if (imageList is null) {
+        Rectangle bounds = image.getBounds ();
+        imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+        int index = imageList.add (image);
+        auto hImageList = imageList.getHandle ();
+        OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, hImageList);
+        return index;
+    }
+    int index = imageList.indexOf (image);
+    if (index is -1) {
+        index = imageList.add (image);
+    } else {
+        imageList.put (index, image);
+    }
+    return index;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (TabItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<count; i++) {
+        if (items [i] is item) return i;
+    }
+    return -1;
+}
+
+override Point minimumSize (int wHint, int hHint, bool flushCache) {
+    Control [] children = _getChildren ();
+    int width = 0, height = 0;
+    for (int i=0; i<children.length; i++) {
+        Control child = children [i];
+        int index = 0;
+        int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+        while (index < count) {
+            if (items [index].control is child) break;
+            index++;
+        }
+        if (index is count) {
+            Rectangle rect = child.getBounds ();
+            width = Math.max (width, rect.x + rect.width);
+            height = Math.max (height, rect.y + rect.height);
+        } else {
+            Point size = child.computeSize (wHint, hHint, flushCache);
+            width = Math.max (width, size.x);
+            height = Math.max (height, size.y);
+        }
+    }
+    return new Point (width, height);
+}
+
+override bool mnemonicHit (wchar key) {
+    for (int i=0; i<items.length; i++) {
+        TabItem item = items [i];
+        if (item !is null) {
+            wchar ch = findMnemonic (item.getText ());
+            if (CharacterToUpper (key) is CharacterToUpper (ch)) {
+                if (forceFocus ()) {
+                    if (i !is getSelectionIndex ()) setSelection (i, true);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+override bool mnemonicMatch (wchar key) {
+    for (int i=0; i<items.length; i++) {
+        TabItem item = items [i];
+        if (item !is null) {
+            wchar ch = findMnemonic (item.getText ());
+            if (CharacterToUpper (key) is CharacterToUpper (ch)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+        for (int i=0; i<count; i++) {
+            TabItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (imageList !is null) {
+        OS.SendMessage (handle, OS.TCM_SETIMAGELIST, 0, 0);
+        display.releaseImageList (imageList);
+    }
+    imageList = null;
+}
+
+override void removeControl (Control control) {
+    super.removeControl (control);
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<count; i++) {
+        TabItem item = items [i];
+        if (item.control is control) item.setControl (null);
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selected is first cleared, then the new item is
+ * selected.
+ *
+ * @param item the item to select
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <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.2
+ */
+public void setSelection (TabItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSelection ( [item] );
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selected is first cleared, then the new items are
+ * selected.
+ *
+ * @param items the array of items
+ *
+ * @exception SWTException <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 setSelection (TabItem [] items) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (items.length is 0) {
+        setSelection (-1, false);
+    } else {
+        for (int i=items.length-1; i>=0; --i) {
+            int index = indexOf (items [i]);
+            if (index !is -1) setSelection (index, false);
+        }
+    }
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    Rectangle oldRect = getClientArea ();
+    super.setFont (font);
+    Rectangle newRect = getClientArea ();
+    if (oldRect !=/*eq*/ newRect) {
+        sendResize ();
+        int index = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+        if (index !is -1) {
+            TabItem item = items [index];
+            Control control = item.control;
+            if (control !is null && !control.isDisposed ()) {
+                control.setBounds (getClientArea ());
+            }
+        }
+    }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains selected.
+ * The current selection is first cleared, then the new items are
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 setSelection (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.TCM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) return;
+    setSelection (index, false);
+}
+
+void setSelection (int index, bool notify) {
+    int oldIndex = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+    if (oldIndex is index) return;
+    if (oldIndex !is -1) {
+        TabItem item = items [oldIndex];
+        Control control = item.control;
+        if (control !is null && !control.isDisposed ()) {
+            control.setVisible (false);
+        }
+    }
+    OS.SendMessage (handle, OS.TCM_SETCURSEL, index, 0);
+    int newIndex = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+    if (newIndex !is -1) {
+        TabItem item = items [newIndex];
+        Control control = item.control;
+        if (control !is null && !control.isDisposed ()) {
+            control.setBounds (getClientArea ());
+            control.setVisible (true);
+        }
+        if (notify) {
+            Event event = new Event ();
+            event.item = item;
+            sendEvent (SWT.Selection, event);
+        }
+    }
+}
+
+override String toolTipText (NMTTDISPINFO* hdr) {
+    if ((hdr.uFlags & OS.TTF_IDISHWND) !is 0) {
+        return null;
+    }
+    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 & SWT.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];
+            if (item !is null) return item.toolTipText;
+        }
+    }
+    return super.toolTipText (hdr);
+}
+
+override bool traversePage (bool next) {
+    int count = getItemCount ();
+    if (count <= 1) return false;
+    int index = getSelectionIndex ();
+    if (index is -1) {
+        index = 0;
+    } else {
+        int offset = (next) ? 1 : -1;
+        index = (index + offset + count) % count;
+    }
+    setSelection (index, true);
+    if (index is getSelectionIndex ()) {
+        OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+        return true;
+    }
+    return false;
+}
+
+override int widgetStyle () {
+    /*
+    * Bug in Windows.  Under certain circumstances,
+    * when TCM_SETITEM is used to change the text
+    * in a tab item, the tab folder draws on top
+    * of the client area.  The fix is ensure that
+    * this cannot happen by setting WS_CLIPCHILDREN.
+    */
+    int bits = super.widgetStyle () | OS.WS_CLIPCHILDREN;
+    if ((style & SWT.NO_FOCUS) !is 0) bits |= OS.TCS_FOCUSNEVER;
+    if ((style & SWT.BOTTOM) !is 0) bits |= OS.TCS_BOTTOM;
+    return bits | OS.TCS_TABS | OS.TCS_TOOLTIPS;
+}
+
+override String windowClass () {
+    return TCHARsToStr( TabFolderClass );
+}
+
+override int windowProc () {
+    return cast(int) TabFolderProc;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    /*
+    * Return DLGC_BUTTON so that mnemonics will be
+    * processed without needing to press the ALT key
+    * when the widget has focus.
+    */
+    if (result !is null) return result;
+    return new LRESULT (OS.DLGC_BUTTON);
+}
+
+override LRESULT WM_MOUSELEAVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  On XP, when a tooltip is
+    * hidden due to a time out or mouse press,
+    * the tooltip remains active although no
+    * longer visible and won't show again until
+    * another tooltip becomes active.  If there
+    * is only one tooltip in the window,  it will
+    * never show again.  The fix is to remove the
+    * current tooltip and add it again every time
+    * the mouse leaves the control.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
+        if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+            if ((lpti.uFlags & OS.TTF_IDISHWND) is 0) {
+                OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, &lpti);
+                OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, &lpti);
+            }
+        }
+    }
+    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.  The tab control implements
+    * WM_NCHITTEST to return HTCLIENT when the cursor
+    * is inside the tab buttons.  This causes mouse
+    * events like WM_MOUSEMOVE to be delivered to the
+    * parent.  Also, tool tips for the tab control are
+    * never invoked because tool tips rely on mouse
+    * events to be delivered to the window that wants
+    * to display the tool tip.  The fix is to call the
+    * default window proc that returns HTCLIENT when
+    * the mouse is in the client area.
+    */
+    int /*long*/ hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+    return new LRESULT (hittest);
+}
+
+override LRESULT WM_NOTIFY (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the tab folder window
+    * proc processes WM_NOTIFY, it forwards this
+    * message to its parent.  This is done so that
+    * children of this control that send this message
+    * type to their parent will notify not only
+    * this control but also the parent of this control,
+    * which is typically the application window and
+    * the window that is looking for the message.
+    * If the control did not forward the message,
+    * applications would have to subclass the control
+    * window to see the message. Because the control
+    * window is subclassed by SWT, the message
+    * is delivered twice, once by SWT and once when
+    * the message is forwarded by the window proc.
+    * The fix is to avoid calling the window proc
+    * for this control.
+    */
+    LRESULT result = super.WM_NOTIFY (wParam, lParam);
+    if (result !is null) return result;
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PARENTNOTIFY (int wParam, int lParam) {
+    LRESULT result = super.WM_PARENTNOTIFY (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  Windows does not explicitly set the orientation of
+    * the buddy control.  Instead, the orientation is inherited when WS_EX_LAYOUTRTL
+    * is specified for the tab folder.  This means that when both WS_EX_LAYOUTRTL
+    * and WS_EX_NOINHERITLAYOUT are specified for the tab folder, the buddy control
+    * will not be oriented correctly.  The fix is to explicitly set the orientation
+    * for the buddy control.
+    *
+    * NOTE: WS_EX_LAYOUTRTL is not supported on Windows NT.
+    */
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return result;
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        int code = OS.LOWORD (wParam);
+        switch (code) {
+            case OS.WM_CREATE: {
+                int id = OS.HIWORD (wParam);
+                HWND hwnd = cast(HWND) lParam;
+                if (id is ID_UPDOWN) {
+                    auto bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                    OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYOUTRTL);
+                }
+                break;
+            }
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    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;
+    int index = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+    if (index !is -1) {
+        TabItem item = items [index];
+        Control control = item.control;
+        if (control !is null && !control.isDisposed ()) {
+            control.setBounds (getClientArea ());
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    if (result !is null) return result;
+    if (!OS.IsWindowVisible (handle)) return result;
+    WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+    //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+    if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) !is 0) {
+        return result;
+    }
+    // TEMPORARY CODE
+//  if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+//      OS.InvalidateRect (handle, null, true);
+//      return result;
+//  }
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.TCS_MULTILINE) !is 0) {
+        OS.InvalidateRect (handle, null, true);
+        return result;
+    }
+    RECT rect;
+    OS.SetRect (&rect, 0, 0, lpwp.cx, lpwp.cy);
+    OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &rect);
+    int newWidth = rect.right - rect.left;
+    int newHeight = rect.bottom - rect.top;
+    OS.GetClientRect (handle, &rect);
+    int oldWidth = rect.right - rect.left;
+    int oldHeight = rect.bottom - rect.top;
+    if (newWidth is oldWidth && newHeight is oldHeight) {
+        return result;
+    }
+    RECT inset;
+    OS.SendMessage (handle, OS.TCM_ADJUSTRECT, 0, &inset);
+    int marginX = -inset.right, marginY = -inset.bottom;
+    if (newWidth !is oldWidth) {
+        int left = oldWidth;
+        if (newWidth < oldWidth) left = newWidth;
+        OS.SetRect (&rect, left - marginX, 0, newWidth, newHeight);
+        OS.InvalidateRect (handle, &rect, true);
+    }
+    if (newHeight !is oldHeight) {
+        int bottom = oldHeight;
+        if (newHeight < oldHeight) bottom = newHeight;
+        if (newWidth < oldWidth) oldWidth -= marginX;
+        OS.SetRect (&rect, 0, bottom - marginY, oldWidth, newHeight);
+        OS.InvalidateRect (handle, &rect, true);
+    }
+    return result;
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    int code = hdr.code;
+    switch (code) {
+        case OS.TCN_SELCHANGE:
+        case OS.TCN_SELCHANGING:
+            TabItem item = null;
+            int index = OS.SendMessage (handle, OS.TCM_GETCURSEL, 0, 0);
+            if (index !is -1) item = items [index];
+            if (item !is null) {
+                Control control = item.control;
+                if (control !is null && !control.isDisposed ()) {
+                    if (code is OS.TCN_SELCHANGE) {
+                        control.setBounds (getClientArea ());
+                    }
+                    control.setVisible (code is OS.TCN_SELCHANGE);
+                }
+            }
+            if (code is OS.TCN_SELCHANGE) {
+                Event event = new Event ();
+                event.item = item;
+                postEvent (SWT.Selection, event);
+            }
+        default:
+    }
+    return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TabItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TabItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Control;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * corresponding to a tab for a page in a tab folder.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tabfolder">TabFolder, TabItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class TabItem : Item {
+    TabFolder parent;
+    Control control;
+    String toolTipText;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TabFolder</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (TabFolder parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>TabFolder</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (TabFolder parent, int style, int index) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+void _setText (int index, String string) {
+    /*
+    * Bug in Windows.  In version 6.00 of COMCTL32.DLL, tab
+    * items with an image and a label that includes '&' cause
+    * the tab to draw incorrectly (even when doubled '&&').
+    * The image overlaps the label.  The fix is to remove
+    * all '&' characters from the string.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && image !is null) {
+        if (string.indexOf ('&') !is -1) {
+            int length_ = string.length ;
+            char[] text = new char [length_];
+            string.getChars ( 0, length_, text, 0);
+            int i = 0, j = 0;
+            for (i=0; i<length_; i++) {
+                if (text[i] !is '&') text [j++] = text [i];
+            }
+            if (j < i) string = text[ 0 .. j ].dup;
+        }
+    }
+    auto hwnd = parent.handle;
+    auto hHeap = OS.GetProcessHeap ();
+    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, 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);
+    TCITEM tcItem;
+    tcItem.mask = OS.TCIF_TEXT;
+    tcItem.pszText = pszText;
+    OS.SendMessage (hwnd, OS.TCM_SETITEM, index, &tcItem);
+    OS.HeapFree (hHeap, 0, pszText);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item.  If no
+ * control has been set, return <code>null</code>.
+ * <p>
+ * @return the control
+ *
+ * @exception SWTException <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 Control getControl () {
+    checkWidget();
+    return control;
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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
+ *
+ * @exception SWTException <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 TabFolder getParent () {
+    checkWidget();
+    return parent;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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 String getToolTipText () {
+    checkWidget();
+    return toolTipText;
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    int index = parent.indexOf (this);
+    if (index is parent.getSelectionIndex ()) {
+        if (control !is null) control.setVisible (false);
+    }
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    control = null;
+}
+
+/**
+ * Sets the control that is used to fill the client area of
+ * the tab folder when the user selects the tab item.
+ * <p>
+ * @param control the new control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setControl (Control control) {
+    checkWidget();
+    if (control !is null) {
+        if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
+    }
+    if (this.control !is null && this.control.isDisposed ()) {
+        this.control = null;
+    }
+    Control oldControl = this.control, newControl = control;
+    this.control = control;
+    int index = parent.indexOf (this);
+    if (index !is parent.getSelectionIndex ()) {
+        if (newControl !is null) newControl.setVisible (false);
+        return;
+    }
+    if (newControl !is null) {
+        newControl.setBounds (parent.getClientArea ());
+        newControl.setVisible (true);
+    }
+    if (oldControl !is null) oldControl.setVisible (false);
+}
+
+override public void setImage (Image image) {
+    checkWidget();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    super.setImage (image);
+    /*
+    * Bug in Windows.  In version 6.00 of COMCTL32.DLL, tab
+    * items with an image and a label that includes '&' cause
+    * the tab to draw incorrectly (even when doubled '&&').
+    * The image overlaps the label.  The fix is to remove
+    * all '&' characters from the string and set the text
+    * whenever the image or text is changed.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if (text.indexOf ('&') !is -1) _setText (index, text);
+    }
+    auto hwnd = parent.handle;
+    TCITEM tcItem;
+    tcItem.mask = OS.TCIF_IMAGE;
+    tcItem.iImage = parent.imageIndex (image);
+    OS.SendMessage (hwnd, OS.TCM_SETITEM, index, &tcItem);
+}
+/**
+ * Sets the receiver's text.  The string may include
+ * the mnemonic character.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner.  The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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>
+ *
+ */
+override public void setText (String string) {
+    checkWidget();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (string ==/*eq*/text ) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    super.setText (string);
+    _setText (index, string);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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 setToolTipText (String string) {
+    checkWidget();
+    toolTipText = string;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Table.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,6940 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Table;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import java.lang.all;
+
+
+/**
+ * Instances of this class implement a selectable user interface
+ * object that displays a list of images and strings and issues
+ * notification when selected.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TableItem</code>.
+ * </p><p>
+ * Style <code>VIRTUAL</code> is used to create a <code>Table</code> whose
+ * <code>TableItem</code>s are to be populated by the client on an on-demand basis
+ * instead of up-front.  This can provide significant performance improvements for
+ * tables that are very large or for which <code>TableItem</code> population is
+ * expensive (for example, retrieving values from an external source).
+ * </p><p>
+ * Here is an example of using a <code>Table</code> with style <code>VIRTUAL</code>:
+ * <code><pre>
+ *  final Table table = new Table (parent, SWT.VIRTUAL | SWT.BORDER);
+ *  table.setItemCount (1000000);
+ *  table.addListener (SWT.SetData, new Listener () {
+ *      public void handleEvent (Event event) {
+ *          TableItem item = (TableItem) event.item;
+ *          int index = table.indexOf (item);
+ *          item.setText ("Item " + index);
+ *          System.out.println (item.getText ());
+ *      }
+ *  });
+ * </pre></code>
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * 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, NO_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles SINGLE, and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class Table : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.setBackgroundImage setBackgroundImage;
+    alias Composite.setBounds setBounds;
+    alias Composite.sort sort;
+    alias Composite.update update;
+
+    TableItem [] items;
+    TableColumn [] columns;
+    int columnCount, customCount;
+    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, fullRowSelect;
+    int itemHeight, lastIndexOf, lastWidth, sortDirection, resizeCount, selectionForeground, hotIndex;
+    static /*final*/ WNDPROC HeaderProc;
+    static const int INSET = 4;
+    static const int GRID_WIDTH = 1;
+    static const int SORT_WIDTH = 10;
+    static const int HEADER_MARGIN = 12;
+    static const int HEADER_EXTRA = 3;
+    static const int VISTA_EXTRA = 2;
+    static const int EXPLORER_EXTRA = 2;
+    static const int H_SCROLL_LIMIT = 32;
+    static const int V_SCROLL_LIMIT = 16;
+    static const int DRAG_IMAGE_SIZE = 301;
+    static const bool EXPLORER_THEME = true;
+    private static /+const+/ WNDPROC TableProc;
+    static const TCHAR[] TableClass = OS.WC_LISTVIEW;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, TableClass.ptr, &lpWndClass);
+            TableProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see SWT#HIDE_SELECTION
+ * @see SWT#VIRTUAL
+ * @see SWT#NO_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override void _addListener (int eventType, Listener listener) {
+    super._addListener (eventType, listener);
+    switch (eventType) {
+        case SWT.MeasureItem:
+        case SWT.EraseItem:
+        case SWT.PaintItem:
+            setCustomDraw (true);
+            setBackgroundTransparent (true);
+            if (OS.COMCTL32_MAJOR < 6) style |= SWT.DOUBLE_BUFFERED;
+            if (OS.IsWinCE) OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_LABELTIP, 0);
+            break;
+        default:
+    }
+}
+
+TableItem _getItem (int index) {
+    if ((style & SWT.VIRTUAL) is 0) return items [index];
+    if (items [index] !is null) return items [index];
+    return items [index] = new TableItem (this, SWT.NONE, -1, false);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has the <code>SWT.CHECK</code> style and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    return callWindowProc (hwnd, msg, wParam, lParam, false);
+}
+
+int callWindowProc (HWND hwnd, int msg, int wParam, int lParam, bool forceSelect) {
+    if (handle is null) return 0;
+    if (handle !is hwnd) {
+        return OS.CallWindowProc (HeaderProc, hwnd, msg, wParam, lParam);
+    }
+    int topIndex = 0;
+    bool checkSelection = false, checkActivate = false, redraw = false;
+    switch (msg) {
+        /* Keyboard messages */
+        /*
+        * Feature in Windows.  Windows sends LVN_ITEMACTIVATE from WM_KEYDOWN
+        * instead of WM_CHAR.  This means that application code that expects
+        * to consume the key press and therefore avoid a SWT.DefaultSelection
+        * event will fail.  The fix is to ignore LVN_ITEMACTIVATE when it is
+        * caused by WM_KEYDOWN and send SWT.DefaultSelection from WM_CHAR.
+        */
+        case OS.WM_KEYDOWN:
+            checkActivate = true;
+            //FALL THROUGH
+        case OS.WM_CHAR:
+        case OS.WM_IME_CHAR:
+        case OS.WM_KEYUP:
+        case OS.WM_SYSCHAR:
+        case OS.WM_SYSKEYDOWN:
+        case OS.WM_SYSKEYUP:
+            //FALL THROUGH
+
+        /* Scroll messages */
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL:
+            //FALL THROUGH
+
+        /* Resize messages */
+        case OS.WM_WINDOWPOSCHANGED:
+            redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle);
+            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 */
+        case OS.WM_LBUTTONDBLCLK:
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONUP:
+        case OS.WM_MBUTTONDBLCLK:
+        case OS.WM_MBUTTONDOWN:
+        case OS.WM_MBUTTONUP:
+        case OS.WM_MOUSEHOVER:
+        case OS.WM_MOUSELEAVE:
+        case OS.WM_MOUSEMOVE:
+        case OS.WM_MOUSEWHEEL:
+        case OS.WM_RBUTTONDBLCLK:
+        case OS.WM_RBUTTONDOWN:
+        case OS.WM_RBUTTONUP:
+        case OS.WM_XBUTTONDBLCLK:
+        case OS.WM_XBUTTONDOWN:
+        case OS.WM_XBUTTONUP:
+            checkSelection = true;
+            //FALL THROUGH
+
+        /* Other messages */
+        case OS.WM_SETFONT:
+        case OS.WM_TIMER: {
+            if (findImageControl () !is null) {
+                topIndex = OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+            }
+        }
+        default:
+    }
+    bool oldSelected = wasSelected;
+    if (checkSelection) wasSelected = false;
+    if (checkActivate) ignoreActivate = true;
+
+    /*
+    * 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 & SWT.H_SCROLL) is 0 || (style & SWT.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 & SWT.H_SCROLL) is 0 && (bits & OS.WS_HSCROLL) !is 0) {
+                    fixScroll = true;
+                    bits &= ~OS.WS_HSCROLL;
+                }
+                if ((style & SWT.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);
+            }
+            default:
+        }
+    }
+    int /*long*/ code = 0;
+    if (fixPaint) {
+        PAINTSTRUCT ps;
+        auto hDC = OS.BeginPaint (hwnd, &ps);
+        code = OS.CallWindowProc (TableProc, hwnd, OS.WM_PAINT, cast(int)hDC, lParam);
+        OS.EndPaint (hwnd, &ps);
+    } else {
+        code = OS.CallWindowProc (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) {
+            Event event = new Event ();
+            int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+            if (index !is -1) event.item = _getItem (index);
+            postEvent (SWT.Selection, event);
+        }
+        wasSelected = oldSelected;
+    }
+    switch (msg) {
+        /* Keyboard messages */
+        case OS.WM_KEYDOWN:
+        case OS.WM_CHAR:
+        case OS.WM_IME_CHAR:
+        case OS.WM_KEYUP:
+        case OS.WM_SYSCHAR:
+        case OS.WM_SYSKEYDOWN:
+        case OS.WM_SYSKEYUP:
+            //FALL THROUGH
+
+        /* Scroll messages */
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL:
+            //FALL THROUGH
+
+        /* 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);
+                if (hwndHeader !is null) OS.InvalidateRect (hwndHeader, null, true);
+            }
+            //FALL THROUGH
+
+        /* Mouse messages */
+        case OS.WM_LBUTTONDBLCLK:
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONUP:
+        case OS.WM_MBUTTONDBLCLK:
+        case OS.WM_MBUTTONDOWN:
+        case OS.WM_MBUTTONUP:
+        case OS.WM_MOUSEHOVER:
+        case OS.WM_MOUSELEAVE:
+        case OS.WM_MOUSEMOVE:
+        case OS.WM_MOUSEWHEEL:
+        case OS.WM_RBUTTONDBLCLK:
+        case OS.WM_RBUTTONDOWN:
+        case OS.WM_RBUTTONUP:
+        case OS.WM_XBUTTONDBLCLK:
+        case OS.WM_XBUTTONDOWN:
+        case OS.WM_XBUTTONUP:
+            //FALL THROUGH
+
+        /* Other messages */
+        case OS.WM_SETFONT:
+        case OS.WM_TIMER: {
+            if (findImageControl () !is null) {
+                if (topIndex !is OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+                    OS.InvalidateRect (handle, null, true);
+                }
+            }
+        }
+        default:
+    }
+    return code;
+}
+
+static int checkStyle (int style) {
+    /*
+    * 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.
+    */
+    if ((style & SWT.NO_SCROLL) is 0) {
+        style |= SWT.H_SCROLL | SWT.V_SCROLL;
+    }
+    return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+LRESULT CDDS_ITEMPOSTPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    auto hDC = nmcd.nmcd.hdc;
+    if (explorerTheme && !ignoreCustomDraw) {
+        hotIndex = -1;
+        if (hooks (SWT.EraseItem) && nmcd.nmcd.rc.left !is nmcd.nmcd.rc.right) {
+            OS.RestoreDC (hDC, -1);
+        }
+    }
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows fills
+    * a black rectangle around any column that contains an
+    * image.  The fix is clear LVS_EX_FULLROWSELECT during
+    * custom draw.
+    *
+    * NOTE: Since CDIS_FOCUS is cleared during custom draw,
+    * it is necessary to draw the focus rectangle after the
+    * item has been drawn.
+    */
+    if (!ignoreCustomDraw && !ignoreDrawFocus && nmcd.nmcd.rc.left !is nmcd.nmcd.rc.right) {
+        if (OS.IsWindowVisible (handle) && OS.IsWindowEnabled (handle)) {
+            if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+                if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+                    int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                    if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) is 0) {
+//                      if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+                        if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) 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) {
+                                    RECT rect;
+                                    rect.left = OS.LVIR_BOUNDS;
+                                    bool oldIgnore = ignoreCustomDraw;
+                                    ignoreCustomDraw = true;
+                                    OS.SendMessage (handle, OS. LVM_GETITEMRECT, nmcd.nmcd.dwItemSpec, &rect);
+                                    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                                    int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                                    RECT itemRect;
+                                    if (index is 0) {
+                                        itemRect.left = OS.LVIR_LABEL;
+                                        OS.SendMessage (handle, OS. LVM_GETITEMRECT, index, &itemRect);
+                                    } else {
+                                        itemRect.top = index;
+                                        itemRect.left = OS.LVIR_ICON;
+                                        OS.SendMessage (handle, OS. LVM_GETSUBITEMRECT, nmcd.nmcd.dwItemSpec, &itemRect);
+                                    }
+                                    ignoreCustomDraw = oldIgnore;
+                                    rect.left = itemRect.left;
+                                    OS.DrawFocusRect (nmcd.nmcd.hdc, &rect);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return null;
+}
+
+LRESULT CDDS_ITEMPREPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows fills
+    * a black rectangle around any column that contains an
+    * image.  The fix is clear LVS_EX_FULLROWSELECT during
+    * custom draw.
+    *
+    * NOTE: It is also necessary to clear CDIS_FOCUS to stop
+    * the table from drawing the focus rectangle around the
+    * first item instead of the full row.
+    */
+    if (!ignoreCustomDraw) {
+        if (OS.IsWindowVisible (handle) && OS.IsWindowEnabled (handle)) {
+            if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+                if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+                    int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                    if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) is 0) {
+                        if ((nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+                            nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                            OS.MoveMemory (cast(NMLVCUSTOMDRAW*)lParam, nmcd, OS.NMLVCUSTOMDRAW_sizeof);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (explorerTheme && !ignoreCustomDraw) {
+        hotIndex = (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0 ? nmcd.nmcd.dwItemSpec : -1;
+        if (hooks (SWT.EraseItem) && nmcd.nmcd.rc.left !is nmcd.nmcd.rc.right) {
+            OS.SaveDC (nmcd.nmcd.hdc);
+            auto hrgn = OS.CreateRectRgn (0, 0, 0, 0);
+            OS.SelectClipRgn (nmcd.nmcd.hdc, hrgn);
+            OS.DeleteObject (hrgn);
+        }
+    }
+    return new LRESULT (OS.CDRF_NOTIFYSUBITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+LRESULT CDDS_POSTPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (ignoreCustomDraw) return null;
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows fills
+    * a black rectangle around any column that contains an
+    * image.  The fix is clear LVS_EX_FULLROWSELECT during
+    * custom draw.
+    */
+    if (--customCount is 0 && OS.IsWindowVisible (handle)) {
+        if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+            if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+                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);
+                        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, bits);
+                        OS.ValidateRect (handle, null);
+                        if (damaged) OS.InvalidateRect (handle, &rect, true);
+                    } else {
+                        auto rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                        int result = OS.GetUpdateRgn (handle, rgn, true);
+                        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, bits);
+                        OS.ValidateRect (handle, null);
+                        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);
+                }
+            }
+        }
+    }
+    return null;
+}
+
+LRESULT CDDS_PREPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (ignoreCustomDraw) {
+        return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+    }
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows fills
+    * a black rectangle around any column that contains an
+    * image.  The fix is clear LVS_EX_FULLROWSELECT during
+    * custom draw.
+    */
+    if (customCount++ is 0 && OS.IsWindowVisible (handle)) {
+        if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+            if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+                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);
+                        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, 0);
+                        OS.ValidateRect (handle, null);
+                        if (damaged) OS.InvalidateRect (handle, &rect, true);
+                    } else {
+                        auto rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                        int result = OS.GetUpdateRgn (handle, rgn, true);
+                        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, 0);
+                        OS.ValidateRect (handle, null);
+                        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);
+                }
+            }
+        }
+    }
+    if (OS.IsWindowVisible (handle)) {
+        bool draw = true;
+        /*
+        * Feature in Windows.  On Vista using the explorer theme,
+        * Windows draws a vertical line to separate columns.  When
+        * there is only a single column, the line looks strange.
+        * The fix is to draw the background using custom draw.
+        */
+        if (explorerTheme && columnCount is 0) {
+            auto hDC = nmcd.nmcd.hdc;
+            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.GetSysColor (OS.COLOR_3DFACE), &rect);
+            }
+            draw = false;
+        }
+        if (draw) {
+            Control control = findBackgroundControl ();
+            if (control !is null && control.backgroundImage !is null) {
+                RECT rect;
+                OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                fillImageBackground (nmcd.nmcd.hdc, control, &rect);
+            } else {
+                if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+                    if (OS.IsWindowEnabled (handle)) {
+                        RECT rect;
+                        OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                        if (control is null) control = this;
+                        fillBackground (nmcd.nmcd.hdc, control.getBackgroundPixel (), &rect);
+                        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                            if (sortColumn !is null && sortDirection !is SWT.NONE) {
+                                int index = indexOf (sortColumn);
+                                if (index !is -1) {
+                                    parent.forceResize ();
+                                    int clrSortBk = getSortColumnPixel ();
+                                    RECT columnRect, headerRect;
+                                    OS.GetClientRect (handle, &columnRect);
+                                    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                                    if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect) !is 0) {
+                                        OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2);
+                                        columnRect.left = headerRect.left;
+                                        columnRect.right = headerRect.right;
+                                        if (OS.IntersectRect(&columnRect, &columnRect, &rect)) {
+                                            fillBackground (nmcd.nmcd.hdc, clrSortBk, &columnRect);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+LRESULT CDDS_SUBITEMPOSTPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (ignoreCustomDraw) return null;
+    if (nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) return new LRESULT (OS.CDRF_DODEFAULT);
+    auto hDC = nmcd.nmcd.hdc;
+    if (ignoreDrawForeground) OS.RestoreDC (hDC, -1);
+    if (OS.IsWindowVisible (handle)) {
+        /*
+        * Feature in Windows.  When there is a sort column, the sort column
+        * color draws on top of the background color for an item.  The fix
+        * is to clear the sort column in CDDS_SUBITEMPREPAINT, and reset it
+        * in CDDS_SUBITEMPOSTPAINT.
+        */
+        if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) {
+            if ((sortDirection & (SWT.UP | SWT.DOWN)) !is 0) {
+                if (sortColumn !is null && !sortColumn.isDisposed ()) {
+                    int oldColumn = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+                    if (oldColumn is -1) {
+                        int newColumn = indexOf (sortColumn);
+                        int result = 0;
+                        HRGN rgn;
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                            result = OS.GetUpdateRgn (handle, rgn, true);
+                        }
+                        OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, newColumn, 0);
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            OS.ValidateRect (handle, null);
+                            if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
+                            OS.DeleteObject (rgn);
+                        }
+                    }
+                }
+            }
+        }
+        if (hooks (SWT.PaintItem)) {
+            TableItem item = _getItem (nmcd.nmcd.dwItemSpec);
+            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;
+}
+
+LRESULT CDDS_SUBITEMPREPAINT (NMLVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    auto hDC = nmcd.nmcd.hdc;
+    if (explorerTheme && !ignoreCustomDraw && hooks (SWT.EraseItem) && (nmcd.nmcd.rc.left !is nmcd.nmcd.rc.right)) {
+        OS.RestoreDC (hDC, -1);
+    }
+    /*
+    * Feature in Windows.  When a new table item is inserted
+    * using LVM_INSERTITEM in a table that is transparent
+    * (ie. LVM_SETBKCOLOR has been called with CLR_NONE),
+    * TVM_INSERTITEM calls NM_CUSTOMDRAW before the new item
+    * has been added to the array.  The fix is to check for
+    * null.
+    */
+    TableItem item = _getItem (nmcd.nmcd.dwItemSpec);
+    if (item is null) return null;
+    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);
+    }
+    int code = OS.CDRF_DODEFAULT;
+    selectionForeground = -1;
+    ignoreDrawForeground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawBackground = false;
+    if (OS.IsWindowVisible (handle)) {
+        Event measureEvent = null;
+        if (hooks (SWT.MeasureItem)) {
+            measureEvent = sendMeasureItemEvent (item, nmcd.nmcd.dwItemSpec, nmcd.iSubItem, nmcd.nmcd.hdc);
+            if (isDisposed () || item.isDisposed ()) return null;
+        }
+        if (hooks (SWT.EraseItem)) {
+            sendEraseItemEvent (item, nmcd, lParam, measureEvent);
+            if (isDisposed () || item.isDisposed ()) return null;
+            code |= OS.CDRF_NOTIFYPOSTPAINT;
+        }
+        if (ignoreDrawForeground || hooks (SWT.PaintItem)) code |= OS.CDRF_NOTIFYPOSTPAINT;
+    }
+    int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1;
+    if (clrText is -1) clrText = item.foreground;
+    int clrTextBk = item.cellBackground !is null ? item.cellBackground [nmcd.iSubItem] : -1;
+    if (clrTextBk is -1) clrTextBk = item.background;
+    if (selectionForeground !is -1) clrText = selectionForeground;
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows draws
+    * a black rectangle around any column that contains an
+    * image.  The fix is emulate LVS_EX_FULLROWSELECT by
+    * drawing the selection.
+    */
+    if (OS.IsWindowVisible (handle) && OS.IsWindowEnabled (handle)) {
+        if (!explorerTheme && !ignoreDrawSelection && (style & SWT.FULL_SELECTION) !is 0) {
+            int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+            if ((bits & OS.LVS_EX_FULLROWSELECT) is 0) {
+                /*
+                * Bug in Windows.  For some reason, CDIS_SELECTED always set,
+                * even for items that are not selected.  The fix is to get
+                * the selection state from the item.
+                */
+                LVITEM lvItem;
+                lvItem.mask = OS.LVIF_STATE;
+                lvItem.stateMask = OS.LVIS_SELECTED;
+                lvItem.iItem = nmcd.nmcd.dwItemSpec;
+                int result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, &lvItem);
+                if ((result !is 0 && (lvItem.state & OS.LVIS_SELECTED) !is 0)) {
+                    int clrSelection = -1;
+                    if (nmcd.iSubItem is 0) {
+                        if (OS.GetFocus () is handle || display.getHighContrast ()) {
+                            clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+                        } else {
+                            if ((style & SWT.HIDE_SELECTION) is 0) {
+                                clrSelection = OS.GetSysColor (OS.COLOR_3DFACE);
+                            }
+                        }
+                    } else {
+                        if (OS.GetFocus () is handle || display.getHighContrast ()) {
+                            clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                            clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+                        } else {
+                            if ((style & SWT.HIDE_SELECTION) is 0) {
+                                clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_3DFACE);
+                            }
+                        }
+                    }
+                    if (clrSelection !is -1) {
+                        RECT rect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, nmcd.iSubItem !is 0, true, false, hDC);
+                        fillBackground (hDC, clrSelection, &rect);
+                    }
+                }
+            }
+        }
+    }
+    if (!ignoreDrawForeground) {
+        /*
+        * Bug in Windows.  When the attributes are for one cell in a table,
+        * Windows does not reset them for the next cell.  As a result, all
+        * subsequent cells are drawn using the previous font, foreground and
+        * background colors.  The fix is to set the all attributes when any
+        * attribute could have changed.
+        */
+        bool hasAttributes = true;
+        if (hFont is cast(HFONT)-1 && clrText is -1 && clrTextBk is -1) {
+            if (item.cellForeground is null && item.cellBackground is null && item.cellFont is null) {
+                auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                if (count is 1) hasAttributes = false;
+            }
+        }
+        if (hasAttributes) {
+            if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+            OS.SelectObject (hDC, hFont);
+            if (OS.IsWindowEnabled (handle)) {
+                nmcd.clrText = clrText is -1 ? getForegroundPixel () : clrText;
+                if (clrTextBk is -1) {
+                    nmcd.clrTextBk = OS.CLR_NONE;
+                    if (selectionForeground is -1) {
+                        Control control = findBackgroundControl ();
+                        if (control is null) control = this;
+                        if (control.backgroundImage is null) {
+                            if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) {
+                                nmcd.clrTextBk = control.getBackgroundPixel ();
+                            }
+                        }
+                    }
+                } else {
+                    nmcd.clrTextBk = selectionForeground !is -1 ? OS.CLR_NONE : clrTextBk;
+                }
+                OS.MoveMemory (lParam, nmcd, OS.NMLVCUSTOMDRAW_sizeof);
+            }
+            code |= OS.CDRF_NEWFONT;
+        }
+    }
+    if (OS.IsWindowEnabled (handle)) {
+        /*
+        * Feature in Windows.  When there is a sort column, the sort column
+        * color draws on top of the background color for an item.  The fix
+        * is to clear the sort column in CDDS_SUBITEMPREPAINT, and reset it
+        * in CDDS_SUBITEMPOSTPAINT.
+        */
+        if (clrTextBk !is -1) {
+            int oldColumn = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+            if (oldColumn !is -1 && oldColumn is nmcd.iSubItem) {
+                int result = 0;
+                HRGN rgn;
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                    rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                    result = OS.GetUpdateRgn (handle, rgn, true);
+                }
+                OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, -1, 0);
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                    OS.ValidateRect (handle, null);
+                    if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
+                    OS.DeleteObject (rgn);
+                }
+                code |= OS.CDRF_NOTIFYPOSTPAINT;
+            }
+        }
+    } else {
+        /*
+        * Feature in Windows.  When the table is disabled, it draws
+        * with a gray background but does not gray the text.  The fix
+        * is to explicitly gray the text.
+        */
+        nmcd.clrText = OS.GetSysColor (OS.COLOR_GRAYTEXT);
+        if (findImageControl () !is null) {
+            nmcd.clrTextBk = OS.CLR_NONE;
+        } else {
+            nmcd.clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE);
+        }
+        nmcd.nmcd.uItemState &= ~OS.CDIS_SELECTED;
+        OS.MoveMemory (lParam, nmcd, OS.NMLVCUSTOMDRAW_sizeof);
+        code |= OS.CDRF_NEWFONT;
+    }
+    return new LRESULT (code);
+}
+
+override void checkBuffered () {
+    super.checkBuffered ();
+    if (OS.COMCTL32_MAJOR >= 6) style |= SWT.DOUBLE_BUFFERED;
+    if ((style & SWT.VIRTUAL) !is 0) style |= SWT.DOUBLE_BUFFERED;
+}
+
+bool checkData (TableItem item, bool redraw) {
+    if ((style & SWT.VIRTUAL) is 0) return true;
+    return checkData (item, indexOf (item), redraw);
+}
+
+bool checkData (TableItem item, int index, bool redraw) {
+    if ((style & SWT.VIRTUAL) is 0) return true;
+    if (!item.cached) {
+        item.cached = true;
+        Event event = new Event ();
+        event.item = item;
+        event.index = index;
+        currentItem = item;
+        sendEvent (SWT.SetData, event);
+        //widget could be disposed at this point
+        currentItem = null;
+        if (isDisposed () || item.isDisposed ()) return false;
+        if (redraw) {
+            if (!setScrollWidth (item, false)) {
+                item.redraw ();
+            }
+        }
+    }
+    return true;
+}
+
+override bool checkHandle (HWND hwnd) {
+    if (hwnd is handle) return true;
+    return hwnd is cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value.  If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    TableItem item = items [index];
+    if (item !is null) {
+        if (item !is currentItem) item.clear ();
+        /*
+        * 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 & SWT.VIRTUAL) is 0 && item.cached) {
+            LVITEM lvItem;
+            lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+            lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+            lvItem.iItem = index;
+            OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+            item.cached = false;
+        }
+        if (currentItem is null && drawCount is 0 && OS.IsWindowVisible (handle)) {
+            OS.SendMessage (handle, OS.LVM_REDRAWITEMS, index, index);
+        }
+        setScrollWidth (item, false);
+    }
+}
+
+/**
+ * Removes the items from the receiver which are between the given
+ * zero-relative start and end indices (inclusive).  The text, icon
+ * and other attributes of the items are set to their default values.
+ * If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param start the start index of the item to clear
+ * @param end the end index of the item to clear
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int start, int end) {
+    checkWidget ();
+    if (start > end) return;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    if (start is 0 && end is count - 1) {
+        clearAll ();
+    } else {
+        LVITEM lvItem;
+        bool cleared = false;
+        for (int i=start; i<=end; i++) {
+            TableItem item = items [i];
+            if (item !is null) {
+                if (item !is currentItem) {
+                    cleared = true;
+                    item.clear ();
+                }
+                /*
+                * 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 & SWT.VIRTUAL) is 0 && item.cached) {
+                    //if (lvItem is null) {
+                        //lvItem = new LVITEM ();
+                        lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+                        lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                    //}
+                    lvItem.iItem = i;
+                    OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+                    item.cached = false;
+                }
+            }
+        }
+        if (cleared) {
+            if (currentItem is null && drawCount is 0 && OS.IsWindowVisible (handle)) {
+                OS.SendMessage (handle, OS.LVM_REDRAWITEMS, start, end);
+            }
+            TableItem item = start is end ? items [start] : null;
+            setScrollWidth (item, false);
+        }
+    }
+}
+
+/**
+ * Clears the items at the given zero-relative indices in the receiver.
+ * The text, icon and other attributes of the items are set to their default
+ * values.  If the table was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clear (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (indices.length is 0) return;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<indices.length; i++) {
+        if (!(0 <= indices [i] && indices [i] < count)) {
+            error (SWT.ERROR_INVALID_RANGE);
+        }
+    }
+    LVITEM lvItem;
+    bool cleared = false;
+    for (int i=0; i<indices.length; i++) {
+        int index = indices [i];
+        TableItem item = items [index];
+        if (item !is null) {
+            if (item !is currentItem) {
+                cleared = true;
+                item.clear ();
+            }
+            /*
+            * 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 & SWT.VIRTUAL) is 0 && item.cached) {
+                //if (lvItem is null) {
+                    //lvItem = new LVITEM ();
+                    lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+                    lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                //}
+                lvItem.iItem = i;
+                OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+                item.cached = false;
+            }
+            if (currentItem is null && drawCount is 0 && OS.IsWindowVisible (handle)) {
+                OS.SendMessage (handle, OS.LVM_REDRAWITEMS, index, index);
+            }
+        }
+    }
+    if (cleared) setScrollWidth (null, false);
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * table was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.0
+ */
+public void clearAll () {
+    checkWidget ();
+    LVITEM lvItem;
+    bool cleared = false;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<count; i++) {
+        TableItem item = items [i];
+        if (item !is null) {
+            if (item !is currentItem) {
+                cleared = true;
+                item.clear ();
+            }
+            /*
+            * 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 & SWT.VIRTUAL) is 0 && item.cached) {
+                //if (lvItem is null) {
+                    //lvItem = new LVITEM ();
+                    lvItem.mask = OS.LVIF_TEXT | OS.LVIF_INDENT;
+                    lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                //}
+                lvItem.iItem = i;
+                OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+                item.cached = false;
+            }
+        }
+    }
+    if (cleared) {
+        if (currentItem is null && drawCount is 0 && OS.IsWindowVisible (handle)) {
+            OS.SendMessage (handle, OS.LVM_REDRAWITEMS, 0, count - 1);
+        }
+        setScrollWidth (null, false);
+    }
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    if (fixScrollWidth) setScrollWidth (null, true);
+    //This code is intentionally commented
+//  if (itemHeight is -1 && hooks (SWT.MeasureItem)) {
+//      int i = 0;
+//      TableItem item = items [i];
+//      if (item !is null) {
+//          int hDC = OS.GetDC (handle);
+//          int oldFont = 0, newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+//          if (newFont !is 0) oldFont = OS.SelectObject (hDC, newFont);
+//          int index = 0, count = Math.max (1, columnCount);
+//          while (index < count) {
+//              int hFont = item.cellFont !is null ? item.cellFont [index] : -1;
+//              if (hFont is -1) hFont = item.font;
+//              if (hFont !is -1) hFont = OS.SelectObject (hDC, hFont);
+//              sendMeasureItemEvent (item, i, index, hDC);
+//              if (hFont !is -1) hFont = OS.SelectObject (hDC, hFont);
+//              if (isDisposed () || item.isDisposed ()) break;
+//              index++;
+//          }
+//          if (newFont !is 0) OS.SelectObject (hDC, oldFont);
+//          OS.ReleaseDC (handle, hDC);
+//      }
+//  }
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    RECT rect;
+    OS.GetWindowRect (hwndHeader, &rect);
+    int height = rect.bottom - rect.top;
+    int bits = 0;
+    if (wHint !is SWT.DEFAULT) {
+        bits |= wHint & 0xFFFF;
+    } else {
+        int width = 0;
+        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+        for (int i=0; i<count; i++) {
+            width += OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, i, 0);
+        }
+        bits |= width & 0xFFFF;
+    }
+    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;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2;  height += border * 2;
+    if ((style & SWT.V_SCROLL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    }
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    /* Use the Explorer theme */
+    if (EXPLORER_THEME) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
+            explorerTheme = true;
+            OS.SetWindowTheme (handle, Display.EXPLORER.ptr, null);
+        }
+    }
+
+    /* 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.GetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC);
+    }
+
+    /*
+    * Feature in Windows.  In version 5.8 of COMCTL32.DLL,
+    * if the font is changed for an item, the bounds for the
+    * item are not updated, causing the text to be clipped.
+    * The fix is to detect the version of COMCTL32.DLL, and
+    * if it is one of the versions with the problem, then
+    * use version 5.00 of the control (a version that does
+    * not have the problem).  This is the recommended work
+    * around from the MSDN.
+    */
+    static if (!OS.IsWinCE) {
+        if (OS.COMCTL32_MAJOR < 6) {
+            OS.SendMessage (handle, OS.CCM_SETVERSION, 5, 0);
+        }
+    }
+
+    /*
+    * This code is intentionally commented.  According to
+    * the documentation, setting the default item size is
+    * supposed to improve performance.  By experimentation,
+    * this does not seem to have much of an effect.
+    */
+//  OS.SendMessage (handle, OS.LVM_SETITEMCOUNT, 1024 * 2, 0);
+
+    /* Set the checkbox image list */
+    if ((style & SWT.CHECK) !is 0) {
+        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);
+    }
+
+    /*
+    * Feature in Windows.  When the control is created,
+    * it does not use the default system font.  A new HFONT
+    * is created and destroyed when the control is destroyed.
+    * This means that a program that queries the font from
+    * this control, uses the font in another control and then
+    * destroys this control will have the font unexpectedly
+    * destroyed in the other control.  The fix is to assign
+    * the font ourselves each time the control is created.
+    * The control will not destroy a font that it did not
+    * create.
+    */
+    auto hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+
+    /*
+    * Bug in Windows.  When the first column is inserted
+    * without setting the header text, Windows will never
+    * allow the header text for the first column to be set.
+    * The fix is to set the text to an empty string when
+    * the column is inserted.
+    */
+    LVCOLUMN lvColumn;
+    lvColumn.mask = OS.LVCF_TEXT | OS.LVCF_WIDTH;
+    auto hHeap = OS.GetProcessHeap ();
+    auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+    lvColumn.pszText = pszText;
+    OS.SendMessage (handle, OS.LVM_INSERTCOLUMN, 0, &lvColumn);
+    OS.HeapFree (hHeap, 0, pszText);
+
+    /* Set the extended style bits */
+    int bits1 = OS.LVS_EX_LABELTIP;
+    if ((style & SWT.FULL_SELECTION) !is 0) bits1 |= OS.LVS_EX_FULLROWSELECT;
+    if (OS.COMCTL32_MAJOR >= 6) bits1 |= OS.LVS_EX_DOUBLEBUFFER;
+    OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits1, bits1);
+
+    /*
+    * Feature in Windows.  Windows does not explicitly set the orientation of
+    * the header.  Instead, the orientation is inherited when WS_EX_LAYOUTRTL
+    * is specified for the table.  This means that when both WS_EX_LAYOUTRTL
+    * and WS_EX_NOINHERITLAYOUT are specified for the table, the header will
+    * not be oriented correctly.  The fix is to explicitly set the orientation
+    * for the header.
+    *
+    * NOTE: WS_EX_LAYOUTRTL is not supported on Windows NT.
+    */
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & SWT.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 & SWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
+    headerToolTipHandle = OS.CreateWindowEx (
+        bits,
+        OS.TOOLTIPS_CLASS.ptr,
+        null,
+        OS.TTS_NOPREFIX,
+        OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+        handle,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (headerToolTipHandle is null) error (SWT.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 (headerToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+}
+
+void createItem (TableColumn column, int index) {
+    if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE);
+    int oldColumn = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+    if (oldColumn >= index) {
+        OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, oldColumn + 1, 0);
+    }
+    if (columnCount is columns.length) {
+        TableColumn [] newColumns = new TableColumn [columns.length + 4];
+        System.arraycopy (columns, 0, newColumns, 0, columns.length);
+        columns = newColumns;
+    }
+    int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<itemCount; i++) {
+        TableItem item = items [i];
+        if (item !is null) {
+            String [] strings = item.strings;
+            if (strings !is null) {
+                String [] temp = new String [columnCount + 1];
+                System.arraycopy (strings, 0, temp, 0, index);
+                System.arraycopy (strings, index, temp, index + 1, columnCount -  index);
+                item.strings = temp;
+            }
+            Image [] images = item.images;
+            if (images !is null) {
+                Image [] temp = new Image [columnCount + 1];
+                System.arraycopy (images, 0, temp, 0, index);
+                System.arraycopy (images, index, temp, index + 1, columnCount - index);
+                item.images = temp;
+            }
+            if (index is 0) {
+                if (columnCount !is 0) {
+                    if (strings is null) {
+                        item.strings = new String [columnCount + 1];
+                        item.strings [1] = item.text;
+                    }
+                    item.text = ""; //$NON-NLS-1$
+                    if (images is null) {
+                        item.images = new Image [columnCount + 1];
+                        item.images [1] = item.image;
+                    }
+                    item.image = null;
+                }
+            }
+            if (item.cellBackground !is null) {
+                int [] cellBackground = item.cellBackground;
+                int [] temp = new int [columnCount + 1];
+                System.arraycopy (cellBackground, 0, temp, 0, index);
+                System.arraycopy (cellBackground, index, temp, index + 1, columnCount - index);
+                temp [index] = -1;
+                item.cellBackground = temp;
+            }
+            if (item.cellForeground !is null) {
+                int [] cellForeground = item.cellForeground;
+                int [] temp = new int [columnCount + 1];
+                System.arraycopy (cellForeground, 0, temp, 0, index);
+                System.arraycopy (cellForeground, index, temp, index + 1, columnCount - index);
+                temp [index] = -1;
+                item.cellForeground = temp;
+            }
+            if (item.cellFont !is null) {
+                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);
+                item.cellFont = temp;
+            }
+        }
+    }
+    /*
+    * Insert the column into the columns array before inserting
+    * it into the widget so that the column will be present when
+    * any callbacks are issued as a result of LVM_INSERTCOLUMN
+    * or LVM_SETCOLUMN.
+    */
+    System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
+    columns [index] = column;
+
+    /*
+    * Ensure that resize listeners for the table and for columns
+    * within the table are not called.  This can happen when the
+    * first column is inserted into a table or when a new column
+    * is inserted in the first position.
+    */
+    ignoreColumnResize = true;
+    if (index is 0) {
+        if (columnCount > 1) {
+            LVCOLUMN lvColumn;
+            lvColumn.mask = OS.LVCF_WIDTH;
+            OS.SendMessage (handle, OS.LVM_INSERTCOLUMN, 1, &lvColumn);
+            OS.SendMessage (handle, OS.LVM_GETCOLUMN, 1, &lvColumn);
+            int width = lvColumn.cx;
+            int cchTextMax = 1024;
+            auto hHeap = OS.GetProcessHeap ();
+            int byteCount = cchTextMax * TCHAR.sizeof;
+            auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            lvColumn.mask = OS.LVCF_TEXT | OS.LVCF_IMAGE | OS.LVCF_WIDTH | OS.LVCF_FMT;
+            lvColumn.pszText = pszText;
+            lvColumn.cchTextMax = cchTextMax;
+            OS.SendMessage (handle, OS.LVM_GETCOLUMN, 0, &lvColumn);
+            OS.SendMessage (handle, OS.LVM_SETCOLUMN, 1, &lvColumn);
+            lvColumn.fmt = OS.LVCFMT_IMAGE;
+            lvColumn.cx = width;
+            lvColumn.iImage = OS.I_IMAGENONE;
+            lvColumn.pszText = null, lvColumn.cchTextMax = 0;
+            OS.SendMessage (handle, OS.LVM_SETCOLUMN, 0, &lvColumn);
+            lvColumn.mask = OS.LVCF_FMT;
+            lvColumn.fmt = OS.LVCFMT_LEFT;
+            OS.SendMessage (handle, OS.LVM_SETCOLUMN, 0, &lvColumn);
+            if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+        } else {
+            OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, 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 & SWT.VIRTUAL) is 0) {
+            LVITEM lvItem;
+            lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
+            lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+            lvItem.iImage = OS.I_IMAGECALLBACK;
+            for (int i=0; i<itemCount; i++) {
+                lvItem.iItem = i;
+                OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+            }
+        }
+    } else {
+        int fmt = OS.LVCFMT_LEFT;
+        if ((column.style & SWT.CENTER) is SWT.CENTER) fmt = OS.LVCFMT_CENTER;
+        if ((column.style & SWT.RIGHT) is SWT.RIGHT) fmt = OS.LVCFMT_RIGHT;
+        LVCOLUMN lvColumn;
+        lvColumn.mask = OS.LVCF_WIDTH | OS.LVCF_FMT;
+        lvColumn.fmt = fmt;
+        OS.SendMessage (handle, OS.LVM_INSERTCOLUMN, index, &lvColumn);
+    }
+    ignoreColumnResize = false;
+
+    /* Add the tool tip item for the header */
+    if (headerToolTipHandle !is null) {
+        RECT rect;
+        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &rect) !is 0) {
+            TOOLINFO lpti;
+            lpti.cbSize = OS.TOOLINFO_sizeof;
+            lpti.uFlags = OS.TTF_SUBCLASS;
+            lpti.hwnd = hwndHeader;
+            lpti.uId = column.id = display.nextToolTipId++;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+            OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, &lpti);
+        }
+    }
+}
+
+void createItem (TableItem item, int index) {
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+    if (count is items.length) {
+        /*
+        * Grow the array faster when redraw is off or the
+        * table is not visible.  When the table is painted,
+        * the items array is resized to be smaller to reduce
+        * memory usage.
+        */
+        bool small = drawCount is 0 && OS.IsWindowVisible (handle);
+        int length = small ? items.length + 4 : Math.max (4, items.length * 3 / 2);
+        TableItem [] newItems = new TableItem [length];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
+    lvItem.iItem = index;
+    lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+    /*
+    * Bug in Windows.  Despite the fact that the image list
+    * index has never been set for the item, Windows always
+    * assumes that the image index for the item is valid.
+    * When an item is inserted, the image index is zero.
+    * Therefore, when the first image is inserted and is
+    * assigned image index zero, every item draws with this
+    * image.  The fix is to set the image index when the
+    * the item is created.
+    */
+    lvItem.iImage = OS.I_IMAGECALLBACK;
+
+    /* Insert the item */
+    setDeferResize (true);
+    ignoreSelect = ignoreShrink = true;
+    int result = OS.SendMessage (handle, OS.LVM_INSERTITEM, 0, &lvItem);
+    ignoreSelect = ignoreShrink = false;
+    if (result is -1) error (SWT.ERROR_ITEM_NOT_ADDED);
+    System.arraycopy (items, index, items, index + 1, count - index);
+    items [index] = item;
+    setDeferResize (false);
+
+    /* Resize to show the first item */
+    if (count is 0) setScrollWidth (item, false);
+}
+
+override void createWidget () {
+    super.createWidget ();
+    itemHeight = hotIndex = -1;
+    items = new TableItem [4];
+    columns = new TableColumn [4];
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+override void deregister () {
+    super.deregister ();
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    if (hwndHeader !is null) display.removeControl (hwndHeader);
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected.  If the item at the index
+ * was not selected, it remains deselected. Indices that are out
+ * of range and duplicate indices are ignored.
+ *
+ * @param indices the array of indices for the items to deselect
+ *
+ * @exception SWTException <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 deselect (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (indices.length is 0) return;
+    LVITEM lvItem;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    for (int i=0; i<indices.length; i++) {
+        /*
+        * An index of -1 will apply the change to all
+        * items.  Ensure that indices are greater than -1.
+        */
+        if (indices [i] >= 0) {
+            ignoreSelect = true;
+            OS.SendMessage (handle, OS.LVM_SETITEMSTATE, indices [i], &lvItem);
+            ignoreSelect = false;
+        }
+    }
+}
+
+/**
+ * Deselects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already deselected, it remains
+ * deselected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to deselect
+ *
+ * @exception SWTException <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 deselect (int index) {
+    checkWidget ();
+    /*
+    * An index of -1 will apply the change to all
+    * items.  Ensure that index is greater than -1.
+    */
+    if (index < 0) return;
+    LVITEM lvItem;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    ignoreSelect = true;
+    OS.SendMessage (handle, OS.LVM_SETITEMSTATE, index, &lvItem);
+    ignoreSelect = false;
+}
+
+/**
+ * Deselects the items at the given zero-relative indices in the receiver.
+ * If the item at the given zero-relative index in the receiver
+ * is selected, it is deselected.  If the item at the index
+ * was not selected, it remains deselected.  The range of the
+ * indices is inclusive. Indices that are out of range are ignored.
+ *
+ * @param start the start index of the items to deselect
+ * @param end the end index of the items to deselect
+ *
+ * @exception SWTException <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 deselect (int start, int end) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (start is 0 && end is count - 1) {
+        deselectAll ();
+    } else {
+        LVITEM lvItem;
+        lvItem.stateMask = OS.LVIS_SELECTED;
+        /*
+        * An index of -1 will apply the change to all
+        * items.  Ensure that indices are greater than -1.
+        */
+        start = Math.max (0, start);
+        for (int i=start; i<=end; i++) {
+            ignoreSelect = true;
+            OS.SendMessage (handle, OS.LVM_SETITEMSTATE, i, &lvItem);
+            ignoreSelect = false;
+        }
+    }
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @exception SWTException <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 deselectAll () {
+    checkWidget ();
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_STATE;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    ignoreSelect = true;
+    OS.SendMessage (handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+    ignoreSelect = false;
+}
+
+void destroyItem (TableColumn column) {
+    int index = 0;
+    while (index < columnCount) {
+        if (columns [index] is column) break;
+        index++;
+    }
+    int oldColumn = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+    if (oldColumn is index) {
+        OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, -1, 0);
+    } else {
+        if (oldColumn > index) {
+            OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, oldColumn - 1, 0);
+        }
+    }
+    int orderIndex = 0;
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, oldOrder.ptr);
+    while (orderIndex < columnCount) {
+        if (oldOrder [orderIndex] is index) break;
+        orderIndex++;
+    }
+    ignoreColumnResize = true;
+    bool first = false;
+    if (index is 0) {
+        first = true;
+        if (columnCount > 1) {
+            index = 1;
+            int cchTextMax = 1024;
+            auto hHeap = OS.GetProcessHeap ();
+            int byteCount = cchTextMax * TCHAR.sizeof;
+            auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            LVCOLUMN lvColumn;
+            lvColumn.mask = OS.LVCF_TEXT | OS.LVCF_IMAGE | OS.LVCF_WIDTH | OS.LVCF_FMT;
+            lvColumn.pszText = pszText;
+            lvColumn.cchTextMax = cchTextMax;
+            OS.SendMessage (handle, OS.LVM_GETCOLUMN, 1, &lvColumn);
+            lvColumn.fmt &= ~(OS.LVCFMT_CENTER | OS.LVCFMT_RIGHT);
+            lvColumn.fmt |= OS.LVCFMT_LEFT;
+            OS.SendMessage (handle, OS.LVM_SETCOLUMN, 0, &lvColumn);
+            if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+        } else {
+            auto hHeap = OS.GetProcessHeap ();
+            auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+            LVCOLUMN lvColumn;
+            lvColumn.mask = OS.LVCF_TEXT | OS.LVCF_IMAGE | OS.LVCF_WIDTH | OS.LVCF_FMT;
+            lvColumn.pszText = pszText;
+            lvColumn.iImage = OS.I_IMAGENONE;
+            lvColumn.fmt = OS.LVCFMT_LEFT;
+            OS.SendMessage (handle, OS.LVM_SETCOLUMN, 0, &lvColumn);
+            if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+            if (OS.COMCTL32_MAJOR >= 6) {
+                HDITEM hdItem;
+                hdItem.mask = OS.HDI_FORMAT;
+                hdItem.fmt = OS.HDF_LEFT;
+                auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+            }
+        }
+        /*
+        * 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 & SWT.VIRTUAL) is 0) {
+            LVITEM lvItem;
+            lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
+            lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+            lvItem.iImage = OS.I_IMAGECALLBACK;
+            int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+            for (int i=0; i<itemCount; i++) {
+                lvItem.iItem = i;
+                OS.SendMessage (handle, OS.LVM_SETITEM, 0, &lvItem);
+            }
+        }
+    }
+    if (columnCount > 1) {
+        if (OS.SendMessage (handle, OS.LVM_DELETECOLUMN, index, 0) is 0) {
+            error (SWT.ERROR_ITEM_NOT_REMOVED);
+        }
+    }
+    if (first) index = 0;
+    System.arraycopy (columns, index + 1, columns, index, --columnCount - index);
+    columns [columnCount] = null;
+    int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<itemCount; i++) {
+        TableItem item = items [i];
+        if (item !is null) {
+            if (columnCount is 0) {
+                item.strings = null;
+                item.images = null;
+                item.cellBackground = null;
+                item.cellForeground = null;
+                item.cellFont = null;
+            } else {
+                if (item.strings !is null) {
+                    String [] strings = item.strings;
+                    if (index is 0) {
+                        item.text = strings [1] !is null ? strings [1] : ""; //$NON-NLS-1$
+                    }
+                    String [] temp = new String [columnCount];
+                    System.arraycopy (strings, 0, temp, 0, index);
+                    System.arraycopy (strings, index + 1, temp, index, columnCount - index);
+                    item.strings = temp;
+                } else {
+                    if (index is 0) item.text = ""; //$NON-NLS-1$
+                }
+                if (item.images !is null) {
+                    Image [] images = item.images;
+                    if (index is 0) item.image = images [1];
+                    Image [] temp = new Image [columnCount];
+                    System.arraycopy (images, 0, temp, 0, index);
+                    System.arraycopy (images, index + 1, temp, index, columnCount - index);
+                    item.images = temp;
+                } else {
+                    if (index is 0) item.image = null;
+                }
+                if (item.cellBackground !is null) {
+                    int [] cellBackground = item.cellBackground;
+                    int [] temp = new int [columnCount];
+                    System.arraycopy (cellBackground, 0, temp, 0, index);
+                    System.arraycopy (cellBackground, index + 1, temp, index, columnCount - index);
+                    item.cellBackground = temp;
+                }
+                if (item.cellForeground !is null) {
+                    int [] cellForeground = item.cellForeground;
+                    int [] temp = new int [columnCount];
+                    System.arraycopy (cellForeground, 0, temp, 0, index);
+                    System.arraycopy (cellForeground, index + 1, temp, index, columnCount - index);
+                    item.cellForeground = temp;
+                }
+                if (item.cellFont !is null) {
+                    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;
+                }
+            }
+        }
+    }
+    if (columnCount is 0) setScrollWidth (null, true);
+    updateMoveable ();
+    ignoreColumnResize = false;
+    if (columnCount !is 0) {
+        /*
+        * Bug in Windows.  When LVM_DELETECOLUMN is used to delete a
+        * column zero when that column is both the first column in the
+        * table and the first column in the column order array, Windows
+        * incorrectly computes the new column order.  For example, both
+        * the orders {0, 3, 1, 2} and {0, 3, 2, 1} give a new column
+        * order of {0, 2, 1}, while {0, 2, 1, 3} gives {0, 1, 2, 3}.
+        * The fix is to compute the new order and compare it with the
+        * order that Windows is using.  If the two differ, the new order
+        * is used.
+        */
+        int count = 0;
+        int oldIndex = oldOrder [orderIndex];
+        int [] newOrder = new int [columnCount];
+        for (int i=0; i<oldOrder.length; i++) {
+            if (oldOrder [i] !is oldIndex) {
+                int newIndex = oldOrder [i] <= oldIndex ? oldOrder [i] : oldOrder [i] - 1;
+                newOrder [count++] = newIndex;
+            }
+        }
+        OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, oldOrder.ptr);
+        int j = 0;
+        while (j < newOrder.length) {
+            if (oldOrder [j] !is newOrder [j]) break;
+            j++;
+        }
+        if (j !is newOrder.length) {
+            OS.SendMessage (handle, OS.LVM_SETCOLUMNORDERARRAY, newOrder.length, newOrder.ptr);
+            /*
+            * Bug in Windows.  When LVM_SETCOLUMNORDERARRAY is used to change
+            * the column order, the header redraws correctly but the table does
+            * not.  The fix is to force a redraw.
+            */
+            OS.InvalidateRect (handle, null, true);
+        }
+        TableColumn [] newColumns = new TableColumn [columnCount - orderIndex];
+        for (int i=orderIndex; i<newOrder.length; i++) {
+            newColumns [i - orderIndex] = columns [newOrder [i]];
+            newColumns [i - orderIndex].updateToolTip (newOrder [i]);
+        }
+        for (int i=0; i<newColumns.length; i++) {
+            if (!newColumns [i].isDisposed ()) {
+                newColumns [i].sendEvent (SWT.Move);
+            }
+        }
+    }
+
+    /* Remove the tool tip item for the header */
+    if (headerToolTipHandle !is null) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        lpti.uId = column.id;
+        lpti.hwnd = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        OS.SendMessage (headerToolTipHandle, OS.TTM_DELTOOL, 0, &lpti);
+    }
+}
+
+void destroyItem (TableItem item) {
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    int index = 0;
+    while (index < count) {
+        if (items [index] is item) break;
+        index++;
+    }
+    if (index is count) return;
+    setDeferResize (true);
+    ignoreSelect = ignoreShrink = true;
+    int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+    ignoreSelect = ignoreShrink = false;
+    if (code is 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    System.arraycopy (items, index + 1, items, index, --count - index);
+    items [count] = null;
+    if (count is 0) setTableEmpty ();
+    setDeferResize (false);
+}
+
+void fixCheckboxImageList (bool fixScroll) {
+    /*
+    * Bug in Windows.  When the state image list is larger than the
+    * image list, Windows incorrectly positions the state images.  When
+    * the table is scrolled, Windows draws garbage.  The fix is to force
+    * the state image list to be the same size as the image list.
+    */
+    if ((style & SWT.CHECK) is 0) return;
+    HANDLE hImageList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+    if (hImageList is null) return;
+    int cx, cy;
+    OS.ImageList_GetIconSize (hImageList, &cx, &cy);
+    HANDLE hStateList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+    if (hStateList is null) return;
+    int stateCx, stateCy;
+    OS.ImageList_GetIconSize (hStateList, &stateCx, &stateCy);
+    if (cx is stateCx && cy is stateCy ) return;
+    setCheckboxImageList (cx, cy, fixScroll);
+}
+
+void fixCheckboxImageListColor (bool fixScroll) {
+    if ((style & SWT.CHECK) is 0) return;
+    auto hStateList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+    if (hStateList is null) return;
+    int cx, cy;
+    OS.ImageList_GetIconSize (hStateList, &cx, &cy);
+    setCheckboxImageList (cx, cy, fixScroll);
+}
+
+void fixItemHeight (bool fixScroll) {
+    /*
+    * Bug in Windows.  When both a header and grid lines are
+    * displayed, the grid lines do not take into account the
+    * height of the header and draw in the wrong place.  The
+    * fix is to set the height of the table items to be the
+    * height of the header so that the lines draw in the right
+    * place.  The height of a table item is the maximum of the
+    * height of the font or the height of image list.
+    *
+    * NOTE: In version 5.80 of COMCTL32.DLL, the bug is fixed.
+    */
+    if (itemHeight !is -1) return;
+    if (OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) return;
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if ((bits & OS.LVS_EX_GRIDLINES) is 0) return;
+    bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.LVS_NOCOLUMNHEADER) !is 0) return;
+    /*
+    * Bug in Windows.  Making any change to an item that
+    * changes the item height of a table while the table
+    * is scrolled can cause the lines to draw incorrectly.
+    * This happens even when the lines are not currently
+    * visible and are shown afterwards.  The fix is to
+    * save the top index, scroll to the top of the table
+    * and then restore the original top index.
+    */
+    int topIndex = getTopIndex ();
+    if (fixScroll && topIndex !is 0) {
+        setRedraw (false);
+        setTopIndex (0);
+    }
+    auto hOldList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+    if (hOldList !is null) return;
+    auto hwndHeader = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    RECT rect;
+    OS.GetWindowRect (hwndHeader, &rect);
+    int height = rect.bottom - rect.top - 1;
+    auto hImageList = OS.ImageList_Create (1, height, 0, 0, 0);
+    OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+    fixCheckboxImageList (false);
+    OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, 0);
+    if (headerImageList !is null) {
+        auto hHeaderImageList = headerImageList.getHandle ();
+        OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hHeaderImageList);
+    }
+    OS.ImageList_Destroy (hImageList);
+    if (fixScroll && topIndex !is 0) {
+        setTopIndex (topIndex);
+        setRedraw (true);
+    }
+}
+
+/**
+ * Returns the column at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ * Columns are returned in the order that they were created.
+ * If no <code>TableColumn</code>s were created by the programmer,
+ * this method will throw <code>ERROR_INVALID_RANGE</code> despite
+ * the fact that a single column of data may be visible in the table.
+ * This occurs when the programmer uses the table like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(bool)
+ * @see SWT#Move
+ */
+public TableColumn getColumn (int index) {
+    checkWidget ();
+    if (!(0 <= index && index < columnCount)) error (SWT.ERROR_INVALID_RANGE);
+    return columns [index];
+}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no <code>TableColumn</code>s were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the table like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @exception SWTException <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 int getColumnCount () {
+    checkWidget ();
+    return columnCount;
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException <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 Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public int[] getColumnOrder () {
+    checkWidget ();
+    if (columnCount is 0) return new int [0];
+    int [] order = new int [columnCount];
+    OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr);
+    return order;
+}
+
+/**
+ * Returns an array of <code>TableColumn</code>s which are the
+ * columns in the receiver.  Columns are returned in the order
+ * that they were created.  If no <code>TableColumn</code>s were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the table like a list, adding items but
+ * never creating a column.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(bool)
+ * @see SWT#Move
+ */
+public TableColumn [] getColumns () {
+    checkWidget ();
+    TableColumn [] result = new TableColumn [columnCount];
+    System.arraycopy (columns, 0, result, 0, columnCount);
+    return result;
+}
+
+int getFocusIndex () {
+//  checkWidget ();
+    return OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+}
+
+/**
+ * Returns the width in pixels of a grid line.
+ *
+ * @return the width of a grid line in pixels
+ *
+ * @exception SWTException <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 int getGridLineWidth () {
+    checkWidget ();
+    return GRID_WIDTH;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @exception SWTException <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 2.0
+ */
+public int getHeaderHeight () {
+    checkWidget ();
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    if (hwndHeader is null) return 0;
+    RECT rect;
+    OS.GetWindowRect (hwndHeader, &rect);
+    return rect.bottom - rect.top;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's header 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 header's visibility state
+ *
+ * @exception SWTException <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 getHeaderVisible () {
+    checkWidget ();
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return (bits & OS.LVS_NOCOLUMNHEADER) is 0;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 TableItem getItem (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    return _getItem (index);
+}
+
+/**
+ * Returns the 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.
+ * <p>
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ * </p>
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 TableItem getItem (Point point) {
+    checkWidget ();
+    if (point is null) error (SWT.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;
+    if ((style & SWT.FULL_SELECTION) is 0) {
+        if (hooks (SWT.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) {
+        /*
+        * Bug in Windows.  When the point that is used by
+        * LVM_HITTEST is inside the header, Windows returns
+        * the first item in the table.  The fix is to check
+        * when LVM_HITTEST returns the first item and make
+        * sure that when the point is within the header,
+        * the first item is not returned.
+        */
+        if (pinfo.iItem is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.LVS_NOCOLUMNHEADER) is 0) {
+                auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                if (hwndHeader !is null) {
+                    RECT rect;
+                    OS.GetWindowRect (hwndHeader, &rect);
+                    POINT pt;
+                    pt.x = pinfo.pt.x;
+                    pt.y = pinfo.pt.y;
+                    OS.MapWindowPoints (handle, null, &pt, 1);
+                    if (OS.PtInRect (&rect, pt)) return null;
+                }
+            }
+        }
+        return _getItem (pinfo.iItem);
+    }
+    return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the receiver.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException <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 int getItemHeight () {
+    checkWidget ();
+    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);
+}
+
+/**
+ * Returns a (possibly empty) array of <code>TableItem</code>s which
+ * are the items in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 TableItem [] getItems () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    TableItem [] result = new TableItem [count];
+    if ((style & SWT.VIRTUAL) !is 0) {
+        for (int i=0; i<count; i++) {
+            result [i] = _getItem (i);
+        }
+    } else {
+        System.arraycopy (items, 0, result, 0, count);
+    }
+    return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's lines are 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 visibility state of the lines
+ *
+ * @exception SWTException <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 getLinesVisible () {
+    checkWidget ();
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    return (bits & OS.LVS_EX_GRIDLINES) !is 0;
+}
+
+/**
+ * Returns an array of <code>TableItem</code>s that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @exception SWTException <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 TableItem [] getSelection () {
+    checkWidget ();
+    int i = -1, j = 0, count = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+    TableItem [] result = new TableItem [count];
+    while ((i = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) !is -1) {
+        result [j++] = _getItem (i);
+    }
+    return result;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @exception SWTException <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 int getSelectionCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * selected in the receiver, or -1 if no item is selected.
+ *
+ * @return the index of the selected item
+ *
+ * @exception SWTException <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 int getSelectionIndex () {
+    checkWidget ();
+    int focusIndex = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+    int selectedIndex = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_SELECTED);
+    if (focusIndex is selectedIndex) return selectedIndex;
+    int i = -1;
+    while ((i = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) !is -1) {
+        if (i is focusIndex) return i;
+    }
+    return selectedIndex;
+}
+
+/**
+ * Returns the zero-relative indices of the items which are currently
+ * selected in the receiver. The order of the indices is unspecified.
+ * The array is empty if no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return the array of indices of the selected items
+ *
+ * @exception SWTException <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 int [] getSelectionIndices () {
+    checkWidget ();
+    int i = -1, j = 0, count = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+    int [] result = new int [count];
+    while ((i = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, i, OS.LVNI_SELECTED)) !is -1) {
+        result [j++] = i;
+    }
+    return result;
+}
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @exception SWTException <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 #setSortColumn(TableColumn)
+ *
+ * @since 3.2
+ */
+public TableColumn getSortColumn () {
+    checkWidget ();
+    return sortColumn;
+}
+
+int getSortColumnPixel () {
+    int pixel = OS.IsWindowEnabled (handle) ? getBackgroundPixel () : OS.GetSysColor (OS.COLOR_3DFACE);
+    int red = pixel & 0xFF;
+    int green = (pixel & 0xFF00) >> 8;
+    int blue = (pixel & 0xFF0000) >> 16;
+    if (red > 240 && green > 240 && blue > 240) {
+        red -= 8;
+        green -= 8;
+        blue -= 8;
+    } else {
+        red = Math.min (0xFF, (red / 10) + red);
+        green = Math.min (0xFF, (green / 10) + green);
+        blue = Math.min (0xFF, (blue / 10) + blue);
+    }
+    return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of <code>UP</code>, <code>DOWN</code>
+ * or <code>NONE</code>.
+ *
+ * @return the sort direction
+ *
+ * @exception SWTException <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 #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+    checkWidget ();
+    return sortDirection;
+}
+
+/**
+ * Returns the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items are
+ * scrolled or new items are added or removed.
+ *
+ * @return the index of the top item
+ *
+ * @exception SWTException <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 int getTopIndex () {
+    checkWidget ();
+    /*
+    * Bug in Windows.  Under rare circumstances, LVM_GETTOPINDEX
+    * can return a negative number.  When this happens, the table
+    * is displaying blank lines at the top of the controls.  The
+    * fix is to check for a negative number and return zero instead.
+    */
+    return Math.max (0, OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+}
+
+bool hasChildren () {
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    auto hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+    while (hwndChild !is null) {
+        if (hwndChild !is hwndHeader) return true;
+        hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+    }
+    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 (SWT.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) {
+        firstColumnImage = true;
+    } else {
+        setSubImagesVisible (true);
+    }
+    if (imageList is null) {
+        Rectangle bounds = image.getBounds ();
+        imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+        int index = imageList.indexOf (image);
+        if (index is -1) index = imageList.add (image);
+        auto hImageList = imageList.getHandle ();
+        /*
+        * Bug in Windows.  Making any change to an item that
+        * changes the item height of a table while the table
+        * is scrolled can cause the lines to draw incorrectly.
+        * This happens even when the lines are not currently
+        * visible and are shown afterwards.  The fix is to
+        * save the top index, scroll to the top of the table
+        * and then restore the original top index.
+        */
+        int topIndex = getTopIndex ();
+        if (topIndex !is 0) {
+            setRedraw (false);
+            setTopIndex (0);
+        }
+        OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+        if (headerImageList !is null) {
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            auto hHeaderImageList = headerImageList.getHandle ();
+            OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hHeaderImageList);
+        }
+        fixCheckboxImageList (false);
+        if (itemHeight !is -1) setItemHeight (false);
+        if (topIndex !is 0) {
+            setTopIndex (topIndex);
+            setRedraw (true);
+        }
+        return index;
+    }
+    int index = imageList.indexOf (image);
+    if (index !is -1) return index;
+    return imageList.add (image);
+}
+
+int imageIndexHeader (Image image) {
+    if (image is null) return OS.I_IMAGENONE;
+    if (headerImageList is null) {
+        Rectangle bounds = image.getBounds ();
+        headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+        int index = headerImageList.indexOf (image);
+        if (index is -1) index = headerImageList.add (image);
+        auto hImageList = headerImageList.getHandle ();
+        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList);
+        return index;
+    }
+    int index = headerImageList.indexOf (image);
+    if (index !is -1) return index;
+    return headerImageList.add (image);
+}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (TableColumn column) {
+    checkWidget ();
+    if (column is null) error (SWT.ERROR_NULL_ARGUMENT);
+    for (int i=0; i<columnCount; i++) {
+        if (columns [i] is column) return i;
+    }
+    return -1;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (TableItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (1 <= lastIndexOf && lastIndexOf < count - 1) {
+        if (items [lastIndexOf] is item) return lastIndexOf;
+        if (items [lastIndexOf + 1] is item) return ++lastIndexOf;
+        if (items [lastIndexOf - 1] is item) return --lastIndexOf;
+    }
+    if (lastIndexOf < count / 2) {
+        for (int i=0; i<count; i++) {
+            if (items [i] is item) return lastIndexOf = i;
+        }
+    } else {
+        for (int i=count - 1; i>=0; --i) {
+            if (items [i] is item) return lastIndexOf = i;
+        }
+    }
+    return -1;
+}
+
+bool isCustomToolTip () {
+    return hooks (SWT.MeasureItem);
+}
+
+bool isOptimizedRedraw () {
+    if ((style & SWT.H_SCROLL) is 0 || (style & SWT.V_SCROLL) is 0) return false;
+    return !hasChildren () && !hooks (SWT.Paint) && !filters (SWT.Paint);
+}
+
+/**
+ * Returns <code>true</code> if the item is selected,
+ * and <code>false</code> otherwise.  Indices out of
+ * range are ignored.
+ *
+ * @param index the index of the item
+ * @return the selection state of the item at the index
+ *
+ * @exception SWTException <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 isSelected (int index) {
+    checkWidget ();
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_STATE;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    lvItem.iItem = index;
+    int result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, &lvItem);
+    return (result !is 0) && ((lvItem.state & OS.LVIS_SELECTED) !is 0);
+}
+
+override void register () {
+    super.register ();
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    if (hwndHeader !is null) display.addControl (hwndHeader, this);
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+        /*
+        * Feature in Windows 98.  When there are a large number
+        * of columns and items in a table (>1000) where each
+        * of the subitems in the table has a string, it is much
+        * faster to delete each item with LVM_DELETEITEM rather
+        * than using LVM_DELETEALLITEMS.  The fix is to detect
+        * this case and delete the items, one by one.  The fact
+        * that the fix is only necessary on Windows 98 was
+        * confirmed using version 5.81 of COMCTL32.DLL on both
+        * Windows 98 and NT.
+        *
+        * NOTE: LVM_DELETEALLITEMS is also sent by the table
+        * when the table is destroyed.
+        */
+        if (OS.IsWin95 && columnCount > 1) {
+            /* Turn off redraw and resize events and leave them off */
+            resizeCount = 1;
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+            for (int i=itemCount-1; i>=0; --i) {
+                TableItem item = items [i];
+                if (item !is null && !item.isDisposed ()) item.release (false);
+                ignoreSelect = ignoreShrink = true;
+                OS.SendMessage (handle, OS.LVM_DELETEITEM, i, 0);
+                ignoreSelect = ignoreShrink = false;
+            }
+        } else {
+            for (int i=0; i<itemCount; i++) {
+                TableItem item = items [i];
+                if (item !is null && !item.isDisposed ()) item.release (false);
+            }
+        }
+        items = null;
+    }
+    if (columns !is null) {
+        for (int i=0; i<columnCount; i++) {
+            TableColumn column = columns [i];
+            if (!column.isDisposed ()) column.release (false);
+        }
+        columns = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    customDraw = false;
+    currentItem = null;
+    if (imageList !is null) {
+        OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, 0);
+        display.releaseImageList (imageList);
+    }
+    if (headerImageList !is null) {
+        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, 0);
+        display.releaseImageList (headerImageList);
+    }
+    imageList = headerImageList = null;
+    auto hStateList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+    OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_STATE, 0);
+    if (hStateList !is null) OS.ImageList_Destroy (hStateList);
+    if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle);
+    headerToolTipHandle = null;
+}
+
+/**
+ * Removes the items from the receiver's list at the given
+ * zero-relative indices.
+ *
+ * @param indices the array of indices of the items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (indices.length is 0) return;
+    int [] newIndices = new int [indices.length];
+    System.arraycopy (indices, 0, newIndices, 0, indices.length);
+    sort (newIndices);
+    int start = newIndices [newIndices.length - 1], end = newIndices [0];
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    setDeferResize (true);
+    int last = -1;
+    for (int i=0; i<newIndices.length; i++) {
+        int index = newIndices [i];
+        if (index !is last) {
+            TableItem item = items [index];
+            if (item !is null && !item.isDisposed ()) item.release (false);
+            ignoreSelect = ignoreShrink = true;
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+            ignoreSelect = ignoreShrink = false;
+            if (code is 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+            System.arraycopy (items, index + 1, items, index, --count - index);
+            items [count] = null;
+            last = index;
+        }
+    }
+    if (count is 0) setTableEmpty ();
+    setDeferResize (false);
+}
+
+/**
+ * Removes the item from the receiver at the given
+ * zero-relative index.
+ *
+ * @param index the index for the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    TableItem item = items [index];
+    if (item !is null && !item.isDisposed ()) item.release (false);
+    setDeferResize (true);
+    ignoreSelect = ignoreShrink = true;
+    int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+    ignoreSelect = ignoreShrink = false;
+    if (code is 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    System.arraycopy (items, index + 1, items, index, --count - index);
+    items [count] = null;
+    if (count is 0) setTableEmpty ();
+    setDeferResize (false);
+}
+
+/**
+ * Removes the items from the receiver which are
+ * between the given zero-relative start and end
+ * indices (inclusive).
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 remove (int start, int end) {
+    checkWidget ();
+    if (start > end) return;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (!(0 <= start && start <= end && end < count)) {
+        error (SWT.ERROR_INVALID_RANGE);
+    }
+    if (start is 0 && end is count - 1) {
+        removeAll ();
+    } else {
+        setDeferResize (true);
+        int index = start;
+        while (index <= end) {
+            TableItem item = items [index];
+            if (item !is null && !item.isDisposed ()) item.release (false);
+            ignoreSelect = ignoreShrink = true;
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0);
+            ignoreSelect = ignoreShrink = false;
+            if (code is 0) break;
+            index++;
+        }
+        System.arraycopy (items, index, items, start, count - index);
+        for (int i=count-(index-start); i<count; i++) items [i] = null;
+        if (index <= end) error (SWT.ERROR_ITEM_NOT_REMOVED);
+        /*
+        * This code is intentionally commented.  It is not necessary
+        * to check for an empty table because removeAll() was called
+        * when the start is 0 and end is count - 1.
+        */
+        //if (count - index is 0) setTableEmpty ();
+        setDeferResize (false);
+    }
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @exception SWTException <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 removeAll () {
+    checkWidget ();
+    int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    for (int i=0; i<itemCount; i++) {
+        TableItem item = items [i];
+        if (item !is null && !item.isDisposed ()) item.release (false);
+    }
+    /*
+    * Feature in Windows 98.  When there are a large number
+    * of columns and items in a table (>1000) where each
+    * of the subitems in the table has a string, it is much
+    * faster to delete each item with LVM_DELETEITEM rather
+    * than using LVM_DELETEALLITEMS.  The fix is to detect
+    * this case and delete the items, one by one.  The fact
+    * that the fix is only necessary on Windows 98 was
+    * confirmed using version 5.81 of COMCTL32.DLL on both
+    * Windows 98 and NT.
+    *
+    * NOTE: LVM_DELETEALLITEMS is also sent by the table
+    * when the table is destroyed.
+    */
+    setDeferResize (true);
+    if (OS.IsWin95 && columnCount > 1) {
+        bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+        int index = itemCount - 1;
+        while (index >= 0) {
+            ignoreSelect = ignoreShrink = true;
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+            ignoreSelect = ignoreShrink = false;
+            if (code is 0) break;
+            --index;
+        }
+        if (redraw) {
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            /*
+            * This code is intentionally commented.  The window proc
+            * for the table implements WM_SETREDRAW to invalidate
+            * and erase the table so it is not necessary to do this
+            * again.
+            */
+//          int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+//          OS.RedrawWindow (handle, null, 0, flags);
+        }
+        if (index !is -1) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    } else {
+        ignoreSelect = ignoreShrink = true;
+        int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0);
+        ignoreSelect = ignoreShrink = false;
+        if (code is 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    }
+    setTableEmpty ();
+    setDeferResize (false);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener(SelectionListener)
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If the item at a given index is not selected, it is selected.
+ * If the item at a given index was already selected, it remains selected.
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ * </p>
+ *
+ * @param indices the array of indices for the items to select
+ *
+ * @exception SWTException <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 Table#setSelection(int[])
+ */
+public void select (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int length = indices.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    LVITEM lvItem;
+    lvItem.state = OS.LVIS_SELECTED;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    for (int i=length-1; i>=0; --i) {
+        /*
+        * An index of -1 will apply the change to all
+        * items.  Ensure that indices are greater than -1.
+        */
+        if (indices [i] >= 0) {
+            ignoreSelect = true;
+            OS.SendMessage (handle, OS.LVM_SETITEMSTATE, indices [i], &lvItem);
+            ignoreSelect = false;
+        }
+    }
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * If the item at the index was already selected, it remains
+ * selected. Indices that are out of range are ignored.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 select (int index) {
+    checkWidget ();
+    /*
+    * An index of -1 will apply the change to all
+    * items.  Ensure that index is greater than -1.
+    */
+    if (index < 0) return;
+    LVITEM lvItem;
+    lvItem.state = OS.LVIS_SELECTED;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    ignoreSelect = true;
+    OS.SendMessage (handle, OS.LVM_SETITEMSTATE, index, &lvItem);
+    ignoreSelect = false;
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is not cleared before the new items are selected.
+ * <p>
+ * If an item in the given range is not selected, it is selected.
+ * If an item in the given range was already selected, it remains selected.
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException <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 Table#setSelection(int,int)
+ */
+public void select (int start, int end) {
+    checkWidget ();
+    if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is 0 || start >= count) return;
+    start = Math.max (0, start);
+    end = Math.min (end, count - 1);
+    if (start is 0 && end is count - 1) {
+        selectAll ();
+    } else {
+        /*
+        * An index of -1 will apply the change to all
+        * items.  Indices must be greater than -1.
+        */
+        LVITEM lvItem;
+        lvItem.state = OS.LVIS_SELECTED;
+        lvItem.stateMask = OS.LVIS_SELECTED;
+        for (int i=start; i<=end; i++) {
+            ignoreSelect = true;
+            OS.SendMessage (handle, OS.LVM_SETITEMSTATE, i, &lvItem);
+            ignoreSelect = false;
+        }
+    }
+}
+
+/**
+ * Selects all of the items in the receiver.
+ * <p>
+ * If the receiver is single-select, do nothing.
+ * </p>
+ *
+ * @exception SWTException <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 selectAll () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) return;
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_STATE;
+    lvItem.state = OS.LVIS_SELECTED;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    ignoreSelect = true;
+    OS.SendMessage (handle, OS.LVM_SETITEMSTATE, -1, &lvItem);
+    ignoreSelect = false;
+}
+
+void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd, int lParam, Event measureEvent) {
+    auto hDC = nmcd.nmcd.hdc;
+    int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1;
+    if (clrText is -1) clrText = item.foreground;
+    int clrTextBk = -1;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (sortColumn !is null && sortDirection !is SWT.NONE) {
+            if (findImageControl () is null) {
+                if (indexOf (sortColumn) is nmcd.iSubItem) {
+                    clrTextBk = getSortColumnPixel ();
+                }
+            }
+        }
+    }
+    clrTextBk = item.cellBackground !is null ? item.cellBackground [nmcd.iSubItem] : -1;
+    if (clrTextBk is -1) clrTextBk = item.background;
+    /*
+    * Bug in Windows.  For some reason, CDIS_SELECTED always set,
+    * even for items that are not selected.  The fix is to get
+    * the selection state from the item.
+    */
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_STATE;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    lvItem.iItem = nmcd.nmcd.dwItemSpec;
+    int result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, &lvItem);
+    bool selected = (result !is 0 && (lvItem.state & OS.LVIS_SELECTED) !is 0);
+    GCData data = new GCData ();
+    data.device = display;
+    int clrSelectionBk = -1;
+    bool drawSelected = false, drawBackground = false, drawHot = false;
+    if (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0) {
+        drawHot = hotIndex is nmcd.nmcd.dwItemSpec;
+    }
+    if (OS.IsWindowEnabled (handle)) {
+        if (selected && (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0)) {
+            if (OS.GetFocus () is handle || display.getHighContrast ()) {
+                drawSelected = true;
+                data.foreground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                data.background = clrSelectionBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+            } else {
+                drawSelected = (style & SWT.HIDE_SELECTION) is 0;
+                data.foreground = OS.GetTextColor (hDC);
+                data.background = clrSelectionBk = OS.GetSysColor (OS.COLOR_3DFACE);
+            }
+            if (explorerTheme) {
+                data.foreground = clrText !is -1 ? clrText : getForegroundPixel ();
+            }
+        } else {
+            drawBackground = clrTextBk !is -1;
+            /*
+            * 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 (clrText is -1 || clrTextBk is -1) {
+                Control control = findBackgroundControl ();
+                if (control is null) control = this;
+                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);
+        }
+    } else {
+        data.foreground = OS.GetSysColor (OS.COLOR_GRAYTEXT);
+        data.background = OS.GetSysColor (OS.COLOR_3DFACE);
+        if (selected) clrSelectionBk = data.background;
+    }
+    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);
+    RECT cellRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, true, hDC);
+    Event event = new Event ();
+    event.item = item;
+    event.gc = gc;
+    event.index = nmcd.iSubItem;
+    event.detail |= SWT.FOREGROUND;
+//  if ((nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+    if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) is nmcd.nmcd.dwItemSpec) {
+        if (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0) {
+            if (handle is OS.GetFocus ()) {
+                int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= SWT.FOCUSED;
+            }
+        }
+    }
+    bool focused = (event.detail & SWT.FOCUSED) !is 0;
+    if (drawHot) event.detail |= SWT.HOT;
+    if (drawSelected) event.detail |= SWT.SELECTED;
+    if (drawBackground) event.detail |= SWT.BACKGROUND;
+    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 (SWT.EraseItem, event);
+    event.gc = null;
+    auto clrSelectionText = data.foreground;
+    gc.dispose ();
+    OS.RestoreDC (hDC, nSavedDC);
+    if (isDisposed () || item.isDisposed ()) return;
+    if (event.doit) {
+        ignoreDrawForeground = (event.detail & SWT.FOREGROUND) is 0;
+        ignoreDrawBackground = (event.detail & SWT.BACKGROUND) is 0;
+        ignoreDrawSelection = (event.detail & SWT.SELECTED) is 0;
+        ignoreDrawFocus = (event.detail & SWT.FOCUSED) is 0;
+        ignoreDrawHot = (event.detail & SWT.HOT) is 0;
+    } else {
+        ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+    }
+    if (drawSelected) {
+        if (ignoreDrawSelection) {
+            ignoreDrawHot = true;
+            if (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0) {
+                selectionForeground = clrSelectionText;
+            }
+            nmcd.nmcd.uItemState &= ~OS.CDIS_SELECTED;
+            OS.MoveMemory (lParam, nmcd, OS.NMLVCUSTOMDRAW_sizeof);
+        }
+    } else {
+        if (ignoreDrawSelection) {
+            nmcd.nmcd.uItemState |= OS.CDIS_SELECTED;
+            OS.MoveMemory (lParam, nmcd, OS.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) {
+        if (!ignoreDrawBackground && drawBackground) {
+            RECT backgroundRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, true, false, hDC);
+            fillBackground (hDC, clrTextBk, &backgroundRect);
+        }
+    }
+    focusRect = null;
+    if (!ignoreDrawHot || !ignoreDrawSelection || !ignoreDrawFocus) {
+        bool fullText = (style & SWT.FULL_SELECTION) !is 0 || !firstColumn;
+        RECT textRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC);
+        if ((style & SWT.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, OS.NMLVCUSTOMDRAW_sizeof);
+                focusRect = new RECT;
+                *focusRect = textRect;
+            }
+        }
+        if (explorerTheme) {
+            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 & SWT.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);
+            }
+        } else {
+            if (!ignoreDrawSelection && clrSelectionBk !is -1) fillBackground (hDC, clrSelectionBk, &textRect);
+        }
+    }
+    if (focused && ignoreDrawFocus) {
+        nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+        OS.MoveMemory (lParam, nmcd, OS.NMLVCUSTOMDRAW_sizeof);
+    }
+    if (ignoreDrawForeground) {
+        RECT clipRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, false, hDC);
+        OS.SaveDC (hDC);
+        OS.SelectClipRgn (hDC, null);
+        OS.ExcludeClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+    }
+}
+
+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.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 |= SWT.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 (SWT.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 ();
+    event.item = item;
+    event.gc = gc;
+    event.index = column;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    sendEvent (SWT.MeasureItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (hDC, nSavedDC);
+    if (!isDisposed () && !item.isDisposed ()) {
+        if (columnCount is 0) {
+            int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+            if (event.x + event.width > width) {
+                OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, event.x + event.width);
+            }
+        }
+        if (event.height > getItemHeight ()) setItemHeight (event.height);
+    }
+    return event;
+}
+
+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
+    * to begin a drag/drop operation or marque select.  Unfortunately,
+    * this modal loop eats the corresponding mouse up.  The fix is to
+    * detect the cases when the modal loop has eaten the mouse up and
+    * issue a fake mouse up.
+    *
+    * By observation, when the mouse is clicked anywhere but the check
+    * box, the widget eats the mouse up.  When the mouse is dragged,
+    * the widget does not eat the mouse up.
+    */
+    LVHITTESTINFO pinfo;
+    pinfo.pt.x = OS.GET_X_LPARAM (lParam);
+    pinfo.pt.y = OS.GET_Y_LPARAM (lParam);
+    OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
+    if ((style & SWT.FULL_SELECTION) is 0) {
+        if (hooks (SWT.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;
+            }
+        }
+    }
+
+    /*
+    * Force the table to have focus so that when the user
+    * reselects the focus item, the LVIS_FOCUSED state bits
+    * for the item will be set.  If the user did not click on
+    * an item, then set focus to the table so that it will
+    * come to the front and take focus in the work around
+    * below.
+    */
+    OS.SetFocus (handle);
+
+    /*
+    * Feature in Windows.  When the user selects outside of
+    * a table item, Windows deselects all the items, even
+    * when the table is multi-select.  While not strictly
+    * wrong, this is unexpected.  The fix is to detect the
+    * case and avoid calling the window proc.
+    */
+    if ((style & SWT.SINGLE) !is 0 || hooks (SWT.MouseDown) || hooks (SWT.MouseUp)) {
+        if (pinfo.iItem is -1) {
+            if (!display.captureChanged && !isDisposed ()) {
+                if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+            }
+            return LRESULT.ZERO;
+        }
+    }
+
+    /*
+    * Feature in Windows.  When a table item is reselected
+    * in a single-select table, Windows does not issue a
+    * WM_NOTIFY because the item state has not changed.
+    * This is strictly correct but is inconsistent with the
+    * list widget and other widgets in Windows.  The fix is
+    * to detect the case when an item is reselected and mark
+    * it as selected.
+    */
+    bool forceSelect = false;
+    int count = OS.SendMessage (handle, OS.LVM_GETSELECTEDCOUNT, 0, 0);
+    if (count is 1 && pinfo.iItem !is -1) {
+        LVITEM lvItem;
+        lvItem.mask = OS.LVIF_STATE;
+        lvItem.stateMask = OS.LVIS_SELECTED;
+        lvItem.iItem = pinfo.iItem;
+        OS.SendMessage (handle, OS.LVM_GETITEM, 0, &lvItem);
+        if ((lvItem.state & OS.LVIS_SELECTED) !is 0) {
+            forceSelect = true;
+        }
+    }
+
+    /* Determine whether the user has selected an item based on SWT.MeasureItem */
+    fullRowSelect = false;
+    if (pinfo.iItem !is -1) {
+        if ((style & SWT.FULL_SELECTION) is 0) {
+            if (hooks (SWT.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
+    * to begin a drag/drop operation or marque select.  This modal
+    * loop eats mouse events until a drag is detected.  The fix is
+    * to avoid this behavior by only running the drag and drop when
+    * the event is hooked and the mouse is over an item.
+    */
+    bool dragDetect = (state & DRAG_DETECT) !is 0 && hooks (SWT.DragDetect);
+    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 SWT.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 /*long*/ code = callWindowProc (handle, msg, wParam, lParam, forceSelect);
+    if (!dragDetect) display.runDragDrop = true;
+    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);
+        }
+    } else {
+        int flags = OS.LVHT_ONITEMLABEL | OS.LVHT_ONITEMICON;
+        bool fakeMouseUp = (pinfo.flags & flags) !is 0;
+        if (!fakeMouseUp && (style & SWT.MULTI) !is 0) {
+            fakeMouseUp = (pinfo.flags & OS.LVHT_ONITEMSTATEICON) is 0;
+        }
+        if (fakeMouseUp) {
+            sendMouseEvent (SWT.MouseUp, button, handle, msg, wParam, lParam);
+        }
+    }
+    return new LRESULT (code);
+}
+
+void sendPaintItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd) {
+    auto hDC = nmcd.nmcd.hdc;
+    GCData data = new GCData ();
+    data.device = display;
+    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
+    * the selection state from the item.
+    */
+    LVITEM lvItem;
+    lvItem.mask = OS.LVIF_STATE;
+    lvItem.stateMask = OS.LVIS_SELECTED;
+    lvItem.iItem = nmcd.nmcd.dwItemSpec;
+    int result = OS.SendMessage (handle, OS.LVM_GETITEM, 0, &lvItem);
+    bool selected = result !is 0 && (lvItem.state & OS.LVIS_SELECTED) !is 0;
+    bool drawSelected = false, drawBackground = false, drawHot = false;
+    if (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0) {
+        drawHot = hotIndex is nmcd.nmcd.dwItemSpec;
+    }
+    if (OS.IsWindowEnabled (handle)) {
+        if (selected && (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0)) {
+            if (OS.GetFocus () is handle || display.getHighContrast ()) {
+                drawSelected = true;
+                if (selectionForeground !is -1) {
+                    data.foreground = selectionForeground;
+                } else {
+                    data.foreground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                }
+                data.background = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
+            } else {
+                drawSelected = (style & SWT.HIDE_SELECTION) is 0;
+                data.foreground = OS.GetTextColor (hDC);
+                data.background = OS.GetSysColor (OS.COLOR_3DFACE);
+            }
+            if (explorerTheme && selectionForeground is -1) {
+                int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1;
+                if (clrText is -1) clrText = item.foreground;
+                data.foreground = clrText !is -1 ? clrText : getForegroundPixel ();
+            }
+        } else {
+            int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1;
+            if (clrText is -1) clrText = item.foreground;
+            int clrTextBk = item.cellBackground !is null ? item.cellBackground [nmcd.iSubItem] : -1;
+            if (clrTextBk is -1) clrTextBk = item.background;
+            drawBackground = clrTextBk !is -1;
+            /*
+            * 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 (clrText is -1 || clrTextBk is -1) {
+                Control control = findBackgroundControl ();
+                if (control is null) control = this;
+                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);
+        }
+    } else {
+        data.foreground = OS.GetSysColor (OS.COLOR_GRAYTEXT);
+        data.background = OS.GetSysColor (OS.COLOR_3DFACE);
+    }
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    auto nSavedDC = OS.SaveDC (hDC);
+    GC gc = GC.win32_new (hDC, data);
+    RECT itemRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, false, false, hDC);
+    Event event = new Event ();
+    event.item = item;
+    event.gc = gc;
+    event.index = nmcd.iSubItem;
+    event.detail |= SWT.FOREGROUND;
+//  if ((nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+    if (OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED) is nmcd.nmcd.dwItemSpec) {
+        if (nmcd.iSubItem is 0 || (style & SWT.FULL_SELECTION) !is 0) {
+            if (handle is OS.GetFocus ()) {
+                int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= SWT.FOCUSED;
+            }
+        }
+    }
+    if (drawHot) event.detail |= SWT.HOT;
+    if (drawSelected) event.detail |= SWT.SELECTED;
+    if (drawBackground) event.detail |= SWT.BACKGROUND;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    RECT cellRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, true, hDC);
+    int cellWidth = cellRect.right - cellRect.left;
+    int cellHeight = cellRect.bottom - cellRect.top;
+    gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+    sendEvent (SWT.PaintItem, event);
+    if (data.focusDrawn) focusRect = null;
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (hDC, nSavedDC);
+}
+
+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 |= SWT.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 (SWT.PaintItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+void setBackgroundImage (HBITMAP hBitmap) {
+    super.setBackgroundImage (hBitmap);
+    if (hBitmap !is null) {
+        setBackgroundTransparent (true);
+    } else {
+        if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+            setBackgroundTransparent (false);
+        }
+    }
+}
+
+override void setBackgroundPixel (int newPixel) {
+    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 ();
+        if (oldPixel !is newPixel) {
+            OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel);
+            OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel);
+            if ((style & SWT.CHECK) !is 0) fixCheckboxImageListColor (true);
+        }
+    }
+    /*
+    * Feature in Windows.  When the background color is changed,
+    * the table does not redraw until the next WM_PAINT.  The fix
+    * is to force a redraw.
+    */
+    OS.InvalidateRect (handle, null, true);
+}
+
+void setBackgroundTransparent (bool transparent) {
+    /*
+    * Bug in Windows.  When the table has the extended style
+    * LVS_EX_FULLROWSELECT and LVM_SETBKCOLOR is used with
+    * CLR_NONE to make the table transparent, Windows draws
+    * a black rectangle around the first column.  The fix is
+    * clear LVS_EX_FULLROWSELECT.
+    *
+    * Feature in Windows.  When LVM_SETBKCOLOR is used with
+    * CLR_NONE and LVM_SETSELECTEDCOLUMN is used to select
+    * a column, Windows fills the column with the selection
+    * color, drawing on top of the background image and any
+    * other custom drawing.  The fix is to clear the selected
+    * column.
+    */
+    int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+    if (transparent) {
+        if (oldPixel !is OS.CLR_NONE) {
+            /*
+            * Bug in Windows.  When the background color is changed,
+            * the table does not redraw until the next WM_PAINT.  The
+            * fix is to force a redraw.
+            */
+            OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
+            OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, OS.CLR_NONE);
+            OS.InvalidateRect (handle, null, true);
+
+            /* Clear LVS_EX_FULLROWSELECT */
+            if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+                int bits = OS.LVS_EX_FULLROWSELECT;
+                OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, 0);
+            }
+
+            /* Clear LVM_SETSELECTEDCOLUMN */
+            if ((sortDirection & (SWT.UP | SWT.DOWN)) !is 0) {
+                if (sortColumn !is null && !sortColumn.isDisposed ()) {
+                    OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, -1, 0);
+                    /*
+                    * Bug in Windows.  When LVM_SETSELECTEDCOLUMN is set, Windows
+                    * does not redraw either the new or the previous selected column.
+                    * The fix is to force a redraw.
+                    */
+                    OS.InvalidateRect (handle, null, true);
+                }
+            }
+        }
+    } else {
+        if (oldPixel is OS.CLR_NONE) {
+            Control control = findBackgroundControl ();
+            if (control is null) control = this;
+            if (control.backgroundImage is null) {
+                int newPixel = control.getBackgroundPixel ();
+                OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel);
+                OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel);
+                if ((style & SWT.CHECK) !is 0) fixCheckboxImageListColor (true);
+                OS.InvalidateRect (handle, null, true);
+            }
+
+            /* Set LVS_EX_FULLROWSELECT */
+            if (!explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+                if (!hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                    int bits = OS.LVS_EX_FULLROWSELECT;
+                    OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, bits, bits);
+                }
+            }
+
+            /* Set LVM_SETSELECTEDCOLUMN */
+            if ((sortDirection & (SWT.UP | SWT.DOWN)) !is 0) {
+                if (sortColumn !is null && !sortColumn.isDisposed ()) {
+                    int column = indexOf (sortColumn);
+                    if (column !is -1) {
+                        OS.SendMessage (handle, OS.LVM_SETSELECTEDCOLUMN, column, 0);
+                        /*
+                        * Bug in Windows.  When LVM_SETSELECTEDCOLUMN is set, Windows
+                        * does not redraw either the new or the previous selected column.
+                        * The fix is to force a redraw.
+                        */
+                        OS.InvalidateRect (handle, null, true);
+                    }
+                }
+            }
+        }
+    }
+}
+
+override void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    /*
+    * Bug in Windows.  If the table column widths are adjusted
+    * in WM_SIZE or WM_POSITIONCHANGED using LVM_SETCOLUMNWIDTH
+    * blank lines may be inserted at the top of the table.  A
+    * call to LVM_GETTOPINDEX will return a negative number (this
+    * is an impossible result).  Once the blank lines appear,
+    * there seems to be no way to get rid of them, other than
+    * destroying and recreating the table.  The fix is to send
+    * the resize notification after the size has been changed in
+    * the operating system.
+    *
+    * NOTE:  This does not fix the case when the user is resizing
+    * columns dynamically.  There is no fix for this case at this
+    * time.
+    */
+    setDeferResize (true);
+    super.setBounds (x, y, width, height, flags, false);
+    setDeferResize (false);
+}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @exception SWTException <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_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ *
+ * @see Table#getColumnOrder()
+ * @see TableColumn#getMoveable()
+ * @see TableColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setColumnOrder (int [] order) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (order is null) error (SWT.ERROR_NULL_ARGUMENT);
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    if (columnCount is 0) {
+        if (order.length !is 0) error (SWT.ERROR_INVALID_ARGUMENT);
+        return;
+    }
+    if (order.length !is columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, oldOrder.ptr);
+    bool reorder = false;
+    bool [] seen = new bool [columnCount];
+    for (int i=0; i<order.length; i++) {
+        int index = order [i];
+        if (index < 0 || index >= columnCount) error (SWT.ERROR_INVALID_RANGE);
+        if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+        seen [index] = true;
+        if (index !is oldOrder [i]) reorder = true;
+    }
+    if (reorder) {
+        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 (handle, OS.LVM_SETCOLUMNORDERARRAY, order.length, order.ptr);
+        /*
+        * Bug in Windows.  When LVM_SETCOLUMNORDERARRAY is used to change
+        * the column order, the header redraws correctly but the table does
+        * not.  The fix is to force a redraw.
+        */
+        OS.InvalidateRect (handle, null, true);
+        TableColumn[] newColumns = new TableColumn [columnCount];
+        System.arraycopy (columns, 0, newColumns, 0, columnCount);
+        RECT newRect;
+        for (int i=0; i<columnCount; i++) {
+            TableColumn column = newColumns [i];
+            if (!column.isDisposed ()) {
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect);
+                if (newRect.left !is oldRects [i].left) {
+                    column.updateToolTip (i);
+                    column.sendEvent (SWT.Move);
+                }
+            }
+        }
+    }
+}
+
+void setCustomDraw (bool customDraw) {
+    if (this.customDraw is customDraw) return;
+    if (!this.customDraw && customDraw && currentItem !is null) {
+        OS.InvalidateRect (handle, null, true);
+    }
+    this.customDraw = customDraw;
+}
+
+void setDeferResize (bool defer) {
+    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 (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                if (drawCount++ is 0 && OS.IsWindowVisible (handle)) {
+                    OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                    OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
+                }
+            }
+        }
+    } else {
+        if (--resizeCount is 0) {
+            if (hooks (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.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);
+                        if (hwndHeader !is null) OS.InvalidateRect (hwndHeader, null, true);
+                        OS.InvalidateRect (handle, null, true);
+                    } else {
+                        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                        OS.RedrawWindow (handle, null, null, flags);
+                    }
+                }
+            }
+            if (wasResized) {
+                wasResized = false;
+                setResizeChildren (false);
+                sendEvent (SWT.Resize);
+                if (isDisposed ()) return;
+                if (layout_ !is null) {
+                    markLayout (false, false);
+                    updateLayout (false, false);
+                }
+                setResizeChildren (true);
+            }
+        }
+    }
+}
+
+void setCheckboxImageList (int width, int height, bool fixScroll) {
+    if ((style & SWT.CHECK) is 0) return;
+    int count = 4, flags = 0;
+    static if (OS.IsWinCE) {
+        flags |= OS.ILC_COLOR;
+    } else {
+        {// new scope for hDC
+        auto hDC = OS.GetDC (handle);
+        auto bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+        auto planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+        OS.ReleaseDC (handle, hDC);
+        int depth = bits * planes;
+        switch (depth) {
+            case 4: flags |= OS.ILC_COLOR4; break;
+            case 8: flags |= OS.ILC_COLOR8; break;
+            case 16: flags |= OS.ILC_COLOR16; break;
+            case 24: flags |= OS.ILC_COLOR24; break;
+            case 32: flags |= OS.ILC_COLOR32; break;
+            default: flags |= OS.ILC_COLOR; break;
+        }
+        }
+    }
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) flags |= OS.ILC_MIRROR;
+    if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) flags |= OS.ILC_MASK;
+    auto hStateList = OS.ImageList_Create (width, height, flags, count, count);
+    auto hDC = OS.GetDC (handle);
+    auto memDC = OS.CreateCompatibleDC (hDC);
+    auto hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height);
+    auto hOldBitmap = OS.SelectObject (memDC, hBitmap);
+    RECT rect;
+    OS.SetRect (&rect, 0, 0, width * count, height);
+    int clrBackground;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        clrBackground = control.getBackgroundPixel ();
+    } else {
+        clrBackground = 0x020000FF;
+        if ((clrBackground & 0xFFFFFF) is OS.GetSysColor (OS.COLOR_WINDOW)) {
+            clrBackground = 0x0200FF00;
+        }
+    }
+    auto hBrush = OS.CreateSolidBrush (clrBackground);
+    OS.FillRect (memDC, &rect, hBrush);
+    OS.DeleteObject (hBrush);
+    auto oldFont = OS.SelectObject (hDC, defaultFont ());
+    TEXTMETRIC tm;
+    OS.GetTextMetrics (hDC, &tm);
+    OS.SelectObject (hDC, oldFont);
+    int itemWidth = Math.min (tm.tmHeight, width);
+    int itemHeight = Math.min (tm.tmHeight, height);
+    int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1;
+    OS.SetRect (&rect, left, top, left + itemWidth, top + itemHeight);
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        auto hTheme = display.hButtonTheme ();
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDNORMAL, &rect, null);
+    } else {
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+    }
+    OS.SelectObject (memDC, hOldBitmap);
+    OS.DeleteDC (memDC);
+    OS.ReleaseDC (handle, hDC);
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        OS.ImageList_Add (hStateList, hBitmap, null);
+    } else {
+        OS.ImageList_AddMasked (hStateList, hBitmap, clrBackground);
+    }
+    OS.DeleteObject (hBitmap);
+    /*
+    * Bug in Windows.  Making any change to an item that
+    * changes the item height of a table while the table
+    * is scrolled can cause the lines to draw incorrectly.
+    * This happens even when the lines are not currently
+    * visible and are shown afterwards.  The fix is to
+    * save the top index, scroll to the top of the table
+    * and then restore the original top index.
+    */
+    int topIndex = getTopIndex ();
+    if (fixScroll && topIndex !is 0) {
+        setRedraw (false);
+        setTopIndex (0);
+    }
+    auto hOldStateList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+    OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_STATE, hStateList);
+    if (hOldStateList !is null) OS.ImageList_Destroy (hOldStateList);
+    /*
+    * Bug in Windows.  Setting the LVSIL_STATE state image list
+    * when the table already has a LVSIL_SMALL image list causes
+    * pixel corruption of the images.  The fix is to reset the
+    * LVSIL_SMALL image list.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        auto hImageList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+        OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+    }
+    if (fixScroll && topIndex !is 0) {
+        setTopIndex (topIndex);
+        setRedraw (true);
+    }
+}
+
+void setFocusIndex (int index) {
+//  checkWidget ();
+    /*
+    * An index of -1 will apply the change to all
+    * items.  Ensure that index is greater than -1.
+    */
+    if (index < 0) return;
+    LVITEM lvItem;
+    lvItem.state = OS.LVIS_FOCUSED;
+    lvItem.stateMask = OS.LVIS_FOCUSED;
+    ignoreSelect = true;
+    OS.SendMessage (handle, OS.LVM_SETITEMSTATE, index, &lvItem);
+    ignoreSelect = false;
+    OS.SendMessage (handle, OS.LVM_SETSELECTIONMARK, 0, index);
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    /*
+    * Bug in Windows.  Making any change to an item that
+    * changes the item height of a table while the table
+    * is scrolled can cause the lines to draw incorrectly.
+    * This happens even when the lines are not currently
+    * visible and are shown afterwards.  The fix is to
+    * save the top index, scroll to the top of the table
+    * and then restore the original top index.
+    */
+    int topIndex = getTopIndex ();
+    if (topIndex !is 0) {
+        setRedraw (false);
+        setTopIndex (0);
+    }
+    if (itemHeight !is -1) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.LVS_OWNERDRAWFIXED);
+    }
+    super.setFont (font);
+    if (itemHeight !is -1) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits & ~OS.LVS_OWNERDRAWFIXED);
+    }
+    setScrollWidth (null, true);
+    if (topIndex !is 0) {
+        setTopIndex (topIndex);
+        setRedraw (true);
+    }
+
+    /*
+    * Bug in Windows.  Setting the font will cause the table
+    * to be redrawn but not the column headers.  The fix is
+    * to force a redraw of the column headers.
+    */
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    OS.InvalidateRect (hwndHeader, null, true);
+}
+
+override void setForegroundPixel (int pixel) {
+    /*
+    * The Windows table control uses CLR_DEFAULT to indicate
+    * that it is using the default foreground color.  This
+    * is undocumented.
+    */
+    if (pixel is -1) pixel = OS.CLR_DEFAULT;
+    OS.SendMessage (handle, OS.LVM_SETTEXTCOLOR, 0, pixel);
+
+    /*
+    * Feature in Windows.  When the foreground color is
+    * changed, the table does not redraw until the next
+    * WM_PAINT.  The fix is to force a redraw.
+    */
+    OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * Marks the receiver's header 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 show the new visibility state
+ *
+ * @exception SWTException <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 setHeaderVisible (bool show) {
+    checkWidget ();
+    int newBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    newBits &= ~OS.LVS_NOCOLUMNHEADER;
+    if (!show) newBits |= OS.LVS_NOCOLUMNHEADER;
+    /*
+    * Feature in Windows.  Setting or clearing LVS_NOCOLUMNHEADER
+    * causes the table to scroll to the beginning.  The fix is to
+    * save and restore the top index causing the table to scroll
+    * to the new location.
+    */
+    int oldIndex = getTopIndex ();
+    OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+
+    /*
+    * Bug in Windows.  Making any change to an item that
+    * changes the item height of a table while the table
+    * is scrolled can cause the lines to draw incorrectly.
+    * This happens even when the lines are not currently
+    * visible and are shown afterwards.  The fix is to
+    * save the top index, scroll to the top of the table
+    * and then restore the original top index.
+    */
+    int newIndex = getTopIndex ();
+    if (newIndex !is 0) {
+        setRedraw (false);
+        setTopIndex (0);
+    }
+    if (show) {
+        int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+        if ((bits & OS.LVS_EX_GRIDLINES) !is 0) fixItemHeight (false);
+    }
+    setTopIndex (oldIndex);
+    if (newIndex !is 0) {
+        setRedraw (true);
+    }
+    updateHeaderToolTips ();
+}
+
+/**
+ * Sets the number of items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @exception SWTException <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.0
+ */
+public void setItemCount (int count) {
+    checkWidget ();
+    count = Math.max (0, count);
+    int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is itemCount) return;
+    setDeferResize (true);
+    bool isVirtual = (style & SWT.VIRTUAL) !is 0;
+    if (!isVirtual) setRedraw (false);
+    int index = count;
+    while (index < itemCount) {
+        TableItem item = items [index];
+        if (item !is null && !item.isDisposed ()) item.release (false);
+        if (!isVirtual) {
+            ignoreSelect = ignoreShrink = true;
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0);
+            ignoreSelect = ignoreShrink = false;
+            if (code is 0) break;
+        }
+        index++;
+    }
+    if (index < itemCount) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    int length = Math.max (4, (count + 3) / 4 * 4);
+    TableItem [] newItems = new TableItem [length];
+    System.arraycopy (items, 0, newItems, 0, Math.min (count, itemCount));
+    items = newItems;
+    if (isVirtual) {
+        int flags = OS.LVSICF_NOINVALIDATEALL | OS.LVSICF_NOSCROLL;
+        OS.SendMessage (handle, OS.LVM_SETITEMCOUNT, count, flags);
+        /*
+        * Bug in Windows.  When a virtual table contains items and
+        * LVM_SETITEMCOUNT is used to set the new item count to zero,
+        * Windows does not redraw the table.  Note that simply not
+        * specifying LVSICF_NOINVALIDATEALL or LVSICF_NOSCROLL does
+        * correct the problem.  The fix is to force a redraw.
+        */
+        if (count is 0 && itemCount !is 0) {
+            OS.InvalidateRect (handle, null, true);
+        }
+    } else {
+        for (int i=itemCount; i<count; i++) {
+            items [i] = new TableItem (this, SWT.NONE, i, true);
+        }
+    }
+    if (!isVirtual) setRedraw (true);
+    if (itemCount is 0) setScrollWidth (null, false);
+    setDeferResize (false);
+}
+
+void setItemHeight (bool fixScroll) {
+    /*
+    * Bug in Windows.  Making any change to an item that
+    * changes the item height of a table while the table
+    * is scrolled can cause the lines to draw incorrectly.
+    * This happens even when the lines are not currently
+    * visible and are shown afterwards.  The fix is to
+    * save the top index, scroll to the top of the table
+    * and then restore the original top index.
+    */
+    int topIndex = getTopIndex ();
+    if (fixScroll && topIndex !is 0) {
+        setRedraw (false);
+        setTopIndex (0);
+    }
+    if (itemHeight is -1) {
+        /*
+        * Feature in Windows.  Windows has no API to restore the
+        * defualt item height for a table.  The fix is to use
+        * WM_SETFONT which recomputes and assigns the default item
+        * height.
+        */
+        auto hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+    } else {
+        /*
+        * Feature in Windows.  Window has no API to set the item
+        * height for a table.  The fix is to set temporarily set
+        * LVS_OWNERDRAWFIXED then resize the table, causing a
+        * WM_MEASUREITEM to be sent, then clear LVS_OWNERDRAWFIXED.
+        */
+        forceResize ();
+        RECT rect;
+        OS.GetWindowRect (handle, &rect);
+        int width = rect.right - rect.left, height = rect.bottom - rect.top;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.LVS_OWNERDRAWFIXED);
+        int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+        ignoreResize = true;
+        SetWindowPos (handle, null , 0, 0, width, height + 1, flags);
+        SetWindowPos (handle, null , 0, 0, width, height, flags);
+        ignoreResize = false;
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    }
+    if (fixScroll && topIndex !is 0) {
+        setTopIndex (topIndex);
+        setRedraw (true);
+    }
+}
+
+/**
+ * Sets the height of the area which would be used to
+ * display <em>one</em> of the items in the table.
+ *
+ * @param itemHeight the height of one item
+ *
+ * @exception SWTException <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.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+    checkWidget ();
+    if (itemHeight < -1) error (SWT.ERROR_INVALID_ARGUMENT);
+    this.itemHeight = itemHeight;
+    setItemHeight (true);
+    setScrollWidth (null, true);
+}
+
+/**
+ * Marks the receiver's lines 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 show the new visibility state
+ *
+ * @exception SWTException <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 setLinesVisible (bool show) {
+    checkWidget ();
+    int newBits = show  ? OS.LVS_EX_GRIDLINES : 0;
+    OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_GRIDLINES, newBits);
+    if (show) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.LVS_NOCOLUMNHEADER) is 0) fixItemHeight (true);
+    }
+}
+
+override public void setRedraw (bool redraw) {
+    checkWidget ();
+    /*
+     * Feature in Windows.  When WM_SETREDRAW is used to turn
+     * off drawing in a widget, it clears the WS_VISIBLE bits
+     * and then sets them when redraw is turned back on.  This
+     * means that WM_SETREDRAW will make a widget unexpectedly
+     * visible.  The fix is to track the visibility state while
+     * drawing is turned off and restore it when drawing is turned
+     * back on.
+     */
+    if (drawCount is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.WS_VISIBLE) is 0) state |= HIDDEN;
+    }
+    if (redraw) {
+        if (--drawCount is 0) {
+            /*
+            * When many items are added to a table, it is faster to
+            * temporarily unsubclass the window proc so that messages
+            * are dispatched directly to the table.
+            *
+            * NOTE: This is optimization somewhat dangerous because any
+            * operation can occur when redraw is turned off, even operations
+            * where the table must be subclassed in order to have the correct
+            * behavior or work around a Windows bug.
+            *
+            * This code is intentionally commented.
+            */
+//          subclass ();
+
+            /* Set the width of the horizontal scroll bar */
+            setScrollWidth (null, true);
+
+            /*
+            * Bug in Windows.  For some reason, when WM_SETREDRAW is used
+            * to turn redraw back on this may result in a WM_SIZE.  If the
+            * table column widths are adjusted in WM_SIZE, blank lines may
+            * be inserted at the top of the widget.  A call to LVM_GETTOPINDEX
+            * will return a negative number (this is an impossible result).
+            * The fix is to send the resize notification after the size has
+            * been changed in the operating system.
+            */
+            setDeferResize (true);
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 1, 0);
+            if ((state & HIDDEN) !is 0) {
+                state &= ~HIDDEN;
+                OS.ShowWindow (handle, OS.SW_HIDE);
+            } else {
+                static if (OS.IsWinCE) {
+                    OS.InvalidateRect (handle, null, false);
+                    if (hwndHeader !is null) {
+                        OS.InvalidateRect (hwndHeader, null, false);
+                    }
+                } else {
+                    int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                    OS.RedrawWindow (handle, null, null, flags);
+                }
+            }
+            setDeferResize (false);
+        }
+    } else {
+        if (drawCount++ is 0) {
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.WM_SETREDRAW, 0, 0);
+
+            /*
+            * When many items are added to a table, it is faster to
+            * temporarily unsubclass the window proc so that messages
+            * are dispatched directly to the table.
+            *
+            * NOTE: This is optimization somewhat dangerous because any
+            * operation can occur when redraw is turned off, even operations
+            * where the table must be subclassed in order to have the correct
+            * behavior or work around a Windows bug.
+            *
+            * This code is intentionally commented.
+            */
+//          unsubclass ();
+        }
+    }
+}
+
+bool setScrollWidth (TableItem item, bool force) {
+    if (currentItem !is null) {
+        if (currentItem !is item) fixScrollWidth = true;
+        return false;
+    }
+    if (!force && (drawCount !is 0 || !OS.IsWindowVisible (handle))) {
+        fixScrollWidth = true;
+        return false;
+    }
+    fixScrollWidth = false;
+    /*
+    * NOTE: It is much faster to measure the strings and compute the
+    * width of the scroll bar in non-virtual table rather than using
+    * LVM_SETCOLUMNWIDTH with LVSCW_AUTOSIZE.
+    */
+    if (columnCount is 0) {
+        int newWidth = 0, imageIndent = 0, index = 0;
+        int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+        while (index < itemCount) {
+            String string = null;
+            HFONT hFont = cast(HFONT)-1;
+            if (item !is null) {
+                string = item.text;
+                imageIndent = Math.max (imageIndent, item.imageIndent);
+                hFont = item.fontHandle (0);
+            } else {
+                if (items [index] !is null) {
+                    TableItem tableItem = items [index];
+                    string = tableItem.text;
+                    imageIndent = Math.max (imageIndent, tableItem.imageIndent);
+                    hFont = tableItem.fontHandle (0);
+                }
+            }
+            if (string !is null && string.length !is 0) {
+                if (hFont !is cast(HFONT)-1) {
+                    auto hDC = OS.GetDC (handle);
+                    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;
+                    OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
+                    OS.SelectObject (hDC, oldFont);
+                    OS.ReleaseDC (handle, hDC);
+                    newWidth = Math.max (newWidth, rect.right - rect.left);
+                } else {
+                    TCHAR* buffer = StrToTCHARz (getCodePage (), string );
+                    newWidth = Math.max (newWidth, OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer));
+                }
+            }
+            if (item !is null) break;
+            index++;
+        }
+        /*
+        * Bug in Windows.  When the width of the first column is
+        * small but not zero, Windows draws '...' outside of the
+        * bounds of the text.  This is strange, but only causes
+        * problems when the item is selected.  In this case, Windows
+        * clears the '...' but doesn't redraw it when the item is
+        * deselected, causing pixel corruption.  The fix is to ensure
+        * that the column is at least wide enough to draw a single
+        * space.
+        */
+        if (newWidth is 0) {
+            TCHAR[] buffer = StrToTCHARs (getCodePage (), " ", true);
+            newWidth = Math.max (newWidth, OS.SendMessage (handle, OS.LVM_GETSTRINGWIDTH, 0, buffer.ptr));
+        }
+        auto hStateList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+        if (hStateList !is null) {
+            int cx, cy;
+            OS.ImageList_GetIconSize (hStateList, &cx, &cy);
+            newWidth += cx + INSET;
+        }
+        auto hImageList = cast(HANDLE) OS.SendMessage (handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+        if (hImageList !is null) {
+            int cx, cy;
+            OS.ImageList_GetIconSize (hImageList, &cx, &cy);
+            newWidth += (imageIndent + 1) * cx;
+        } else {
+            /*
+            * Bug in Windows.  When LVM_SETIMAGELIST is used to remove the
+            * image list by setting it to NULL, the item width and height
+            * is not changed and space is reserved for icons despite the
+            * fact that there are none.  The fix is to set the image list
+            * to be very small before setting it to NULL.  This causes
+            * Windows to reserve the smallest possible space when an image
+            * list is removed.  In this case, the scroll width must be one
+            * pixel larger.
+            */
+            newWidth++;
+        }
+        newWidth += INSET * 2;
+        int oldWidth = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            newWidth += VISTA_EXTRA;
+        }
+        if (newWidth > oldWidth) {
+            /*
+            * Feature in Windows.  When LVM_SETCOLUMNWIDTH is sent,
+            * Windows draws right away instead of queuing a WM_PAINT.
+            * This can cause recursive calls when called from paint
+            * or from messages that are retrieving the item data,
+            * such as WM_NOTIFY, causing a stack overflow.  The fix
+            * is to turn off redraw and queue a repaint, collapsing
+            * the recursive calls.
+            */
+            bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+            if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, newWidth);
+            if (redraw) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                static if (OS.IsWinCE) {
+                    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                    if (hwndHeader !is null) OS.InvalidateRect (hwndHeader, null, true);
+                    OS.InvalidateRect (handle, null, true);
+                } else {
+                    int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                    OS.RedrawWindow (handle, null, null, flags);
+                }
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * Selects the items at the given zero-relative indices in the receiver.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range and duplicate indices are ignored.
+ * If the receiver is single-select and multiple indices are specified,
+ * then all indices are ignored.
+ * </p>
+ *
+ * @param indices the indices of the items to select
+ *
+ * @exception SWTException <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 Table#deselectAll()
+ * @see Table#select(int[])
+ */
+public void setSelection (int [] indices) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (indices is null) error (SWT.ERROR_NULL_ARGUMENT);
+    deselectAll ();
+    int length = indices.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    select (indices);
+    int focusIndex = indices [0];
+    if (focusIndex !is -1) setFocusIndex (focusIndex);
+    showSelection ();
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected.
+ * <p>
+ * If the item is not in the receiver, then it is ignored.
+ * </p>
+ *
+ * @param item the item to select
+ *
+ * @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 SWTException <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.2
+ */
+public void setSelection (TableItem  item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSelection ([item]);
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ * </p>
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 Table#deselectAll()
+ * @see Table#select(int[])
+ * @see Table#setSelection(int[])
+ */
+public void setSelection (TableItem [] items) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    deselectAll ();
+    int length = items.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) return;
+    int focusIndex = -1;
+    for (int i=length-1; i>=0; --i) {
+        int index = indexOf (items [i]);
+        if (index !is -1) {
+            select (focusIndex = index);
+        }
+    }
+    if (focusIndex !is -1) setFocusIndex (focusIndex);
+    showSelection ();
+}
+
+/**
+ * Selects the item at the given zero-relative index in the receiver.
+ * The current selection is first cleared, then the new item is selected.
+ *
+ * @param index the index of the item to select
+ *
+ * @exception SWTException <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 Table#deselectAll()
+ * @see Table#select(int)
+ */
+public void setSelection (int index) {
+    checkWidget ();
+    deselectAll ();
+    select (index);
+    if (index !is -1) setFocusIndex (index);
+    showSelection ();
+}
+
+/**
+ * Selects the items in the range specified by the given zero-relative
+ * indices in the receiver. The range of indices is inclusive.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Indices that are out of range are ignored and no items will be selected
+ * if start is greater than end.
+ * If the receiver is single-select and there is more than one item in the
+ * given range, then all indices are ignored.
+ * </p>
+ *
+ * @param start the start index of the items to select
+ * @param end the end index of the items to select
+ *
+ * @exception SWTException <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 Table#deselectAll()
+ * @see Table#select(int,int)
+ */
+public void setSelection (int start, int end) {
+    checkWidget ();
+    deselectAll ();
+    if (end < 0 || start > end || ((style & SWT.SINGLE) !is 0 && start !is end)) return;
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is 0 || start >= count) return;
+    start = Math.max (0, start);
+    end = Math.min (end, count - 1);
+    select (start, end);
+    setFocusIndex (start);
+    showSelection ();
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator.  The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the column is disposed</li>
+ * </ul>
+ * @exception SWTException <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.2
+ */
+public void setSortColumn (TableColumn column) {
+    checkWidget ();
+    if (column !is null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        sortColumn.setSortDirection (SWT.NONE);
+    }
+    sortColumn = column;
+    if (sortColumn !is null && sortDirection !is SWT.NONE) {
+        sortColumn.setSortDirection (sortDirection);
+    }
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @exception SWTException <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.2
+ */
+public void setSortDirection (int direction) {
+    checkWidget ();
+    if ((direction & (SWT.UP | SWT.DOWN)) is 0 && direction !is SWT.NONE) return;
+    sortDirection = direction;
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        sortColumn.setSortDirection (direction);
+    }
+}
+
+void setSubImagesVisible (bool visible) {
+    int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if (((dwExStyle & OS.LVS_EX_SUBITEMIMAGES) !is 0 ) is visible) return;
+    int bits = visible ? OS.LVS_EX_SUBITEMIMAGES : 0;
+    OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_SUBITEMIMAGES, bits);
+}
+
+void setTableEmpty () {
+    if (imageList !is null) {
+        /*
+        * Bug in Windows.  When LVM_SETIMAGELIST is used to remove the
+        * image list by setting it to NULL, the item width and height
+        * is not changed and space is reserved for icons despite the
+        * fact that there are none.  The fix is to set the image list
+        * to be very small before setting it to NULL.  This causes
+        * Windows to reserve the smallest possible space when an image
+        * list is removed.
+        */
+        auto hImageList = OS.ImageList_Create (1, 1, 0, 0, 0);
+        OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, hImageList);
+        OS.SendMessage (handle, OS.LVM_SETIMAGELIST, OS.LVSIL_SMALL, 0);
+        if (headerImageList !is null) {
+            auto hHeaderImageList = headerImageList.getHandle ();
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hHeaderImageList);
+        }
+        OS.ImageList_Destroy (hImageList);
+        display.releaseImageList (imageList);
+        imageList = null;
+        if (itemHeight !is -1) setItemHeight (false);
+    }
+    if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        if (control.backgroundImage is null) {
+            setCustomDraw (false);
+            setBackgroundTransparent (false);
+            if (OS.COMCTL32_MAJOR < 6) style &= ~SWT.DOUBLE_BUFFERED;
+        }
+    }
+    items = new TableItem [4];
+    if (columnCount is 0) {
+        OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, 0);
+        setScrollWidth (null, false);
+    }
+}
+
+/**
+ * Sets the zero-relative index of the item which is currently
+ * at the top of the receiver. This index can change when items
+ * are scrolled or new items are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException <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 setTopIndex (int index) {
+    checkWidget ();
+    int topIndex = OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+    if (index is topIndex) return;
+
+    /*
+    * Bug in Windows.  For some reason, LVM_SCROLL refuses to
+    * scroll a table vertically when the width and height of
+    * the table is smaller than a certain size.  The values
+    * that seem to cause the problem are width=68 and height=6
+    * but there is no guarantee that these values cause the
+    * failure on different machines or on different versions
+    * of Windows.  It may depend on the font and any number
+    * of other factors.  For example, setting the font to
+    * anything but the default sometimes fixes the problem.
+    * The fix is to use LVM_GETCOUNTPERPAGE to detect the
+    * case when the number of visible items is zero and
+    * use LVM_ENSUREVISIBLE to scroll the table to make the
+    * index visible.
+    */
+
+    /*
+    * Bug in Windows.  When the table header is visible and
+    * there is not enough space to show a single table item,
+    * LVM_GETCOUNTPERPAGE can return a negative number instead
+    * of zero.  The fix is to test for negative or zero.
+    */
+    if (OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0) <= 0) {
+        /*
+        * Bug in Windows.  For some reason, LVM_ENSUREVISIBLE can
+        * scroll one item more or one item less when there is not
+        * enough space to show a single table item.  The fix is
+        * to detect the case and call LVM_ENSUREVISIBLE again with
+        * the same arguments.  It seems that once LVM_ENSUREVISIBLE
+        * has scrolled into the general area, it is able to scroll
+        * to the exact item.
+        */
+        OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+        if (index !is OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+            OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+        }
+        return;
+    }
+
+    /* Use LVM_SCROLL to scroll the table */
+    RECT rect;
+    rect.left = OS.LVIR_BOUNDS;
+    ignoreCustomDraw = true;
+    OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, &rect);
+    ignoreCustomDraw = false;
+    int dy = (index - topIndex) * (rect.bottom - rect.top);
+    OS.SendMessage (handle, OS.LVM_SCROLL, 0, dy);
+}
+
+/**
+ * Shows the column.  If the column is already showing in the receiver,
+ * this method simply returns.  Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the column has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void showColumn (TableColumn column) {
+    checkWidget ();
+    if (column is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    if (column.parent !is this) return;
+    int index = indexOf (column);
+    if (!(0 <= index && index < columnCount)) return;
+    /*
+    * Feature in Windows.  Calling LVM_GETSUBITEMRECT with -1 for the
+    * row number gives the bounds of the item that would be above the
+    * first row in the table.  This is undocumented and does not work
+    * for the first column. In this case, to get the bounds of the
+    * first column, get the bounds of the second column and subtract
+    * the width of the first. The left edge of the second column is
+    * also used as the right edge of the first.
+    */
+    RECT itemRect;
+    itemRect.left = OS.LVIR_BOUNDS;
+    if (index is 0) {
+        itemRect.top = 1;
+        ignoreCustomDraw = true;
+        OS.SendMessage (handle, OS.LVM_GETSUBITEMRECT, -1, &itemRect);
+        ignoreCustomDraw = false;
+        itemRect.right = itemRect.left;
+        int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+        itemRect.left = itemRect.right - width;
+    } else {
+        itemRect.top = index;
+        ignoreCustomDraw = true;
+        OS.SendMessage (handle, OS.LVM_GETSUBITEMRECT, -1, &itemRect);
+        ignoreCustomDraw = false;
+    }
+    /*
+    * Bug in Windows.  When a table that is drawing grid lines
+    * is slowly scrolled horizontally to the left, the table does
+    * not redraw the newly exposed vertical grid lines.  The fix
+    * is to save the old scroll position, call the window proc,
+    * get the new scroll position and redraw the new area.
+    */
+    int oldPos = 0;
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_POS;
+        OS.GetScrollInfo (handle, OS.SB_HORZ, &info);
+        oldPos = info.nPos;
+    }
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    if (itemRect.left < rect.left) {
+        int dx = itemRect.left - rect.left;
+        OS.SendMessage (handle, OS.LVM_SCROLL, dx, 0);
+    } else {
+        int width = Math.min (rect.right - rect.left, itemRect.right - itemRect.left);
+        if (itemRect.left + width > rect.right) {
+            int dx = itemRect.left + width - rect.right;
+            OS.SendMessage (handle, OS.LVM_SCROLL, dx, 0);
+        }
+    }
+    /*
+    * Bug in Windows.  When a table that is drawing grid lines
+    * is slowly scrolled horizontally to the left, the table does
+    * not redraw the newly exposed vertical grid lines.  The fix
+    * is to save the old scroll position, call the window proc,
+    * get the new scroll position and redraw the new area.
+    */
+    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_POS;
+        OS.GetScrollInfo (handle, OS.SB_HORZ, &info);
+        int newPos = info.nPos;
+        if (newPos < oldPos) {
+            rect.right = oldPos - newPos + GRID_WIDTH;
+            OS.InvalidateRect (handle, &rect, true);
+        }
+    }
+}
+
+void showItem (int index) {
+    /*
+    * Bug in Windows.  For some reason, when there is insufficient space
+    * to show an item, LVM_ENSUREVISIBLE causes blank lines to be
+    * inserted at the top of the widget.  A call to LVM_GETTOPINDEX will
+    * return a negative number (this is an impossible result).  The fix
+    * is to use LVM_GETCOUNTPERPAGE to detect the case when the number
+    * of visible items is zero and use LVM_ENSUREVISIBLE with the
+    * fPartialOK flag set to true to scroll the table.
+    */
+    if (OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0) <= 0) {
+        /*
+        * Bug in Windows.  For some reason, LVM_ENSUREVISIBLE can
+        * scroll one item more or one item less when there is not
+        * enough space to show a single table item.  The fix is
+        * to detect the case and call LVM_ENSUREVISIBLE again with
+        * the same arguments.  It seems that once LVM_ENSUREVISIBLE
+        * has scrolled into the general area, it is able to scroll
+        * to the exact item.
+        */
+        OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+        if (index !is OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0)) {
+            OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 1);
+        }
+    } else {
+        OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+    }
+}
+
+/**
+ * Shows the item.  If the item is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @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 SWTException <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 Table#showSelection()
+ */
+public void showItem (TableItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    int index = indexOf (item);
+    if (index !is -1) showItem (index);
+}
+
+/**
+ * Shows the selection.  If the selection is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException <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 Table#showItem(TableItem)
+ */
+public void showSelection () {
+    checkWidget ();
+    int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_SELECTED);
+    if (index !is -1) showItem (index);
+}
+
+/*public*/ void sort () {
+    checkWidget ();
+//  if ((style & SWT.VIRTUAL) !is 0) return;
+//  int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+//  if (itemCount is 0 || itemCount is 1) return;
+//  Comparator comparator = new Comparator () {
+//      int index = sortColumn is null ? 0 : indexOf (sortColumn);
+//      public int compare (Object object1, Object object2) {
+//          TableItem item1 = (TableItem) object1, item2 = (TableItem) object2;
+//          if (sortDirection is SWT.UP || sortDirection is SWT.NONE) {
+//              return item1.getText (index).compareTo (item2.getText (index));
+//          } else {
+//              return item2.getText (index).compareTo (item1.getText (index));
+//          }
+//      }
+//  };
+//  Arrays.sort (items, 0, itemCount, comparator);
+//  redraw ();
+}
+
+override void subclass () {
+    super.subclass ();
+    if (HeaderProc !is null) {
+        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        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) {
+    auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+    if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$
+    if (headerToolTipHandle is hdr.hdr.hwndFrom) {
+        for (int i=0; i<columnCount; i++) {
+            TableColumn column = columns [i];
+            if (column.id is hdr.hdr.idFrom) return column.toolTipText;
+        }
+    }
+    return super.toolTipText (hdr);
+}
+
+override void unsubclass () {
+    super.unsubclass ();
+    if (HeaderProc !is null) {
+        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
+    }
+}
+
+override void update (bool all) {
+//  checkWidget ();
+    /*
+    * 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.
+    *
+    * NOTE: The header tooltip can subclass the header proc so the
+    * current proc must be restored or header tooltips stop working.
+    */
+    WNDPROC oldHeaderProc, oldTableProc;
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    bool fixSubclass = isOptimizedRedraw ();
+    if (fixSubclass) {
+        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.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
+    }
+}
+
+void updateHeaderToolTips () {
+    if (headerToolTipHandle is null) return;
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    RECT rect;
+    TOOLINFO lpti;
+    lpti.cbSize = OS.TOOLINFO_sizeof;
+    lpti.uFlags = OS.TTF_SUBCLASS;
+    lpti.hwnd = hwndHeader;
+    lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+    for (int i=0; i<columnCount; i++) {
+        TableColumn column = columns [i];
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &rect) !is 0) {
+            lpti.uId = column.id = display.nextToolTipId++;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, &lpti);
+        }
+    }
+}
+
+override void updateImages () {
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        if (OS.COMCTL32_MAJOR < 6) {
+            switch (sortDirection) {
+                case SWT.UP:
+                case SWT.DOWN:
+                    sortColumn.setImage (display.getSortImage (sortDirection), true, true);
+                    break;
+                default:
+            }
+        }
+    }
+}
+
+void updateMoveable () {
+    int index = 0;
+    while (index < columnCount) {
+        if (columns [index].moveable) break;
+        index++;
+    }
+    int newBits = index < columnCount ? OS.LVS_EX_HEADERDRAGDROP : 0;
+    OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_HEADERDRAGDROP, newBits);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.LVS_SHAREIMAGELISTS;
+    if ((style & SWT.HIDE_SELECTION) is 0) bits |= OS.LVS_SHOWSELALWAYS;
+    if ((style & SWT.SINGLE) !is 0) bits |= OS.LVS_SINGLESEL;
+    /*
+    * This code is intentionally commented.  In the future,
+    * the FLAT bit may be used to make the header flat and
+    * unresponsive to mouse clicks.
+    */
+//  if ((style & SWT.FLAT) !is 0) bits |= OS.LVS_NOSORTHEADER;
+    bits |= OS.LVS_REPORT | OS.LVS_NOCOLUMNHEADER;
+    if ((style & SWT.VIRTUAL) !is 0) bits |= OS.LVS_OWNERDATA;
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARsToStr( TableClass );
+}
+
+override int windowProc () {
+    return cast(int) TableProc;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwnd !is handle) {
+        switch (msg) {
+            /* This code is intentionally commented */
+//          case OS.WM_CONTEXTMENU: {
+//              LRESULT result = wmContextMenu (hwnd, wParam, lParam);
+//              if (result !is null) return result.value;
+//              break;
+//          }
+            case OS.WM_CAPTURECHANGED: {
+                /*
+                * Bug in Windows.  When the capture changes during a
+                * header drag, Windows does not redraw the header item
+                * such that the header remains pressed.  For example,
+                * when focus is assigned to a push button, the mouse is
+                * pressed (but not released), then the SPACE key is
+                * pressed to activate the button, the capture changes,
+                * the header not notified and NM_RELEASEDCAPTURE is not
+                * sent.  The fix is to redraw the header when the capture
+                * changes to another control.
+                *
+                * This does not happen on XP.
+                */
+                if (OS.COMCTL32_MAJOR < 6) {
+                    if (lParam !is 0) {
+                        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                        if (lParam !is cast(int)hwndHeader) OS.InvalidateRect (hwndHeader, null, true);
+                    }
+                }
+                break;
+            }
+            case OS.WM_MOUSELEAVE: {
+                /*
+                * Bug in Windows.  On XP, when a tooltip is hidden
+                * due to a time out or mouse press, the tooltip
+                * remains active although no longer visible and
+                * won't show again until another tooltip becomes
+                * active.  The fix is to reset the tooltip bounds.
+                */
+                if (OS.COMCTL32_MAJOR >= 6) updateHeaderToolTips ();
+                updateHeaderToolTips ();
+                break;
+            }
+            case OS.WM_NOTIFY: {
+                NMHDR* hdr = cast(NMHDR*)lParam;
+                //OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+                switch (hdr.code) {
+                    case OS.TTN_SHOW:
+                    case OS.TTN_POP:
+                    case OS.TTN_GETDISPINFOA:
+                    case OS.TTN_GETDISPINFOW:
+                        return OS.SendMessage (handle, msg, wParam, lParam);
+                    default:
+                }
+                break;
+            }
+            case OS.WM_SETCURSOR: {
+                if (wParam is cast(int)hwnd) {
+                    int hitTest = cast(short) OS.LOWORD (lParam);
+                    if (hitTest is OS.HTCLIENT) {
+                        HDHITTESTINFO pinfo;
+                        int pos = OS.GetMessagePos ();
+                        POINT pt;
+                        OS.POINTSTOPOINT (pt, pos);
+                        OS.ScreenToClient (hwnd, &pt);
+                        pinfo.pt.x = pt.x;
+                        pinfo.pt.y = pt.y;
+                        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 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) {
+                                OS.SetCursor (OS.LoadCursor (null, cast(TCHAR*)OS.IDC_ARROW));
+                                return 1;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+        }
+        return callWindowProc (hwnd, msg, wParam, lParam);
+    }
+    if (msg is Display.DI_GETDRAGIMAGE) {
+        /*
+        * Bug in Windows.  On Vista, for some reason, DI_GETDRAGIMAGE
+        * returns an image that does not contain strings.
+        *
+        * Bug in Windows. For custom draw control the window origin the 
+        * in HDC is wrong.
+        * 
+        * The fix for both cases is to create the image using PrintWindow(). 
+        */
+        if ((!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) || (style & SWT.VIRTUAL) !is 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+            int topIndex = OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0);
+            int selection = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, topIndex - 1, OS.LVNI_SELECTED);
+            if (selection is -1) return 0;
+            POINT mousePos;
+            OS.POINTSTOPOINT (mousePos, OS.GetMessagePos ());
+            OS.MapWindowPoints(null, handle, &mousePos, 1);
+            RECT clientRect;
+            OS.GetClientRect (handle, &clientRect);
+            TableItem item = _getItem (selection);
+            RECT rect = item.getBounds (selection, 0, true, true, true);
+            if ((style & SWT.FULL_SELECTION) !is 0) {
+                int width = DRAG_IMAGE_SIZE;
+                rect.left = Math.max (clientRect.left, mousePos.x - width / 2);
+                if (clientRect.right > rect.left + width) {
+                    rect.right = rect.left + width;
+                } else {
+                    rect.right = clientRect.right;
+                    rect.left = Math.max (clientRect.left, rect.right - width);
+                }
+            }
+            auto hRgn = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+            while ((selection = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, selection, OS.LVNI_SELECTED)) !is -1) {
+                if (rect.bottom - rect.top > DRAG_IMAGE_SIZE) break;
+                if (rect.bottom > clientRect.bottom) break;
+                RECT itemRect = item.getBounds (selection, 0, true, true, true);
+                auto rectRgn = OS.CreateRectRgn (rect.left, itemRect.top, rect.right, itemRect.bottom);
+                OS.CombineRgn (hRgn, hRgn, rectRgn, OS.RGN_OR);
+                OS.DeleteObject (rectRgn);
+                rect.bottom = itemRect.bottom;
+            }
+            OS.GetRgnBox (hRgn, &rect);
+            
+            /* Create resources */
+            auto hdc = OS.GetDC (handle);
+            auto memHdc = OS.CreateCompatibleDC (hdc);
+            BITMAPINFOHEADER bmiHeader;
+            bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+            bmiHeader.biWidth = rect.right - rect.left;
+            bmiHeader.biHeight = -(rect.bottom - rect.top);
+            bmiHeader.biPlanes = 1;
+            bmiHeader.biBitCount = 32;
+            bmiHeader.biCompression = OS.BI_RGB;
+            byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+            OS.MoveMemory (bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+            void*[1] pBits;
+            auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*) bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+            if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+            auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+            int colorKey = 0x0000FD;
+            POINT pt;
+            OS.SetWindowOrgEx (memHdc, rect.left, rect.top, &pt);
+            OS.FillRect (memHdc, &rect, findBrush (colorKey, OS.BS_SOLID));
+            OS.OffsetRgn (hRgn, -rect.left, -rect.top);
+            OS.SelectClipRgn (memHdc, hRgn);
+            OS.PrintWindow (handle, memHdc, 0);
+            OS.SetWindowOrgEx (memHdc, pt.x, pt.y, null);
+            OS.SelectObject (memHdc, oldMemBitmap);
+            OS.DeleteDC (memHdc);
+            OS.ReleaseDC (null, hdc);
+            OS.DeleteObject (hRgn);
+            
+            SHDRAGIMAGE shdi;
+            shdi.hbmpDragImage = memDib;
+            shdi.crColorKey = colorKey;
+            shdi.sizeDragImage.cx = bmiHeader.biWidth;
+            shdi.sizeDragImage.cy = -bmiHeader.biHeight;
+            shdi.ptOffset.x = mousePos.x - rect.left;
+            shdi.ptOffset.y = mousePos.y - rect.top;
+            if ((style & SWT.MIRRORED) !is 0) {
+                shdi.ptOffset.x = shdi.sizeDragImage.cx - shdi.ptOffset.x; 
+            }
+            OS.MoveMemory (cast(void*)lParam, &shdi, SHDRAGIMAGE.sizeof);
+            return 1;
+        }
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+    switch (wParam) {
+        case ' ':
+            if ((style & SWT.CHECK) !is 0) {
+                int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+                if (index !is -1) {
+                    TableItem item = _getItem (index);
+                    item.setChecked (!item.getChecked (), true);
+                    static if (!OS.IsWinCE) {
+                        OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+                    }
+                }
+            }
+            /*
+            * NOTE: Call the window proc with WM_KEYDOWN rather than WM_CHAR
+            * so that the key that was ignored during WM_KEYDOWN is processed.
+            * This allows the application to cancel an operation that is normally
+            * performed in WM_KEYDOWN from WM_CHAR.
+            */
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            return new LRESULT (code);
+        case SWT.CR:
+            /*
+            * Feature in Windows.  Windows sends LVN_ITEMACTIVATE from WM_KEYDOWN
+            * instead of WM_CHAR.  This means that application code that expects
+            * to consume the key press and therefore avoid a SWT.DefaultSelection
+            * event will fail.  The fix is to ignore LVN_ITEMACTIVATE when it is
+            * caused by WM_KEYDOWN and send SWT.DefaultSelection from WM_CHAR.
+            */
+            int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+            if (index !is -1) {
+                Event event = new Event ();
+                event.item = _getItem (index);
+                postEvent (SWT.DefaultSelection, event);
+            }
+            return LRESULT.ZERO;
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_CONTEXTMENU (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  For some reason, when the right
+    * mouse button is pressed over an item, Windows sends
+    * a WM_CONTEXTMENU from WM_RBUTTONDOWN, instead of from
+    * WM_RBUTTONUP.  This causes two context menus requests
+    * to be sent.  The fix is to ignore WM_CONTEXTMENU on
+    * mouse down.
+    *
+    * NOTE: This only happens when dragging is disabled.
+    * When the table is detecting drag, the WM_CONTEXTMENU
+    * is not sent WM_RBUTTONUP.
+    */
+    if (!display.runDragDrop) return LRESULT.ZERO;
+    return super.WM_CONTEXTMENU (wParam, lParam);
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if (findImageControl () !is null) return LRESULT.ONE;
+    if (OS.COMCTL32_MAJOR < 6) {
+        if ((style & SWT.DOUBLE_BUFFERED) !is 0) {
+            int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+            if ((bits & OS.LVS_EX_DOUBLEBUFFER) is 0) return LRESULT.ONE;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_GETOBJECT (int wParam, int lParam) {
+    /*
+    * Ensure that there is an accessible object created for this
+    * control because support for checked item accessibility is
+    * temporarily implemented in the accessibility package.
+    */
+    if ((style & SWT.CHECK) !is 0) {
+        if (accessible is null) accessible = new_Accessible (this);
+    }
+    return super.WM_GETOBJECT (wParam, lParam);
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    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_ADD:
+            if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                int index = 0;
+                while (index < columnCount) {
+                    if (!columns [index].getResizable ()) break;
+                    index++;
+                }
+                if (index !is columnCount || hooks (SWT.MeasureItem)) {
+                    TableColumn [] newColumns = new TableColumn [columnCount];
+                    System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                    for (int i=0; i<newColumns.length; i++) {
+                        TableColumn column = newColumns [i];
+                        if (!column.isDisposed () && column.getResizable ()) {
+                            column.pack ();
+                        }
+                    }
+                    return LRESULT.ZERO;
+                }
+            }
+            break;
+        case OS.VK_PRIOR:
+        case OS.VK_NEXT:
+        case OS.VK_HOME:
+        case OS.VK_END:
+            /*
+            * 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, the window
+            * proc cannot be unsubclassed or the event will not be seen.
+            *
+            * NOTE: The header tooltip can subclass the header proc so the
+            * current proc must be restored or header tooltips stop working.
+            */
+            int /*long*/ oldHeaderProc = 0, oldTableProc = 0;
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            bool fixSubclass = isOptimizedRedraw ();
+            if (fixSubclass) {
+                oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc);
+                oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
+            }
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            result = code is 0 ? LRESULT.ZERO : new LRESULT (code);
+            if (fixSubclass) {
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc);
+                OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, oldHeaderProc);
+            }
+            //FALL THROUGH
+        case OS.VK_UP:
+        case OS.VK_DOWN:
+            OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            break;
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
+    /*
+    * Bug in Windows.  When focus is lost, Windows does not
+    * redraw the selection properly, leaving the image and
+    * check box appearing selected.  The fix is to redraw
+    * the table.
+    */
+    if (imageList !is null || (style & SWT.CHECK) !is 0) {
+        OS.InvalidateRect (handle, null, false);
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+
+    /*
+    * Feature in Windows.  When the user selects outside of
+    * a table item, Windows deselects all the items, even
+    * when the table is multi-select.  While not strictly
+    * wrong, this is unexpected.  The fix is to detect the
+    * case and avoid calling the window proc.
+    */
+    LVHITTESTINFO pinfo;
+    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;
+    sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (!sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+        return LRESULT.ZERO;
+    }
+    if (pinfo.iItem !is -1) callWindowProc (handle, OS.WM_LBUTTONDBLCLK, wParam, lParam);
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+    }
+
+    /* Look for check/uncheck */
+    if ((style & SWT.CHECK) !is 0) {
+        /*
+        * Note that when the table has LVS_EX_FULLROWSELECT and the
+        * user clicks anywhere on a row except on the check box, all
+        * of the bits are set.  The hit test flags are LVHT_ONITEM.
+        * This means that a bit test for LVHT_ONITEMSTATEICON is not
+        * the correct way to determine that the user has selected
+        * the check box, equality is needed.
+        */
+        if (index !is -1 && pinfo.flags is OS.LVHT_ONITEMSTATEICON) {
+            TableItem item = _getItem (index);
+            item.setChecked (!item.getChecked (), true);
+            static if (!OS.IsWinCE) {
+                OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+            }
+        }
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  For some reason, capturing
+    * the mouse after processing the mouse event for the
+    * widget interferes with the normal mouse processing
+    * for the widget.  The fix is to avoid the automatic
+    * mouse capture.
+    */
+    LRESULT result = sendMouseDownEvent (SWT.MouseDown, 1, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+
+    /* Look for check/uncheck */
+    if ((style & SWT.CHECK) !is 0) {
+        LVHITTESTINFO pinfo;
+        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
+        * of the bits are set.  The hit test flags are LVHT_ONITEM.
+        * This means that a bit test for LVHT_ONITEMSTATEICON is not
+        * the correct way to determine that the user has selected
+        * the check box, equality is needed.
+        */
+        int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
+        if (index !is -1 && pinfo.flags is OS.LVHT_ONITEMSTATEICON) {
+            TableItem item = _getItem (index);
+            item.setChecked (!item.getChecked (), true);
+            static if (!OS.IsWinCE) {
+                OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, index + 1);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_MOUSEHOVER (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  Despite the fact that hot
+    * tracking is not enabled, the hot tracking code
+    * in WM_MOUSEHOVER is executed causing the item
+    * under the cursor to be selected.  The fix is to
+    * avoid calling the window proc.
+    */
+    LRESULT result = super.WM_MOUSEHOVER (wParam, lParam);
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    int mask = OS.LVS_EX_ONECLICKACTIVATE | OS.LVS_EX_TRACKSELECT | OS.LVS_EX_TWOCLICKACTIVATE;
+    if ((bits & mask) !is 0) return result;
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    if (!ignoreShrink) {
+        /* Resize the item array to match the item count */
+        int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+        if (items.length > 4 && items.length - count > 3) {
+            int length = Math.max (4, (count + 3) / 4 * 4);
+            TableItem [] newItems = new TableItem [length];
+            System.arraycopy (items, 0, newItems, 0, count);
+            items = newItems;
+        }
+    }
+    if (fixScrollWidth) setScrollWidth (null, true);
+    if (OS.COMCTL32_MAJOR < 6) {
+        if ((style & SWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) {
+            int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+            if ((bits & OS.LVS_EX_DOUBLEBUFFER) is 0) {
+                GC gc = null;
+                HDC paintDC;
+                PAINTSTRUCT ps;
+                bool hooksPaint = hooks (SWT.Paint);
+                if (hooksPaint) {
+                    GCData data = new GCData ();
+                    data.ps = &ps;
+                    data.hwnd = handle;
+                    gc = GC.win32_new (this, data);
+                    paintDC = gc.handle;
+                } else {
+                    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);
+                    if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) {
+                        RECT rect;
+                        OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+                        drawBackground (hDC, &rect);
+                    }
+                    callWindowProc (handle, OS.WM_PAINT, cast(int) hDC, 0);
+                    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);
+                    if (hooksPaint) {
+                        Event event = new Event ();
+                        event.gc = gc;
+                        event.x = ps.rcPaint.left;
+                        event.y = ps.rcPaint.top;
+                        event.width = ps.rcPaint.right - ps.rcPaint.left;
+                        event.height = ps.rcPaint.bottom - ps.rcPaint.top;
+                        sendEvent (SWT.Paint, event);
+                        // widget could be disposed at this point
+                        event.gc = null;
+                    }
+                }
+                if (hooksPaint) {
+                    gc.dispose ();
+                } else {
+                    OS.EndPaint (handle, &ps);
+                }
+                return LRESULT.ZERO;
+            }
+        }
+    }
+    return super.WM_PAINT (wParam, lParam);
+}
+
+override LRESULT WM_RBUTTONDBLCLK (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the user selects outside of
+    * a table item, Windows deselects all the items, even
+    * when the table is multi-select.  While not strictly
+    * wrong, this is unexpected.  The fix is to detect the
+    * case and avoid calling the window proc.
+    */
+    LVHITTESTINFO pinfo;
+    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;
+    sendMouseEvent (SWT.MouseDown, 3, handle, OS.WM_RBUTTONDOWN, wParam, lParam);
+    if (sendMouseEvent (SWT.MouseDoubleClick, 3, handle, OS.WM_RBUTTONDBLCLK, wParam, lParam)) {
+        if (pinfo.iItem !is -1) callWindowProc (handle, OS.WM_RBUTTONDBLCLK, wParam, lParam);
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_RBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  For some reason, capturing
+    * the mouse after processing the mouse event for the
+    * widget interferes with the normal mouse processing
+    * for the widget.  The fix is to avoid the automatic
+    * mouse capture.
+    */
+    return sendMouseDownEvent (SWT.MouseDown, 3, OS.WM_RBUTTONDOWN, wParam, lParam);
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    /*
+    * Bug in Windows.  When focus is gained after the
+    * selection has been changed using LVM_SETITEMSTATE,
+    * Windows redraws the selected text but does not
+    * redraw the image or the check box, leaving them
+    * appearing unselected.  The fix is to redraw
+    * the table.
+    */
+    if (imageList !is null || (style & SWT.CHECK) !is 0) {
+        OS.InvalidateRect (handle, null, false);
+    }
+
+    /*
+    * Bug in Windows.  For some reason, the table does
+    * not set the default focus rectangle to be the first
+    * item in the table when it gets focus and there is
+    * no selected item.  The fix to make the first item
+    * be the focus item.
+    */
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is 0) return result;
+    int index = OS.SendMessage (handle, OS.LVM_GETNEXTITEM, -1, OS.LVNI_FOCUSED);
+    if (index is -1) {
+        LVITEM lvItem;
+        lvItem.state = OS.LVIS_FOCUSED;
+        lvItem.stateMask = OS.LVIS_FOCUSED;
+        ignoreSelect = true;
+        OS.SendMessage (handle, OS.LVM_SETITEMSTATE, 0, &lvItem);
+        ignoreSelect = false;
+    }
+    return result;
+}
+
+override LRESULT WM_SETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFONT (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Bug in Windows.  When a header has a sort indicator
+    * triangle, Windows resizes the indicator based on the
+    * size of the n-1th font.  The fix is to always make
+    * the n-1th font be the default.  This makes the sort
+    * indicator always be the default size.
+    *
+    * NOTE: The table window proc sets the actual font in
+    * the header so that all that is necessary here is to
+    * set the default first.
+    */
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    OS.SendMessage (hwndHeader, OS.WM_SETFONT, 0, lParam);
+
+    if (headerToolTipHandle !is null) {
+        OS.SendMessage (headerToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+    }
+    return result;
+}
+
+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 (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.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 (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+        OS.InvalidateRect (handle, null, true);
+    }
+    if (resizeCount !is 0) {
+        wasResized = true;
+        return null;
+    }
+    return super.WM_SIZE (wParam, lParam);
+}
+
+override LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    if (findBackgroundControl () is null) {
+        setBackgroundPixel (defaultBackground ());
+    } else {
+        int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+        if (oldPixel !is OS.CLR_NONE) {
+            if (findImageControl () is null) {
+                if ((style & SWT.CHECK) !is 0) fixCheckboxImageListColor (true);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_HSCROLL (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When a table that is drawing grid lines
+    * is slowly scrolled horizontally to the left, the table does
+    * not redraw the newly exposed vertical grid lines.  The fix
+    * is to save the old scroll position, call the window proc,
+    * get the new scroll position and redraw the new area.
+    */
+    int oldPos = 0;
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_POS;
+        OS.GetScrollInfo (handle, OS.SB_HORZ, &info);
+        oldPos = info.nPos;
+    }
+
+    /*
+    * 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.
+    */
+    WNDPROC oldHeaderProc, oldTableProc;
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    bool fixSubclass = isOptimizedRedraw ();
+    if (fixSubclass) {
+        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.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
+    }
+
+    /*
+    * Bug in Windows.  When a table that is drawing grid lines
+    * is slowly scrolled horizontally to the left, the table does
+    * not redraw the newly exposed vertical grid lines.  The fix
+    * is to save the old scroll position, call the window proc,
+    * get the new scroll position and redraw the new area.
+    */
+    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+        SCROLLINFO info;
+        info.cbSize = SCROLLINFO.sizeof;
+        info.fMask = OS.SIF_POS;
+        OS.GetScrollInfo (handle, OS.SB_HORZ, &info);
+        int newPos = info.nPos;
+        if (newPos < oldPos) {
+            RECT rect;
+            OS.GetClientRect (handle, &rect);
+            rect.right = oldPos - newPos + GRID_WIDTH;
+            OS.InvalidateRect (handle, &rect, true);
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_VSCROLL (int wParam, int lParam) {
+    /*
+    * 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.
+    *
+    * NOTE: The header tooltip can subclass the header proc so the
+    * current proc must be restored or header tooltips stop working.
+    */
+    WNDPROC oldHeaderProc, oldTableProc;
+    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    bool fixSubclass = isOptimizedRedraw ();
+    if (fixSubclass) {
+        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.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
+    }
+
+    /*
+    * Bug in Windows.  When a table is drawing grid lines and the
+    * user scrolls vertically up or down by a line or a page, the
+    * table does not redraw the grid lines for newly exposed items.
+    * The fix is to invalidate the items.
+    */
+    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+        int code = OS.LOWORD (wParam);
+        switch (code) {
+            case OS.SB_ENDSCROLL:
+            case OS.SB_THUMBPOSITION:
+            case OS.SB_THUMBTRACK:
+            case OS.SB_TOP:
+            case OS.SB_BOTTOM:
+                break;
+            case OS.SB_LINEDOWN:
+            case OS.SB_LINEUP:
+                RECT rect;
+                OS.GetWindowRect (hwndHeader, &rect);
+                int headerHeight = rect.bottom - rect.top;
+                RECT clientRect;
+                OS.GetClientRect (handle, &clientRect);
+                clientRect.top += headerHeight;
+                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 {
+                    clientRect.bottom = clientRect.top + itemHeight + GRID_WIDTH;
+                }
+                OS.InvalidateRect (handle, &clientRect, true);
+                break;
+            case OS.SB_PAGEDOWN:
+            case OS.SB_PAGEUP:
+                OS.InvalidateRect (handle, null, true);
+                break;
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT wmMeasureChild (int wParam, int lParam) {
+    MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;
+    //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof);
+    if (itemHeight is -1) {
+        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;
+    }
+    //OS.MoveMemory (lParam, struct_, MEASUREITEMSTRUCT.sizeof);
+    return null;
+}
+
+override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
+    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) {
+        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) {
+    switch (hdr.code) {
+        case OS.LVN_ODFINDITEMA:
+        case OS.LVN_ODFINDITEMW: {
+            if ((style & SWT.VIRTUAL) !is 0) return new LRESULT (-1);
+            break;
+        }
+        case OS.LVN_ODSTATECHANGED: {
+            if ((style & SWT.VIRTUAL) !is 0) {
+                if (!ignoreSelect) {
+                    NMLVODSTATECHANGE* lpStateChange  = cast(NMLVODSTATECHANGE*)lParam;
+                    //OS.MoveMemory (lpStateChange, lParam, NMLVODSTATECHANGE.sizeof);
+                    bool oldSelected = (lpStateChange.uOldState & OS.LVIS_SELECTED) !is 0;
+                    bool newSelected = (lpStateChange.uNewState & OS.LVIS_SELECTED) !is 0;
+                    if (oldSelected !is newSelected) wasSelected = true;
+                }
+            }
+            break;
+        }
+        case OS.LVN_GETDISPINFOA:
+        case OS.LVN_GETDISPINFOW: {
+//          if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break;
+            NMLVDISPINFO* plvfi = cast(NMLVDISPINFO*)lParam;
+            //OS.MoveMemory (plvfi, lParam, OS.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
+            * becomes visible until the item has been removed from the
+            * items array.  Because arbitrary application code can run
+            * during the callback, the items array might be accessed
+            * in an inconsistent state.  Rather than answering the data
+            * right away, queue a redraw for later.
+            */
+            if ((style & SWT.VIRTUAL) !is 0) {
+                if (ignoreShrink) {
+                    OS.SendMessage (handle, OS.LVM_REDRAWITEMS, plvfi.item.iItem, plvfi.item.iItem);
+                    break;
+                }
+            }
+
+            /*
+            * Feature in Windows.  When a new table item is inserted
+            * using LVM_INSERTITEM in a table that is transparent
+            * (ie. LVM_SETBKCOLOR has been called with CLR_NONE),
+            * TVM_INSERTITEM calls LVN_GETDISPINFO before the item
+            * has been added to the array.  The fix is to check for
+            * null.
+            */
+            TableItem item = _getItem (plvfi.item.iItem);
+            if (item is null) break;
+
+            /*
+            * The cached flag is used by both virtual and non-virtual
+            * tables to indicate that Windows has asked at least once
+            * for a table item.
+            */
+            if (!item.cached) {
+                if ((style & SWT.VIRTUAL) !is 0) {
+                    lastIndexOf = plvfi.item.iItem;
+                    if (!checkData (item, lastIndexOf, false)) break;
+                    TableItem newItem = fixScrollWidth ? null : item;
+                    if (setScrollWidth (newItem, true)) {
+                        OS.InvalidateRect (handle, null, true);
+                    }
+                }
+                item.cached = true;
+            }
+            if ((plvfi.item.mask & OS.LVIF_TEXT) !is 0) {
+                String string = null;
+                if (plvfi.item.iSubItem is 0) {
+                    string = item.text;
+                } else {
+                    String [] strings  = item.strings;
+                    if (strings !is null) string = strings [plvfi.item.iSubItem];
+                }
+                if (string !is null) {
+                    /*
+                    * Bug in Windows.  When pszText points to a zero length
+                    * NULL terminated string, Windows correctly draws the
+                    * empty string but the cache of the bounds for the item
+                    * is not reset.  This means that when the text for the
+                    * item is set and then reset to an empty string, the
+                    * selection draws using the bounds of the previous text.
+                    * The fix is to use a space rather than an empty string
+                    * when anything but a tool tip is requested (to avoid
+                    * a tool tip that is a single space).
+                    *
+                    * NOTE: This is only a problem for items in the first
+                    * column.  Assigning NULL to other columns stops Windows
+                    * from drawing the selection when LVS_EX_FULLROWSELECT
+                    * is set.
+                    */
+                    int length_ = Math.min (string.length, plvfi.item.cchTextMax - 1);
+                    if (!tipRequested && plvfi.item.iSubItem is 0 && length_ is 0) {
+                        string = " "; //$NON-NLS-1$
+                        length_ = 1;
+                    }
+                    char [] buffer = display.tableBuffer;
+                    if (buffer is null || plvfi.item.cchTextMax > buffer.length) {
+                        buffer = display.tableBuffer = new char [plvfi.item.cchTextMax];
+                    }
+                    string.getChars (0, length_, buffer, 0);
+                    buffer [length_++] = 0;
+                    static if (OS.IsUnicode) {
+                        OS.MoveMemory (plvfi.item.pszText, StrToTCHARz( buffer[0..length_] ), length_ * 2);
+                    } else {
+                        OS.WideCharToMultiByte (getCodePage (), 0, buffer.ptr, length_, plvfi.item.pszText, plvfi.item.cchTextMax, null, null);
+                        byte dummy;
+                        OS.MoveMemory (plvfi.item.pszText + plvfi.item.cchTextMax - 1, &dummy, 1);
+                    }
+                }
+            }
+            bool move = false;
+            if ((plvfi.item.mask & OS.LVIF_IMAGE) !is 0) {
+                Image image = null;
+                if (plvfi.item.iSubItem is 0) {
+                    image = item.image;
+                } else {
+                    Image [] images = item.images;
+                    if (images !is null) image = images [plvfi.item.iSubItem];
+                }
+                if (image !is null) {
+                    plvfi.item.iImage = imageIndex (image, plvfi.item.iSubItem);
+                    move = true;
+                }
+            }
+            if ((plvfi.item.mask & OS.LVIF_STATE) !is 0) {
+                if (plvfi.item.iSubItem is 0) {
+                    int state = 1;
+                    if (item.checked) state++;
+                    if (item.grayed) state +=2;
+                    plvfi.item.state = state << 12;
+                    plvfi.item.stateMask = OS.LVIS_STATEIMAGEMASK;
+                    move = true;
+                }
+            }
+            if ((plvfi.item.mask & OS.LVIF_INDENT) !is 0) {
+                if (plvfi.item.iSubItem is 0) {
+                    plvfi.item.iIndent = item.imageIndent;
+                    move = true;
+                }
+            }
+            //if (move) OS.MoveMemory (lParam, plvfi, OS.NMLVDISPINFO_sizeof);
+            break;
+        }
+        case OS.NM_CUSTOMDRAW: {
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            if (hdr.hwndFrom is hwndHeader) break;
+            if (!customDraw && findImageControl () is null) {
+                /*
+                * Feature in Windows.  When the table is disabled, it draws
+                * with a gray background but does not gray the text.  The fix
+                * is to explicitly gray the text using Custom Draw.
+                */
+                if (OS.IsWindowEnabled (handle)) {
+                    /*
+                    * Feature in Windows.  On Vista using the explorer theme,
+                    * Windows draws a vertical line to separate columns.  When
+                    * there is only a single column, the line looks strange.
+                    * The fix is to draw the background using custom draw.
+                    */
+                    if (!explorerTheme || columnCount !is 0) break;
+                }
+            }
+            NMLVCUSTOMDRAW* nmcd = cast(NMLVCUSTOMDRAW*)lParam;
+            //OS.MoveMemory (nmcd, lParam, OS.NMLVCUSTOMDRAW_sizeof);
+            switch (nmcd.nmcd.dwDrawStage) {
+                case OS.CDDS_PREPAINT: return CDDS_PREPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_ITEMPREPAINT: return CDDS_ITEMPREPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_ITEMPOSTPAINT: return CDDS_ITEMPOSTPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_SUBITEMPREPAINT: return CDDS_SUBITEMPREPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_SUBITEMPOSTPAINT: return CDDS_SUBITEMPOSTPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_POSTPAINT: return CDDS_POSTPAINT (nmcd, wParam, lParam);
+                default:
+            }
+            break;
+        }
+        case OS.LVN_MARQUEEBEGIN: {
+            if ((style & SWT.SINGLE) !is 0) return LRESULT.ONE;
+            if (hooks (SWT.MouseDown) || hooks (SWT.MouseUp)) {
+                return LRESULT.ONE;
+            }
+            if ((style & SWT.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;
+                OS.POINTSTOPOINT (pt, pos);
+                OS.ScreenToClient (handle, &pt);
+                sendDragEvent (1, pt.x, pt.y);
+            }
+            break;
+        }
+        case OS.LVN_COLUMNCLICK: {
+            NMLISTVIEW* pnmlv = cast(NMLISTVIEW*)lParam;
+            //OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+            TableColumn column = columns [pnmlv.iSubItem];
+            if (column !is null) {
+                column.postEvent (SWT.Selection);
+            }
+            break;
+        }
+        case OS.LVN_ITEMACTIVATE: {
+            if (ignoreActivate) break;
+            NMLISTVIEW* pnmlv = cast(NMLISTVIEW*)lParam;
+            //OS.MoveMemory(pnmlv, lParam, NMLISTVIEW.sizeof);
+            if (pnmlv.iItem !is -1) {
+                Event event = new Event ();
+                event.item = _getItem (pnmlv.iItem);
+                postEvent (SWT.DefaultSelection, event);
+            }
+            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);
+                if ((pnmlv.uChanged & OS.LVIF_STATE) !is 0) {
+                    if (pnmlv.iItem is -1) {
+                        wasSelected = true;
+                    } else {
+                        bool oldSelected = (pnmlv.uOldState & OS.LVIS_SELECTED) !is 0;
+                        bool newSelected = (pnmlv.uNewState & OS.LVIS_SELECTED) !is 0;
+                        if (oldSelected !is newSelected) wasSelected = true;
+                    }
+                }
+            }
+            if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+                auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+                int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                if (count !is 0) {
+                    forceResize ();
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    NMLISTVIEW* pnmlv = cast(NMLISTVIEW*)lParam;
+                    //OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof);
+                    if (pnmlv.iItem !is -1) {
+                        RECT itemRect;
+                        itemRect.left = OS.LVIR_BOUNDS;
+                        ignoreCustomDraw = true;
+                        OS.SendMessage (handle, OS. LVM_GETITEMRECT, pnmlv.iItem, &itemRect);
+                        ignoreCustomDraw = false;
+                        RECT headerRect;
+                        int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0);
+                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+                        OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2);
+                        rect.left = headerRect.right;
+                        rect.top = itemRect.top;
+                        rect.bottom = itemRect.bottom;
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
+                }
+            }
+            break;
+        }
+        case OS.NM_RECOGNIZEGESTURE:
+            /*
+            * Feature on Pocket PC.  The tree and table controls detect the tap
+            * and hold gesture by default. They send a GN_CONTEXTMENU message to show
+            * the popup menu.  This default behaviour is unwanted on Pocket PC 2002
+            * when no menu has been set, as it still draws a red circle.  The fix
+            * is to disable this default behaviour when no menu is set by returning
+            * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE
+            * message.
+            */
+            if (OS.IsPPC) {
+                bool hasMenu = menu !is null && !menu.isDisposed ();
+                if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE;
+            }
+            break;
+        case OS.GN_CONTEXTMENU:
+            if (OS.IsPPC) {
+                bool hasMenu = menu !is null && !menu.isDisposed ();
+                if (hasMenu || hooks (SWT.MenuDetect)) {
+                    NMRGINFO* nmrg = cast(NMRGINFO*)lParam;
+                    //OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof);
+                    showMenu (nmrg.x, nmrg.y);
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        default:
+    }
+    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 (SWT.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 (SWT.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 (SWT.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 (SWT.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 (SWT.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);
+        }
+        default:
+    }
+    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 (SWT.EraseItem)) {
+                    Event event = sendEraseItemEvent (item, nmcd, pinfo.iSubItem, &cellRect);
+                    if (isDisposed () || item.isDisposed ()) break;
+                    if (event.doit) {
+                        drawForeground = (event.detail & SWT.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 & SWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                            if ((column.style & SWT.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 (SWT.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);
+            }
+        }
+        default:
+    }
+    return null;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TableColumn.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,888 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TableColumn;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a column in a table widget.
+ * <p><dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TableColumn : Item {
+    Table parent;
+    bool resizable, moveable;
+    String toolTipText;
+    int id;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Table parent, int style) {
+    super (parent, checkStyle (style));
+    resizable = true;
+    this.parent = parent;
+    parent.createItem (this, parent.getColumnCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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>
+ * 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Table parent, int style, int index) {
+    super (parent, checkStyle (style));
+    resizable = true;
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Resize,typedListener);
+    addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the column header is selected.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <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 int getAlignment () {
+    checkWidget ();
+    if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+    if ((style & SWT.CENTER) !is 0) return SWT.CENTER;
+    if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+    return SWT.LEFT;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Table</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Table getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @exception SWTException <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 Table#getColumnOrder()
+ * @see Table#setColumnOrder(int[])
+ * @see TableColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public bool getMoveable () {
+    checkWidget ();
+    return moveable;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @exception SWTException <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 getResizable () {
+    checkWidget ();
+    return resizable;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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.2
+ */
+public String getToolTipText () {
+    checkWidget();
+    return toolTipText;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <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 int getWidth () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return 0;
+    auto hwnd = parent.handle;
+    return OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @exception SWTException <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 pack () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    auto hwnd = parent.handle;
+    int oldWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+    TCHAR* buffer = StrToTCHARz (parent.getCodePage (), text);
+    int headerWidth = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + Table.HEADER_MARGIN;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) headerWidth += Table.HEADER_EXTRA;
+    bool hasHeaderImage = false;
+    if (image !is null || parent.sortColumn is this) {
+        hasHeaderImage = true;
+        Image headerImage = null;
+        if (parent.sortColumn is this && parent.sortDirection !is SWT.NONE) {
+            if (OS.COMCTL32_MAJOR < 6) {
+                headerImage = display.getSortImage (parent.sortDirection);
+            } else {
+                headerWidth += Table.SORT_WIDTH;
+            }
+        } else {
+            headerImage = image;
+        }
+        if (headerImage !is null) {
+            Rectangle bounds = headerImage.getBounds ();
+            headerWidth += bounds.width;
+        }
+        int margin = 0;
+        if (OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) {
+            auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+            margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+        } else {
+            margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3;
+        }
+        headerWidth += margin * 4;
+    }
+    parent.ignoreColumnResize = true;
+    int columnWidth = 0;
+    /*
+    * 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.
+    */
+    if ((index is 0 && !parent.firstColumnImage) || parent.hooks (SWT.MeasureItem)) {
+        RECT headerRect;
+        auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+        OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*) &headerRect, 2);
+        auto hDC = OS.GetDC (hwnd);
+        HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        int count = OS.SendMessage (hwnd, OS.LVM_GETITEMCOUNT, 0, 0);
+        for (int i=0; i<count; i++) {
+            TableItem item = parent.items [i];
+            if (item !is null) {
+                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);
+                if (isDisposed () || parent.isDisposed ()) break;
+                columnWidth = Math.max (columnWidth, event.x + event.width - headerRect.left);
+            }
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (hwnd, hDC);
+        OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
+    } else {
+        OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE);
+        columnWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+        if (index is 0) {
+            /*
+            * Bug in Windows.  When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
+            * where each item has I_IMAGECALLBACK but there are no images in the
+            * table, the size computed by LVM_SETCOLUMNWIDTH is too small for the
+            * first column, causing long items to be clipped with '...'.  The fix
+            * is to increase the column width by a small amount.
+            */
+            if (parent.imageList is null) columnWidth += 2;
+            /*
+            * Bug in Windows.  When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
+            * for a table with a state image list, the column is width does not
+            * include space for the state icon.  The fix is to increase the column
+            * width by the width of the image list.
+            */
+            if ((parent.style & SWT.CHECK) !is 0) {
+                auto hStateList = cast(HANDLE) OS.SendMessage (hwnd, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
+                if (hStateList !is null) {
+                    int cx, cy;
+                    OS.ImageList_GetIconSize (hStateList, &cx, &cy);
+                    columnWidth += cx;
+                }
+            }
+        }
+    }
+    if (headerWidth > columnWidth) {
+        if (!hasHeaderImage) {
+            /*
+            * Feature in Windows.  When LVSCW_AUTOSIZE_USEHEADER is used
+            * with LVM_SETCOLUMNWIDTH to resize the last column, the last
+            * column is expanded to fill the client area.  The fix is to
+            * resize the table to be small, set the column width and then
+            * restore the table to its original size.
+            */
+            RECT rect;
+            bool fixWidth = index is parent.getColumnCount () - 1;
+            if (fixWidth) {
+                //rect = new RECT ();
+                OS.GetWindowRect (hwnd, &rect);
+                OS.UpdateWindow (hwnd);
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+                SetWindowPos (hwnd, null, 0, 0, 0, rect.bottom - rect.top, flags);
+            }
+            OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER);
+            if (fixWidth) {
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER;
+                SetWindowPos (hwnd, null, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
+            }
+        } else {
+            OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth);
+        }
+    } else {
+        if (index is 0) {
+            OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
+        }
+    }
+    parent.ignoreColumnResize = false;
+    int newWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
+    if (oldWidth !is newWidth) {
+        updateToolTip (index);
+        sendEvent (SWT.Resize);
+        if (isDisposed ()) return;
+        bool moved = false;
+        int [] order = parent.getColumnOrder ();
+        TableColumn [] columns = parent.getColumns ();
+        for (int i=0; i<order.length; i++) {
+            TableColumn column = columns [order [i]];
+            if (moved && !column.isDisposed ()) {
+                column.updateToolTip (order [i]);
+                column.sendEvent (SWT.Move);
+            }
+            if (column is this) moved = true;
+        }
+    }
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (parent.sortColumn is this) {
+        parent.sortColumn = null;
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Move, listener);
+    eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * 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 SWTException <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 setAlignment (int alignment) {
+    checkWidget ();
+    if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return;
+    int index = parent.indexOf (this);
+    if (index is -1 || index is 0) return;
+    style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    auto hwnd = parent.handle;
+    LVCOLUMN lvColumn;
+    lvColumn.mask = OS.LVCF_FMT;
+    OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, &lvColumn);
+    lvColumn.fmt &= ~OS.LVCFMT_JUSTIFYMASK;
+    int fmt = 0;
+    if ((style & SWT.LEFT) is SWT.LEFT) fmt = OS.LVCFMT_LEFT;
+    if ((style & SWT.CENTER) is SWT.CENTER) fmt = OS.LVCFMT_CENTER;
+    if ((style & SWT.RIGHT) is SWT.RIGHT) fmt = OS.LVCFMT_RIGHT;
+    lvColumn.fmt |= fmt;
+    OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, &lvColumn);
+    /*
+    * Bug in Windows.  When LVM_SETCOLUMN is used to change
+    * the alignment of a column, the column is not redrawn
+    * to show the new alignment.  The fix is to compute the
+    * visible rectangle for the column and redraw it.
+    */
+    if (index !is 0) {
+        parent.forceResize ();
+        RECT rect, headerRect;
+        OS.GetClientRect (hwnd, &rect);
+        auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+        OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*) &headerRect, 2);
+        rect.left = headerRect.left;
+        rect.right = headerRect.right;
+        OS.InvalidateRect (hwnd, &rect, true);
+    }
+}
+
+override public void setImage (Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    super.setImage (image);
+    if (parent.sortColumn !is this || parent.sortDirection !is SWT.NONE) {
+        setImage (image, false, false);
+    }
+}
+
+void setImage (Image image, bool sort, bool right) {
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    auto hwnd = parent.handle;
+    if (OS.COMCTL32_MAJOR < 6) {
+        auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+        HDITEM hdItem;
+        hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE | OS.HDI_BITMAP;
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, cast(int) &hdItem);
+        hdItem.fmt &= ~OS.HDF_BITMAP_ON_RIGHT;
+        if (image !is null) {
+            if (sort) {
+                hdItem.mask &= ~OS.HDI_IMAGE;
+                hdItem.fmt &= ~OS.HDF_IMAGE;
+                hdItem.fmt |= OS.HDF_BITMAP;
+                hdItem.hbm = image.handle;
+            } else {
+                hdItem.mask &= ~OS.HDI_BITMAP;
+                hdItem.fmt &= ~OS.HDF_BITMAP;
+                hdItem.fmt |= OS.HDF_IMAGE;
+                hdItem.iImage = parent.imageIndexHeader (image);
+            }
+            if (right) hdItem.fmt |= OS.HDF_BITMAP_ON_RIGHT;
+        } else {
+            hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_BITMAP);
+        }
+        OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, cast(int) &hdItem);
+    } else {
+        LVCOLUMN lvColumn;
+        lvColumn.mask = OS.LVCF_FMT | OS.LVCF_IMAGE;
+        OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, &lvColumn);
+        if (image !is null) {
+            lvColumn.fmt |= OS.LVCFMT_IMAGE;
+            lvColumn.iImage = parent.imageIndexHeader (image);
+            if (right) lvColumn.fmt |= OS.LVCFMT_BITMAP_ON_RIGHT;
+        } else {
+            lvColumn.mask &= ~OS.LVCF_IMAGE;
+            lvColumn.fmt &= ~(OS.LVCFMT_IMAGE | OS.LVCFMT_BITMAP_ON_RIGHT);
+        }
+        OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, &lvColumn);
+    }
+}
+
+/**
+ * Sets the moveable attribute.  A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @exception SWTException <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 Table#setColumnOrder(int[])
+ * @see Table#getColumnOrder()
+ * @see TableColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public void setMoveable (bool moveable) {
+    checkWidget ();
+    this.moveable = moveable;
+    parent.updateMoveable ();
+}
+
+/**
+ * Sets the resizable attribute.  A column that is
+ * resizable can be resized by the user dragging the
+ * edge of the header.  A column that is not resizable
+ * cannot be dragged by the user but may be resized
+ * by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @exception SWTException <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 setResizable (bool resizable) {
+    checkWidget ();
+    this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+    if (OS.COMCTL32_MAJOR >= 6) {
+        int index = parent.indexOf (this);
+        if (index is -1) return;
+        auto hwnd = parent.handle;
+        auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+        HDITEM hdItem;
+        hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE;
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+        switch (direction) {
+            case SWT.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 SWT.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 SWT.NONE:
+                hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
+                if (image !is null) {
+                    hdItem.fmt |= OS.HDF_IMAGE;
+                    hdItem.iImage = parent.imageIndexHeader (image);
+                } else {
+                    hdItem.fmt &= ~OS.HDF_IMAGE;
+                    hdItem.mask &= ~OS.HDI_IMAGE;
+                }
+                break;
+            default:
+        }
+        OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+        /*
+        * Bug in Windows.  When LVM_SETSELECTEDCOLUMN is used to
+        * specify a selected column, Windows does not redraw either
+        * the new or the previous selected column.  The fix is to
+        * force a redraw of both.
+        *
+        * Feature in Windows.  When LVM_SETBKCOLOR is used with
+        * CLR_NONE and LVM_SETSELECTEDCOLUMN is used to select
+        * a column, Windows fills the column with the selection
+        * color, drawing on top of the background image and any
+        * other custom drawing.  The fix is to avoid setting the
+        * selected column.
+        */
+        parent.forceResize ();
+        RECT rect;
+        OS.GetClientRect (hwnd, &rect);
+        if (OS.SendMessage (hwnd, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) {
+            int oldColumn = OS.SendMessage (hwnd, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
+            int newColumn = direction is SWT.NONE ? -1 : index;
+            OS.SendMessage (hwnd, OS.LVM_SETSELECTEDCOLUMN, newColumn, 0);
+            RECT headerRect;
+            if (oldColumn !is -1) {
+                if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, oldColumn, &headerRect) !is 0) {
+                    OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*) &headerRect, 2);
+                    rect.left = headerRect.left;
+                    rect.right = headerRect.right;
+                    OS.InvalidateRect (hwnd, &rect, true);
+                }
+            }
+        }
+        RECT headerRect;
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect) !is 0) {
+            OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*)  &headerRect, 2);
+            rect.left = headerRect.left;
+            rect.right = headerRect.right;
+            OS.InvalidateRect (hwnd, &rect, true);
+        }
+    } else {
+        switch (direction) {
+            case SWT.UP:
+            case SWT.DOWN:
+                setImage (display.getSortImage (direction), true, true);
+                break;
+            case SWT.NONE:
+                setImage (image, false, false);
+                break;
+            default:
+        }
+    }
+}
+
+override public void setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (string.equals (text)) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    super.setText (string);
+
+    /*
+    * Bug in Windows.  For some reason, when the title
+    * of a column is changed after the column has been
+    * created, the alignment must also be reset or the
+    * text does not draw.  The fix is to query and then
+    * set the alignment.
+    */
+    auto hwnd = parent.handle;
+    LVCOLUMN lvColumn;
+    lvColumn.mask = OS.LVCF_FMT;
+    OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, cast(int) &lvColumn);
+
+    /*
+    * Bug in Windows.  When a column header contains a
+    * mnemonic character, Windows does not measure the
+    * text properly.  This causes '...' to always appear
+    * at the end of the text.  The fix is to remove
+    * mnemonic characters and replace doubled mnemonics
+    * with spaces.
+    */
+    auto hHeap = OS.GetProcessHeap ();
+    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);
+    lvColumn.mask |= OS.LVCF_TEXT;
+    lvColumn.pszText = pszText;
+    int result = OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, cast(int) &lvColumn);
+    if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+    if (result is 0) error (SWT.ERROR_CANNOT_SET_TEXT);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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.2
+ */
+public void setToolTipText (String string) {
+    checkWidget();
+    toolTipText = string;
+    auto hwndHeaderToolTip = parent.headerToolTipHandle;
+    if (hwndHeaderToolTip is null) {
+        parent.createHeaderToolTips ();
+        parent.updateHeaderToolTips ();
+    }
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException <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 setWidth (int width) {
+    checkWidget ();
+    if (width < 0) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    auto hwnd = parent.handle;
+    OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, width);
+}
+
+void updateToolTip (int index) {
+    auto hwndHeaderToolTip = parent.headerToolTipHandle;
+    if (hwndHeaderToolTip !is null) {
+        auto hwnd = parent.handle;
+        auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+        RECT rect;
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &rect) !is 0) {
+            TOOLINFO lpti;
+            lpti.cbSize = OS.TOOLINFO_sizeof;
+            lpti.hwnd = hwndHeader;
+            lpti.uId = id;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            OS.SendMessage (hwndHeaderToolTip, OS.TTM_NEWTOOLRECT, 0, &lpti);
+        }
+    }
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TableItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TableItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents an item in a table.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class TableItem : Item {
+    Table parent;
+    String [] strings;
+    Image [] images;
+    Font font;
+    Font [] cellFont;
+    bool checked, grayed, cached;
+    int imageIndent, background = -1, foreground = -1;
+    int [] cellBackground, cellForeground;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Table parent, int style) {
+    this (parent, style, checkNull (parent).getItemCount (), true);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Table</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Table parent, int style, int index) {
+    this (parent, style, index, true);
+}
+
+this (Table parent, int style, int index, bool create) {
+    super (parent, style);
+    this.parent = parent;
+    if (create) parent.createItem (this, index);
+}
+
+static Table checkNull (Table control) {
+    if (control is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return control;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void clear () {
+    text = "";
+    image = null;
+    strings = null;
+    images = null;
+    imageIndent = 0;
+    checked = grayed = false;
+    font = null;
+    background = foreground = -1;
+    cellFont = null;
+    cellBackground = cellForeground = null;
+    cellFont = null;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = false;
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    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.
+ *
+ * @return the background color
+ *
+ * @exception SWTException <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 2.0
+ */
+public Color getBackground () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (background is -1) return parent.getBackground ();
+    return Color.win32_new (display, background);
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @exception SWTException <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.0
+ */
+public Color getBackground (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return getBackground ();
+    int pixel = cellBackground !is null ? cellBackground [index] : -1;
+    return pixel is -1 ? getBackground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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.2
+ */
+public Rectangle getBounds () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int itemIndex = parent.indexOf (this);
+    if (itemIndex is -1) return new Rectangle (0, 0, 0, 0);
+    RECT rect = getBounds (itemIndex, 0, true, false, false);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the table.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int itemIndex = parent.indexOf (this);
+    if (itemIndex is -1) return new Rectangle (0, 0, 0, 0);
+    RECT rect = getBounds (itemIndex, index, true, true, true);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+RECT getBounds (int row, int column, bool getText, bool getImage, bool fullText) {
+    return getBounds (row, column, getText, getImage, fullText, false, null);
+}
+
+RECT getBounds (int row, int column, bool getText, bool getImage, bool fullText, bool fullImage, HDC hDC) {
+    if (!getText && !getImage) return RECT.init;
+    int columnCount = parent.getColumnCount ();
+    if (!(0 <= column && column < Math.max (1, columnCount))) {
+        return RECT.init;
+    }
+    if (parent.fixScrollWidth) parent.setScrollWidth (null, true);
+    RECT rect;
+    auto hwnd = parent.handle;
+    int bits = OS.SendMessage (hwnd, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+    if (column is 0 && (bits & OS.LVS_EX_FULLROWSELECT) is 0) {
+        if (parent.explorerTheme) {
+            rect.left = OS.LVIR_ICON;
+            parent.ignoreCustomDraw = true;
+            int code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, &rect);
+            parent.ignoreCustomDraw = false;
+            if (code is 0) return RECT.init;
+            if (getText) {
+                int width = 0;
+                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);
+                } else {
+                    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), text, false);
+                    auto textDC = hDC !is null ? hDC : OS.GetDC (hwnd), oldFont = cast(HFONT)-1;
+                    if (hDC is null) {
+                        if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+                        oldFont = OS.SelectObject (textDC, hFont);
+                    }
+                    RECT textRect;
+                    int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                    OS.DrawText (textDC, buffer.ptr, buffer.length, &textRect, flags);
+                    width = textRect.right - textRect.left;
+                    if (hDC is null) {
+                        if (oldFont !is cast(HFONT)-1) OS.SelectObject (textDC, oldFont);
+                        OS.ReleaseDC (hwnd, textDC);
+                    }
+                }
+                if (!getImage) rect.left = rect.right;
+                rect.right += width + Table.INSET * 2;
+            }
+        } else {
+            if (getText) {
+                rect.left = OS.LVIR_SELECTBOUNDS;
+                parent.ignoreCustomDraw = true;
+                int code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, &rect);
+                parent.ignoreCustomDraw = false;
+                if (code is 0) return RECT.init;
+                if (!getImage) {
+                    RECT iconRect;
+                    iconRect.left = OS.LVIR_ICON;
+                    parent.ignoreCustomDraw = true;
+                    code = OS.SendMessage (hwnd, OS. LVM_GETITEMRECT, row, &iconRect);
+                    parent.ignoreCustomDraw = false;
+                    if (code !is 0) rect.left = iconRect.right;
+                }
+            } else {
+                rect.left = OS.LVIR_ICON;
+                parent.ignoreCustomDraw = true;
+                int code = OS.SendMessage (hwnd, OS.LVM_GETITEMRECT, row, &rect);
+                parent.ignoreCustomDraw = false;
+                if (code is 0) return RECT.init;
+            }
+        }
+        if (fullText || fullImage) {
+            RECT headerRect;
+            auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, &headerRect);
+            OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*) &headerRect, 2);
+            if (getText && fullText) rect.right = headerRect.right;
+            if (getImage && fullImage) rect.left = headerRect.left;
+        }
+    } else {
+        /*
+        * Feature in Windows.  LVM_GETSUBITEMRECT returns an image width
+        * even when the subitem does not contain an image.  The fix is to
+        * test for this case and adjust the rectangle to represent the area
+        * the table is actually drawing.
+        */
+        bool hasImage = (column is 0 && image !is null) || (images !is null && images [column] !is null);
+        rect.top = column;
+        if (fullText || fullImage || hDC is null) {
+            /*
+            * Bug in Windows.  Despite the fact that the documentation states
+            * that LVIR_BOUNDS and LVIR_LABEL are identical when used with
+            * LVM_GETSUBITEMRECT, LVIR_BOUNDS can return a zero height.  The
+            * fix is to use LVIR_LABEL.
+            */
+            rect.left = getText ? OS.LVIR_LABEL : OS.LVIR_ICON;
+            parent.ignoreCustomDraw = true;
+            int code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, &rect);
+            parent.ignoreCustomDraw = false;
+            if (code is 0) return RECT.init;
+            /*
+            * Feature in Windows.  Calling LVM_GETSUBITEMRECT with LVIR_LABEL
+            * and zero for the column number gives the bounds of the first item
+            * without including the bounds of the icon.  This is undocumented.
+            * When called with values greater than zero, the icon bounds are
+            * included and this behavior is documented.  If the icon is needed
+            * in the bounds of the first item, the fix is to adjust the item
+            * bounds using the icon bounds.
+            */
+            if (column is 0 && getText && getImage) {
+                RECT iconRect;
+                iconRect.left = OS.LVIR_ICON;
+                parent.ignoreCustomDraw = true;
+                code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, &iconRect);
+                parent.ignoreCustomDraw = false;
+                if (code !is 0) rect.left = iconRect.left;
+            }
+            if (hasImage) {
+                if (column !is 0 && getText && !getImage) {
+                    RECT iconRect;
+                    iconRect.top = column;
+                    iconRect.left = OS.LVIR_ICON;
+                    if (OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, &iconRect) !is 0) {
+                        rect.left = iconRect.right + Table.INSET / 2;
+                    }
+                }
+            } else {
+                if (getImage && !getText) rect.right = rect.left;
+            }
+            if (column is 0 && fullImage) {
+                RECT headerRect;
+                auto hwndHeader = cast(HWND) OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, 0, &headerRect);
+                OS.MapWindowPoints (hwndHeader, hwnd, cast(POINT*) &headerRect, 2);
+                rect.left = headerRect.left;
+            }
+        } else {
+            rect.left = OS.LVIR_ICON;
+            parent.ignoreCustomDraw = true;
+            int code = OS.SendMessage (hwnd, OS. LVM_GETSUBITEMRECT, row, &rect);
+            parent.ignoreCustomDraw = false;
+            if (code is 0) return RECT.init;
+            if (!hasImage) rect.right = rect.left;
+            if (getText) {
+                String string = column is 0 ? text : strings !is null ? strings [column] : null;
+                if (string !is null) {
+                    RECT textRect;
+                    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, false);
+                    int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                    OS.DrawText (hDC, buffer.ptr, buffer.length, &textRect, flags);
+                    rect.right += textRect.right - textRect.left + Table.INSET * 3 + 1;
+                }
+            }
+        }
+    }
+    /*
+    * Bug in Windows.  In version 5.80 of COMCTL32.DLL, the top
+    * of the rectangle returned by LVM_GETSUBITEMRECT is off by
+    * the grid width when the grid is visible.  The fix is to
+    * move the top of the rectangle up by the grid width.
+    */
+    int gridWidth = parent.getLinesVisible () ? Table.GRID_WIDTH : 0;
+    if (OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) rect.top -= gridWidth;
+    if (column !is 0) rect.left += gridWidth;
+    rect.right = Math.max (rect.right, rect.left);
+    rect.top += gridWidth;
+    rect.bottom = Math.max (rect.bottom - gridWidth, rect.top);
+    return rect;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is checked,
+ * and false otherwise.  When the parent does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the checked state of the checkbox
+ *
+ * @exception SWTException <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 getChecked () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if ((parent.style & SWT.CHECK) is 0) return false;
+    return checked;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.0
+ */
+public Font getFont () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return font !is null ? font : parent.getFont ();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.0
+ */
+public Font getFont (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count -1) return getFont ();
+    if (cellFont is null || cellFont [index] is null) return getFont ();
+    return cellFont [index];
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException <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 2.0
+ */
+public Color getForeground () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (foreground is -1) return parent.getForeground ();
+    return Color.win32_new (display, foreground);
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @exception SWTException <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.0
+ */
+public Color getForeground (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count -1) return getForeground ();
+    int pixel = cellForeground !is null ? cellForeground [index] : -1;
+    return pixel is -1 ? getForeground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception SWTException <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 (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if ((parent.style & SWT.CHECK) is 0) return false;
+    return grayed;
+}
+
+override public Image getImage () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return super.getImage ();
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @exception SWTException <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 Image getImage (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (index is 0) return getImage ();
+    if (images !is null) {
+        if (0 <= index && index < images.length) return images [index];
+    }
+    return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * table.  An empty rectangle is returned if index exceeds
+ * the index of the table's last column.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @exception SWTException <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 Rectangle getImageBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int itemIndex = parent.indexOf (this);
+    if (itemIndex is -1) return new Rectangle (0, 0, 0, 0);
+    RECT rect = getBounds (itemIndex, index, false, true, false);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Gets the image indent.
+ *
+ * @return the indent
+ *
+ * @exception SWTException <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 int getImageIndent () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return imageIndent;
+}
+
+override String getNameText () {
+    if ((parent.style & SWT.VIRTUAL) !is 0) {
+        if (!cached) return "*virtual*"; //$NON-NLS-1$
+    }
+    return super.getNameText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Table</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Table getParent () {
+    checkWidget();
+    return parent;
+}
+
+override public String getText () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return super.getText ();
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @exception SWTException <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 String getText (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (index is 0) return getText ();
+    if (strings !is null) {
+        if (0 <= index && index < strings.length) {
+            String string = strings [index];
+            return string !is null ? string : "";
+        }
+    }
+    return "";
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of the text at a column in the
+ * table.  An empty rectangle is returned if index exceeds
+ * the index of the table's last column.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding text rectangle
+ *
+ * @exception SWTException <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 Rectangle getTextBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int itemIndex = parent.indexOf (this);
+    if (itemIndex is -1) return new Rectangle (0, 0, 0, 0);
+    RECT rect = getBounds (itemIndex, index, true, false, true);
+    rect.left += 2;
+    if (index !is 0) rect.left += Table.INSET;
+    rect.left = Math.min (rect.left, rect.right);
+    rect.right = rect.right - Table.INSET;
+    int width = Math.max (0, rect.right - rect.left);
+    int height = Math.max (0, rect.bottom - rect.top);
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+void redraw () {
+    if (parent.currentItem is this || parent.drawCount !is 0) return;
+    auto hwnd = parent.handle;
+    if (!OS.IsWindowVisible (hwnd)) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    OS.SendMessage (hwnd, OS.LVM_REDRAWITEMS, index, index);
+}
+
+void redraw (int column, bool drawText, bool drawImage) {
+    if (parent.currentItem is this || parent.drawCount !is 0) return;
+    auto hwnd = parent.handle;
+    if (!OS.IsWindowVisible (hwnd)) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    RECT rect = getBounds (index, column, drawText, drawImage, true);
+    OS.InvalidateRect (hwnd, &rect, true);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    strings = null;
+    images = null;
+    cellFont = null;
+    cellBackground = cellForeground = null;
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ */
+public void setBackground (Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int pixel = -1;
+    if (color !is null) {
+        parent.setCustomDraw (true);
+        pixel = color.handle;
+    }
+    if (background is pixel) return;
+    background = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw ();
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setBackground (int index, Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    int pixel = -1;
+    if (color !is null) {
+        parent.setCustomDraw (true);
+        pixel = color.handle;
+    }
+    if (cellBackground is null) {
+        cellBackground = new int [count];
+        for (int i = 0; i < count; i++) {
+            cellBackground [i] = -1;
+        }
+    }
+    if (cellBackground [index] is pixel) return;
+    cellBackground [index] = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw (index, true, true);
+}
+
+/**
+ * Sets the checked state of the checkbox for this item.  This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param checked the new checked state of the checkbox
+ *
+ * @exception SWTException <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 setChecked (bool checked) {
+    checkWidget();
+    if ((parent.style & SWT.CHECK) is 0) return;
+    if (this.checked is checked) return;
+    setChecked (checked, false);
+}
+
+void setChecked (bool checked, bool notify) {
+    this.checked = checked;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    if (notify) {
+        Event event = new Event();
+        event.item = this;
+        event.detail = SWT.CHECK;
+        parent.postEvent (SWT.Selection, event);
+    }
+    redraw ();
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setFont (Font font){
+    checkWidget ();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    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 & SWT.VIRTUAL) !is 0) cached = true;
+    /*
+    * 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 ((parent.style & SWT.VIRTUAL) is 0 && cached) {
+        int itemIndex = parent.indexOf (this);
+        if (itemIndex !is -1) {
+            auto hwnd = parent.handle;
+            LVITEM lvItem;
+            lvItem.mask = OS.LVIF_TEXT;
+            lvItem.iItem = itemIndex;
+            lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+            OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, cast(int) &lvItem);
+            cached = false;
+        }
+    }
+    parent.setScrollWidth (this, false);
+    redraw ();
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setFont (int index, Font font) {
+    checkWidget ();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (cellFont is null) {
+        if (font is null) return;
+        cellFont = new Font [count];
+    }
+    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 & SWT.VIRTUAL) !is 0) cached = true;
+    if (index 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 ((parent.style & SWT.VIRTUAL) is 0 && cached) {
+            int itemIndex = parent.indexOf (this);
+            if (itemIndex !is -1) {
+                auto hwnd = parent.handle;
+                LVITEM lvItem;
+                lvItem.mask = OS.LVIF_TEXT;
+                lvItem.iItem = itemIndex;
+                lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, cast(int) &lvItem);
+                cached = false;
+            }
+        }
+        parent.setScrollWidth (this, false);
+    }
+    redraw (index, true, false);
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ */
+public void setForeground (Color color){
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int pixel = -1;
+    if (color !is null) {
+        parent.setCustomDraw (true);
+        pixel = color.handle;
+    }
+    if (foreground is pixel) return;
+    foreground = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw ();
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setForeground (int index, Color color){
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    int pixel = -1;
+    if (color !is null) {
+        parent.setCustomDraw (true);
+        pixel = color.handle;
+    }
+    if (cellForeground is null) {
+        cellForeground = new int [count];
+        for (int i = 0; i < count; i++) {
+            cellForeground [i] = -1;
+        }
+    }
+    if (cellForeground [index] is pixel) return;
+    cellForeground [index] = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw (index, true, false);
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item.  This state change
+ * only applies if the Table was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox;
+ *
+ * @exception SWTException <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 ((parent.style & SWT.CHECK) is 0) return;
+    if (this.grayed is grayed) return;
+    this.grayed = grayed;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw ();
+}
+
+/**
+ * Sets the image for multiple columns in the table.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (Image [] images) {
+    checkWidget();
+    for (int i=0; i<images.length; i++) {
+        setImage (i, images [i]);
+    }
+}
+
+/**
+ * Sets the receiver's image at a column.
+ *
+ * @param index the column index
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setImage (int index, Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    Image oldImage = null;
+    if (index is 0) {
+        if (image !is null && image.type is SWT.ICON) {
+            if (image ==/*eq*/ this.image) return;
+        }
+        oldImage = this.image;
+        super.setImage (image);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (images is null && index !is 0) {
+        images = new Image [count];
+        images [0] = image;
+    }
+    if (images !is null) {
+        if (image !is null && image.type is SWT.ICON) {
+            if (image ==/*eq*/ images [index] ) return;
+        }
+        oldImage = images [index];
+        images [index] = image;
+    }
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+
+    /* Ensure that the image list is created */
+    parent.imageIndex (image, index);
+
+    if (index is 0) parent.setScrollWidth (this, false);
+    bool drawText = (image is null && oldImage !is null) || (image !is null && oldImage is null);
+    redraw (index, drawText, true);
+}
+
+override public void setImage (Image image) {
+    checkWidget ();
+    setImage (0, image);
+}
+
+/**
+ * Sets the indent of the first column's image, expressed in terms of the image's width.
+ *
+ * @param indent the new indent
+ *
+ * </ul>
+ * @exception SWTException <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>
+ *
+ * @deprecated this functionality is not supported on most platforms
+ */
+public void setImageIndent (int indent) {
+    checkWidget();
+    if (indent < 0) return;
+    if (imageIndent is indent) return;
+    imageIndent = indent;
+    if ((parent.style & SWT.VIRTUAL) !is 0) {
+        cached = true;
+    } else {
+        int index = parent.indexOf (this);
+        if (index !is -1) {
+            auto hwnd = parent.handle;
+            LVITEM lvItem;
+            lvItem.mask = OS.LVIF_INDENT;
+            lvItem.iItem = index;
+            lvItem.iIndent = indent;
+            OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, cast(int) &lvItem);
+        }
+    }
+    parent.setScrollWidth (this, false);
+    redraw ();
+}
+
+/**
+ * Sets the text for multiple columns in the table.
+ *
+ * @param strings the array of new strings
+ *
+ * @exception SWTException <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 setText (String [] strings) {
+    checkWidget();
+    for (int i=0; i<strings.length; i++) {
+        String string = strings [i];
+        if (string !is null) setText (i, string);
+    }
+}
+
+/**
+ * Sets the receiver's text at a column
+ *
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (int index, String string) {
+    checkWidget();
+    if (index is 0) {
+        if (string.equals(text)) return;
+        super.setText (string.dup);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (strings is null && index !is 0)  {
+        strings = new String[] (count);
+        strings [0] = text;
+    }
+    if (strings !is null) {
+        if (string==/*eq*/strings [index]) return;
+        strings [index] = string.dup;
+    }
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    if (index 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 ((parent.style & SWT.VIRTUAL) is 0 && cached) {
+            int itemIndex = parent.indexOf (this);
+            if (itemIndex !is -1) {
+                auto hwnd = parent.handle;
+                LVITEM lvItem;
+                lvItem.mask = OS.LVIF_TEXT;
+                lvItem.iItem = itemIndex;
+                lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+                OS.SendMessage (hwnd, OS.LVM_SETITEM, 0, cast(int) &lvItem);
+                cached = false;
+            }
+        }
+        parent.setScrollWidth (this, false);
+    }
+    redraw (index, true, false);
+}
+
+override public void setText (String string) {
+    checkWidget();
+    setText (0, string);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Text.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2484 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Text;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Scrollable;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Control;
+
+import java.lang.all;
+
+/**
+ * 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>
+ * <dd>CANCEL, CENTER, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, Modify, Verify</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles MULTI and SINGLE may be specified,
+ * and only one of the styles LEFT, CENTER, and RIGHT may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#text">Text snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Text : Scrollable {
+
+    alias Scrollable.computeSize computeSize;
+    alias Scrollable.dragDetect dragDetect;
+    alias Scrollable.sendKeyEvent sendKeyEvent;
+    alias Scrollable.setBounds setBounds;
+
+    int tabs, oldStart, oldEnd;
+    bool doubleClick, ignoreModify, ignoreVerify, ignoreCharacter;
+    String message;
+
+    /**
+    * The maximum number of characters that can be entered
+    * into a text widget.
+    * <p>
+    * Note that this value is platform dependent, based upon
+    * the native widget implementation.
+    * </p>
+    */
+    private static int LIMIT_;
+    public static int LIMIT(){
+        assert( static_this_completed );
+        return LIMIT_;
+    }
+
+    /**
+    * The delimiter used by multi-line text widgets.  When text
+    * is queried and from the widget, it will be delimited using
+    * this delimiter.
+    */
+    public static const String DELIMITER = "\r\n";
+
+    /*
+    * This code is intentionally commented.
+    */
+//  static final char PASSWORD;
+
+    /*
+    * These values can be different on different platforms.
+    * Therefore they are not initialized in the declaration
+    * to stop the compiler from inlining.
+    */
+
+    private static /+const+/ WNDPROC EditProc;
+    static const TCHAR[] EditClass = "EDIT\0";
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            LIMIT_ = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, EditClass.ptr, &lpWndClass);
+            EditProc = lpWndClass.lpfnWndProc;
+            /*
+            * This code is intentionally commented.
+            */
+    //      int hwndText = OS.CreateWindowEx (0,
+    //          EditClass,
+    //          null,
+    //          OS.WS_OVERLAPPED | OS.ES_PASSWORD,
+    //          0, 0, 0, 0,
+    //          0,
+    //          0,
+    //          OS.GetModuleHandle (null),
+    //          null);
+    //      char echo = (char) OS.SendMessage (hwndText, OS.EM_GETPASSWORDCHAR, 0, 0);
+    //      OS.DestroyWindow (hwndText);
+    //      PASSWORD = echo !is 0 ? echo : '*';
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#READ_ONLY
+ * @see SWT#WRAP
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    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;
+        }
+        default:
+    }
+    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;
+        }
+        default:
+    }
+    return code;
+}
+
+override void createHandle () {
+    super.createHandle ();
+    OS.SendMessage (handle, OS.EM_LIMITTEXT, 0, 0);
+    if ((style & SWT.READ_ONLY) !is 0) {
+        if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+            state |= THEME_BACKGROUND;
+        }
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is modified, by sending
+ * it one of the messages defined in the <code>ModifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #removeModifyListener
+ */
+public void addModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Modify, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is not called for texts.
+ * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text,
+ * or when ENTER is pressed in a search text. If the receiver has the <code>SWT.SEARCH | SWT.CANCEL</code> style
+ * and the user cancels the search, the event object detail field contains the value <code>SWT.CANCEL</code>.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver's text is verified, by sending
+ * it one of the messages defined in the <code>VerifyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #removeVerifyListener
+ */
+public void addVerifyListener (VerifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Verify, typedListener);
+}
+
+/**
+ * Appends a string.
+ * <p>
+ * The new text is appended to the text at
+ * the end of the widget.
+ * </p>
+ *
+ * @param string the string to be appended
+ *
+ * @exception SWTException <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 append (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    string = Display.withCrLf (string);
+    int length = OS.GetWindowTextLength (handle);
+    if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+        string = verifyText (string, length, length, null);
+        if (string is null) return;
+    }
+    OS.SendMessage (handle, OS.EM_SETSEL, length, length);
+    TCHAR* buffer = StrToTCHARz (getCodePage (), string);
+    /*
+    * Feature in Windows.  When an edit control with ES_MULTILINE
+    * style that does not have the WS_VSCROLL style is full (i.e.
+    * there is no space at the end to draw any more characters),
+    * EM_REPLACESEL sends a WM_CHAR with a backspace character
+    * to remove any further text that is added.  This is an
+    * implementation detail of the edit control that is unexpected
+    * and can cause endless recursion when EM_REPLACESEL is sent
+    * from a WM_CHAR handler.  The fix is to ignore calling the
+    * handler from WM_CHAR.
+    */
+    ignoreCharacter = true;
+    OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+    ignoreCharacter = false;
+    OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+}
+
+static int checkStyle (int style) {
+    if ((style & SWT.SEARCH) !is 0) {
+        style |= SWT.SINGLE | SWT.BORDER;
+        style &= ~SWT.PASSWORD;
+    }
+    if (OS.COMCTL32_MAJOR < 6) style &= ~SWT.SEARCH;
+    if ((style & SWT.SINGLE) !is 0 && (style & SWT.MULTI) !is 0) {
+        style &= ~SWT.MULTI;
+    }
+    style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+    if ((style & SWT.SINGLE) !is 0) style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
+    if ((style & SWT.WRAP) !is 0) {
+        style |= SWT.MULTI;
+        style &= ~SWT.H_SCROLL;
+    }
+    if ((style & SWT.MULTI) !is 0) style &= ~SWT.PASSWORD;
+    if ((style & (SWT.SINGLE | SWT.MULTI)) !is 0) return style;
+    if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) !is 0) return style | SWT.MULTI;
+    return style | SWT.SINGLE;
+}
+
+/**
+ * Clears the selection.
+ *
+ * @exception SWTException <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 clearSelection () {
+    checkWidget ();
+    static if (OS.IsWinCE) {
+        /*
+        * Bug in WinCE.  Calling EM_SETSEL with -1 and 0 is equivalent
+        * to calling EM_SETSEL with 0 and -1.  It causes the entire
+        * text to be selected instead of clearing the selection.  The
+        * fix is to set the start of the selection to the  end of the
+        * current selection.
+        */
+        int end;
+        OS.SendMessage (handle, OS.EM_GETSEL, null, &end);
+        OS.SendMessage (handle, OS.EM_SETSEL, end , end );
+    } else {
+        OS.SendMessage (handle, OS.EM_SETSEL, -1, 0);
+    }
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int height = 0, width = 0;
+    if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
+        HFONT newFont, oldFont;
+        auto hDC = OS.GetDC (handle);
+        newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        TEXTMETRIC tm;
+        OS.GetTextMetrics (hDC, &tm);
+        int count = (style & SWT.SINGLE) !is 0 ? 1 : OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
+        height = count * tm.tmHeight;
+        RECT rect;
+        int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
+        bool wrap = (style & SWT.MULTI) !is 0 && (style & SWT.WRAP) !is 0;
+        if (wrap && wHint !is SWT.DEFAULT) {
+            flags |= OS.DT_WORDBREAK;
+            rect.right = wHint;
+        }
+        int length = OS.GetWindowTextLength (handle);
+        if (length !is 0) {
+            TCHAR[] buffer = NewTCHARs (getCodePage (), length + 1);
+            OS.GetWindowText (handle, buffer.ptr, length + 1);
+            OS.DrawText (hDC, buffer.ptr, length, &rect, flags);
+            width = rect.right - rect.left;
+        }
+        //This code is intentionally commented
+//      if (OS.COMCTL32_MAJOR >= 6) {
+//          if ((style & SWT.SEARCH) !is 0) {
+//              length = message.length ();
+//              if (length !is 0) {
+//                  char [] buffer = new char [length + 1];
+//                  message.getChars (0, length, buffer, 0);
+//                  SIZE size = new SIZE ();
+//                  OS.GetTextExtentPoint32W (hDC, buffer, length, size);
+//                  width = Math.max (width, size.cx);
+//              }
+//          }
+//      }
+        if (wrap && hHint is SWT.DEFAULT) {
+            int newHeight = rect.bottom - rect.top;
+            if (newHeight !is 0) height = newHeight;
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    Rectangle trim = computeTrim (0, 0, width, height);
+    return new Point (trim.width, trim.height);
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    Rectangle rect = super.computeTrim (x, y, width, height);
+    /*
+    * The preferred height of a single-line text widget
+    * has been hand-crafted to be the same height as
+    * the single-line text widget in an editable combo
+    * box.
+    */
+    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 & SWT.H_SCROLL) !is 0) rect.width++;
+    if ((style & SWT.BORDER) !is 0) {
+        rect.x -= 1;
+        rect.y -= 1;
+        rect.width += 2;
+        rect.height += 2;
+    }
+    return rect;
+}
+
+/**
+ * Copies the selected text.
+ * <p>
+ * The current selection is copied to the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 copy () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.WM_COPY, 0, 0);
+}
+
+override void createWidget () {
+    super.createWidget ();
+    message = "";
+    doubleClick = true;
+    setTabStops (tabs = 8);
+    fixAlignment ();
+}
+
+/**
+ * Cuts the selected text.
+ * <p>
+ * The current selection is first copied to the
+ * clipboard and then deleted from the widget.
+ * </p>
+ *
+ * @exception SWTException <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 cut () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (handle, OS.WM_CUT, 0, 0);
+}
+
+override int defaultBackground () {
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return OS.GetSysColor ((bits & OS.ES_READONLY) !is 0 ? OS.COLOR_3DFACE : OS.COLOR_WINDOW);
+}
+
+override bool dragDetect (HWND hwnd, int x, int y, bool filter, bool [] detect, bool [] consume) {
+    if (filter) {
+        int start, end;
+        OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+        if (start !is end ) {
+            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;
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    return super.dragDetect (hwnd, x, y, filter, detect, consume);
+}
+
+void fixAlignment () {
+    /*
+    * Feature in Windows.  When the edit control is not
+    * mirrored, it uses WS_EX_RIGHT, WS_EX_RTLREADING and
+    * WS_EX_LEFTSCROLLBAR to give the control a right to
+    * left appearance.  This causes the control to be lead
+    * aligned no matter what alignment was specified by
+    * the programmer.  For example, setting ES_RIGHT and
+    * WS_EX_LAYOUTRTL should cause the contents of the
+    * control to be left (trail) aligned in a mirrored world.
+    * When the orientation is changed by the user or
+    * specified by the programmer, WS_EX_RIGHT conflicts
+    * with the mirrored alignment.  The fix is to clear
+    * or set WS_EX_RIGHT to achieve the correct alignment
+    * according to the orientation and mirroring.
+    */
+    if ((style & SWT.MIRRORED) !is 0) return;
+    int bits1 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+    int bits2 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((style & SWT.LEFT_TO_RIGHT) !is 0) {
+        /*
+        * Bug in Windows 98. When the edit control is created
+        * with the style ES_RIGHT it automatically sets the
+        * WS_EX_LEFTSCROLLBAR bit.  The fix is to clear the
+        * bit when the orientation of the control is left
+        * to right.
+        */
+        bits1 &= ~OS.WS_EX_LEFTSCROLLBAR;
+        if ((style & SWT.RIGHT) !is 0) {
+            bits1 |= OS.WS_EX_RIGHT;
+            bits2 |= OS.ES_RIGHT;
+        }
+        if ((style & SWT.LEFT) !is 0) {
+            bits1 &= ~OS.WS_EX_RIGHT;
+            bits2 &= ~OS.ES_RIGHT;
+        }
+    } else {
+        if ((style & SWT.RIGHT) !is 0) {
+            bits1 &= ~OS.WS_EX_RIGHT;
+            bits2 &= ~OS.ES_RIGHT;
+        }
+        if ((style & SWT.LEFT) !is 0) {
+            bits1 |= OS.WS_EX_RIGHT;
+            bits2 |= OS.ES_RIGHT;
+        }
+    }
+    if ((style & SWT.CENTER) !is 0) {
+        bits2 |= OS.ES_CENTER;
+    }
+    OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits1);
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits2);
+}
+
+override public int getBorderWidth () {
+    checkWidget ();
+    /*
+    * Feature in Windows 2000 and XP.  Despite the fact that WS_BORDER
+    * is set when the edit control is created, the style bit is cleared.
+    * The fix is to avoid the check for WS_BORDER and use the SWT widget
+    * style bits instead.
+    */
+//  if ((style & SWT.BORDER) !is 0 && (style & SWT.FLAT) !is 0) {
+//      return OS.GetSystemMetrics (OS.SM_CXBORDER);
+//  }
+    return super.getBorderWidth ();
+}
+
+/**
+ * Returns the line number of the caret.
+ * <p>
+ * The line number of the caret is returned.
+ * </p>
+ *
+ * @return the line number
+ *
+ * @exception SWTException <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 int getCaretLineNumber () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.EM_LINEFROMCHAR, -1, 0);
+}
+
+/**
+ * Returns a point describing the receiver's location relative
+ * to its parent (or its display if its parent is null).
+ * <p>
+ * The location of the caret is returned.
+ * </p>
+ *
+ * @return a point, the location of the caret
+ *
+ * @exception SWTException <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 Point getCaretLocation () {
+    checkWidget ();
+    /*
+    * Bug in Windows.  For some reason, Windows is unable
+    * to return the pixel coordinates of the last character
+    * in the widget.  The fix is to temporarily insert a
+    * space, query the coordinates and delete the space.
+    * The selection is always an i-beam in this case because
+    * this is the only time the start of the selection can
+    * be equal to the last character position in the widget.
+    * If EM_POSFROMCHAR fails for any other reason, return
+    * pixel coordinates (0,0).
+    */
+    int position = getCaretPosition ();
+    int /*long*/ caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
+    if (caretPos is -1) {
+        caretPos = 0;
+        if (position >= OS.GetWindowTextLength (handle)) {
+            int cp = getCodePage ();
+            int start, end;
+            OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+            OS.SendMessage (handle, OS.EM_SETSEL, position, position);
+            /*
+            * Feature in Windows.  When an edit control with ES_MULTILINE
+            * style that does not have the WS_VSCROLL style is full (i.e.
+            * there is no space at the end to draw any more characters),
+            * EM_REPLACESEL sends a WM_CHAR with a backspace character
+            * to remove any further text that is added.  This is an
+            * implementation detail of the edit control that is unexpected
+            * and can cause endless recursion when EM_REPLACESEL is sent
+            * from a WM_CHAR handler.  The fix is to ignore calling the
+            * handler from WM_CHAR.
+            */
+            ignoreCharacter = ignoreModify = true;
+            OS.SendMessage (handle, OS.EM_REPLACESEL, 0, StrToTCHARz (cp, " "));
+            caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
+            OS.SendMessage (handle, OS.EM_SETSEL, position, position + 1);
+            OS.SendMessage (handle, OS.EM_REPLACESEL, 0, StrToTCHARz (cp, ""));
+            ignoreCharacter = ignoreModify = false;
+            OS.SendMessage (handle, OS.EM_SETSEL, start , start );
+            OS.SendMessage (handle, OS.EM_SETSEL, start , end );
+        }
+    }
+    return new Point (OS.GET_X_LPARAM (caretPos), OS.GET_Y_LPARAM (caretPos));
+}
+
+/**
+ * Returns the character position of the caret.
+ * <p>
+ * Indexing is zero based.
+ * </p>
+ *
+ * @return the position of the caret
+ *
+ * @exception SWTException <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 int getCaretPosition () {
+    checkWidget ();
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    /*
+    * In Windows, there is no API to get the position of the caret
+    * when the selection is not an i-beam.  The best that can be done
+    * is to query the pixel position of the current caret and compare
+    * it to the pixel position of the start and end of the selection.
+    *
+    * NOTE:  This does not work when the i-beam belongs to another
+    * control.  In this case, guess that the i-beam is at the start
+    * of the selection.
+    */
+    int caret = start ;
+    if (start !is end ) {
+        int startLine = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, start, 0);
+        int endLine = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end, 0);
+        if (startLine is endLine) {
+            static if (!OS.IsWinCE) {
+                int idThread = OS.GetWindowThreadProcessId (handle, null);
+                GUITHREADINFO lpgui;
+                lpgui.cbSize = GUITHREADINFO.sizeof;
+                if (OS.GetGUIThreadInfo (idThread, &lpgui)) {
+                    if (lpgui.hwndCaret is handle || lpgui.hwndCaret is null) {
+                        POINT ptCurrentPos;
+                        if (OS.GetCaretPos (&ptCurrentPos)) {
+                            int endPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, end, 0);
+                            if (endPos is -1) {
+                                int startPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, start, 0);
+                                int startX = cast(short) (startPos & 0xFFFF);
+                                if (ptCurrentPos.x > startX) caret = end;
+                            } else {
+                                int endX = cast(short) (endPos & 0xFFFF);
+                                if (ptCurrentPos.x >= endX) caret = end;
+                            }
+                        }
+                    }
+                }
+            }
+        } else {
+            int caretPos = OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
+            int caretLine = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, caretPos, 0);
+            if (caretLine is endLine) caret = end;
+        }
+    }
+    if (!OS.IsUnicode && OS.IsDBLocale) caret = mbcsToWcsPos (caret);
+    return caret;
+}
+
+/**
+ * Returns the number of characters.
+ *
+ * @return number of characters in the widget
+ *
+ * @exception SWTException <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 int getCharCount () {
+    checkWidget ();
+    int length = OS.GetWindowTextLength (handle);
+    if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length);
+    return length;
+}
+
+/**
+ * Returns the double click enabled flag.
+ * <p>
+ * The double click flag enables or disables the
+ * default action of the text widget when the user
+ * double clicks.
+ * </p>
+ *
+ * @return whether or not double click is enabled
+ *
+ * @exception SWTException <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 getDoubleClickEnabled () {
+    checkWidget ();
+    return doubleClick;
+}
+
+/**
+ * Returns the echo character.
+ * <p>
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer.
+ * </p>
+ *
+ * @return the echo character
+ *
+ * @exception SWTException <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 #setEchoChar
+ */
+public char getEchoChar () {
+    checkWidget ();
+    wchar echo = cast(wchar) OS.SendMessage (handle, OS.EM_GETPASSWORDCHAR, 0, 0);
+    if (echo !is 0 && (echo = Display.mbcsToWcs (echo, getCodePage ())) is 0) echo = '*';
+    return echo;
+}
+
+/**
+ * Returns the editable state.
+ *
+ * @return whether or not the receiver is editable
+ *
+ * @exception SWTException <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 getEditable () {
+    checkWidget ();
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    return (bits & OS.ES_READONLY) is 0;
+}
+
+/**
+ * Returns the number of lines.
+ *
+ * @return the number of lines in the widget
+ *
+ * @exception SWTException <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 int getLineCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
+}
+
+/**
+ * Returns the line delimiter.
+ *
+ * @return a string that is the line delimiter
+ *
+ * @exception SWTException <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 #DELIMITER
+ */
+public String getLineDelimiter () {
+    checkWidget ();
+    return DELIMITER;
+}
+
+/**
+ * Returns the height of a line.
+ *
+ * @return the height of a row of text
+ *
+ * @exception SWTException <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 int getLineHeight () {
+    checkWidget ();
+    HFONT newFont, oldFont;
+    auto hDC = OS.GetDC (handle);
+    newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    TEXTMETRIC tm;
+    OS.GetTextMetrics (hDC, &tm);
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    return tm.tmHeight;
+}
+
+/**
+ * Returns the orientation of the receiver, which will be one of the
+ * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public int getOrientation () {
+    checkWidget();
+    return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+}
+
+/**
+ * Returns the widget message. When the widget is created
+ * with the style <code>SWT.SEARCH</code>, the message text
+ * is displayed as a hint for the user, indicating the
+ * purpose of the field.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not
+ * supported on platforms that do not have this concept.
+ * </p>
+ *
+ * @return the widget message
+ *
+ * @exception SWTException <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 String getMessage () {
+    checkWidget ();
+    return message;
+}
+
+/**
+ * Returns the character position at the given point in the receiver
+ * or -1 if no such position exists. The point is in the coordinate
+ * system of the receiver.
+ * <p>
+ * Indexing is zero based.
+ * </p>
+ *
+ * @return the position of the caret
+ *
+ * @exception SWTException <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
+ */
+//TODO - Javadoc
+/*public*/ int getPosition (Point point) {
+    checkWidget();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    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;
+}
+
+/**
+ * Returns a <code>Point</code> whose x coordinate is the
+ * character position representing the start of the selected
+ * text, and whose y coordinate is the character position
+ * representing the end of the selection. An "empty" selection
+ * is indicated by the x and y coordinates having the same value.
+ * <p>
+ * Indexing is zero based.  The range of a selection is from
+ * 0..N where N is the number of characters in the widget.
+ * </p>
+ *
+ * @return a point representing the selection start and end
+ *
+ * @exception SWTException <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 Point getSelection () {
+    checkWidget ();
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        start = mbcsToWcsPos (start);
+        end = mbcsToWcsPos (end);
+    }
+    return new Point (start, end);
+}
+
+/**
+ * Returns the number of selected characters.
+ *
+ * @return the number of selected characters.
+ *
+ * @exception SWTException <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 int getSelectionCount () {
+    checkWidget ();
+    Point selection = getSelection ();
+    return selection.y - selection.x;
+}
+
+/**
+ * Gets the selected text, or an empty string if there is no current selection.
+ *
+ * @return the selected text
+ *
+ * @exception SWTException <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 String getSelectionText () {
+    checkWidget ();
+    int length = OS.GetWindowTextLength (handle);
+    if (length is 0) return "";
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    if (start is end ) return "";
+    TCHAR[] buffer = NewTCHARs (getCodePage (), length + 1);
+    OS.GetWindowText (handle, buffer.ptr, length + 1);
+    return TCHARsToStr( buffer[ start .. end ] );
+}
+
+/**
+ * Returns the number of tabs.
+ * <p>
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character.  The width of a single
+ * tab stop is the pixel width of the spaces.
+ * </p>
+ *
+ * @return the number of tab characters
+ *
+ * @exception SWTException <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 int getTabs () {
+    checkWidget ();
+    return tabs;
+}
+
+int getTabWidth (int tabs) {
+    HFONT oldFont;
+    RECT rect;
+    auto hDC = OS.GetDC (handle);
+    HFONT newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
+    TCHAR[] SPACE = StrToTCHARs (getCodePage (), " ", false);
+    OS.DrawText (hDC, SPACE.ptr, SPACE.length, &rect, flags);
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+    return (rect.right - rect.left) * tabs;
+}
+
+/**
+ * Returns the widget text.
+ * <p>
+ * The text for a text widget is the characters in the widget, or
+ * an empty string if this has never been set.
+ * </p>
+ *
+ * @return the widget text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget ();
+    int length_ = OS.GetWindowTextLength (handle);
+    if (length_ is 0) return "";
+    TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
+    OS.GetWindowText (handle, buffer.ptr, length_ + 1);
+    return TCHARsToStr( buffer[0 .. length_] );
+}
+
+/**
+ * Returns a range of text.  Returns an empty string if the
+ * start of the range is greater than the end.
+ * <p>
+ * Indexing is zero based.  The range of
+ * a selection is from 0..N-1 where N is
+ * the number of characters in the widget.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ * @return the range of text
+ *
+ * @exception SWTException <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 String getText (int start, int end) {
+    checkWidget ();
+    if (!(start <= end && 0 <= end)) return "";
+    int length = OS.GetWindowTextLength (handle);
+    if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length);
+    start = Math.max (0, start);
+    end = Math.min (end, length - 1);
+    /*
+    * NOTE: The current implementation uses substring ()
+    * which can reference a potentially large character
+    * array.
+    */
+    return getText ().substring (start, end + 1);
+}
+
+/**
+ * Returns the maximum number of characters that the receiver is capable of holding.
+ * <p>
+ * If this has not been changed by <code>setTextLimit()</code>,
+ * it will be the constant <code>Text.LIMIT</code>.
+ * </p>
+ *
+ * @return the text limit
+ *
+ * @exception SWTException <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
+ */
+public int getTextLimit () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+}
+
+/**
+ * Returns the zero-relative index of the line which is currently
+ * at the top of the receiver.
+ * <p>
+ * This index can change when lines are scrolled or new lines are added or removed.
+ * </p>
+ *
+ * @return the index of the top line
+ *
+ * @exception SWTException <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 int getTopIndex () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) return 0;
+    return OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
+}
+
+/**
+ * Returns the top pixel.
+ * <p>
+ * The top pixel is the pixel position of the line
+ * that is currently at the top of the widget.  On
+ * some platforms, a text widget can be scrolled by
+ * pixels instead of lines so that a partial line
+ * is displayed at the top of the widget.
+ * </p><p>
+ * The top pixel changes when the widget is scrolled.
+ * The top pixel does not include the widget trimming.
+ * </p>
+ *
+ * @return the pixel position of the top line
+ *
+ * @exception SWTException <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 int getTopPixel () {
+    checkWidget ();
+    /*
+    * Note, EM_GETSCROLLPOS is implemented in Rich Edit 3.0
+    * and greater.  The plain text widget and previous versions
+    * of Rich Edit return zero.
+    */
+    int [2] buffer;
+    int code = OS.SendMessage (handle, OS.EM_GETSCROLLPOS, 0, buffer.ptr);
+    if (code is 1) return buffer [1];
+    return getTopIndex () * getLineHeight ();
+}
+
+/**
+ * Inserts a string.
+ * <p>
+ * The old selection is replaced with the new text.
+ * </p>
+ *
+ * @param string the string
+ *
+ * @exception SWTException <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 insert (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    string = Display.withCrLf (string);
+    if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+        int start, end;
+        OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+        string = verifyText (string, start, end, null);
+        if (string is null) return;
+    }
+    TCHAR* buffer = StrToTCHARz (getCodePage (), string );
+    /*
+    * Feature in Windows.  When an edit control with ES_MULTILINE
+    * style that does not have the WS_VSCROLL style is full (i.e.
+    * there is no space at the end to draw any more characters),
+    * EM_REPLACESEL sends a WM_CHAR with a backspace character
+    * to remove any further text that is added.  This is an
+    * implementation detail of the edit control that is unexpected
+    * and can cause endless recursion when EM_REPLACESEL is sent
+    * from a WM_CHAR handler.  The fix is to ignore calling the
+    * handler from WM_CHAR.
+    */
+    ignoreCharacter = true;
+    OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+    ignoreCharacter = false;
+}
+
+int mbcsToWcsPos (int mbcsPos) {
+    if (mbcsPos <= 0) return 0;
+    if (OS.IsUnicode) return mbcsPos;
+    int cp = getCodePage ();
+    int wcsTotal = 0, mbcsTotal = 0;
+    CHAR [] buffer = new CHAR [128];
+    String delimiter = getLineDelimiter();
+    int delimiterSize = delimiter.length;
+    int count = OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0);
+    for (int line=0; line<count; line++) {
+        int wcsSize = 0;
+        int linePos = OS.SendMessageA (handle, OS.EM_LINEINDEX, line, 0);
+        int mbcsSize = OS.SendMessageA (handle, OS.EM_LINELENGTH, linePos, 0);
+        if (mbcsSize !is 0) {
+            if (mbcsSize + delimiterSize > buffer.length) {
+                buffer = new CHAR [mbcsSize + delimiterSize];
+            }
+            //ENDIAN
+            buffer [0] = cast(char) (mbcsSize & 0xFF);
+            buffer [1] = cast(char) (mbcsSize >> 8);
+            mbcsSize = OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer.ptr);
+            wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer.ptr, mbcsSize, null, 0);
+        }
+        if (line - 1 !is count) {
+            for (int i=0; i<delimiterSize; i++) {
+                buffer [mbcsSize++] = cast(CHAR) delimiter.charAt (i);
+            }
+            wcsSize += delimiterSize;
+        }
+        if ((mbcsTotal + mbcsSize) >= mbcsPos) {
+            int bufferSize = mbcsPos - mbcsTotal;
+            wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer.ptr, bufferSize, null, 0);
+            return wcsTotal + wcsSize;
+        }
+        wcsTotal += wcsSize;
+        mbcsTotal += mbcsSize;
+    }
+    return wcsTotal;
+}
+
+/**
+ * Pastes text from clipboard.
+ * <p>
+ * The selected text is deleted from the widget
+ * and new text inserted from the clipboard.
+ * </p>
+ *
+ * @exception SWTException <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 paste () {
+    checkWidget ();
+    if ((style & SWT.READ_ONLY) !is 0) return;
+    OS.SendMessage (handle, OS.WM_PASTE, 0, 0);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    message = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver's text is modified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ModifyListener
+ * @see #addModifyListener
+ */
+public void removeModifyListener (ModifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Modify, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is verified.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 VerifyListener
+ * @see #addVerifyListener
+ */
+public void removeVerifyListener (VerifyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Verify, listener);
+}
+
+/**
+ * Selects all the text in the receiver.
+ *
+ * @exception SWTException <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 selectAll () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
+}
+
+override bool sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+    if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
+        return false;
+    }
+    if ((style & SWT.READ_ONLY) !is 0) return true;
+    if (ignoreVerify) return true;
+    if (type !is SWT.KeyDown) return true;
+    if (msg !is OS.WM_CHAR && msg !is OS.WM_KEYDOWN && msg !is OS.WM_IME_CHAR) {
+        return true;
+    }
+    if (event.character is 0) return true;
+    if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
+    char key = event.character;
+    int stateMask = event.stateMask;
+
+    /*
+    * Disable all magic keys that could modify the text
+    * and don't send events when Alt, Shift or Ctrl is
+    * pressed.
+    */
+    switch (msg) {
+        case OS.WM_CHAR:
+            if (key !is 0x08 && key !is 0x7F && key !is '\r' && key !is '\t' && key !is '\n') break;
+            // FALL THROUGH
+        case OS.WM_KEYDOWN:
+            if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) !is 0) return false;
+            break;
+        default:
+    }
+
+    /*
+    * Feature in Windows.  If the left button is down in
+    * the text widget, it refuses the character.  The fix
+    * is to detect this case and avoid sending a verify
+    * event.
+    */
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
+        if (handle is OS.GetCapture()) return true;
+    }
+
+    /* Verify the character */
+    String oldText = "";
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    switch (key) {
+        case 0x08:  /* Bs */
+            if (start is end ) {
+                if (start is 0) return true;
+                int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
+                if (start is lineStart) {
+                    start = start - DELIMITER.length;
+                } else {
+                    start = start - 1;
+                    if (!OS.IsUnicode && OS.IsDBLocale) {
+                        int newStart, newEnd;
+                        OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+                        OS.SendMessage (handle, OS.EM_GETSEL, &newStart, &newEnd);
+                        if (start !is newStart) start = start - 1;
+                    }
+                }
+                start = Math.max (start, 0);
+            }
+            break;
+        case 0x7F:  /* Del */
+            if (start is end) {
+                int length = OS.GetWindowTextLength (handle);
+                if (start is length) return true;
+                int line = OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end, 0);
+                int lineStart = OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0);
+                if (end is lineStart - DELIMITER.length) {
+                    end = end + DELIMITER.length;
+                } else {
+                    end = end + 1;
+                    if (!OS.IsUnicode && OS.IsDBLocale) {
+                        int newStart, newEnd;
+                        OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+                        OS.SendMessage (handle, OS.EM_GETSEL, &newStart, &newEnd);
+                        if (end !is newEnd) end = end + 1;
+                    }
+                }
+                end = Math.min (end, length);
+            }
+            break;
+        case '\r':  /* Return */
+            if ((style & SWT.SINGLE) !is 0) return true;
+            oldText = DELIMITER;
+            break;
+        default:    /* Tab and other characters */
+            if (key !is '\t' && key < 0x20) return true;
+            oldText = [key];
+            break;
+    }
+    String newText = verifyText (oldText, start, end, event);
+    if (newText is null) return false;
+    if (newText is oldText) return true;
+    newText = Display.withCrLf (newText);
+    TCHAR* buffer = StrToTCHARz (getCodePage (), newText);
+    OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+    /*
+    * Feature in Windows.  When an edit control with ES_MULTILINE
+    * style that does not have the WS_VSCROLL style is full (i.e.
+    * there is no space at the end to draw any more characters),
+    * EM_REPLACESEL sends a WM_CHAR with a backspace character
+    * to remove any further text that is added.  This is an
+    * implementation detail of the edit control that is unexpected
+    * and can cause endless recursion when EM_REPLACESEL is sent
+    * from a WM_CHAR handler.  The fix is to ignore calling the
+    * handler from WM_CHAR.
+    */
+    ignoreCharacter = true;
+    OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+    ignoreCharacter = false;
+    return false;
+}
+
+override void setBounds (int x, int y, int width, int height, int flags) {
+    /*
+    * Feature in Windows.  When the caret is moved,
+    * the text widget scrolls to show the new location.
+    * This means that the text widget may be scrolled
+    * to the right in order to show the caret when the
+    * widget is not large enough to show both the caret
+    * location and all the text.  Unfortunately, when
+    * the text widget is resized such that all the text
+    * and the caret could be visible, Windows does not
+    * scroll the widget back.  The fix is to resize the
+    * text widget, set the selection to the start of the
+    * text and then restore the selection.  This will
+    * cause the text widget compute the correct scroll
+    * position.
+    */
+    if ((flags & OS.SWP_NOSIZE) is 0 && width !is 0) {
+        RECT rect;
+        OS.GetWindowRect (handle, &rect);
+        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);
+            if (start !is 0 || end !is 0) {
+                SetWindowPos (handle, null, x, y, width, height, flags);
+                OS.SendMessage (handle, OS.EM_SETSEL, 0, 0);
+                OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+                return;
+            }
+        }
+    }
+    super.setBounds (x, y, width, height, flags);
+}
+
+override void setDefaultFont () {
+    super.setDefaultFont ();
+    setMargins ();
+}
+
+/**
+ * Sets the double click enabled flag.
+ * <p>
+ * The double click flag enables or disables the
+ * default action of the text widget when the user
+ * double clicks.
+ * </p><p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param doubleClick the new double click flag
+ *
+ * @exception SWTException <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 setDoubleClickEnabled (bool doubleClick) {
+    checkWidget ();
+    this.doubleClick = doubleClick;
+}
+
+/**
+ * Sets the echo character.
+ * <p>
+ * The echo character is the character that is
+ * displayed when the user enters text or the
+ * text is changed by the programmer. Setting
+ * the echo character to '\0' clears the echo
+ * character and redraws the original text.
+ * If for any reason the echo character is invalid,
+ * or if the platform does not allow modification
+ * of the echo character, the default echo character
+ * for the platform is used.
+ * </p>
+ *
+ * @param echo the new echo character
+ *
+ * @exception SWTException <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 setEchoChar (char echo) {
+    checkWidget ();
+    if ((style & SWT.MULTI) !is 0) return;
+    if (echo !is 0) {
+        if ((echo = cast(char) Display.wcsToMbcs (echo, getCodePage ())) is 0) echo = '*';
+    }
+    OS.SendMessage (handle, OS.EM_SETPASSWORDCHAR, echo, 0);
+    /*
+    * Bug in Windows.  When the password character is changed,
+    * Windows does not redraw to show the new password character.
+    * The fix is to force a redraw when the character is set.
+    */
+    OS.InvalidateRect (handle, null, true);
+}
+
+/**
+ * Sets the editable state.
+ *
+ * @param editable the new editable state
+ *
+ * @exception SWTException <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 setEditable (bool editable) {
+    checkWidget ();
+    style &= ~SWT.READ_ONLY;
+    if (!editable) style |= SWT.READ_ONLY;
+    OS.SendMessage (handle, OS.EM_SETREADONLY, editable ? 0 : 1, 0);
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    super.setFont (font);
+    setTabStops (tabs);
+    setMargins ();
+}
+
+void setMargins () {
+    /*
+    * Bug in Windows.  When EM_SETCUEBANNER is used to set the
+    * banner text, the control does not take into account the
+    * margins, causing the first character to be clipped.  The
+    * fix is to set the margins to zero.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if ((style & SWT.SEARCH) !is 0) {
+            OS.SendMessage (handle, OS.EM_SETMARGINS, OS.EC_LEFTMARGIN | OS.EC_RIGHTMARGIN, 0);
+        }
+    }
+}
+
+/**
+ * Sets the widget message. When the widget is created
+ * with the style <code>SWT.SEARCH</code>, the message text
+ * is displayed as a hint for the user, indicating the
+ * purpose of the field.
+ * <p>
+ * Note: This operation is a <em>HINT</em> and is not
+ * supported on platforms that do not have this concept.
+ * </p>
+ *
+ * @param message the new message
+ *
+ * @exception SWTException <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 setMessage (String message) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (message is null) error (SWT.ERROR_NULL_ARGUMENT);
+    this.message = message;
+    if (OS.COMCTL32_MAJOR >= 6) {
+        if ((style & SWT.SEARCH) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.ES_MULTILINE) is 0) {
+                OS.SendMessage (handle, OS.EM_SETCUEBANNER, 0, StrToTCHARz( 0, message ));
+            }
+        }
+    }
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ * <p>
+ * Note: This operation is a hint and is not supported on
+ * platforms that do not have this concept.
+ * </p>
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <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 2.1.2
+ */
+public void setOrientation (int orientation) {
+    checkWidget();
+    static if (OS.IsWinCE) return;
+    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
+    int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+    if ((orientation & flags) is 0 || (orientation & flags) is flags) return;
+    style &= ~flags;
+    style |= orientation & flags;
+    int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) {
+        bits |= OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR;
+    } else {
+        bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
+    }
+    OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+    fixAlignment ();
+}
+
+/**
+ * Sets the selection.
+ * <p>
+ * Indexing is zero based.  The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions.  In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N.  This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * regular array indexing rules.
+ * </p>
+ *
+ * @param start new caret position
+ *
+ * @exception SWTException <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 setSelection (int start) {
+    checkWidget ();
+    if (!OS.IsUnicode && OS.IsDBLocale) start = wcsToMbcsPos (start);
+    OS.SendMessage (handle, OS.EM_SETSEL, start, start);
+    OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+}
+
+/**
+ * Sets the selection to the range specified
+ * by the given start and end indices.
+ * <p>
+ * Indexing is zero based.  The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions.  In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N.  This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ * </p>
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @exception SWTException <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 setSelection (int start, int end) {
+    checkWidget ();
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        start = wcsToMbcsPos (start);
+        end = wcsToMbcsPos (end);
+    }
+    OS.SendMessage (handle, OS.EM_SETSEL, start, end);
+    OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+}
+
+override public void setRedraw (bool redraw) {
+    checkWidget ();
+    super.setRedraw (redraw);
+    /*
+    * Feature in Windows.  When WM_SETREDRAW is used to turn
+    * redraw off, the edit control is not scrolled to show the
+    * i-beam.  The fix is to detect that the i-beam has moved
+    * while redraw is turned off and force it to be visible
+    * when redraw is restored.
+    */
+    if (drawCount !is 0) return;
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    if (!redraw) {
+        oldStart = start;  oldEnd = end;
+    } else {
+        if (oldStart is start && oldEnd is end) return;
+        OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+    }
+}
+
+/**
+ * Sets the selection to the range specified
+ * by the given point, where the x coordinate
+ * represents the start index and the y coordinate
+ * represents the end index.
+ * <p>
+ * Indexing is zero based.  The range of
+ * a selection is from 0..N where N is
+ * the number of characters in the widget.
+ * </p><p>
+ * Text selections are specified in terms of
+ * caret positions.  In a text widget that
+ * contains N characters, there are N+1 caret
+ * positions, ranging from 0..N.  This differs
+ * from other functions that address character
+ * position such as getText () that use the
+ * usual array indexing rules.
+ * </p>
+ *
+ * @param selection the point
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setSelection (Point selection) {
+    checkWidget ();
+    if (selection is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSelection (selection.x, selection.y);
+}
+
+/**
+ * Sets the number of tabs.
+ * <p>
+ * Tab stop spacing is specified in terms of the
+ * space (' ') character.  The width of a single
+ * tab stop is the pixel width of the spaces.
+ * </p>
+ *
+ * @param tabs the number of tabs
+ *
+ * </ul>
+ * @exception SWTException <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 setTabs (int tabs) {
+    checkWidget ();
+    if (tabs < 0) return;
+    setTabStops (this.tabs = tabs);
+}
+
+void setTabStops (int tabs) {
+    /*
+    * Feature in Windows.  Windows expects the tab spacing in
+    * dialog units so we must convert from space widths.  Due
+    * 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.LOWORD (OS.GetDialogBaseUnits ());
+    OS.SendMessage (handle, OS.EM_SETTABSTOPS, 1, &width);
+}
+
+/**
+ * Sets the contents of the receiver to the given string. If the receiver has style
+ * SINGLE and the argument contains multiple lines of text, the result of this
+ * operation is undefined and may vary from platform to platform.
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    string = Display.withCrLf (string);
+    if (hooks (SWT.Verify) || filters (SWT.Verify)) {
+        int length = OS.GetWindowTextLength (handle);
+        string = verifyText (string, 0, length, null);
+        if (string is null) return;
+    }
+    int limit = OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+    if (string.length > limit) string = string.substring (0, limit);
+    TCHAR* buffer = StrToTCHARz (getCodePage (), string);
+    OS.SetWindowText (handle, buffer);
+    /*
+    * Bug in Windows.  When the widget is multi line
+    * text widget, it does not send a WM_COMMAND with
+    * control code EN_CHANGE from SetWindowText () to
+    * notify the application that the text has changed.
+    * The fix is to send the event.
+    */
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.ES_MULTILINE) !is 0) {
+        sendEvent (SWT.Modify);
+        // widget could be disposed at this point
+    }
+}
+
+/**
+ * Sets the maximum number of characters that the receiver
+ * is capable of holding to be the argument.
+ * <p>
+ * Instead of trying to set the text limit to zero, consider
+ * creating a read-only text widget.
+ * </p><p>
+ * To reset this value to the default, use <code>setTextLimit(Text.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Text.LIMIT</code> sets the
+ * receiver's limit to <code>Text.LIMIT</code>.
+ * </p>
+ *
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
+ * </ul>
+ * @exception SWTException <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
+ */
+public void setTextLimit (int limit) {
+    checkWidget ();
+    if (limit is 0) error (SWT.ERROR_CANNOT_BE_ZERO);
+    OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit, 0);
+}
+
+/**
+ * Sets the zero-relative index of the line which is currently
+ * at the top of the receiver. This index can change when lines
+ * are scrolled or new lines are added and removed.
+ *
+ * @param index the index of the top item
+ *
+ * @exception SWTException <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 setTopIndex (int index) {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) return;
+    int count = OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
+    index = Math.min (Math.max (index, 0), count - 1);
+    int topIndex = OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
+    OS.SendMessage (handle, OS.EM_LINESCROLL, 0, index - topIndex);
+}
+
+/**
+ * Shows the selection.
+ * <p>
+ * If the selection is already showing
+ * in the receiver, this method simply returns.  Otherwise,
+ * lines are scrolled until the selection is visible.
+ * </p>
+ *
+ * @exception SWTException <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 showSelection () {
+    checkWidget ();
+    OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+}
+
+String verifyText (String string, int start, int end, Event keyEvent) {
+    if (ignoreVerify) return string;
+    Event event = new Event ();
+    event.text = string;
+    event.start = start;
+    event.end = end;
+    if (keyEvent !is null) {
+        event.character = keyEvent.character;
+        event.keyCode = keyEvent.keyCode;
+        event.stateMask = keyEvent.stateMask;
+    }
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        event.start = mbcsToWcsPos (start);
+        event.end = mbcsToWcsPos (end);
+    }
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the verify
+    * event.  If this happens, answer null to cancel
+    * the operation.
+    */
+    sendEvent (SWT.Verify, event);
+    if (!event.doit || isDisposed ()) return null;
+    return event.text;
+}
+
+int wcsToMbcsPos (int wcsPos) {
+    if (wcsPos <= 0) return 0;
+    if (OS.IsUnicode) return wcsPos;
+    int cp = getCodePage ();
+    int wcsTotal = 0, mbcsTotal = 0;
+    CHAR [] buffer = new CHAR [128];
+    String delimiter = getLineDelimiter ();
+    int delimiterSize = delimiter.length;
+    int count = OS.SendMessageA (handle, OS.EM_GETLINECOUNT, 0, 0);
+    for (int line=0; line<count; line++) {
+        int wcsSize = 0;
+        int linePos = OS.SendMessageA (handle, OS.EM_LINEINDEX, line, 0);
+        int mbcsSize = OS.SendMessageA (handle, OS.EM_LINELENGTH, linePos, 0);
+        if (mbcsSize !is 0) {
+            if (mbcsSize + delimiterSize > buffer.length) {
+                buffer = new CHAR [mbcsSize + delimiterSize];
+            }
+            //ENDIAN
+            buffer [0] = cast(char) (mbcsSize & 0xFF);
+            buffer [1] = cast(char) (mbcsSize >> 8);
+            mbcsSize = OS.SendMessageA (handle, OS.EM_GETLINE, line, buffer.ptr);
+            wcsSize = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer.ptr, mbcsSize, null, 0);
+        }
+        if (line - 1 !is count) {
+            for (int i=0; i<delimiterSize; i++) {
+                buffer [mbcsSize++] = cast(byte) delimiter.charAt (i);
+            }
+            wcsSize += delimiterSize;
+        }
+        if ((wcsTotal + wcsSize) >= wcsPos) {
+            wcsSize = 0;
+            int index = 0;
+            while (index < mbcsSize) {
+                if ((wcsTotal + wcsSize) is wcsPos) {
+                    return mbcsTotal + index;
+                }
+                if (OS.IsDBCSLeadByte (buffer [index++])) index++;
+                wcsSize++;
+            }
+            return mbcsTotal + mbcsSize;
+        }
+        wcsTotal += wcsSize;
+        mbcsTotal += mbcsSize;
+    }
+    return mbcsTotal;
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.ES_AUTOHSCROLL;
+    if ((style & SWT.PASSWORD) !is 0) bits |= OS.ES_PASSWORD;
+    if ((style & SWT.CENTER) !is 0) bits |= OS.ES_CENTER;
+    if ((style & SWT.RIGHT) !is 0) bits |= OS.ES_RIGHT;
+    if ((style & SWT.READ_ONLY) !is 0) bits |= OS.ES_READONLY;
+    if ((style & SWT.SINGLE) !is 0) {
+        /*
+        * Feature in Windows.  When a text control is read-only,
+        * uses COLOR_3DFACE for the background .  If the text
+        * controls single-line and is within a tab folder or
+        * some other themed control, using WM_ERASEBKGND and
+        * WM_CTRCOLOR to draw the theme background results in
+        * pixel corruption.  The fix is to use an ES_MULTILINE
+        * text control instead.
+        */
+        if ((style & SWT.READ_ONLY) !is 0) {
+            if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+                if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                    bits |= OS.ES_MULTILINE;
+                }
+            }
+        }
+        return bits;
+    }
+    bits |= OS.ES_MULTILINE | OS.ES_NOHIDESEL | OS.ES_AUTOVSCROLL;
+    if ((style & SWT.WRAP) !is 0) bits &= ~(OS.WS_HSCROLL | OS.ES_AUTOHSCROLL);
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARsToStr(EditClass);
+}
+
+override int windowProc () {
+    return cast(int)EditProc;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (msg is OS.EM_UNDO) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.ES_MULTILINE) is 0) {
+            LRESULT result = wmClipboard (OS.EM_UNDO, wParam, lParam);
+            if (result !is null) return result.value;
+            return callWindowProc (hwnd, OS.EM_UNDO, wParam, lParam);
+        }
+    }
+    if (msg is Display.SWT_RESTORECARET) {
+        callWindowProc (hwnd, OS.WM_KILLFOCUS, 0, 0);
+        callWindowProc (hwnd, OS.WM_SETFOCUS, 0, 0);
+        return 1;
+    }
+    return super.windowProc (hwnd, msg, wParam, lParam);
+}
+
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    if (ignoreCharacter) return null;
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Bug in Windows.  When the user types CTRL and BS
+    * in an edit control, a DEL character is generated.
+    * Rather than deleting the text, the DEL character
+    * is inserted into the control.  The fix is to detect
+    * this case and not call the window proc.
+    */
+    switch (wParam) {
+        case SWT.DEL:
+            if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                return LRESULT.ZERO;
+            }
+        default:
+    }
+
+    /*
+    * Feature in Windows.  For some reason, when the
+    * widget is a single line text widget, when the
+    * user presses tab, return or escape, Windows beeps.
+    * The fix is to look for these keys and not call
+    * the window proc.
+    */
+    if ((style & SWT.SINGLE) !is 0) {
+        switch (wParam) {
+            case SWT.CR:
+                postEvent (SWT.DefaultSelection);
+                // FALL THROUGH
+            case SWT.TAB:
+            case SWT.ESC: return LRESULT.ZERO;
+            default:
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_CLEAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CLEAR (wParam, lParam);
+    if (result !is null) return result;
+    return wmClipboard (OS.WM_CLEAR, wParam, lParam);
+}
+
+override LRESULT WM_CUT (int wParam, int lParam) {
+    LRESULT result = super.WM_CUT (wParam, lParam);
+    if (result !is null) return result;
+    return wmClipboard (OS.WM_CUT, wParam, lParam);
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if ((style & SWT.READ_ONLY) !is 0) {
+        if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.ES_MULTILINE) !is 0) {
+                Control control = findBackgroundControl ();
+                if (control is null && background is -1) {
+                    if ((state & THEME_BACKGROUND) !is 0) {
+                        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                            control = findThemeControl ();
+                            if (control !is null) {
+                                RECT rect;
+                                OS.GetClientRect (handle, &rect);
+                                fillThemeBackground (cast(HANDLE)wParam, control, &rect);
+                                return LRESULT.ONE;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Bug in WinCE PPC.  For some reason, sending WM_GETDLGCODE
+    * to a multi-line edit control causes it to ignore return and
+    * tab keys.  The fix is to return the value which is normally
+    * returned by the text window proc on other versions of Windows.
+    */
+    if (OS.IsPPC) {
+        if ((style & SWT.MULTI) !is 0 && (style & SWT.READ_ONLY) is 0 && lParam is 0) {
+            return new LRESULT (OS.DLGC_HASSETSEL | OS.DLGC_WANTALLKEYS | OS.DLGC_WANTCHARS);
+        }
+    }
+
+    /*
+    * Feature in Windows.  Despite the fact that the
+    * edit control is read only, it still returns a
+    * dialog code indicating that it wants all keys.
+    * The fix is to detect this case and clear the bits.
+    *
+    * NOTE: A read only edit control processes arrow keys
+    * so DLGC_WANTARROWS should not be cleared.
+    */
+    if ((style & SWT.READ_ONLY) !is 0) {
+        int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+        code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB);
+        return new LRESULT (code);
+    }
+    return null;
+}
+
+override LRESULT WM_IME_CHAR (int wParam, int lParam) {
+
+    /* Process a DBCS character */
+    Display display = this.display;
+    display.lastKey = 0;
+    display.lastAscii = wParam;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
+        return LRESULT.ZERO;
+    }
+
+    /*
+    * Feature in Windows.  The Windows text widget uses
+    * two 2 WM_CHAR's to process a DBCS key instead of
+    * using WM_IME_CHAR.  The fix is to allow the text
+    * widget to get the WM_CHAR's but ignore sending
+    * them to the application.
+    */
+    ignoreCharacter = true;
+    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)) {
+        OS.TranslateMessage (&msg);
+        OS.DispatchMessage (&msg);
+    }
+    ignoreCharacter = false;
+
+    sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
+    // widget could be disposed at this point
+    display.lastKey = display.lastAscii = 0;
+    return new LRESULT (result);
+}
+
+override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+    /*
+    * Prevent Windows from processing WM_LBUTTONDBLCLK
+    * when double clicking behavior is disabled by not
+    * calling the window proc.
+    */
+    LRESULT result = null;
+    sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (!sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+    }
+    if (!doubleClick) return LRESULT.ZERO;
+
+    /*
+    * Bug in Windows.  When the last line of text in the
+    * widget is double clicked and the line is empty, Windows
+    * hides the i-beam then moves it to the first line in
+    * the widget but does not scroll to show the user.
+    * If the user types without clicking the mouse, invalid
+    * characters are displayed at the end of each line of
+    * text in the widget.  The fix is to detect this case
+    * and avoid calling the window proc.
+    */
+    int start, end;
+    OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+    if (start  is end ) {
+        int length = OS.GetWindowTextLength (handle);
+        if (length is start) {
+            int code = OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0);
+            if (code is 0) return LRESULT.ZERO;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    static if( OS.IsWinCE )
+    if (OS.IsPPC) {
+        LRESULT result = null;
+        Display display = this.display;
+        display.captureChanged = false;
+        bool dispatch = sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+        /*
+        * Note: On WinCE PPC, only attempt to recognize the gesture for
+        * a context menu when the control contains a valid menu or there
+        * are listeners for the MenuDetect event.
+        *
+        * Note: On WinCE PPC, the gesture that brings up a popup menu
+        * on the text widget must keep the current text selection.  As a
+        * result, the window proc is only called if the menu is not shown.
+        */
+        bool hasMenu = menu !is null && !menu.isDisposed ();
+        if (hasMenu || hooks (SWT.MenuDetect)) {
+            int x = OS.GET_X_LPARAM (lParam);
+            int y = OS.GET_Y_LPARAM (lParam);
+            SHRGINFO shrg;
+            shrg.cbSize = SHRGINFO.sizeof;
+            shrg.hwndClient = handle;
+            shrg.ptDown.x = x;
+            shrg.ptDown.y = y;
+            shrg.dwFlags = OS.SHRG_RETURNCMD;
+            int type = OS.SHRecognizeGesture (&shrg);
+            if (type is OS.GN_CONTEXTMENU) {
+                showMenu (x, y);
+                return LRESULT.ONE;
+            }
+        }
+        if (dispatch) {
+            result = new LRESULT (callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam));
+        } else {
+            result = LRESULT.ZERO;
+        }
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+        return result;
+    }
+    return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+override LRESULT WM_PASTE (int wParam, int lParam) {
+    LRESULT result = super.WM_PASTE (wParam, lParam);
+    if (result !is null) return result;
+    return wmClipboard (OS.WM_PASTE, wParam, lParam);
+}
+
+override LRESULT WM_UNDO (int wParam, int lParam) {
+    LRESULT result = super.WM_UNDO (wParam, lParam);
+    if (result !is null) return result;
+    return wmClipboard (OS.WM_UNDO, wParam, lParam);
+}
+
+LRESULT wmClipboard (int msg, int /*long*/ wParam, int /*long*/ lParam) {
+    if ((style & SWT.READ_ONLY) !is 0) return null;
+    if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
+    bool call = false;
+    int start, end;
+    String newText = null;
+    switch (msg) {
+        case OS.WM_CLEAR:
+        case OS.WM_CUT:
+            OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+            if (start !is end ) {
+                newText = "";
+                call = true;
+            }
+            break;
+        case OS.WM_PASTE:
+            OS.SendMessage (handle, OS.EM_GETSEL, start, end);
+            newText = getClipboardText ();
+            break;
+        case OS.EM_UNDO:
+        case OS.WM_UNDO:
+            if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) !is 0) {
+                ignoreModify = ignoreCharacter = true;
+                OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
+                callWindowProc (handle, msg, wParam, lParam);
+                int length = OS.GetWindowTextLength (handle);
+                int newStart, newEnd;
+                OS.SendMessage (handle, OS.EM_GETSEL, &newStart, &newEnd);
+                if (length !is 0 && newStart !is newEnd) {
+                    TCHAR[] buffer = NewTCHARs (getCodePage (), length + 1);
+                    OS.GetWindowText (handle, buffer.ptr, length + 1);
+                    newText = TCHARsToStr( buffer[ newStart .. newEnd ] );
+                } else {
+                    newText = "";
+                }
+                callWindowProc (handle, msg, wParam, lParam);
+                ignoreModify = ignoreCharacter = false;
+            }
+            break;
+        default:
+    }
+    if (newText !is null) {
+        String oldText = newText;
+        newText = verifyText (newText, start, end, null);
+        if (newText is null) return LRESULT.ZERO;
+        if (newText !=/*eq*/oldText) {
+            if (call) {
+                callWindowProc (handle, msg, wParam, lParam);
+            }
+            newText = Display.withCrLf (newText);
+            TCHAR* buffer = StrToTCHARz(getCodePage (), newText);
+            /*
+            * Feature in Windows.  When an edit control with ES_MULTILINE
+            * style that does not have the WS_VSCROLL style is full (i.e.
+            * there is no space at the end to draw any more characters),
+            * EM_REPLACESEL sends a WM_CHAR with a backspace character
+            * to remove any further text that is added.  This is an
+            * implementation detail of the edit control that is unexpected
+            * and can cause endless recursion when EM_REPLACESEL is sent
+            * from a WM_CHAR handler.  The fix is to ignore calling the
+            * handler from WM_CHAR.
+            */
+            ignoreCharacter = true;
+            OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
+            ignoreCharacter = false;
+            return LRESULT.ZERO;
+        }
+    }
+    if (msg is OS.WM_UNDO) {
+        ignoreVerify = ignoreCharacter = true;
+        callWindowProc (handle, OS.WM_UNDO, wParam, lParam);
+        ignoreVerify = ignoreCharacter = false;
+        return LRESULT.ONE;
+    }
+    return null;
+}
+
+override LRESULT wmColorChild (int wParam, int lParam) {
+    if ((style & SWT.READ_ONLY) !is 0) {
+        if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.ES_MULTILINE) !is 0) {
+                Control control = findBackgroundControl ();
+                if (control is null && background is -1) {
+                    if ((state & THEME_BACKGROUND) !is 0) {
+                        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                            control = findThemeControl ();
+                            if (control !is null) {
+                                OS.SetTextColor (cast(HANDLE) wParam, getForegroundPixel ());
+                                OS.SetBkColor (cast(HANDLE) wParam, getBackgroundPixel ());
+                                OS.SetBkMode (cast(HANDLE) wParam, OS.TRANSPARENT);
+                                return new LRESULT ( cast(int) OS.GetStockObject (OS.NULL_BRUSH));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return super.wmColorChild (wParam, lParam);
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    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
+            * code could have disposed the widget in the modify
+            * event.  If this happens, end the processing of the
+            * Windows message by returning zero as the result of
+            * the window proc.
+            */
+            sendEvent (SWT.Modify);
+            if (isDisposed ()) return LRESULT.ZERO;
+            break;
+        case OS.EN_ALIGN_LTR_EC:
+            style &= ~SWT.RIGHT_TO_LEFT;
+            style |= SWT.LEFT_TO_RIGHT;
+            fixAlignment ();
+            break;
+        case OS.EN_ALIGN_RTL_EC:
+            style &= ~SWT.LEFT_TO_RIGHT;
+            style |= SWT.RIGHT_TO_LEFT;
+            fixAlignment ();
+            break;
+        default:
+    }
+    return super.wmCommandChild (wParam, lParam);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolBar.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1422 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ToolBar;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+
+/**
+ * Instances of this class support the layout of selectable
+ * tool bar items.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>ToolItem</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.
+ * </p><p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>FLAT, WRAP, RIGHT, HORIZONTAL, VERTICAL, SHADOW_OUT</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#toolbar">ToolBar, ToolItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class ToolBar : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.setBackgroundImage setBackgroundImage;
+    alias Composite.setBounds setBounds;
+    alias Composite.windowProc windowProc;
+
+    int lastFocusId;
+    ToolItem [] items;
+    bool ignoreResize, ignoreMouse;
+    ImageList imageList, disabledImageList, hotImageList;
+    private static /+const+/ WNDPROC ToolBarProc;
+    static const TCHAR[] ToolBarClass = OS.TOOLBARCLASSNAME;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, ToolBarClass.ptr, &lpWndClass);
+            ToolBarProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+
+
+
+    /*
+    * From the Windows SDK for TB_SETBUTTONSIZE:
+    *
+    *   "If an application does not explicitly
+    *   set the button size, the size defaults
+    *   to 24 by 22 pixels".
+    */
+    static const int DEFAULT_WIDTH = 24;
+    static const int DEFAULT_HEIGHT = 22;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#FLAT
+ * @see SWT#WRAP
+ * @see SWT#RIGHT
+ * @see SWT#HORIZONTAL
+ * @see SWT#SHADOW_OUT
+ * @see SWT#VERTICAL
+ * @see Widget#checkSubclass()
+ * @see Widget#getStyle()
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+    /*
+    * Ensure that either of HORIZONTAL or VERTICAL is set.
+    * NOTE: HORIZONTAL and VERTICAL have the same values
+    * as H_SCROLL and V_SCROLL so it is necessary to first
+    * clear these bits to avoid scroll bars and then reset
+    * the bits using the original style supplied by the
+    * programmer.
+    *
+    * NOTE: The CCS_VERT style cannot be applied when the
+    * widget is created because of this conflict.
+    */
+    if ((style & SWT.VERTICAL) !is 0) {
+        this.style |= SWT.VERTICAL;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        /*
+        * Feature in Windows.  When a tool bar has the style
+        * TBSTYLE_LIST and has a drop down item, Window leaves
+        * too much padding around the button.  This affects
+        * every button in the tool bar and makes the preferred
+        * height too big.  The fix is to set the TBSTYLE_LIST
+        * when the tool bar contains both text and images.
+        *
+        * NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
+        * set before any item is added or the tool bar does
+        * not lay out properly.  The work around does not run
+        * in this case.
+        */
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            if ((style & SWT.RIGHT) !is 0) bits |= OS.TBSTYLE_LIST;
+        }
+        OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
+    } else {
+        this.style |= SWT.HORIZONTAL;
+    }
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    /*
+    * Bug in Windows.  For some reason, during the processing
+    * of WM_SYSCHAR, the tool bar window proc does not call the
+    * default window proc causing mnemonics for the menu bar
+    * to be ignored.  The fix is to always call the default
+    * window proc for WM_SYSCHAR.
+    */
+    if (msg is OS.WM_SYSCHAR) {
+        return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+    }
+    return OS.CallWindowProc (ToolBarProc, hwnd, msg, wParam, lParam);
+}
+
+static int checkStyle (int style) {
+    /*
+    * On Windows, only flat tool bars can be traversed.
+    */
+    if ((style & SWT.FLAT) is 0) style |= SWT.NO_FOCUS;
+
+    /*
+    * A vertical tool bar cannot wrap because TB_SETROWS
+    * fails when the toolbar has TBSTYLE_WRAPABLE.
+    */
+    if ((style & SWT.VERTICAL) !is 0) style &= ~SWT.WRAP;
+
+    /*
+    * Even though it is legal to create this widget
+    * with scroll bars, they serve no useful purpose
+    * because they do not automatically scroll the
+    * widget's client area.  The fix is to clear
+    * the SWT style.
+    */
+    return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
+}
+
+override void checkBuffered () {
+    super.checkBuffered ();
+    if (OS.COMCTL32_MAJOR >= 6) style |= SWT.DOUBLE_BUFFERED;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if ((style & SWT.VERTICAL) !is 0) {
+        RECT rect;
+        TBBUTTON lpButton;
+        int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+        for (int i=0; i<count; i++) {
+            OS.SendMessage (handle, OS.TB_GETITEMRECT, i, &rect);
+            height = Math.max (height, rect.bottom);
+            OS.SendMessage (handle, OS.TB_GETBUTTON, i, &lpButton);
+            if ((lpButton.fsStyle & OS.BTNS_SEP) !is 0) {
+                TBBUTTONINFO info;
+                info.cbSize = TBBUTTONINFO.sizeof;
+                info.dwMask = OS.TBIF_SIZE;
+                OS.SendMessage (handle, OS.TB_GETBUTTONINFO, lpButton.idCommand, &info);
+                width = Math.max (width, info.cx);
+            } else {
+                width = Math.max (width, rect.right);
+            }
+        }
+    } else {
+        RECT oldRect;
+        OS.GetWindowRect (handle, &oldRect);
+        int oldWidth = oldRect.right - oldRect.left;
+        int oldHeight = oldRect.bottom - oldRect.top;
+        int border = getBorderWidth ();
+        int newWidth = wHint is SWT.DEFAULT ? 0x3FFF : wHint + border * 2;
+        int newHeight = hHint is SWT.DEFAULT ? 0x3FFF : hHint + border * 2;
+        bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        ignoreResize = true;
+        if (redraw) OS.UpdateWindow (handle);
+        int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
+        SetWindowPos (handle, null, 0, 0, newWidth, newHeight, flags);
+        int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+        if (count !is 0) {
+            RECT rect;
+            OS.SendMessage (handle, OS.TB_GETITEMRECT, count - 1, &rect);
+            width = Math.max (width, rect.right);
+            height = Math.max (height, rect.bottom);
+        }
+        SetWindowPos (handle, null, 0, 0, oldWidth, oldHeight, flags);
+        if (redraw) OS.ValidateRect (handle, null);
+        ignoreResize = false;
+    }
+
+    /*
+    * From the Windows SDK for TB_SETBUTTONSIZE:
+    *
+    *   "If an application does not explicitly
+    *   set the button size, the size defaults
+    *   to 24 by 22 pixels".
+    */
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    Rectangle trim = computeTrim (0, 0, width, height);
+    width = trim.width;  height = trim.height;
+    return new Point (width, height);
+}
+
+override public Rectangle computeTrim (int x, int y, int width, int height) {
+    checkWidget ();
+    Rectangle trim = super.computeTrim (x, y, width, height);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.CCS_NODIVIDER) is 0) trim.height += 2;
+    return trim;
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~CANVAS;
+
+    /*
+    * Feature in Windows.  When TBSTYLE_FLAT is used to create
+    * a flat toolbar, for some reason TBSTYLE_TRANSPARENT is
+    * also set.  This causes the toolbar to flicker when it is
+    * moved or resized.  The fix is to clear TBSTYLE_TRANSPARENT.
+    *
+    * NOTE:  This work around is unnecessary on XP.  There is no
+    * flickering and clearing the TBSTYLE_TRANSPARENT interferes
+    * with the XP theme.
+    */
+    if ((style & SWT.FLAT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            bits &= ~OS.TBSTYLE_TRANSPARENT;
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
+    }
+
+    /*
+    * 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.
+    */
+    /*
+    * These lines are intentionally commented.  The tool
+    * bar currently sets this value to 300 so it is not
+    * necessary to set TTM_SETMAXTIPWIDTH.
+    */
+//  int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+//  OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+
+    /*
+    * Feature in Windows.  When the control is created,
+    * it does not use the default system font.  A new HFONT
+    * is created and destroyed when the control is destroyed.
+    * This means that a program that queries the font from
+    * this control, uses the font in another control and then
+    * destroys this control will have the font unexpectedly
+    * destroyed in the other control.  The fix is to assign
+    * the font ourselves each time the control is created.
+    * The control will not destroy a font that it did not
+    * create.
+    */
+    HFONT hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+
+    /* Set the button struct, bitmap and button sizes */
+    OS.SendMessage (handle, OS.TB_BUTTONSTRUCTSIZE, TBBUTTON.sizeof, 0);
+    OS.SendMessage (handle, OS.TB_SETBITMAPSIZE, 0, 0);
+    OS.SendMessage (handle, OS.TB_SETBUTTONSIZE, 0, 0);
+
+    /* Set the extended style bits */
+    int bits = OS.TBSTYLE_EX_DRAWDDARROWS | OS.TBSTYLE_EX_MIXEDBUTTONS | OS.TBSTYLE_EX_HIDECLIPPEDBUTTONS;
+    if (OS.COMCTL32_MAJOR >= 6) bits |= OS.TBSTYLE_EX_DOUBLEBUFFER;
+    OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
+}
+
+void createItem (ToolItem item, int index) {
+    int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+    if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
+    int id = 0;
+    while (id < items.length && items [id] !is null) id++;
+    if (id is items.length) {
+        ToolItem [] newItems = new ToolItem [items.length + 4];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    int bits = item.widgetStyle ();
+    TBBUTTON lpButton;
+    lpButton.idCommand = id;
+    lpButton.fsStyle = cast(byte) bits;
+    lpButton.fsState = cast(byte) OS.TBSTATE_ENABLED;
+
+    /*
+    * Bug in Windows.  Despite the fact that the image list
+    * index has never been set for the item, Windows always
+    * assumes that the image index for the item is valid.
+    * When an item is inserted, the image index is zero.
+    * Therefore, when the first image is inserted and is
+    * assigned image index zero, every item draws with this
+    * image.  The fix is to set the image index to none
+    * when the item is created.  This is not necessary in
+    * the case when the item has the BTNS_SEP style because
+    * separators cannot show images.
+    */
+    if ((bits & OS.BTNS_SEP) is 0) lpButton.iBitmap = OS.I_IMAGENONE;
+    if (OS.SendMessage (handle, OS.TB_INSERTBUTTON, index, &lpButton) is 0) {
+        error (SWT.ERROR_ITEM_NOT_ADDED);
+    }
+    items [item.id = id] = item;
+    if ((style & SWT.VERTICAL) !is 0) setRowCount (count + 1);
+    layoutItems ();
+}
+
+override void createWidget () {
+    super.createWidget ();
+    items = new ToolItem [4];
+    lastFocusId = -1;
+}
+
+override int defaultBackground () {
+    static if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_BTNFACE);
+    return super.defaultBackground ();
+}
+
+void destroyItem (ToolItem item) {
+    TBBUTTONINFO info;
+    info.cbSize = TBBUTTONINFO.sizeof;
+    info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
+    int index = OS.SendMessage (handle, OS.TB_GETBUTTONINFO, item.id, &info);
+    /*
+    * Feature in Windows.  For some reason, a tool item that has
+    * the style BTNS_SEP does not return I_IMAGENONE when queried
+    * for an image index, despite the fact that no attempt has been
+    * made to assign an image to the item.  As a result, operations
+    * on an image list that use the wrong index cause random results.
+    * The fix is to ensure that the tool item is not a separator
+    * before using the image index.  Since separators cannot have
+    * an image and one is never assigned, this is not a problem.
+    */
+    if ((info.fsStyle & OS.BTNS_SEP) is 0 && info.iImage !is OS.I_IMAGENONE) {
+        if (imageList !is null) imageList.put (info.iImage, null);
+        if (hotImageList !is null) hotImageList.put (info.iImage, null);
+        if (disabledImageList !is null) disabledImageList.put (info.iImage, null);
+    }
+    OS.SendMessage (handle, OS.TB_DELETEBUTTON, index, 0);
+    if (item.id is lastFocusId) lastFocusId = -1;
+    items [item.id] = null;
+    item.id = -1;
+    int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+    if (count is 0) {
+        if (imageList !is null) {
+            OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
+            display.releaseToolImageList (imageList);
+        }
+        if (hotImageList !is null) {
+            OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
+            display.releaseToolHotImageList (hotImageList);
+        }
+        if (disabledImageList !is null) {
+            OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
+            display.releaseToolDisabledImageList (disabledImageList);
+        }
+        imageList = hotImageList = disabledImageList = null;
+        items = new ToolItem [4];
+    }
+    if ((style & SWT.VERTICAL) !is 0) setRowCount (count - 1);
+    layoutItems ();
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    /*
+    * Bug in Windows.  When a tool item with the style
+    * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
+    * disabled, the item does not draw using the disabled
+    * image.  The fix is to use the disabled image in all
+    * image lists for the item.
+    *
+    * Feature in Windows.  When a tool bar is disabled,
+    * the text draws disabled but the images do not.
+    * The fix is to use the disabled image in all image
+    * lists for all items.
+    */
+    for (int i=0; i<items.length; i++) {
+        ToolItem item = items [i];
+        if (item !is null) {
+            if ((item.style & SWT.SEPARATOR) is 0) {
+                item.updateImages (enabled && item.getEnabled ());
+            }
+        }
+    }
+}
+
+ImageList getDisabledImageList () {
+    return disabledImageList;
+}
+
+ImageList getHotImageList () {
+    return hotImageList;
+}
+
+ImageList getImageList () {
+    return imageList;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 ToolItem getItem (int index) {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+    if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
+    TBBUTTON lpButton;
+    int result = OS.SendMessage (handle, OS.TB_GETBUTTON, index, &lpButton);
+    if (result is 0) error (SWT.ERROR_CANNOT_GET_ITEM);
+    return items [lpButton.idCommand];
+}
+
+/**
+ * Returns the 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 item at the given point
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 ToolItem getItem (Point point) {
+    checkWidget ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    ToolItem [] items = getItems ();
+    for (int i=0; i<items.length; i++) {
+        Rectangle rect = items [i].getBounds ();
+        if (rect.contains (point)) return items [i];
+    }
+    return null;
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+}
+
+/**
+ * Returns an array of <code>ToolItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 ToolItem [] getItems () {
+    checkWidget ();
+    int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+    TBBUTTON lpButton;
+    ToolItem [] result = new ToolItem [count];
+    for (int i=0; i<count; i++) {
+        OS.SendMessage (handle, OS.TB_GETBUTTON, i, &lpButton);
+        result [i] = items [lpButton.idCommand];
+    }
+    return result;
+}
+
+/**
+ * Returns the number of rows in the receiver. When
+ * the receiver has the <code>WRAP</code> style, the
+ * number of rows can be greater than one.  Otherwise,
+ * the number of rows is always one.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getRowCount () {
+    checkWidget ();
+    if ((style & SWT.VERTICAL) !is 0) {
+        return OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+    }
+    return OS.SendMessage (handle, OS.TB_GETROWS, 0, 0);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the tool item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the tool item has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 int indexOf (ToolItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    return OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, item.id, 0);
+}
+
+void layoutItems () {
+    /*
+    * Feature in Windows.  When a tool bar has the style
+    * TBSTYLE_LIST and has a drop down item, Window leaves
+    * too much padding around the button.  This affects
+    * every button in the tool bar and makes the preferred
+    * height too big.  The fix is to set the TBSTYLE_LIST
+    * when the tool bar contains both text and images.
+    *
+    * NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
+    * set before any item is added or the tool bar does
+    * not lay out properly.  The work around does not run
+    * in this case.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if ((style & SWT.RIGHT) !is 0 && (style & SWT.VERTICAL) is 0) {
+            bool hasText = false, hasImage = false;
+            for (int i=0; i<items.length; i++) {
+                ToolItem item = items [i];
+                if (item !is null) {
+                    if (!hasText) hasText = item.text.length !is 0;
+                    if (!hasImage) hasImage = item.image !is null;
+                    if (hasText && hasImage) break;
+                }
+            }
+            int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+            if (hasText && hasImage) {
+                newBits |= OS.TBSTYLE_LIST;
+            } else {
+                newBits &= ~OS.TBSTYLE_LIST;
+            }
+            if (newBits !is oldBits) {
+                setDropDownItems (false);
+                OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+                /*
+                * Feature in Windows.  For some reason, when the style
+                * is changed to TBSTYLE_LIST, Windows does not lay out
+                * the tool items.  The fix is to use WM_SETFONT to force
+                * the tool bar to redraw and lay out.
+                */
+                auto hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+                setDropDownItems (true);
+            }
+        }
+    }
+
+    if ((style & SWT.WRAP) !is 0) {
+        OS.SendMessage (handle, OS.TB_AUTOSIZE, 0, 0);
+    }
+    /*
+    *  When the tool bar is vertical, make the width of each button
+    *  be the width of the widest button in the tool bar.  Note that
+    *  when the tool bar contains a drop down item, it needs to take
+    *  into account extra padding.
+    */
+    if ((style & SWT.VERTICAL) !is 0) {
+        TBBUTTONINFO info;
+        info.cbSize = TBBUTTONINFO.sizeof;
+        info.dwMask = OS.TBIF_SIZE;
+        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];
+            if (item !is null && (item.style & SWT.DROP_DOWN) !is 0) break;
+            index++;
+        }
+        if (index < items.length) {
+            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];
+            if (item !is null && (item.style & SWT.SEPARATOR) is 0) {
+                OS.SendMessage (handle, OS.TB_SETBUTTONINFO, item.id, &info);
+            }
+        }
+    }
+    for (int i=0; i<items.length; i++) {
+        ToolItem item = items [i];
+        if (item !is null) item.resizeControl ();
+    }
+}
+
+override bool mnemonicHit (wchar ch) {
+    int key = Display.wcsToMbcs (ch);
+    int id;
+    if (OS.SendMessage (handle, OS.TB_MAPACCELERATOR, key, &id) is 0) {
+        return false;
+    }
+    if ((style & SWT.FLAT) !is 0 && !setTabGroupFocus ()) return false;
+    int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, id, 0);
+    if (index is -1) return false;
+    OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
+    items [id].click (false);
+    return true;
+}
+
+override bool mnemonicMatch (wchar ch) {
+    int key = Display.wcsToMbcs (ch);
+    int id;
+    if (OS.SendMessage (handle, OS.TB_MAPACCELERATOR, key, &id) is 0) {
+        return false;
+    }
+    /*
+    * Feature in Windows.  TB_MAPACCELERATOR matches either the mnemonic
+    * character or the first character in a tool item.  This behavior is
+    * undocumented and unwanted.  The fix is to ensure that the tool item
+    * contains a mnemonic when TB_MAPACCELERATOR returns true.
+    */
+    int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, id, 0);
+    if (index is -1) return false;
+    return findMnemonic (items [id].text) !is '\0';
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        for (int i=0; i<items.length; i++) {
+            ToolItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (imageList !is null) {
+        OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
+        display.releaseToolImageList (imageList);
+    }
+    if (hotImageList !is null) {
+        OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
+        display.releaseToolHotImageList (hotImageList);
+    }
+    if (disabledImageList !is null) {
+        OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
+        display.releaseToolDisabledImageList (disabledImageList);
+    }
+    imageList = hotImageList = disabledImageList = null;
+}
+
+override void removeControl (Control control) {
+    super.removeControl (control);
+    for (int i=0; i<items.length; i++) {
+        ToolItem item = items [i];
+        if (item !is null && item.control is control) {
+            item.setControl (null);
+        }
+    }
+}
+
+override void setBackgroundImage (HBITMAP hBitmap) {
+    super.setBackgroundImage (hBitmap);
+    setBackgroundTransparent (hBitmap !is null);
+}
+
+override void setBackgroundPixel (int pixel) {
+    super.setBackgroundPixel (pixel);
+    setBackgroundTransparent (pixel !is -1);
+}
+
+void setBackgroundTransparent (bool transparent) {
+    /*
+    * Feature in Windows.  When TBSTYLE_TRANSPARENT is set
+    * in a tool bar that is drawing a background, images in
+    * the image list that include transparency information
+    * do not draw correctly.  The fix is to clear and set
+    * TBSTYLE_TRANSPARENT depending on the background color.
+    *
+    * NOTE:  This work around is unnecessary on XP.  The
+    * TBSTYLE_TRANSPARENT style is never cleared on that
+    * platform.
+    */
+    if ((style & SWT.FLAT) !is 0) {
+        if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if (!transparent && findBackgroundControl () is null) {
+                bits &= ~OS.TBSTYLE_TRANSPARENT;
+            } else {
+                bits |= OS.TBSTYLE_TRANSPARENT;
+            }
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
+    }
+}
+
+override void setBounds (int x, int y, int width, int height, int flags) {
+    /*
+    * Feature in Windows.  For some reason, when a tool bar is
+    * repositioned more than once using DeferWindowPos () into
+    * the same HDWP, the toolbar redraws more than once, defeating
+    * the purpose of DeferWindowPos ().  The fix is to end the
+    * deferred positioning before the next tool bar is added,
+    * ensuring that only one tool bar position is deferred at
+    * any given time.
+    */
+    if (parent.lpwp !is null) {
+        if (drawCount is 0 && OS.IsWindowVisible (handle)) {
+            parent.setResizeChildren (false);
+            parent.setResizeChildren (true);
+        }
+    }
+    super.setBounds (x, y, width, height, flags);
+}
+
+override void setDefaultFont () {
+    super.setDefaultFont ();
+    OS.SendMessage (handle, OS.TB_SETBITMAPSIZE, 0, 0);
+    OS.SendMessage (handle, OS.TB_SETBUTTONSIZE, 0, 0);
+}
+
+void setDropDownItems (bool set) {
+    /*
+    * Feature in Windows.  When the first button in a tool bar
+    * is a drop down item, Window leaves too much padding around
+    * the button.  This affects every button in the tool bar and
+    * makes the preferred height too big.  The fix is clear the
+    * BTNS_DROPDOWN before Windows lays out the tool bar and set
+    * the bit afterwards.
+    *
+    * NOTE:  This work around only runs when the tool bar contains
+    * both text and images.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        bool hasText = false, hasImage = false;
+        for (int i=0; i<items.length; i++) {
+            ToolItem item = items [i];
+            if (item !is null) {
+                if (!hasText) hasText = item.text.length !is 0;
+                if (!hasImage) hasImage = item.image !is null;
+                if (hasText && hasImage) break;
+            }
+        }
+        if (hasImage && !hasText) {
+            for (int i=0; i<items.length; i++) {
+                ToolItem item = items [i];
+                if (item !is null && (item.style & SWT.DROP_DOWN) !is 0) {
+                    TBBUTTONINFO info;
+                    info.cbSize = TBBUTTONINFO.sizeof;
+                    info.dwMask = OS.TBIF_STYLE;
+                    OS.SendMessage (handle, OS.TB_GETBUTTONINFO, item.id, &info);
+                    if (set) {
+                        info.fsStyle |= OS.BTNS_DROPDOWN;
+                    } else {
+                        info.fsStyle &= ~OS.BTNS_DROPDOWN;
+                    }
+                    OS.SendMessage (handle, OS.TB_SETBUTTONINFO, item.id, &info);
+                }
+            }
+        }
+    }
+}
+
+void setDisabledImageList (ImageList imageList) {
+    if (disabledImageList is imageList) return;
+    HBITMAP hImageList;
+    if ((disabledImageList = imageList) !is null) {
+        hImageList = disabledImageList.getHandle ();
+    }
+    setDropDownItems (false);
+    OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, hImageList);
+    setDropDownItems (true);
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    setDropDownItems (false);
+    super.setFont (font);
+    setDropDownItems (true);
+    /*
+    * Bug in Windows.  When WM_SETFONT is sent to a tool bar
+    * that contains only separators, causes the bitmap and button
+    * sizes to be set.  The fix is to reset these sizes after the font
+    * has been changed when the tool bar contains only separators.
+    */
+    int index = 0;
+    int mask = SWT.PUSH | SWT.CHECK | SWT.RADIO | SWT.DROP_DOWN;
+    while (index < items.length) {
+        ToolItem item = items [index];
+        if (item !is null && (item.style & mask) !is 0) break;
+        index++;
+    }
+    if (index is items.length) {
+        OS.SendMessage (handle, OS.TB_SETBITMAPSIZE, 0, 0);
+        OS.SendMessage (handle, OS.TB_SETBUTTONSIZE, 0, 0);
+    }
+    layoutItems ();
+}
+
+void setHotImageList (ImageList imageList) {
+    if (hotImageList is imageList) return;
+    HBITMAP hImageList;
+    if ((hotImageList = imageList) !is null) {
+        hImageList = hotImageList.getHandle ();
+    }
+    setDropDownItems (false);
+    OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, hImageList);
+    setDropDownItems (true);
+}
+
+void setImageList (ImageList imageList) {
+    if (this.imageList is imageList) return;
+    HBITMAP hImageList;
+    if ((this.imageList = imageList) !is null) {
+        hImageList = imageList.getHandle ();
+    }
+    setDropDownItems (false);
+    OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, hImageList);
+    setDropDownItems (true);
+}
+
+override public bool setParent (Composite parent) {
+    checkWidget ();
+    if (!super.setParent (parent)) return false;
+    OS.SendMessage (handle, OS.TB_SETPARENT, parent.handle, 0);
+    return true;
+}
+
+override public void setRedraw (bool redraw) {
+    checkWidget ();
+    setDropDownItems (false);
+    super.setRedraw (redraw);
+    setDropDownItems (true);
+}
+
+void setRowCount (int count) {
+    if ((style & SWT.VERTICAL) !is 0) {
+        /*
+        * Feature in Windows.  When the TB_SETROWS is used to set the
+        * number of rows in a tool bar, the tool bar is resized to show
+        * the items.  This is unexpected.  The fix is to save and restore
+        * the current size of the tool bar.
+        */
+        RECT rect;
+        OS.GetWindowRect (handle, &rect);
+        OS.MapWindowPoints (null, parent.handle, cast(POINT*) &rect, 2);
+        ignoreResize = true;
+        /*
+        * Feature in Windows.  When the last button in a tool bar has the
+        * style BTNS_SEP and TB_SETROWS is used to set the number of rows
+        * in the tool bar, depending on the number of buttons, the toolbar
+        * will wrap items with the style BTNS_CHECK, even when the fLarger
+        * flags is used to force the number of rows to be larger than the
+        * number of items.  The fix is to set the number of rows to be two
+        * larger than the actual number of rows in the tool bar.  When items
+        * are being added, as long as the number of rows is at least one
+        * item larger than the count, the tool bar is laid out properly.
+        * When items are being removed, setting the number of rows to be
+        * one more than the item count has no effect.  The number of rows
+        * is already one more causing TB_SETROWS to do nothing.  Therefore,
+        * choosing two instead of one as the row increment fixes both cases.
+        */
+        count += 2;
+        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;
+    }
+}
+
+override bool setTabItemFocus () {
+    int index = 0;
+    while (index < items.length) {
+        ToolItem item = items [index];
+        if (item !is null && (item.style & SWT.SEPARATOR) is 0) {
+            if (item.getEnabled ()) break;
+        }
+        index++;
+    }
+    if (index is items.length) return false;
+    return super.setTabItemFocus ();
+}
+
+override String toolTipText (NMTTDISPINFO* hdr) {
+    if ((hdr.uFlags & OS.TTF_IDISHWND) !is 0) {
+        return null;
+    }
+    /*
+    * Bug in Windows.  On Windows XP, when TB_SETHOTITEM is
+    * used to set the hot item, the tool bar control attempts
+    * to display the tool tip, even when the cursor is not in
+    * the hot item.  The fix is to detect this case and fail to
+    * provide the string, causing no tool tip to be displayed.
+    */
+    if (!hasCursor ()) return ""; //$NON-NLS-1$
+    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 & SWT.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];
+            if (item !is null) return item.toolTipText;
+        }
+    }
+    return super.toolTipText (hdr);
+}
+
+override int widgetStyle () {
+    int bits = super.widgetStyle () | OS.CCS_NORESIZE | OS.TBSTYLE_TOOLTIPS | OS.TBSTYLE_CUSTOMERASE;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) bits |= OS.TBSTYLE_TRANSPARENT;
+    if ((style & SWT.SHADOW_OUT) is 0) bits |= OS.CCS_NODIVIDER;
+    if ((style & SWT.WRAP) !is 0) bits |= OS.TBSTYLE_WRAPABLE;
+    if ((style & SWT.FLAT) !is 0) bits |= OS.TBSTYLE_FLAT;
+    /*
+    * Feature in Windows.  When a tool bar has the style
+    * TBSTYLE_LIST and has a drop down item, Window leaves
+    * too much padding around the button.  This affects
+    * every button in the tool bar and makes the preferred
+    * height too big.  The fix is to set the TBSTYLE_LIST
+    * when the tool bar contains both text and images.
+    *
+    * NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
+    * set before any item is added or the tool bar does
+    * not lay out properly.  The work around does not run
+    * in this case.
+    */
+    if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
+        if ((style & SWT.RIGHT) !is 0) bits |= OS.TBSTYLE_LIST;
+    }
+    return bits;
+}
+
+override String windowClass () {
+    return TCHARsToStr(ToolBarClass);
+}
+
+override int windowProc () {
+    return cast(int)ToolBarProc;
+}
+
+override LRESULT WM_CAPTURECHANGED (int wParam, int lParam) {
+    LRESULT result = super.WM_CAPTURECHANGED (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  When the tool bar loses capture while an
+    * item is pressed, the item remains pressed.  The fix is
+    * unpress all items using TB_SETSTATE and TBSTATE_PRESSED.
+    */
+    for (int i=0; i<items.length; i++) {
+        ToolItem item = items [i];
+        if (item !is null) {
+            int fsState = OS.SendMessage (handle, OS.TB_GETSTATE, item.id, 0);
+            if ((fsState & OS.TBSTATE_PRESSED) !is 0) {
+                fsState &= ~OS.TBSTATE_PRESSED;
+                OS.SendMessage (handle, OS.TB_SETSTATE, item.id, fsState);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+    switch (wParam) {
+        case ' ':
+            int index = OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
+            if (index !is -1) {
+                TBBUTTON lpButton;
+                int code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, &lpButton);
+                if (code !is 0) {
+                    items [lpButton.idCommand].click (false);
+                    return LRESULT.ZERO;
+                }
+            }
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_COMMAND (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the toolbar window
+    * proc processes WM_COMMAND, it forwards this
+    * message to its parent.  This is done so that
+    * children of this control that send this message
+    * type to their parent will notify not only
+    * this control but also the parent of this control,
+    * which is typically the application window and
+    * the window that is looking for the message.
+    * If the control did not forward the message,
+    * applications would have to subclass the control
+    * window to see the message. Because the control
+    * window is subclassed by SWT, the message
+    * is delivered twice, once by SWT and once when
+    * the message is forwarded by the window proc.
+    * The fix is to avoid calling the window proc
+    * for this control.
+    */
+    LRESULT result = super.WM_COMMAND (wParam, lParam);
+    if (result !is null) return result;
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    /*
+    * Bug in Windows.  For some reason, NM_CUSTOMDRAW with
+    * CDDS_PREERASE and CDDS_POSTERASE is never sent for
+    * versions of Windows earlier than XP.  The fix is to
+    * draw the background in WM_ERASEBKGND;
+    */
+    if (findBackgroundControl () !is null) {
+        if (OS.COMCTL32_MAJOR < 6) {
+            drawBackground (cast(HANDLE) wParam);
+            return LRESULT.ONE;
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+    LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+    /*
+    * Return DLGC_BUTTON so that mnemonics will be
+    * processed without needing to press the ALT key
+    * when the widget has focus.
+    */
+    if (result !is null) return result;
+    return new LRESULT (OS.DLGC_BUTTON);
+}
+
+override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    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 the opportunity to cancel the operation.
+            */
+            return LRESULT.ZERO;
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    int index = OS.SendMessage (handle, OS.TB_GETHOTITEM, 0, 0);
+    TBBUTTON lpButton;
+    int code = OS.SendMessage (handle, OS.TB_GETBUTTON, index, &lpButton);
+    if (code !is 0) lastFocusId = lpButton.idCommand;
+    return super.WM_KILLFOCUS (wParam, lParam);
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    if (ignoreMouse) return null;
+    return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
+override LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+    if (ignoreMouse) return null;
+    return super.WM_LBUTTONUP (wParam, lParam);
+}
+
+override LRESULT WM_MOUSELEAVE (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSELEAVE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  On XP, when a tooltip is
+    * hidden due to a time out or mouse press,
+    * the tooltip remains active although no
+    * longer visible and won't show again until
+    * another tooltip becomes active.  If there
+    * is only one tooltip in the window,  it will
+    * never show again.  The fix is to remove the
+    * current tooltip and add it again every time
+    * the mouse leaves the control.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+        if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+            if ((lpti.uFlags & OS.TTF_IDISHWND) is 0) {
+                OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, &lpti);
+                OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, &lpti);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_NOTIFY (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the toolbar window
+    * proc processes WM_NOTIFY, it forwards this
+    * message to its parent.  This is done so that
+    * children of this control that send this message
+    * type to their parent will notify not only
+    * this control but also the parent of this control,
+    * which is typically the application window and
+    * the window that is looking for the message.
+    * If the control did not forward the message,
+    * applications would have to subclass the control
+    * window to see the message. Because the control
+    * window is subclassed by SWT, the message
+    * is delivered twice, once by SWT and once when
+    * the message is forwarded by the window proc.
+    * The fix is to avoid calling the window proc
+    * for this control.
+    */
+    LRESULT result = super.WM_NOTIFY (wParam, lParam);
+    if (result !is null) return result;
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFOCUS (wParam, lParam);
+    if (lastFocusId !is -1 && handle is OS.GetFocus ()) {
+        int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lastFocusId, 0);
+        OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    if (ignoreResize) {
+        int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+        if (code is 0) return LRESULT.ZERO;
+        return new LRESULT (code);
+    }
+    LRESULT result = super.WM_SIZE (wParam, lParam);
+    if (isDisposed ()) return result;
+    /*
+    * Bug in Windows.  The code in Windows that determines
+    * when tool items should wrap seems to use the window
+    * bounds rather than the client area.  Unfortunately,
+    * tool bars with the style TBSTYLE_EX_HIDECLIPPEDBUTTONS
+    * use the client area.  This means that buttons which
+    * overlap the border are hidden before they are wrapped.
+    * The fix is to compute TBSTYLE_EX_HIDECLIPPEDBUTTONS
+    * and set it each time the tool bar is resized.
+    */
+    if ((style & SWT.BORDER) !is 0 && (style & SWT.WRAP) !is 0) {
+        RECT windowRect;
+        OS.GetWindowRect (handle, &windowRect);
+        int index = 0, border = getBorderWidth () * 2;
+        RECT rect;
+        int count = OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
+        while (index < count) {
+            OS.SendMessage (handle, OS.TB_GETITEMRECT, index, &rect);
+            OS.MapWindowPoints (handle, null, cast(POINT*) &rect, 2);
+            if (rect.right > windowRect.right - border * 2) break;
+            index++;
+        }
+        int bits = OS.SendMessage (handle, OS.TB_GETEXTENDEDSTYLE, 0, 0);
+        if (index is count) {
+            bits |= OS.TBSTYLE_EX_HIDECLIPPEDBUTTONS;
+        } else {
+            bits &= ~OS.TBSTYLE_EX_HIDECLIPPEDBUTTONS;
+        }
+        OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
+    }
+    layoutItems ();
+    return result;
+}
+
+override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    if (result !is null) return result;
+    if (ignoreResize) return result;
+    /*
+    * Bug in Windows.  When a flat tool bar is wrapped,
+    * Windows draws a horizontal separator between the
+    * rows.  The tool bar does not draw the first or
+    * the last two pixels of this separator.  When the
+    * toolbar is resized to be bigger, only the new
+    * area is drawn and the last two pixels, which are
+    * blank are drawn over by separator.  This leaves
+    * garbage on the screen.  The fix is to damage the
+    * pixels.
+    */
+    if (drawCount !is 0) return result;
+    if ((style & SWT.WRAP) is 0) return result;
+    if (!OS.IsWindowVisible (handle)) return result;
+    if (OS.SendMessage (handle, OS.TB_GETROWS, 0, 0) is 1) {
+        return result;
+    }
+    WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+    //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
+    if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) !is 0) {
+        return result;
+    }
+    RECT oldRect;
+    OS.GetClientRect (handle, &oldRect);
+    RECT newRect;
+    OS.SetRect (&newRect, 0, 0, lpwp.cx, lpwp.cy);
+    OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &newRect);
+    int oldWidth = oldRect.right - oldRect.left;
+    int newWidth = newRect.right - newRect.left;
+    if (newWidth > oldWidth) {
+        RECT rect;
+        int newHeight = newRect.bottom - newRect.top;
+        OS.SetRect (&rect, oldWidth - 2, 0, oldWidth, newHeight);
+        OS.InvalidateRect (handle, &rect, false);
+    }
+    return result;
+}
+
+override LRESULT wmCommandChild (int wParam, int lParam) {
+    ToolItem child = items [OS.LOWORD (wParam)];
+    if (child is null) return null;
+    return child.wmCommandChild (wParam, lParam);
+}
+
+override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
+    switch (hdr.code) {
+        case OS.TBN_DROPDOWN:
+            NMTOOLBAR* lpnmtb = cast(NMTOOLBAR*)lParam;
+            //OS.MoveMemory (lpnmtb, lParam, NMTOOLBAR.sizeof);
+            ToolItem child = items [lpnmtb.iItem];
+            if (child !is null) {
+                Event event = new Event ();
+                event.detail = SWT.ARROW;
+                int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmtb.iItem, 0);
+                RECT rect;
+                OS.SendMessage (handle, OS.TB_GETITEMRECT, index, &rect);
+                event.x = rect.left;
+                event.y = rect.bottom;
+                child.postEvent (SWT.Selection, event);
+            }
+            break;
+        case OS.NM_CUSTOMDRAW:
+            if (OS.COMCTL32_MAJOR < 6) break;
+            /*
+            * Bug in Windows.  For some reason, under the XP Silver
+            * theme, tool bars continue to draw using the gray color
+            * from the default Blue theme.  The fix is to draw the
+            * background.
+            */
+            NMCUSTOMDRAW* nmcd = cast(NMCUSTOMDRAW*)lParam;
+            //OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
+//          if (drawCount !is 0 || !OS.IsWindowVisible (handle)) {
+//              if (!OS.IsWinCE && OS.WindowFromDC (nmcd.hdc) is handle) break;
+//          }
+            switch (nmcd.dwDrawStage) {
+                case OS.CDDS_PREERASE: {
+                    /*
+                    * Bug in Windows.  When a tool bar does not have the style
+                    * TBSTYLE_FLAT, the rectangle to be erased in CDDS_PREERASE
+                    * is empty.  The fix is to draw the whole client area.
+                    */
+                    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                    if ((bits & OS.TBSTYLE_FLAT) is 0) {
+                        drawBackground (nmcd.hdc);
+                    } else {
+                        RECT rect;
+                        OS.SetRect (&rect, nmcd.rc.left, nmcd.rc.top, nmcd.rc.right, nmcd.rc.bottom);
+                        drawBackground (nmcd.hdc, &rect);
+                    }
+                    return new LRESULT (OS.CDRF_SKIPDEFAULT);
+                }
+                default:
+            }
+            break;
+        case OS.TBN_HOTITEMCHANGE:
+            static if (!OS.IsWinCE) {
+                auto lpnmhi = cast(NMTBHOTITEM*)lParam;
+                //OS.MoveMemory (lpnmhi, lParam, NMTBHOTITEM.sizeof);
+                switch (lpnmhi.dwFlags) {
+                    case OS.HICF_ARROWKEYS:
+                        RECT client;
+                        OS.GetClientRect (handle, &client);
+                        int index = OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmhi.idNew, 0);
+                        RECT rect;
+                        OS.SendMessage (handle, OS.TB_GETITEMRECT, index, &rect);
+                        if (rect.right > client.right || rect.bottom > client.bottom) {
+                            return LRESULT.ONE;
+                        }
+                        break;
+                    default:
+                }
+            }
+            break;
+        default:
+    }
+    return super.wmNotifyChild (hdr, wParam, lParam);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,972 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ToolItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a button in a tool bar.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>PUSH, CHECK, RADIO, SEPARATOR, DROP_DOWN</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the styles CHECK, PUSH, RADIO, SEPARATOR and DROP_DOWN
+ * may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#toolbar">ToolBar, ToolItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class ToolItem : Item {
+    ToolBar parent;
+    Control control;
+    String toolTipText;
+    Image disabledImage, hotImage;
+    Image disabledImage2;
+    int id;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>ToolBar</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (ToolBar parent, int style) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    parent.createItem (this, parent.getItemCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>ToolBar</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#PUSH
+ * @see SWT#CHECK
+ * @see SWT#RADIO
+ * @see SWT#SEPARATOR
+ * @see SWT#DROP_DOWN
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (ToolBar parent, int style, int index) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called when the mouse is over the arrow portion of a drop-down tool,
+ * the event object detail field contains the value <code>SWT.ARROW</code>.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user,
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.PUSH, SWT.CHECK, SWT.RADIO, SWT.SEPARATOR, SWT.DROP_DOWN, 0);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void click (bool dropDown) {
+    auto hwnd = parent.handle;
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) return;
+    int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+    RECT rect;
+    OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect);
+    int hotIndex = OS.SendMessage (hwnd, OS.TB_GETHOTITEM, 0, 0);
+
+    /*
+    * In order to emulate all the processing that
+    * happens when a mnemonic key is pressed, fake
+    * a mouse press and release.  This will ensure
+    * that radio and pull down items are handled
+    * properly.
+    */
+    int y = rect.top + (rect.bottom - rect.top) / 2;
+    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);
+    parent.ignoreMouse = false;
+
+    if (hotIndex !is -1) {
+        OS.SendMessage (hwnd, OS.TB_SETHOTITEM, hotIndex, 0);
+    }
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    checkWidget();
+    auto hwnd = parent.handle;
+    int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+    RECT rect;
+    OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect);
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns the control that is used to fill the bounds of
+ * the item when the item is a <code>SEPARATOR</code>.
+ *
+ * @return the control
+ *
+ * @exception SWTException <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 Control getControl () {
+    checkWidget();
+    return control;
+}
+
+/**
+ * Returns the receiver's disabled image if it has one, or null
+ * if it does not.
+ * <p>
+ * The disabled image is displayed when the receiver is disabled.
+ * </p>
+ *
+ * @return the receiver's disabled image
+ *
+ * @exception SWTException <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 Image getDisabledImage () {
+    checkWidget();
+    return disabledImage;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled, and
+ * <code>false</code> otherwise. A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #isEnabled
+ */
+public bool getEnabled () {
+    checkWidget();
+    if ((style & SWT.SEPARATOR) !is 0) {
+        return (state & DISABLED) is 0;
+    }
+    auto hwnd = parent.handle;
+    int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    return (fsState & OS.TBSTATE_ENABLED) !is 0;
+}
+
+/**
+ * Returns the receiver's hot image if it has one, or null
+ * if it does not.
+ * <p>
+ * The hot image is displayed when the mouse enters the receiver.
+ * </p>
+ *
+ * @return the receiver's hot image
+ *
+ * @exception SWTException <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 Image getHotImage () {
+    checkWidget();
+    return hotImage;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>ToolBar</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 ToolBar getParent () {
+    checkWidget();
+    return parent;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is selected,
+ * and false otherwise.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button). If the receiver is of any other type, this method
+ * returns false.
+ * </p>
+ *
+ * @return the selection state
+ *
+ * @exception SWTException <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 getSelection () {
+    checkWidget();
+    if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return false;
+    auto hwnd = parent.handle;
+    int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    return (fsState & OS.TBSTATE_CHECKED) !is 0;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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 String getToolTipText () {
+    checkWidget();
+    return toolTipText;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <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 int getWidth () {
+    checkWidget();
+    auto hwnd = parent.handle;
+    int index = OS.SendMessage (hwnd, OS.TB_COMMANDTOINDEX, id, 0);
+    RECT rect;
+    OS.SendMessage (hwnd, OS.TB_GETITEMRECT, index, &rect);
+    return rect.right - rect.left;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is enabled and all
+ * of the receiver's ancestors are enabled, and <code>false</code>
+ * otherwise. A disabled control is typically not selectable from the
+ * user interface and draws with an inactive or "grayed" look.
+ *
+ * @return the receiver's enabled state
+ *
+ * @exception SWTException <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 #getEnabled
+ */
+public bool isEnabled () {
+    checkWidget();
+    return getEnabled () && parent.isEnabled ();
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    releaseImages ();
+    control = null;
+    toolTipText = null;
+    disabledImage = hotImage = null;
+    if (disabledImage2 !is null) disabledImage2.dispose ();
+    disabledImage2 = null;
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+    id = -1;
+}
+
+void releaseImages () {
+    TBBUTTONINFO info;
+    info.cbSize = TBBUTTONINFO.sizeof;
+    info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
+    auto hwnd = parent.handle;
+    OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info);
+    /*
+    * Feature in Windows.  For some reason, a tool item that has
+    * the style BTNS_SEP does not return I_IMAGENONE when queried
+    * for an image index, despite the fact that no attempt has been
+    * made to assign an image to the item.  As a result, operations
+    * on an image list that use the wrong index cause random results.
+    * The fix is to ensure that the tool item is not a separator
+    * before using the image index.  Since separators cannot have
+    * an image and one is never assigned, this is not a problem.
+    */
+    if ((info.fsStyle & OS.BTNS_SEP) is 0 && info.iImage !is OS.I_IMAGENONE) {
+        ImageList imageList = parent.getImageList ();
+        ImageList hotImageList = parent.getHotImageList ();
+        ImageList disabledImageList = parent.getDisabledImageList();
+        if (imageList !is null) imageList.put (info.iImage, null);
+        if (hotImageList !is null) hotImageList.put (info.iImage, null);
+        if (disabledImageList !is null) disabledImageList.put (info.iImage, null);
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+void resizeControl () {
+    if (control !is null && !control.isDisposed ()) {
+        /*
+        * Set the size and location of the control
+        * separately to minimize flashing in the
+        * case where the control does not resize
+        * to the size that was requested.  This
+        * case can occur when the control is a
+        * combo box.
+        */
+        Rectangle itemRect = getBounds ();
+        control.setSize (itemRect.width, itemRect.height);
+        Rectangle rect = control.getBounds ();
+        rect.x = itemRect.x + (itemRect.width - rect.width) / 2;
+        rect.y = itemRect.y + (itemRect.height - rect.height) / 2;
+        control.setLocation (rect.x, rect.y);
+    }
+}
+
+void selectRadio () {
+    int index = 0;
+    ToolItem [] items = parent.getItems ();
+    while (index < items.length && items [index] !is this) index++;
+    int i = index - 1;
+    while (i >= 0 && items [i].setRadioSelection (false)) --i;
+    int j = index + 1;
+    while (j < items.length && items [j].setRadioSelection (false)) j++;
+    setSelection (true);
+}
+
+/**
+ * Sets the control that is used to fill the bounds of
+ * the item when the item is a <code>SEPARATOR</code>.
+ *
+ * @param control the new control
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
+ * </ul>
+ * @exception SWTException <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 setControl (Control control) {
+    checkWidget();
+    if (control !is null) {
+        if (control.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
+        if (control.parent !is parent) error (SWT.ERROR_INVALID_PARENT);
+    }
+    if ((style & SWT.SEPARATOR) is 0) return;
+    this.control = control;
+    /*
+    * Feature in Windows.  When a tool bar wraps, tool items
+    * with the style BTNS_SEP are used as wrap points.  This
+    * means that controls that are placed on top of separator
+    * items are not positioned properly.  Also, vertical tool
+    * bars are implemented using TB_SETROWS to set the number
+    * of rows.  When a control is placed on top of a separator,
+    * the height of the separator does not grow.  The fix in
+    * both cases is to change the tool item style from BTNS_SEP
+    * to BTNS_BUTTON, causing the item to wrap like a tool item
+    * button.  The new tool item button is disabled to avoid key
+    * traversal and the image is set to I_IMAGENONE to avoid
+    * getting the first image from the image list.
+    */
+    if ((parent.style & (SWT.WRAP | SWT.VERTICAL)) !is 0) {
+        bool changed = false;
+        auto hwnd = parent.handle;
+        TBBUTTONINFO info;
+        info.cbSize = TBBUTTONINFO.sizeof;
+        info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE;
+        OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info);
+        if (control is null) {
+            if ((info.fsStyle & OS.BTNS_SEP) is 0) {
+                changed = true;
+                info.fsStyle &= ~OS.BTNS_BUTTON;
+                info.fsStyle |= OS.BTNS_SEP;
+                if ((state & DISABLED) !is 0) {
+                    info.fsState &= ~OS.TBSTATE_ENABLED;
+                } else {
+                    info.fsState |= OS.TBSTATE_ENABLED;
+                }
+            }
+        } else {
+            if ((info.fsStyle & OS.BTNS_SEP) !is 0) {
+                changed = true;
+                info.fsStyle &= ~OS.BTNS_SEP;
+                info.fsStyle |= OS.BTNS_BUTTON;
+                info.fsState &= ~OS.TBSTATE_ENABLED;
+                info.dwMask |= OS.TBIF_IMAGE;
+                info.iImage = OS.I_IMAGENONE;
+            }
+        }
+        if (changed) {
+            OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info);
+            /*
+            * Bug in Windows.  When TB_SETBUTTONINFO changes the
+            * style of a tool item from BTNS_SEP to BTNS_BUTTON
+            * and the tool bar is wrapped, the tool bar does not
+            * redraw properly.  Windows uses separator items as
+            * wrap points and sometimes draws etching above or
+            * below and entire row.  The fix is to redraw the
+            * tool bar.
+            */
+            if (OS.SendMessage (hwnd, OS.TB_GETROWS, 0, 0) > 1) {
+                OS.InvalidateRect (hwnd, null, true);
+            }
+        }
+    }
+    resizeControl ();
+}
+
+/**
+ * Enables the receiver if the argument is <code>true</code>,
+ * and disables it otherwise.
+ * <p>
+ * A disabled control is typically
+ * not selectable from the user interface and draws with an
+ * inactive or "grayed" look.
+ * </p>
+ *
+ * @param enabled the new enabled state
+ *
+ * @exception SWTException <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 setEnabled (bool enabled) {
+    checkWidget();
+    auto hwnd = parent.handle;
+    int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    /*
+    * Feature in Windows.  When TB_SETSTATE is used to set the
+    * state of a tool item, the item redraws even when the state
+    * has not changed.  The fix is to detect this case and avoid
+    * setting the state.
+    */
+    if (((fsState & OS.TBSTATE_ENABLED) !is 0) is enabled) return;
+    if (enabled) {
+        fsState |= OS.TBSTATE_ENABLED;
+        state &= ~DISABLED;
+    } else {
+        fsState &= ~OS.TBSTATE_ENABLED;
+        state |= DISABLED;
+    }
+    OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState);
+    if ((style & SWT.SEPARATOR) is 0) {
+        if (image !is null) updateImages (enabled && parent.getEnabled ());
+    }
+}
+
+/**
+ * Sets the receiver's disabled image to the argument, which may be
+ * null indicating that no disabled image should be displayed.
+ * <p>
+ * The disabled image is displayed when the receiver is disabled.
+ * </p>
+ *
+ * @param image the disabled image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setDisabledImage (Image image) {
+    checkWidget();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    disabledImage = image;
+    updateImages (getEnabled () && parent.getEnabled ());
+}
+
+/**
+ * Sets the receiver's hot image to the argument, which may be
+ * null indicating that no hot image should be displayed.
+ * <p>
+ * The hot image is displayed when the mouse enters the receiver.
+ * </p>
+ *
+ * @param image the hot image to display on the receiver (may be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setHotImage (Image image) {
+    checkWidget();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    hotImage = image;
+    updateImages (getEnabled () && parent.getEnabled ());
+}
+
+override public void setImage (Image image) {
+    checkWidget();
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    super.setImage (image);
+    updateImages (getEnabled () && parent.getEnabled ());
+}
+
+bool setRadioSelection (bool value) {
+    if ((style & SWT.RADIO) is 0) return false;
+    if (getSelection () !is value) {
+        setSelection (value);
+        postEvent (SWT.Selection);
+    }
+    return true;
+}
+
+/**
+ * Sets the selection state of the receiver.
+ * <p>
+ * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>,
+ * it is selected when it is checked (which some platforms draw as a
+ * pushed in button).
+ * </p>
+ *
+ * @param selected the new selection state
+ *
+ * @exception SWTException <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 setSelection (bool selected) {
+    checkWidget();
+    if ((style & (SWT.CHECK | SWT.RADIO)) is 0) return;
+    auto hwnd = parent.handle;
+    int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    /*
+    * Feature in Windows.  When TB_SETSTATE is used to set the
+    * state of a tool item, the item redraws even when the state
+    * has not changed.  The fix is to detect this case and avoid
+    * setting the state.
+    */
+    if (((fsState & OS.TBSTATE_CHECKED) !is 0) is selected) return;
+    if (selected) {
+        fsState |= OS.TBSTATE_CHECKED;
+    } else {
+        fsState &= ~OS.TBSTATE_CHECKED;
+    }
+    OS.SendMessage (hwnd, OS.TB_SETSTATE, id, fsState);
+
+    /*
+    * Bug in Windows.  When a tool item with the style
+    * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
+    * disabled, the item does not draw using the disabled
+    * image.  The fix is to use the disabled image in all
+    * image lists for the item.
+    *
+    * NOTE: This means that the image list must be updated
+    * when the selection changes in a disabled tool item.
+    */
+    if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+        if (!getEnabled () || !parent.getEnabled ()) {
+            updateImages (false);
+        }
+    }
+}
+
+/**
+ * Sets the receiver's text. The string may include
+ * the mnemonic character.
+ * </p>
+ * <p>
+ * Mnemonics are indicated by an '&amp;' that causes the next
+ * character to be the mnemonic.  When the user presses a
+ * key sequence that matches the mnemonic, a selection
+ * event occurs. On most platforms, the mnemonic appears
+ * underlined but may be emphasised in a platform specific
+ * manner.  The mnemonic indicator character '&amp;' can be
+ * escaped by doubling it in the string, causing a single
+ * '&amp;' to be displayed.
+ * </p>
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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>
+ */
+override public void setText (String string) {
+    checkWidget();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    if (string.equals(text)) return;
+    super.setText (string);
+    auto hwnd = parent.handle;
+    TBBUTTONINFO info;
+    info.cbSize = TBBUTTONINFO.sizeof;
+    info.dwMask = OS.TBIF_TEXT | OS.TBIF_STYLE;
+    info.fsStyle = cast(byte) (widgetStyle () | OS.BTNS_AUTOSIZE);
+    auto hHeap = OS.GetProcessHeap ();
+    TCHAR* pszText;
+    if (string.length !is 0) {
+        info.fsStyle |= OS.BTNS_SHOWTEXT;
+        TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, true );
+        int byteCount = buffer.length * TCHAR.sizeof;
+        pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+        info.pszText = pszText;
+    }
+    OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info);
+    if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+
+    /*
+    * Bug in Windows.  For some reason, when the font is set
+    * before any tool item has text, the tool items resize to
+    * a very small size.  Also, a tool item will only show text
+    * when text has already been set on one item and then a new
+    * item is created.  The fix is to use WM_SETFONT to force
+    * the tool bar to redraw and layout.
+    */
+    parent.setDropDownItems (false);
+    int /*long*/ hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+    OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0);
+    parent.setDropDownItems (true);
+    parent.layoutItems ();
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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 setToolTipText (String string) {
+    checkWidget();
+    toolTipText = string;
+}
+
+/**
+ * Sets the width of the receiver, for <code>SEPARATOR</code> ToolItems.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException <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 setWidth (int width) {
+    checkWidget();
+    if ((style & SWT.SEPARATOR) is 0) return;
+    if (width < 0) return;
+    auto hwnd = parent.handle;
+    TBBUTTONINFO info;
+    info.cbSize = TBBUTTONINFO.sizeof;
+    info.dwMask = OS.TBIF_SIZE;
+    info.cx = cast(short) width;
+    OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info);
+    parent.layoutItems ();
+}
+
+void updateImages (bool enabled) {
+    if ((style & SWT.SEPARATOR) !is 0) return;
+    auto hwnd = parent.handle;
+    TBBUTTONINFO info;
+    info.cbSize = TBBUTTONINFO.sizeof;
+    info.dwMask = OS.TBIF_IMAGE;
+    OS.SendMessage (hwnd, OS.TB_GETBUTTONINFO, id, &info);
+    if (info.iImage is OS.I_IMAGENONE && image is null) return;
+    ImageList imageList = parent.getImageList ();
+    ImageList hotImageList = parent.getHotImageList ();
+    ImageList disabledImageList = parent.getDisabledImageList();
+    if (info.iImage is OS.I_IMAGENONE) {
+        Rectangle bounds = image.getBounds ();
+        int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
+        if (imageList is null) {
+            imageList = display.getImageListToolBar (listStyle, bounds.width, bounds.height);
+        }
+        if (disabledImageList is null) {
+            disabledImageList = display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height);
+        }
+        if (hotImageList is null) {
+            hotImageList = display.getImageListToolBarHot (listStyle, bounds.width, bounds.height);
+        }
+        Image disabled = disabledImage;
+        if (disabledImage is null) {
+            if (disabledImage2 !is null) disabledImage2.dispose ();
+            disabledImage2 = null;
+            disabled = image;
+            if (!enabled) {
+                disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE);
+            }
+        }
+        /*
+        * Bug in Windows.  When a tool item with the style
+        * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
+        * disabled, the item does not draw using the disabled
+        * image.  The fix is to assign the disabled image in
+        * all image lists.
+        */
+        Image image2 = image, hot = hotImage;
+        if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+            if (!enabled) image2 = hot = disabled;
+        }
+        info.iImage = imageList.add (image2);
+        disabledImageList.add (disabled);
+        hotImageList.add (hot !is null ? hot : image2);
+        parent.setImageList (imageList);
+        parent.setDisabledImageList (disabledImageList);
+        parent.setHotImageList (hotImageList);
+    } else {
+        Image disabled = null;
+        if (disabledImageList !is null) {
+            if (image !is null) {
+                if (disabledImage2 !is null) disabledImage2.dispose ();
+                disabledImage2 = null;
+                disabled = disabledImage;
+                if (disabledImage is null) {
+                    disabled = image;
+                    if (!enabled) {
+                        disabled = disabledImage2 = new Image (display, image, SWT.IMAGE_DISABLE);
+                    }
+                }
+            }
+            disabledImageList.put (info.iImage, disabled);
+        }
+        /*
+        * Bug in Windows.  When a tool item with the style
+        * BTNS_CHECK or BTNS_CHECKGROUP is selected and then
+        * disabled, the item does not draw using the disabled
+        * image.  The fix is to use the disabled image in all
+        * image lists.
+        */
+        Image image2 = image, hot = hotImage;
+        if ((style & (SWT.CHECK | SWT.RADIO)) !is 0) {
+            if (!enabled) image2 = hot = disabled;
+        }
+        if (imageList !is null) imageList.put (info.iImage, image2);
+        if (hotImageList !is null) {
+            hotImageList.put (info.iImage, hot !is null ? hot : image2);
+        }
+        if (image is null) info.iImage = OS.I_IMAGENONE;
+    }
+
+    /*
+    * Bug in Windows.  If the width of an item has already been
+    * calculated, the tool bar control will not recalculate it to
+    * include the space for the image.  The fix is to set the width
+    * to zero, forcing the control recalculate the width for the item.
+    */
+    info.dwMask |= OS.TBIF_SIZE;
+    info.cx = 0;
+    OS.SendMessage (hwnd, OS.TB_SETBUTTONINFO, id, &info);
+
+    parent.layoutItems ();
+}
+
+int widgetStyle () {
+    if ((style & SWT.DROP_DOWN) !is 0) return OS.BTNS_DROPDOWN;
+    if ((style & SWT.PUSH) !is 0) return OS.BTNS_BUTTON;
+    if ((style & SWT.CHECK) !is 0) return OS.BTNS_CHECK;
+    /*
+    * This code is intentionally commented.  In order to
+    * consistently support radio tool items across platforms,
+    * the platform radio behavior is not used.
+    */
+//  if ((style & SWT.RADIO) !is 0) return OS.BTNS_CHECKGROUP;
+    if ((style & SWT.RADIO) !is 0) return OS.BTNS_CHECK;
+    if ((style & SWT.SEPARATOR) !is 0) return OS.BTNS_SEP;
+    return OS.BTNS_BUTTON;
+}
+
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
+    if ((style & SWT.RADIO) !is 0) {
+        if ((parent.getStyle () & SWT.NO_RADIO_GROUP) is 0) {
+            selectRadio ();
+        }
+    }
+    postEvent (SWT.Selection);
+    return null;
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/ToolTip.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,562 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.ToolTip;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TrayItem;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.TypedListener;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent popup windows that are used
+ * to inform or warn the user.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>BALLOON, ICON_ERROR, ICON_INFORMATION, ICON_WARNING</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles ICON_ERROR, ICON_INFORMATION,
+ * and ICON_WARNING may be specified.
+ * </p><p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tooltips">Tool Tips snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.2
+ */
+
+public class ToolTip : Widget {
+    Shell parent;
+    TrayItem item;
+    String text = "", message = "";
+    int id, x, y;
+    bool autoHide = true, hasLocation, visible;
+    static const int TIMER_ID = 100;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#ICON_ERROR
+ * @see SWT#ICON_INFORMATION
+ * @see SWT#ICON_WARNING
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Shell parent, int style) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+    checkOrientation (parent);
+    parent.createToolTip (this);
+}
+
+static int checkStyle (int style) {
+    int mask = SWT.ICON_ERROR | SWT.ICON_INFORMATION | SWT.ICON_WARNING;
+    if ((style & mask) is 0) return style;
+    return checkBits (style, SWT.ICON_INFORMATION, SWT.ICON_WARNING, SWT.ICON_ERROR, 0, 0, 0);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the receiver is selected.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the receiver is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener(listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+override void destroyWidget () {
+    if (parent !is null) parent.destroyToolTip (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is automatically
+ * hidden by the platform, and <code>false</code> otherwise.
+ *
+ * @return the receiver's auto hide state
+ *
+ * @exception SWTException <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 getAutoHide () {
+    checkWidget();
+    return autoHide;
+}
+
+/**
+ * Returns the receiver's message, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's message
+ *
+ * @exception SWTException <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 String getMessage () {
+    checkWidget();
+    return message;
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Shell</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Shell getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Returns the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <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 String getText () {
+    checkWidget();
+    return text;
+}
+
+/**
+ * Returns <code>true</code> if the receiver 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 visibility state
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget();
+    static if (OS.IsWinCE) return false;
+    if (item !is null) return visible;
+    auto hwndToolTip_ = hwndToolTip ();
+    if (OS.SendMessage (hwndToolTip_, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        if (OS.SendMessage (hwndToolTip_, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+            return (lpti.uFlags & OS.TTF_IDISHWND) is 0 && lpti.uId is id;
+        }
+    }
+    return false;
+}
+
+HWND hwndToolTip () {
+    return (style & SWT.BALLOON) !is 0 ? parent.balloonTipHandle () : parent.toolTipHandle ();
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and all
+ * of the receiver's ancestors are visible and <code>false</code>
+ * otherwise.
+ *
+ * @return the receiver's visibility state
+ *
+ * @exception SWTException <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 #getVisible
+ */
+public bool isVisible () {
+    checkWidget ();
+    if (item !is null) return getVisible () && item.getVisible ();
+    return getVisible ();
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+    item = null;
+    id = -1;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (item is null) {
+        if (autoHide) {
+            auto hwndToolTip_ = hwndToolTip ();
+            if (OS.SendMessage (hwndToolTip_, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
+                TOOLINFO lpti;
+                lpti.cbSize = OS.TOOLINFO_sizeof;
+                if (OS.SendMessage (hwndToolTip_, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) {
+                    if ((lpti.uFlags & OS.TTF_IDISHWND) is 0) {
+                        if (lpti.uId is id) {
+                            OS.SendMessage (hwndToolTip_, OS.TTM_TRACKACTIVATE, 0, &lpti);
+                            OS.SendMessage (hwndToolTip_, OS.TTM_POP, 0, 0);
+                            OS.KillTimer (hwndToolTip_, TIMER_ID);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (item !is null && item.toolTip is this) {
+        item.toolTip = null;
+    }
+    item = null;
+    text = message = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Makes the receiver hide automatically when <code>true</code>,
+ * and remain visible when <code>false</code>.
+ *
+ * @param autoHide the auto hide state
+ *
+ * @exception SWTException <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 #getVisible
+ * @see #setVisible
+ */
+public void setAutoHide (bool autoHide) {
+    checkWidget ();
+    this.autoHide = autoHide;
+    //TODO - update when visible
+}
+
+/**
+ * Sets the location of the receiver, which must be a tooltip,
+ * to the point specified by the arguments which are relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p>
+ *
+ * @param x the new x coordinate for the receiver
+ * @param y the new y coordinate for the receiver
+ *
+ * @exception SWTException <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 setLocation (int x, int y) {
+    checkWidget ();
+    this.x = x;
+    this.y = y;
+    hasLocation = true;
+    //TODO - update when visible
+}
+
+/**
+ * Sets the location of the receiver, which must be a tooltip,
+ * to the point specified by the argument which is relative
+ * to the display.
+ * <p>
+ * Note that this is different from most widgets where the
+ * location of the widget is relative to the parent.
+ * </p><p>
+ * Note that the platform window manager ultimately has control
+ * over the location of tooltips.
+ * </p>
+ *
+ * @param location the new location for the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 setLocation (Point location) {
+    checkWidget ();
+    if (location is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    setLocation (location.x, location.y);
+}
+
+/**
+ * Sets the receiver's message.
+ *
+ * @param string the new message
+ *
+ * @exception SWTException <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 setMessage (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    message = string;
+    //TODO - update when visible
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param string the new text
+ *
+ * @exception SWTException <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 setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    text = string;
+    //TODO - update when visible
+}
+
+/**
+ * Marks the receiver 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 SWTException <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 setVisible (bool visible) {
+    checkWidget ();
+    static if (OS.IsWinCE) return;
+    if (visible is getVisible ()) return;
+    if (item is null) {
+        auto hwnd = parent.handle;
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        lpti.uId = id;
+        lpti.hwnd = hwnd;
+        auto hwndToolTip_ = hwndToolTip ();
+        Shell shell = parent.getShell ();
+        if (text.length !is 0) {
+            int icon = OS.TTI_NONE;
+            if ((style & SWT.ICON_INFORMATION) !is 0) icon = OS.TTI_INFO;
+            if ((style & SWT.ICON_WARNING) !is 0) icon = OS.TTI_WARNING;
+            if ((style & SWT.ICON_ERROR) !is 0) icon = OS.TTI_ERROR;
+            shell.setToolTipTitle (hwndToolTip_, text, cast(HICON) icon);
+        } else {
+            shell.setToolTipTitle (hwndToolTip_, null, null);
+        }
+        int maxWidth = 0;
+        if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
+            RECT rect;
+            OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
+            maxWidth = (rect.right - rect.left) / 4;
+        } else {
+            auto hmonitor = OS.MonitorFromWindow (hwnd, OS.MONITOR_DEFAULTTONEAREST);
+            MONITORINFO lpmi;
+            lpmi.cbSize = MONITORINFO.sizeof;
+            OS.GetMonitorInfo (hmonitor, &lpmi);
+            maxWidth = (lpmi.rcWork.right - lpmi.rcWork.left) / 4;
+        }
+        OS.SendMessage (hwndToolTip_, OS.TTM_SETMAXTIPWIDTH, 0, maxWidth);
+        if (visible) {
+            int nX = x, nY = y;
+            if (!hasLocation) {
+                POINT pt;
+                if (OS.GetCursorPos (&pt)) {
+                    nX = pt.x;
+                    nY = pt.y;
+                }
+            }
+            int /*long*/ lParam = OS.MAKELPARAM (nX, nY);
+            OS.SendMessage (hwndToolTip_, OS.TTM_TRACKPOSITION, 0, lParam);
+
+            /*
+            * Feature in Windows.  Windows will not show a tool tip
+            * if the cursor is outside the parent window (even on XP,
+            * TTM_POPUP will not do this).  The fix is to temporarily
+            * move the cursor into the tool window, show the tool tip,
+            * and then restore the cursor.
+            */
+            POINT pt;
+            OS.GetCursorPos (&pt);
+            RECT rect;
+            OS.GetClientRect (hwnd, &rect);
+            OS.MapWindowPoints (hwnd, null, cast(POINT*) &rect, 2);
+            if (!OS.PtInRect (&rect, pt)) {
+                HCURSOR hCursor = OS.GetCursor ();
+                OS.SetCursor (null);
+                OS.SetCursorPos (rect.left, rect.top);
+                OS.SendMessage (hwndToolTip_, OS.TTM_TRACKACTIVATE, 1, &lpti);
+                OS.SetCursorPos (pt.x, pt.y);
+                OS.SetCursor (hCursor);
+            } else {
+                OS.SendMessage (hwndToolTip_, OS.TTM_TRACKACTIVATE, 1, &lpti);
+            }
+
+            int time = OS.SendMessage (hwndToolTip_, OS.TTM_GETDELAYTIME, OS.TTDT_AUTOPOP, 0);
+            OS.SetTimer (hwndToolTip_, TIMER_ID, time, null);
+        } else {
+            OS.SendMessage (hwndToolTip_, OS.TTM_TRACKACTIVATE, 0, &lpti);
+            OS.SendMessage (hwndToolTip_, OS.TTM_POP, 0, 0);
+            OS.KillTimer (hwndToolTip_, TIMER_ID);
+        }
+        return;
+    }
+    if (item !is null && OS.SHELL32_MAJOR >= 5) {
+        if (visible) {
+            NOTIFYICONDATA iconData;
+            TCHAR[] buffer1 = StrToTCHARs (0, text, true);
+            TCHAR[] buffer2 = StrToTCHARs (0, message, true);
+            static if (OS.IsUnicode) {
+                TCHAR [] szInfoTitle = iconData.szInfoTitle;
+                int length1 = Math.min (szInfoTitle.length - 1, buffer1.length);
+                System.arraycopy (buffer1, 0, szInfoTitle, 0, length1);
+                TCHAR [] szInfo = iconData.szInfo;
+                int length2 = Math.min (szInfo.length - 1, buffer2.length );
+                System.arraycopy (buffer2, 0, szInfo, 0, length2);
+            } else {
+                byte [] szInfoTitle = iconData.szInfoTitle;
+                int length = Math.min (szInfoTitle.length - 1, buffer1.length );
+                System.arraycopy (buffer1, 0, szInfoTitle, 0, length);
+                byte [] szInfo = iconData.szInfo;
+                int length2 = Math.min (szInfo.length - 1, buffer2.length );
+                System.arraycopy (buffer2, 0, szInfo, 0, length2);
+            }
+            Display display = item.getDisplay ();
+            iconData.cbSize = NOTIFYICONDATA.sizeof;
+            iconData.uID = item.id;
+            iconData.hWnd = display.hwndMessage;
+            iconData.uFlags = OS.NIF_INFO;
+            if ((style & SWT.ICON_INFORMATION) !is 0) iconData.dwInfoFlags = OS.NIIF_INFO;
+            if ((style & SWT.ICON_WARNING) !is 0) iconData.dwInfoFlags = OS.NIIF_WARNING;
+            if ((style & SWT.ICON_ERROR) !is 0) iconData.dwInfoFlags = OS.NIIF_ERROR;
+            sendEvent (SWT.Show);
+            this.visible = cast(bool) OS.Shell_NotifyIcon (OS.NIM_MODIFY, &iconData);
+        } else {
+            //TODO - hide the tray item
+        }
+    }
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tracker.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1192 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Tracker;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ *  Instances of this class implement rubber banding rectangles that are
+ *  drawn onto a parent <code>Composite</code> or <code>Display</code>.
+ *  These rectangles can be specified to respond to mouse and key events
+ *  by either moving or resizing themselves accordingly.  Trackers are
+ *  typically used to represent window geometries in a lightweight manner.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, UP, DOWN, RESIZE</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Move, Resize</dd>
+ * </dl>
+ * <p>
+ * Note: Rectangle move behavior is assumed unless RESIZE is specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tracker">Tracker snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Tracker : Widget {
+    Control parent;
+    bool tracking, cancelled, stippled;
+    Rectangle [] rectangles, proportions;
+    Rectangle bounds;
+    HCURSOR resizeCursor;
+    Cursor clientCursor;
+    int cursorOrientation = SWT.NONE;
+    bool inEvent = false;
+    HWND hwndTransparent;
+    WNDPROC oldProc;
+    int oldX, oldY;
+
+    /*
+    * The following values mirror step sizes on Windows
+    */
+    final static int STEPSIZE_SMALL = 1;
+    final static int STEPSIZE_LARGE = 9;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ * @see SWT#RESIZE
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    super (parent, checkStyle (style));
+    this.parent = parent;
+}
+
+/**
+ * Constructs a new instance of this class given the display
+ * to create it on and a style value describing its behavior
+ * and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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>
+ * Note: Currently, null can be passed in for the display argument.
+ * This has the effect of creating the tracker on the currently active
+ * display if there is one. If there is no current display, the
+ * tracker is created on a "default" display. <b>Passing in null as
+ * the display argument is not considered to be good coding style,
+ * and may not be supported in a future release of SWT.</b>
+ * </p>
+ *
+ * @param display the display to create the tracker on
+ * @param style the style of control to construct
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#UP
+ * @see SWT#DOWN
+ */
+public this (Display display, int style) {
+    if (display is null) display = Display.getCurrent ();
+    if (display is null) display = Display.getDefault ();
+    if (!display.isValidThread ()) {
+        error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    }
+    this.style = checkStyle (style);
+    this.display = display;
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener (ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Resize, typedListener);
+    addListener (SWT.Move, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard, by sending
+ * it one of the messages defined in the <code>KeyListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 KeyListener
+ * @see #removeKeyListener
+ */
+public void addKeyListener (KeyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.KeyUp,typedListener);
+    addListener (SWT.KeyDown,typedListener);
+}
+
+Point adjustMoveCursor () {
+    if (bounds is null) return null;
+    int newX = bounds.x + bounds.width / 2;
+    int newY = bounds.y;
+    POINT pt;
+    pt.x = newX;  pt.y = newY;
+    /*
+     * Convert to screen coordinates iff needed
+     */
+    if (parent !is null) {
+        OS.ClientToScreen (parent.handle, &pt);
+    }
+    OS.SetCursorPos (pt.x, pt.y);
+    return new Point (pt.x, pt.y);
+}
+
+Point adjustResizeCursor () {
+    if (bounds is null) return null;
+    int newX, newY;
+
+    if ((cursorOrientation & SWT.LEFT) !is 0) {
+        newX = bounds.x;
+    } else if ((cursorOrientation & SWT.RIGHT) !is 0) {
+        newX = bounds.x + bounds.width;
+    } else {
+        newX = bounds.x + bounds.width / 2;
+    }
+
+    if ((cursorOrientation & SWT.UP) !is 0) {
+        newY = bounds.y;
+    } else if ((cursorOrientation & SWT.DOWN) !is 0) {
+        newY = bounds.y + bounds.height;
+    } else {
+        newY = bounds.y + bounds.height / 2;
+    }
+
+    POINT pt;
+    pt.x = newX;  pt.y = newY;
+    /*
+     * Convert to screen coordinates iff needed
+     */
+    if (parent !is null) {
+        OS.ClientToScreen (parent.handle, &pt);
+    }
+    OS.SetCursorPos (pt.x, pt.y);
+
+    /*
+    * If the client has not provided a custom cursor then determine
+    * the appropriate resize cursor.
+    */
+    if (clientCursor is null) {
+        HCURSOR newCursor;
+        switch (cursorOrientation) {
+            case SWT.UP:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENS);
+                break;
+            case SWT.DOWN:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENS);
+                break;
+            case SWT.LEFT:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZEWE);
+                break;
+            case SWT.RIGHT:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZEWE);
+                break;
+            case SWT.LEFT | SWT.UP:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENWSE);
+                break;
+            case SWT.RIGHT | SWT.DOWN:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENWSE);
+                break;
+            case SWT.LEFT | SWT.DOWN:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENESW);
+                break;
+            case SWT.RIGHT | SWT.UP:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZENESW);
+                break;
+            default:
+                newCursor = OS.LoadCursor (null, cast(TCHAR*)OS.IDC_SIZEALL);
+                break;
+        }
+        OS.SetCursor (newCursor);
+        if (resizeCursor !is null) {
+            OS.DestroyCursor (resizeCursor);
+        }
+        resizeCursor = newCursor;
+    }
+
+    return new Point (pt.x, pt.y);
+}
+
+static int checkStyle (int style) {
+    if ((style & (SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN)) is 0) {
+        style |= SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN;
+    }
+    return style;
+}
+
+/**
+ * Stops displaying the tracker rectangles.  Note that this is not considered
+ * to be a cancelation by the user.
+ *
+ * @exception SWTException <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 close () {
+    checkWidget ();
+    tracking = false;
+}
+
+Rectangle computeBounds () {
+    if (rectangles.length is 0) return null;
+    int xMin = rectangles [0].x;
+    int yMin = rectangles [0].y;
+    int xMax = rectangles [0].x + rectangles [0].width;
+    int yMax = rectangles [0].y + rectangles [0].height;
+
+    for (int i = 1; i < rectangles.length; i++) {
+        if (rectangles [i].x < xMin) xMin = rectangles [i].x;
+        if (rectangles [i].y < yMin) yMin = rectangles [i].y;
+        int rectRight = rectangles [i].x + rectangles [i].width;
+        if (rectRight > xMax) xMax = rectRight;
+        int rectBottom = rectangles [i].y + rectangles [i].height;
+        if (rectBottom > yMax) yMax = rectBottom;
+    }
+
+    return new Rectangle (xMin, yMin, xMax - xMin, yMax - yMin);
+}
+
+Rectangle [] computeProportions (Rectangle [] rects) {
+    Rectangle [] result = new Rectangle [rects.length];
+    bounds = computeBounds ();
+    if (bounds !is null) {
+        for (int i = 0; i < rects.length; i++) {
+            int x = 0, y = 0, width = 0, height = 0;
+            if (bounds.width !is 0) {
+                x = (rects [i].x - bounds.x) * 100 / bounds.width;
+                width = rects [i].width * 100 / bounds.width;
+            } else {
+                width = 100;
+            }
+            if (bounds.height !is 0) {
+                y = (rects [i].y - bounds.y) * 100 / bounds.height;
+                height = rects [i].height * 100 / bounds.height;
+            } else {
+                height = 100;
+            }
+            result [i] = new Rectangle (x, y, width, height);
+        }
+    }
+    return result;
+}
+
+/**
+ * Draw the rectangles displayed by the tracker.
+ */
+void drawRectangles (Rectangle [] rects, bool stippled) {
+    if (parent is null && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        RECT rect1;
+        int bandWidth = stippled ? 3 : 1;
+        for (int i = 0; i < rects.length; i++) {
+            Rectangle rect = rects[i];
+            rect1.left = rect.x - bandWidth;
+            rect1.top = rect.y - bandWidth;
+            rect1.right = rect.x + rect.width + bandWidth * 2;
+            rect1.bottom = rect.y + rect.height + bandWidth * 2;
+            OS.RedrawWindow (hwndTransparent, &rect1, null, OS.RDW_INVALIDATE);
+        }
+        return;
+    }
+    int bandWidth = 1;
+    auto hwndTrack = OS.GetDesktopWindow ();
+    if (parent !is null) hwndTrack = parent.handle;
+    auto hDC = OS.GetDCEx (hwndTrack, null, OS.DCX_CACHE);
+    HBITMAP hBitmap;
+    HBRUSH hBrush, oldBrush;
+    if (stippled) {
+        bandWidth = 3;
+        byte [] bits = [-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0];
+        hBitmap = OS.CreateBitmap (8, 8, 1, 1, bits.ptr);
+        hBrush = OS.CreatePatternBrush (hBitmap);
+        oldBrush = OS.SelectObject (hDC, hBrush);
+    }
+    for (int i=0; i<rects.length; i++) {
+        Rectangle rect = rects [i];
+        OS.PatBlt (hDC, rect.x, rect.y, rect.width, bandWidth, OS.PATINVERT);
+        OS.PatBlt (hDC, rect.x, rect.y + bandWidth, bandWidth, rect.height - (bandWidth * 2), OS.PATINVERT);
+        OS.PatBlt (hDC, rect.x + rect.width - bandWidth, rect.y + bandWidth, bandWidth, rect.height - (bandWidth * 2), OS.PATINVERT);
+        OS.PatBlt (hDC, rect.x, rect.y + rect.height - bandWidth, rect.width, bandWidth, OS.PATINVERT);
+    }
+    if (stippled) {
+        OS.SelectObject (hDC, oldBrush);
+        OS.DeleteObject (hBrush);
+        OS.DeleteObject (hBitmap);
+    }
+    OS.ReleaseDC (hwndTrack, hDC);
+}
+
+/**
+ * Returns the bounds that are being drawn, expressed relative to the parent
+ * widget.  If the parent is a <code>Display</code> then these are screen
+ * coordinates.
+ *
+ * @return the bounds of the Rectangles being drawn
+ *
+ * @exception SWTException <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 Rectangle [] getRectangles () {
+    checkWidget();
+    Rectangle [] result = new Rectangle [rectangles.length];
+    for (int i = 0; i < rectangles.length; i++) {
+        Rectangle current = rectangles [i];
+        result [i] = new Rectangle (current.x, current.y, current.width, current.height);
+    }
+    return result;
+}
+
+/**
+ * Returns <code>true</code> if the rectangles are drawn with a stippled line, <code>false</code> otherwise.
+ *
+ * @return the stippled effect of the rectangles
+ *
+ * @exception SWTException <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 getStippled () {
+    checkWidget ();
+    return stippled;
+}
+
+void moveRectangles (int xChange, int yChange) {
+    if (bounds is null) return;
+    if (xChange < 0 && ((style & SWT.LEFT) is 0)) xChange = 0;
+    if (xChange > 0 && ((style & SWT.RIGHT) is 0)) xChange = 0;
+    if (yChange < 0 && ((style & SWT.UP) is 0)) yChange = 0;
+    if (yChange > 0 && ((style & SWT.DOWN) is 0)) yChange = 0;
+    if (xChange is 0 && yChange is 0) return;
+    bounds.x += xChange; bounds.y += yChange;
+    for (int i = 0; i < rectangles.length; i++) {
+        rectangles [i].x += xChange;
+        rectangles [i].y += yChange;
+    }
+}
+
+/**
+ * Displays the Tracker rectangles for manipulation by the user.  Returns when
+ * the user has either finished manipulating the rectangles or has cancelled the
+ * Tracker.
+ *
+ * @return <code>true</code> if the user did not cancel the Tracker, <code>false</code> otherwise
+ *
+ * @exception SWTException <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 open () {
+    checkWidget ();
+    cancelled = false;
+    tracking = true;
+
+    /*
+    * If exactly one of UP/DOWN is specified as a style then set the cursor
+    * orientation accordingly (the same is done for LEFT/RIGHT styles below).
+    */
+    int vStyle = style & (SWT.UP | SWT.DOWN);
+    if (vStyle is SWT.UP || vStyle is SWT.DOWN) {
+        cursorOrientation |= vStyle;
+    }
+    int hStyle = style & (SWT.LEFT | SWT.RIGHT);
+    if (hStyle is SWT.LEFT || hStyle is SWT.RIGHT) {
+        cursorOrientation |= hStyle;
+    }
+
+    /*
+    * If this tracker is being created without a mouse drag then
+    * we need to create a transparent window that fills the screen
+    * in order to get all mouse/keyboard events that occur
+    * outside of our visible windows (ie.- over the desktop).
+    */
+    //Callback newProc = null;
+    bool mouseDown = OS.GetKeyState(OS.VK_LBUTTON) < 0;
+    bool isVista = !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0);
+    if ((parent is null && isVista) || !mouseDown) {
+        int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+        int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+        hwndTransparent = OS.CreateWindowEx (
+            isVista ? OS.WS_EX_LAYERED | OS.WS_EX_NOACTIVATE : OS.WS_EX_TRANSPARENT,
+            display.windowClass_.ptr,
+            null,
+            OS.WS_POPUP,
+            0, 0,
+            width, height,
+            null,
+            null,
+            OS.GetModuleHandle (null),
+            null);
+        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) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
+        OS.SetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC, cast(LONG_PTR) &transparentFunc );
+
+        //PORTING_FIXME: Vista version
+        version( VISTA ) if (isVista) {
+            OS.SetLayeredWindowAttributes (hwndTransparent, 0xFFFFFF, cast(byte)0xFF, OS.LWA_COLORKEY | OS.LWA_ALPHA);
+        }
+        OS.ShowWindow (hwndTransparent, OS.SW_SHOWNOACTIVATE);
+    }
+
+    update ();
+    drawRectangles (rectangles, stippled);
+    Point cursorPos = null;
+    if (mouseDown) {
+        POINT pt;
+        OS.GetCursorPos (&pt);
+        cursorPos = new Point (pt.x, pt.y);
+    } else {
+        if ((style & SWT.RESIZE) !is 0) {
+            cursorPos = adjustResizeCursor ();
+        } else {
+            cursorPos = adjustMoveCursor ();
+        }
+    }
+    if (cursorPos !is null) {
+        oldX = cursorPos.x;
+        oldY = cursorPos.y;
+    }
+
+    try {
+        /* Tracker behaves like a Dialog with its own OS event loop. */
+        MSG msg;
+        while (tracking && !cancelled) {
+            if (parent !is null && parent.isDisposed ()) break;
+            OS.GetMessage (&msg, null, 0, 0);
+            OS.TranslateMessage (&msg);
+            switch (msg.message) {
+                case OS.WM_LBUTTONUP:
+                case OS.WM_MOUSEMOVE:
+                    wmMouse (msg.message, msg.wParam, msg.lParam);
+                    break;
+                case OS.WM_IME_CHAR: wmIMEChar (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_CHAR: wmChar (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_KEYDOWN: wmKeyDown (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_KEYUP: wmKeyUp (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_SYSCHAR: wmSysChar (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_SYSKEYDOWN: wmSysKeyDown (msg.hwnd, msg.wParam, msg.lParam); break;
+                case OS.WM_SYSKEYUP: wmSysKeyUp (msg.hwnd, msg.wParam, msg.lParam); break;
+                default:
+            }
+            if (OS.WM_KEYFIRST <= msg.message && msg.message <= OS.WM_KEYLAST) continue;
+            if (OS.WM_MOUSEFIRST <= msg.message && msg.message <= OS.WM_MOUSELAST) continue;
+            if (!(parent is null && isVista)) {
+                if (msg.message is OS.WM_PAINT) {
+                    update ();
+                    drawRectangles (rectangles, stippled);
+                }
+            }
+            OS.DispatchMessage (&msg);
+            if (!(parent is null && isVista)) {
+                if (msg.message is OS.WM_PAINT) {
+                    drawRectangles (rectangles, stippled);
+                }
+            }
+        }
+        if (mouseDown) OS.ReleaseCapture ();
+        if (!isDisposed()) {
+            update ();
+            drawRectangles (rectangles, stippled);
+        }
+    } finally {
+        /*
+        * Cleanup: If a transparent window was created in order to capture events then
+        * destroy it and its callback object now.
+        */
+        if (hwndTransparent !is null) {
+            OS.DestroyWindow (hwndTransparent);
+            hwndTransparent = null;
+        }
+        //if (newProc !is null) {
+            //newProc.dispose ();
+            oldProc = null;
+        //}
+        /*
+        * Cleanup: If this tracker was resizing then the last cursor that it created
+        * needs to be destroyed.
+        */
+        if (resizeCursor !is null) {
+            OS.DestroyCursor (resizeCursor);
+            resizeCursor = null;
+        }
+    }
+    tracking = false;
+    return !cancelled;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    parent = null;
+    rectangles = proportions = null;
+    bounds = null;
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Resize, listener);
+    eventTable.unhook (SWT.Move, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when keys are pressed and released on the system keyboard.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 KeyListener
+ * @see #addKeyListener
+ */
+public void removeKeyListener(KeyListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.KeyUp, listener);
+    eventTable.unhook (SWT.KeyDown, listener);
+}
+
+void resizeRectangles (int xChange, int yChange) {
+    if (bounds is null) return;
+    /*
+    * If the cursor orientation has not been set in the orientation of
+    * this change then try to set it here.
+    */
+    if (xChange < 0 && ((style & SWT.LEFT) !is 0) && ((cursorOrientation & SWT.RIGHT) is 0)) {
+        cursorOrientation |= SWT.LEFT;
+    }
+    if (xChange > 0 && ((style & SWT.RIGHT) !is 0) && ((cursorOrientation & SWT.LEFT) is 0)) {
+        cursorOrientation |= SWT.RIGHT;
+    }
+    if (yChange < 0 && ((style & SWT.UP) !is 0) && ((cursorOrientation & SWT.DOWN) is 0)) {
+        cursorOrientation |= SWT.UP;
+    }
+    if (yChange > 0 && ((style & SWT.DOWN) !is 0) && ((cursorOrientation & SWT.UP) is 0)) {
+        cursorOrientation |= SWT.DOWN;
+    }
+
+    /*
+     * If the bounds will flip about the x or y axis then apply the adjustment
+     * up to the axis (ie.- where bounds width/height becomes 0), change the
+     * cursor's orientation accordingly, and flip each Rectangle's origin (only
+     * necessary for > 1 Rectangles)
+     */
+    if ((cursorOrientation & SWT.LEFT) !is 0) {
+        if (xChange > bounds.width) {
+            if ((style & SWT.RIGHT) is 0) return;
+            cursorOrientation |= SWT.RIGHT;
+            cursorOrientation &= ~SWT.LEFT;
+            bounds.x += bounds.width;
+            xChange -= bounds.width;
+            bounds.width = 0;
+            if (proportions.length > 1) {
+                for (int i = 0; i < proportions.length; i++) {
+                    Rectangle proportion = proportions [i];
+                    proportion.x = 100 - proportion.x - proportion.width;
+                }
+            }
+        }
+    } else if ((cursorOrientation & SWT.RIGHT) !is 0) {
+        if (bounds.width < -xChange) {
+            if ((style & SWT.LEFT) is 0) return;
+            cursorOrientation |= SWT.LEFT;
+            cursorOrientation &= ~SWT.RIGHT;
+            xChange += bounds.width;
+            bounds.width = 0;
+            if (proportions.length > 1) {
+                for (int i = 0; i < proportions.length; i++) {
+                    Rectangle proportion = proportions [i];
+                    proportion.x = 100 - proportion.x - proportion.width;
+                }
+            }
+        }
+    }
+    if ((cursorOrientation & SWT.UP) !is 0) {
+        if (yChange > bounds.height) {
+            if ((style & SWT.DOWN) is 0) return;
+            cursorOrientation |= SWT.DOWN;
+            cursorOrientation &= ~SWT.UP;
+            bounds.y += bounds.height;
+            yChange -= bounds.height;
+            bounds.height = 0;
+            if (proportions.length > 1) {
+                for (int i = 0; i < proportions.length; i++) {
+                    Rectangle proportion = proportions [i];
+                    proportion.y = 100 - proportion.y - proportion.height;
+                }
+            }
+        }
+    } else if ((cursorOrientation & SWT.DOWN) !is 0) {
+        if (bounds.height < -yChange) {
+            if ((style & SWT.UP) is 0) return;
+            cursorOrientation |= SWT.UP;
+            cursorOrientation &= ~SWT.DOWN;
+            yChange += bounds.height;
+            bounds.height = 0;
+            if (proportions.length > 1) {
+                for (int i = 0; i < proportions.length; i++) {
+                    Rectangle proportion = proportions [i];
+                    proportion.y = 100 - proportion.y - proportion.height;
+                }
+            }
+        }
+    }
+
+    // apply the bounds adjustment
+    if ((cursorOrientation & SWT.LEFT) !is 0) {
+        bounds.x += xChange;
+        bounds.width -= xChange;
+    } else if ((cursorOrientation & SWT.RIGHT) !is 0) {
+        bounds.width += xChange;
+    }
+    if ((cursorOrientation & SWT.UP) !is 0) {
+        bounds.y += yChange;
+        bounds.height -= yChange;
+    } else if ((cursorOrientation & SWT.DOWN) !is 0) {
+        bounds.height += yChange;
+    }
+
+    Rectangle [] newRects = new Rectangle [rectangles.length];
+    for (int i = 0; i < rectangles.length; i++) {
+        Rectangle proportion = proportions[i];
+        newRects[i] = new Rectangle (
+            proportion.x * bounds.width / 100 + bounds.x,
+            proportion.y * bounds.height / 100 + bounds.y,
+            proportion.width * bounds.width / 100,
+            proportion.height * bounds.height / 100);
+    }
+    rectangles = newRects;
+}
+
+/**
+ * Sets the <code>Cursor</code> of the Tracker.  If this cursor is <code>null</code>
+ * then the cursor reverts to the default.
+ *
+ * @param newCursor the new <code>Cursor</code> to display
+ *
+ * @exception SWTException <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 setCursor(Cursor newCursor) {
+    checkWidget();
+    clientCursor = newCursor;
+    if (newCursor !is null) {
+        if (inEvent) OS.SetCursor (clientCursor.handle);
+    }
+}
+
+/**
+ * Specifies the rectangles that should be drawn, expressed relative to the parent
+ * widget.  If the parent is a Display then these are screen coordinates.
+ *
+ * @param rectangles the bounds of the rectangles to be drawn
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the set of rectangles contains a null rectangle</li>
+ * </ul>
+ * @exception SWTException <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 setRectangles (Rectangle [] rectangles) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (rectangles is null) error (SWT.ERROR_NULL_ARGUMENT);
+    this.rectangles = new Rectangle [rectangles.length];
+    for (int i = 0; i < rectangles.length; i++) {
+        Rectangle current = rectangles [i];
+        if (current is null) error (SWT.ERROR_NULL_ARGUMENT);
+        this.rectangles [i] = new Rectangle (current.x, current.y, current.width, current.height);
+    }
+    proportions = computeProportions (rectangles);
+}
+
+/**
+ * Changes the appearance of the line used to draw the rectangles.
+ *
+ * @param stippled <code>true</code> if rectangle should appear stippled
+ *
+ * @exception SWTException <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 setStippled (bool stippled) {
+    checkWidget ();
+    this.stippled = stippled;
+}
+
+private static extern(Windows) int transparentFunc (HWND hwnd, int msg, int wParam, int lParam) {
+    Display d = Display.getCurrent();
+    auto t = cast(Tracker) d.findControl( hwnd );
+    return t.transparentProc( hwnd, msg, wParam, lParam );
+}
+
+int transparentProc (HWND hwnd, int msg, int wParam, int lParam) {
+    switch (msg) {
+        /*
+        * We typically do not want to answer that the transparent window is
+        * transparent to hits since doing so negates the effect of having it
+        * to grab events.  However, clients of the tracker should not be aware
+        * of this transparent window.  Therefore if there is a hit query
+        * performed as a result of client code then answer that the transparent
+        * window is transparent to hits so that its existence will not impact
+        * the client.
+        */
+        case OS.WM_NCHITTEST:
+            if (inEvent) return OS.HTTRANSPARENT;
+            break;
+        case OS.WM_SETCURSOR:
+            if (clientCursor !is null) {
+                OS.SetCursor (clientCursor.handle);
+                return 1;
+            }
+            if (resizeCursor !is null) {
+                OS.SetCursor (resizeCursor);
+                return 1;
+            }
+            break;
+        case OS.WM_PAINT:
+            if (parent is null && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                PAINTSTRUCT ps;
+                auto hDC = OS.BeginPaint (hwnd, &ps);
+                HBITMAP hBitmap;
+                HBRUSH hBrush, oldBrush;
+                auto transparentBrush = OS.CreateSolidBrush(0xFFFFFF);
+                oldBrush = OS.SelectObject (hDC, transparentBrush);
+                OS.PatBlt (hDC, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, OS.PATCOPY);
+                OS.SelectObject (hDC, oldBrush);
+                OS.DeleteObject (transparentBrush);
+                int bandWidth = 1;
+                if (stippled) {
+                    bandWidth = 3;
+                    byte [] bits = [-86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0, -86, 0, 85, 0];
+                    hBitmap = OS.CreateBitmap (8, 8, 1, 1, bits.ptr);
+                    hBrush = OS.CreatePatternBrush (hBitmap);
+                    oldBrush = OS.SelectObject (hDC, hBrush);
+                    OS.SetBkColor (hDC, 0xF0F0F0);
+                } else {
+                    oldBrush = OS.SelectObject (hDC, OS.GetStockObject(OS.BLACK_BRUSH));
+                }
+                Rectangle[] rects = this.rectangles;
+                for (int i=0; i<rects.length; i++) {
+                    Rectangle rect = rects [i];
+                    OS.PatBlt (hDC, rect.x, rect.y, rect.width, bandWidth, OS.PATCOPY);
+                    OS.PatBlt (hDC, rect.x, rect.y + bandWidth, bandWidth, rect.height - (bandWidth * 2), OS.PATCOPY);
+                    OS.PatBlt (hDC, rect.x + rect.width - bandWidth, rect.y + bandWidth, bandWidth, rect.height - (bandWidth * 2), OS.PATCOPY);
+                    OS.PatBlt (hDC, rect.x, rect.y + rect.height - bandWidth, rect.width, bandWidth, OS.PATCOPY);
+                }
+                OS.SelectObject (hDC, oldBrush);
+                if (stippled) {
+                    OS.DeleteObject (hBrush);
+                    OS.DeleteObject (hBitmap);
+                }
+                OS.EndPaint (hwnd, &ps);
+                return 0;
+            }
+        default:
+    }
+    return OS.CallWindowProc( oldProc, hwnd, msg, wParam, lParam);
+}
+
+void update () {
+    if (parent is null && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) return;
+    if (parent !is null) {
+        if (parent.isDisposed ()) return;
+        Shell shell = parent.getShell ();
+        shell.update (true);
+    } else {
+        display.update ();
+    }
+}
+
+override LRESULT wmKeyDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    bool isMirrored = parent !is null && (parent.style & SWT.MIRRORED) !is 0;
+    int stepSize = OS.GetKeyState (OS.VK_CONTROL) < 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE;
+    int xChange = 0, yChange = 0;
+    switch (wParam) {
+        case OS.VK_ESCAPE:
+            cancelled = true;
+            tracking = false;
+            break;
+        case OS.VK_RETURN:
+            tracking = false;
+            break;
+        case OS.VK_LEFT:
+            xChange = isMirrored ? stepSize : -stepSize;
+            break;
+        case OS.VK_RIGHT:
+            xChange = isMirrored ? -stepSize : stepSize;
+            break;
+        case OS.VK_UP:
+            yChange = -stepSize;
+            break;
+        case OS.VK_DOWN:
+            yChange = stepSize;
+            break;
+        default:
+    }
+    if (xChange !is 0 || yChange !is 0) {
+        Rectangle [] oldRectangles = rectangles;
+        bool oldStippled = stippled;
+        Rectangle [] rectsToErase = new Rectangle [rectangles.length];
+        for (int i = 0; i < rectangles.length; i++) {
+            Rectangle current = rectangles [i];
+            rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);
+        }
+        Event event = new Event ();
+        event.x = oldX + xChange;
+        event.y = oldY + yChange;
+        Point cursorPos;
+        if ((style & SWT.RESIZE) !is 0) {
+            resizeRectangles (xChange, yChange);
+            inEvent = true;
+            sendEvent (SWT.Resize, event);
+            inEvent = false;
+            /*
+            * It is possible (but unlikely) that application
+            * code could have disposed the widget in the resize
+            * event.  If this happens return false to indicate
+            * that the tracking has failed.
+            */
+            if (isDisposed ()) {
+                cancelled = true;
+                return LRESULT.ONE;
+            }
+            bool draw = false;
+            /*
+             * It is possible that application code could have
+             * changed the rectangles in the resize event.  If this
+             * happens then only redraw the tracker if the rectangle
+             * values have changed.
+             */
+            if (rectangles !is oldRectangles) {
+                int length = rectangles.length;
+                if (length !is rectsToErase.length) {
+                    draw = true;
+                } else {
+                    for (int i = 0; i < length; i++) {
+                        if (rectangles [i]!=/*eq*/rectsToErase [i]) {
+                            draw = true;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                draw = true;
+            }
+            if (draw) {
+                drawRectangles (rectsToErase, oldStippled);
+                update ();
+                drawRectangles (rectangles, stippled);
+            }
+            cursorPos = adjustResizeCursor ();
+        } else {
+            moveRectangles (xChange, yChange);
+            inEvent = true;
+            sendEvent (SWT.Move, event);
+            inEvent = false;
+            /*
+            * It is possible (but unlikely) that application
+            * code could have disposed the widget in the move
+            * event.  If this happens return false to indicate
+            * that the tracking has failed.
+            */
+            if (isDisposed ()) {
+                cancelled = true;
+                return LRESULT.ONE;
+            }
+            bool draw = false;
+            /*
+             * It is possible that application code could have
+             * changed the rectangles in the move event.  If this
+             * happens then only redraw the tracker if the rectangle
+             * values have changed.
+             */
+            if (rectangles !is oldRectangles) {
+                int length = rectangles.length;
+                if (length !is rectsToErase.length) {
+                    draw = true;
+                } else {
+                    for (int i = 0; i < length; i++) {
+                        if (rectangles [i]!=/*eq*/rectsToErase [i]) {
+                            draw = true;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                draw = true;
+            }
+            if (draw) {
+                drawRectangles (rectsToErase, oldStippled);
+                update ();
+                drawRectangles (rectangles, stippled);
+            }
+            cursorPos = adjustMoveCursor ();
+        }
+        if (cursorPos !is null) {
+            oldX = cursorPos.x;
+            oldY = cursorPos.y;
+        }
+    }
+    return result;
+}
+
+override LRESULT wmSysKeyDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = super.wmSysKeyDown (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    cancelled = true;
+    tracking = false;
+    return result;
+}
+
+LRESULT wmMouse (int message, int /*long*/ wParam, int /*long*/ lParam) {
+    bool isMirrored = parent !is null && (parent.style & SWT.MIRRORED) !is 0;
+    int newPos = OS.GetMessagePos ();
+    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;
+        Rectangle [] rectsToErase = new Rectangle [rectangles.length];
+        for (int i = 0; i < rectangles.length; i++) {
+            Rectangle current = rectangles [i];
+            rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);
+        }
+        Event event = new Event ();
+        event.x = newX;
+        event.y = newY;
+        if ((style & SWT.RESIZE) !is 0) {
+            if (isMirrored) {
+               resizeRectangles (oldX - newX, newY - oldY);
+            } else {
+               resizeRectangles (newX - oldX, newY - oldY);
+            }
+            inEvent = true;
+            sendEvent (SWT.Resize, event);
+            inEvent = false;
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the resize
+            * event.  If this happens, return false to indicate
+            * that the tracking has failed.
+            */
+            if (isDisposed ()) {
+                cancelled = true;
+                return LRESULT.ONE;
+            }
+            bool draw = false;
+            /*
+             * It is possible that application code could have
+             * changed the rectangles in the resize event.  If this
+             * happens then only redraw the tracker if the rectangle
+             * values have changed.
+             */
+            if (rectangles !is oldRectangles) {
+                int length = rectangles.length;
+                if (length !is rectsToErase.length) {
+                    draw = true;
+                } else {
+                    for (int i = 0; i < length; i++) {
+                        if (rectangles [i]!=/*eq*/rectsToErase [i]) {
+                            draw = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            else {
+                draw = true;
+            }
+            if (draw) {
+                drawRectangles (rectsToErase, oldStippled);
+                update ();
+                drawRectangles (rectangles, stippled);
+            }
+            Point cursorPos = adjustResizeCursor ();
+            if (cursorPos !is null) {
+                newX = cursorPos.x;
+                newY = cursorPos.y;
+            }
+        } else {
+            if (isMirrored) {
+                moveRectangles (oldX - newX, newY - oldY);
+            } else {
+                moveRectangles (newX - oldX, newY - oldY);
+            }
+            inEvent = true;
+            sendEvent (SWT.Move, event);
+            inEvent = false;
+            /*
+            * It is possible (but unlikely), that application
+            * code could have disposed the widget in the move
+            * event.  If this happens, return false to indicate
+            * that the tracking has failed.
+            */
+            if (isDisposed ()) {
+                cancelled = true;
+                return LRESULT.ONE;
+            }
+            bool draw = false;
+            /*
+             * It is possible that application code could have
+             * changed the rectangles in the move event.  If this
+             * happens then only redraw the tracker if the rectangle
+             * values have changed.
+             */
+            if (rectangles !is oldRectangles) {
+                int length = rectangles.length;
+                if (length !is rectsToErase.length) {
+                    draw = true;
+                } else {
+                    for (int i = 0; i < length; i++) {
+                        if (rectangles [i]!=/*eq*/rectsToErase [i]) {
+                            draw = true;
+                            break;
+                        }
+                    }
+                }
+            } else {
+                draw = true;
+            }
+            if (draw) {
+                drawRectangles (rectsToErase, oldStippled);
+                update ();
+                drawRectangles (rectangles, stippled);
+            }
+        }
+        oldX = newX;
+        oldY = newY;
+    }
+    tracking = message !is OS.WM_LBUTTONUP;
+    return null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tray.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Tray;
+
+import org.eclipse.swt.SWT;
+import java.lang.System;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.TrayItem;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent the system tray that is part
+ * of the task bar status area on some operating systems.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see Display#getSystemTray
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tray">Tray, TrayItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class Tray : Widget {
+    int itemCount;
+    TrayItem [] items;
+
+this (Display display, int style) {
+    items = new TrayItem [4];
+    if (display is null) display = Display.getCurrent ();
+    if (display is null) display = Display.getDefault ();
+    if (!display.isValidThread ()) {
+        error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    }
+    this.display = display;
+}
+
+void createItem (TrayItem item, int index) {
+    if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
+    if (itemCount is items.length) {
+        TrayItem [] newItems = new TrayItem [items.length + 4];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+    }
+    System.arraycopy (items, index, items, index + 1, itemCount++ - index);
+    items [index] = item;
+}
+
+void destroyItem (TrayItem item) {
+    int index = 0;
+    while (index < itemCount) {
+        if (items [index] is item) break;
+        index++;
+    }
+    if (index is itemCount) return;
+    System.arraycopy (items, index + 1, items, index, --itemCount - index);
+    items [itemCount] = null;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 TrayItem getItem (int index) {
+    checkWidget ();
+    if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
+    return items [index];
+}
+
+/**
+ * Returns the number of items contained in the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    return itemCount;
+}
+
+/**
+ * Returns an array of <code>TrayItem</code>s which are the items
+ * in the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 TrayItem [] getItems () {
+    checkWidget ();
+    TrayItem [] result = new TrayItem [itemCount];
+    System.arraycopy (items, 0, result, 0, result.length);
+    return result;
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        for (int i=0; i<items.length; i++) {
+            TrayItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (display.tray is this) display.tray = null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TrayItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,544 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TrayItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.ToolTip;
+import org.eclipse.swt.widgets.Tray;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Display;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent icons that can be placed on the
+ * system tray or task bar status area.
+ * <p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>DefaultSelection, MenuDetect, Selection</dd>
+ * </dl>
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tray">Tray, TrayItem snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.0
+ */
+public class TrayItem : Item {
+    Tray parent;
+    int id;
+    Image image2;
+    ToolTip toolTip;
+    String toolTipText;
+    bool visible = true;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tray</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Tray parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, parent.getItemCount ());
+    createWidget ();
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the receiver is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the receiver is selected
+ * <code>widgetDefaultSelected</code> is called when the receiver is double-clicked
+ * </p>
+ *
+ * @param listener the listener which should be notified when the receiver is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the platform-specific context menu trigger
+ * has occurred, by sending it one of the messages defined in
+ * the <code>MenuDetectListener</code> interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuDetectListener
+ * @see #removeMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void addMenuDetectListener (MenuDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.MenuDetect, typedListener);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void createWidget () {
+    NOTIFYICONDATA iconData;
+    iconData.cbSize = NOTIFYICONDATA.sizeof;
+    iconData.uID = id = display.nextTrayId++;
+    iconData.hWnd = display.hwndMessage;
+    iconData.uFlags = OS.NIF_MESSAGE;
+    iconData.uCallbackMessage = Display.SWT_TRAYICONMSG;
+    OS.Shell_NotifyIcon (OS.NIM_ADD, &iconData);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tray</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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.2
+ */
+public Tray getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Returns the receiver's tool tip, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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.2
+ */
+public ToolTip getToolTip () {
+    checkWidget ();
+    return toolTip;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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 String getToolTipText () {
+    checkWidget ();
+    return toolTipText;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is visible and
+ * <code>false</code> otherwise.
+ *
+ * @return the receiver's visibility
+ *
+ * @exception SWTException <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 getVisible () {
+    checkWidget ();
+    return visible;
+}
+
+int messageProc (HWND hwnd, int msg, int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When the user clicks on the tray
+    * icon, another application may be the foreground window.
+    * This means that the event loop is not running and can
+    * cause problems.  For example, if a menu is shown, when
+    * the user clicks outside of the menu to cancel it, the
+    * menu is not hidden until an event is processed.  If
+    * another application is the foreground window, then the
+    * menu is not hidden.  The fix is to force the tray icon
+    * message window to the foreground when sending an event.
+    */
+    switch (lParam) {
+        case OS.WM_LBUTTONDOWN:
+            if (hooks (SWT.Selection)) {
+                OS.SetForegroundWindow (hwnd);
+                postEvent (SWT.Selection);
+            }
+            break;
+        case OS.WM_LBUTTONDBLCLK:
+        case OS.WM_RBUTTONDBLCLK:
+            if (hooks (SWT.DefaultSelection)) {
+                OS.SetForegroundWindow (hwnd);
+                postEvent (SWT.DefaultSelection);
+            }
+            break;
+        case OS.WM_RBUTTONUP: {
+            if (hooks (SWT.MenuDetect)) {
+                OS.SetForegroundWindow (hwnd);
+                sendEvent (SWT.MenuDetect);
+                // widget could be disposed at this point
+                if (isDisposed()) return 0;
+            }
+            break;
+        }
+        case OS.NIN_BALLOONSHOW:
+            if (toolTip !is null && !toolTip.visible) {
+                toolTip.visible = true;
+                if (toolTip.hooks (SWT.Show)) {
+                    OS.SetForegroundWindow (hwnd);
+                    toolTip.sendEvent (SWT.Show);
+                    // widget could be disposed at this point
+                    if (isDisposed()) return 0;
+                }
+            }
+            break;
+        case OS.NIN_BALLOONHIDE:
+        case OS.NIN_BALLOONTIMEOUT:
+        case OS.NIN_BALLOONUSERCLICK:
+            if (toolTip !is null) {
+                if (toolTip.visible) {
+                    toolTip.visible = false;
+                    if (toolTip.hooks (SWT.Hide)) {
+                        OS.SetForegroundWindow (hwnd);
+                        toolTip.sendEvent (SWT.Hide);
+                        // widget could be disposed at this point
+                        if (isDisposed()) return 0;
+                    }
+                }
+                if (lParam is OS.NIN_BALLOONUSERCLICK) {
+                    if (toolTip.hooks (SWT.Selection)) {
+                        OS.SetForegroundWindow (hwnd);
+                        toolTip.postEvent (SWT.Selection);
+                        // widget could be disposed at this point
+                        if (isDisposed()) return 0;
+                    }
+                }
+            }
+            break;
+        default:
+    }
+    display.wakeThread ();
+    return 0;
+}
+
+void recreate () {
+    createWidget ();
+    if (!visible) setVisible (false);
+    if (text.length  !is 0) setText (text);
+    if (image !is null) setImage (image);
+    if (toolTipText !is null) setToolTipText (toolTipText);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    if (toolTip !is null) toolTip.item = null;
+    toolTip = null;
+    if (image2 !is null) image2.dispose ();
+    image2 = null;
+    toolTipText = null;
+    NOTIFYICONDATA iconData;
+    iconData.cbSize = NOTIFYICONDATA.sizeof;
+    iconData.uID = id;
+    iconData.hWnd = display.hwndMessage;
+    OS.Shell_NotifyIcon (OS.NIM_DELETE, &iconData);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the receiver is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the platform-specific context menu trigger has
+ * occurred.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 MenuDetectListener
+ * @see #addMenuDetectListener
+ *
+ * @since 3.3
+ */
+public void removeMenuDetectListener (MenuDetectListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.MenuDetect, listener);
+}
+
+/**
+ * Sets the receiver's image.
+ *
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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>
+ */
+override public void setImage (Image image) {
+    checkWidget ();
+    if (image !is null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    super.setImage (image);
+    if (image2 !is null) image2.dispose ();
+    image2 = null;
+    HICON hIcon;
+    Image icon = image;
+    if (icon !is null) {
+        switch (icon.type) {
+            case SWT.BITMAP:
+                image2 = Display.createIcon (image);
+                hIcon = image2.handle;
+                break;
+            case SWT.ICON:
+                hIcon = icon.handle;
+                break;
+            default:
+        }
+    }
+    NOTIFYICONDATA iconData;
+    iconData.cbSize = NOTIFYICONDATA.sizeof;
+    iconData.uID = id;
+    iconData.hWnd = display.hwndMessage;
+    iconData.hIcon = hIcon;
+    iconData.uFlags = OS.NIF_ICON;
+    OS.Shell_NotifyIcon (OS.NIM_MODIFY, &iconData);
+}
+
+/**
+ * Sets the receiver's tool tip to the argument, which
+ * may be null indicating that no tool tip should be shown.
+ *
+ * @param toolTip the new tool tip (or null)
+ *
+ * @exception SWTException <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.2
+ */
+public void setToolTip (ToolTip toolTip) {
+    checkWidget ();
+    ToolTip oldTip = this.toolTip, newTip = toolTip;
+    if (oldTip !is null) oldTip.item = null;
+    this.toolTip = newTip;
+    if (newTip !is null) newTip.item = this;
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param value the new tool tip text (or null)
+ *
+ * @exception SWTException <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 setToolTipText (String value) {
+    checkWidget ();
+    toolTipText = value;
+    NOTIFYICONDATA iconData;
+    TCHAR[] buffer = StrToTCHARs (0, toolTipText is null ? "X"[1..1] : toolTipText, true);
+    assert( buffer.ptr !is null );
+    /*
+    * Note that the size of the szTip field is different in version 5.0 of shell32.dll.
+    */
+    int length_ = OS.SHELL32_MAJOR < 5 ? 64 : 128;
+    static if (OS.IsUnicode) {
+        TCHAR [] szTip = iconData.szTip[];
+        length_ = Math.min (length_ - 1, buffer.length );
+        System.arraycopy (buffer, 0, szTip, 0, length_);
+    } else {
+        TCHAR [] szTip = iconData.szTip[];
+        length_ = Math.min (length_ - 1, buffer.length );
+        System.arraycopy (buffer, 0, szTip, 0, length_);
+    }
+    iconData.cbSize = NOTIFYICONDATA.sizeof;
+    iconData.uID = id;
+    iconData.hWnd = display.hwndMessage;
+    iconData.uFlags = OS.NIF_TIP;
+    OS.Shell_NotifyIcon (OS.NIM_MODIFY, &iconData);
+}
+
+/**
+ * Makes the receiver visible if the argument is <code>true</code>,
+ * and makes it invisible otherwise.
+ *
+ * @param visible the new visibility state
+ *
+ * @exception SWTException <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 setVisible (bool visible) {
+    checkWidget ();
+    if (this.visible is visible) return;
+    if (visible) {
+        /*
+        * It is possible (but unlikely), that application
+        * code could have disposed the widget in the show
+        * event.  If this happens, just return.
+        */
+        sendEvent (SWT.Show);
+        if (isDisposed ()) return;
+    }
+    this.visible = visible;
+    NOTIFYICONDATA iconData;
+    iconData.cbSize = NOTIFYICONDATA.sizeof;
+    iconData.uID = id;
+    iconData.hWnd = display.hwndMessage;
+    if (OS.SHELL32_MAJOR < 5) {
+        if (visible) {
+            iconData.uFlags = OS.NIF_MESSAGE;
+            iconData.uCallbackMessage = Display.SWT_TRAYICONMSG;
+            OS.Shell_NotifyIcon (OS.NIM_ADD, &iconData);
+            setImage (image);
+            setToolTipText (toolTipText);
+        } else {
+            OS.Shell_NotifyIcon (OS.NIM_DELETE, &iconData);
+        }
+    } else {
+        iconData.uFlags = OS.NIF_STATE;
+        iconData.dwState = visible ? 0 : OS.NIS_HIDDEN;
+        iconData.dwStateMask = OS.NIS_HIDDEN;
+        OS.Shell_NotifyIcon (OS.NIM_MODIFY, &iconData);
+    }
+    if (!visible) sendEvent (SWT.Hide);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Tree.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,7821 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Tree;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.ImageList;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Table;
+
+import java.lang.all;
+
+
+/**
+ * Instances of this class provide a selectable user interface object
+ * that displays a hierarchy of items and issues notification when an
+ * item in the hierarchy is selected.
+ * <p>
+ * The item children that may be added to instances of this class
+ * must be of type <code>TreeItem</code>.
+ * </p><p>
+ * Style <code>VIRTUAL</code> is used to create a <code>Tree</code> whose
+ * <code>TreeItem</code>s are to be populated by the client on an on-demand basis
+ * instead of up-front.  This can provide significant performance improvements for
+ * trees that are very large or for which <code>TreeItem</code> population is
+ * expensive (for example, retrieving values from an external source).
+ * </p><p>
+ * Here is an example of using a <code>Tree</code> with style <code>VIRTUAL</code>:
+ * <code><pre>
+ *  final Tree tree = new Tree(parent, SWT.VIRTUAL | SWT.BORDER);
+ *  tree.setItemCount(20);
+ *  tree.addListener(SWT.SetData, new Listener() {
+ *      public void handleEvent(Event event) {
+ *          TreeItem item = (TreeItem)event.item;
+ *          TreeItem parentItem = item.getParentItem();
+ *          String text = null;
+ *          if (parentItem is null) {
+ *              text = "node " + tree.indexOf(item);
+ *          } else {
+ *              text = parentItem.getText() + " - " + parentItem.indexOf(item);
+ *          }
+ *          item.setText(text);
+ *          System.out.println(text);
+ *          item.setItemCount(10);
+ *      }
+ *  });
+ * </pre></code>
+ * </p><p>
+ * Note that although this class is a subclass of <code>Composite</code>,
+ * 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, NO_SCROLL</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles SINGLE and MULTI may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class Tree : Composite {
+
+    alias Composite.computeSize computeSize;
+    alias Composite.setBackgroundImage setBackgroundImage;
+    alias Composite.setBounds setBounds;
+    alias Composite.setCursor setCursor;
+    alias Composite.sort sort;
+
+    TreeItem [] items;
+    TreeColumn [] columns;
+    int columnCount;
+    ImageList imageList, headerImageList;
+    TreeItem currentItem;
+    TreeColumn sortColumn;
+    RECT* focusRect;
+    HWND hwndParent, hwndHeader;
+    HANDLE hAnchor, hInsert, hSelect;
+    int lastID;
+    HANDLE hFirstIndexOf, hLastIndexOf;
+    int lastIndexOf, itemCount, sortDirection;
+    bool dragStarted, gestureCompleted, insertAfter, shrink, ignoreShrink;
+    bool ignoreSelect, ignoreExpand, ignoreDeselect, ignoreResize;
+    bool lockSelection, oldSelected, newSelected, ignoreColumnMove;
+    bool linesVisible, customDraw, printClient, painted, ignoreItemHeight;
+    bool ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus;
+    bool ignoreDrawSelection, ignoreDrawHot, ignoreFullSelection, explorerTheme;
+    int scrollWidth, selectionForeground;
+    HANDLE headerToolTipHandle, itemToolTipHandle;
+    static const int INSET = 3;
+    static const int GRID_WIDTH = 1;
+    static const int SORT_WIDTH = 10;
+    static const int HEADER_MARGIN = 12;
+    static const int HEADER_EXTRA = 3;
+    static const int INCREMENT = 5;
+    static const int EXPLORER_EXTRA = 2;
+    static const int DRAG_IMAGE_SIZE = 301;
+    static const bool EXPLORER_THEME = true;
+    private static /+const+/ WNDPROC TreeProc;
+    static const TCHAR[] TreeClass = OS.WC_TREEVIEW;
+    private static /+const+/ WNDPROC HeaderProc;
+    static const TCHAR[] HeaderClass = OS.WC_HEADER;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            WNDCLASS lpWndClass;
+            OS.GetClassInfo (null, TreeClass.ptr, &lpWndClass);
+            TreeProc = lpWndClass.lpfnWndProc;
+            OS.GetClassInfo (null, HeaderClass.ptr, &lpWndClass);
+            HeaderProc = lpWndClass.lpfnWndProc;
+            static_this_completed = true;
+        }
+    }
+
+    private static Tree sThis;
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#SINGLE
+ * @see SWT#MULTI
+ * @see SWT#CHECK
+ * @see SWT#FULL_SELECTION
+ * @see SWT#VIRTUAL
+ * @see SWT#NO_SCROLL
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Composite parent, int style) {
+    static_this();
+    super (parent, checkStyle (style));
+}
+
+static int checkStyle (int style) {
+    /*
+    * 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.
+    */
+    if ((style & SWT.NO_SCROLL) is 0) {
+        style |= SWT.H_SCROLL | SWT.V_SCROLL;
+    }
+    /*
+    * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL.
+    */
+    if ((style & SWT.H_SCROLL) !is 0 && (style & SWT.V_SCROLL) is 0) {
+        style |= SWT.V_SCROLL;
+    }
+    return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0);
+}
+
+override void _addListener (int eventType, Listener listener) {
+    super._addListener (eventType, listener);
+    switch (eventType) {
+        case SWT.DragDetect: {
+            if ((state & DRAG_DETECT) !is 0) {
+                int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                bits &= ~OS.TVS_DISABLEDRAGDROP;
+                OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+            }
+            break;
+        }
+        case SWT.MeasureItem:
+        case SWT.EraseItem:
+        case SWT.PaintItem: {
+            customDraw = true;
+            style |= SWT.DOUBLE_BUFFERED;
+            if (isCustomToolTip ()) createItemToolTips ();
+            OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if (eventType is SWT.MeasureItem) {
+                /*
+                * This code is intentionally commented.
+                */
+//              if (explorerTheme) {
+//                  int bits1 = (int)/*64*/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
+            * entire row is filled when an item is painted,
+            * drawing on top of any custom drawing.  The fix
+            * is to clear TVS_FULLROWSELECT.
+            */
+            if ((style & SWT.FULL_SELECTION) !is 0) {
+                if (eventType !is SWT.MeasureItem) {
+                    if (!explorerTheme) bits &= ~OS.TVS_FULLROWSELECT;
+                }
+            }
+            if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+                OS.InvalidateRect (handle, null, true);
+                /*
+                * Bug in Windows.  When TVS_NOHSCROLL is set after items
+                * have been inserted into the tree, Windows shows the
+                * scroll bar.  The fix is to check for this case and
+                * explicitly hide the scroll bar.
+                */
+                int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+                if (count !is 0 && (bits & OS.TVS_NOHSCROLL) !is 0) {
+                    static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false);
+                }
+            }
+            break;
+        }
+        default:
+    }
+}
+
+TreeItem _getItem (HANDLE hItem) {
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    tvItem.hItem = cast(HTREEITEM)hItem;
+    if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem) !is 0) {
+        return _getItem (tvItem.hItem, tvItem.lParam);
+    }
+    return null;
+}
+
+TreeItem _getItem (HANDLE hItem, int id) {
+    if ((style & SWT.VIRTUAL) is 0) return items [id];
+    return id !is -1 ? items [id] : new TreeItem (this, SWT.NONE, cast(HANDLE)-1, cast(HANDLE)-1, hItem);
+}
+
+void _setBackgroundPixel (int newPixel) {
+    int oldPixel = OS.SendMessage (handle, OS.TVM_GETBKCOLOR, 0, 0);
+    if (oldPixel !is newPixel) {
+        /*
+        * Bug in Windows.  When TVM_SETBKCOLOR is used more
+        * than once to set the background color of a tree,
+        * the background color of the lines and the plus/minus
+        * does not change to the new color.  The fix is to set
+        * the background color to the default before setting
+        * the new color.
+        */
+        if (oldPixel !is -1) {
+            OS.SendMessage (handle, OS.TVM_SETBKCOLOR, 0, -1);
+        }
+
+        /* Set the background color */
+        OS.SendMessage (handle, OS.TVM_SETBKCOLOR, 0, newPixel);
+
+        /*
+        * Feature in Windows.  When TVM_SETBKCOLOR is used to
+        * set the background color of a tree, the plus/minus
+        * animation draws badly.  The fix is to clear the effect.
+        */
+        if (explorerTheme) {
+            int bits2 = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+            if (newPixel is -1 && findImageControl () is null) {
+                bits2 |= OS.TVS_EX_FADEINOUTEXPANDOS;
+            } else {
+                bits2 &= ~OS.TVS_EX_FADEINOUTEXPANDOS;
+            }
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits2);
+        }
+
+        /* Set the checkbox image list */
+        if ((style & SWT.CHECK) !is 0) setCheckboxImageList ();
+    }
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the user changes the receiver's selection, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * When <code>widgetSelected</code> is called, the item field of the event object is valid.
+ * If the receiver has the <code>SWT.CHECK</code> style and the check selection changes,
+ * the event object detail field contains the value <code>SWT.CHECK</code>.
+ * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked.
+ * The item field of the event object is valid for default selection, but the detail field is not used.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the user changes the receiver's selection
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection, typedListener);
+    addListener (SWT.DefaultSelection, typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an item in the receiver is expanded or collapsed
+ * by sending it one of the messages defined in the <code>TreeListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TreeListener
+ * @see #removeTreeListener
+ */
+public void addTreeListener(TreeListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Expand, typedListener);
+    addListener (SWT.Collapse, typedListener);
+}
+
+override HWND borderHandle () {
+    return hwndParent !is null ? hwndParent : handle;
+}
+
+LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (ignoreCustomDraw) return null;
+    if (nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) return new LRESULT (OS.CDRF_DODEFAULT);
+    auto hDC = nmcd.nmcd.hdc;
+    OS.RestoreDC (hDC, -1);
+    TreeItem item = getItem (nmcd);
+
+    /*
+    * Feature in Windows.  When a new tree item is inserted
+    * using TVM_INSERTITEM and the tree is using custom draw,
+    * a NM_CUSTOMDRAW is sent before TVM_INSERTITEM returns
+    * and before the item is added to the items array.  The
+    * fix is to check for null.
+    *
+    * NOTE: This only happens on XP with the version 6.00 of
+    * COMCTL32.DLL,
+    */
+    if (item is null) return null;
+
+    /*
+    * Feature in Windows.  Under certain circumstances, Windows
+    * sends CDDS_ITEMPOSTPAINT for an empty rectangle.  This is
+    * not a problem providing that graphics do not occur outside
+    * the rectangle.  The fix is to test for the rectangle and
+    * draw nothing.
+    *
+    * NOTE:  This seems to happen when both I_IMAGECALLBACK
+    * and LPSTR_TEXTCALLBACK are used at the same time with
+    * TVM_SETITEM.
+    */
+    if (nmcd.nmcd.rc.left >= nmcd.nmcd.rc.right || nmcd.nmcd.rc.top >= nmcd.nmcd.rc.bottom) return null;
+    if (!OS.IsWindowVisible (handle)) return null;
+    if ((style & SWT.FULL_SELECTION) !is 0 || findImageControl () !is null || ignoreDrawSelection || explorerTheme) {
+        OS.SetBkMode (hDC, OS.TRANSPARENT);
+    }
+    bool selected = isItemSelected (nmcd);
+    bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0;
+    if (OS.IsWindowEnabled (handle)) {
+        if (explorerTheme) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_TRACKSELECT) !is 0) {
+                if ((style & SWT.FULL_SELECTION) !is 0 && (selected || hot)) {
+                    OS.SetTextColor (hDC, OS.GetSysColor (OS.COLOR_WINDOWTEXT));
+                } else {
+                    OS.SetTextColor (hDC, getForegroundPixel ());
+                }
+            }
+        }
+    }
+    int [] order = null;
+    RECT clientRect;
+    OS.GetClientRect (scrolledHandle (), &clientRect);
+    if (hwndHeader !is null) {
+        OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2);
+        if (columnCount !is 0) {
+            order = new int [columnCount];
+            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, cast(int) order.ptr);
+        }
+    }
+    int sortIndex = -1, clrSortBk = -1;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (sortColumn !is null && sortDirection !is SWT.NONE) {
+            if (findImageControl () is null) {
+                sortIndex = indexOf (sortColumn);
+                clrSortBk = getSortColumnPixel ();
+            }
+        }
+    }
+    int x = 0;
+    Point size = null;
+    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 (columnCount > 0 && hwndHeader !is null) {
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_WIDTH;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            width = hdItem.cxy;
+        }
+        if (i is 0) {
+            if ((style & SWT.FULL_SELECTION) !is 0) {
+                bool clear = !explorerTheme && !ignoreDrawSelection && findImageControl () is null;
+                if (clear || (selected && !ignoreDrawSelection) || (hot && !ignoreDrawHot)) {
+                    bool draw = true;
+                    RECT pClipRect;
+                    OS.SetRect (&pClipRect, width, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                    if (explorerTheme) {
+                        if (hooks (SWT.EraseItem)) {
+                            RECT* itemRect = item.getBounds (index, true, true, false, false, true, hDC);
+                            itemRect.left -= EXPLORER_EXTRA;
+                            itemRect.right += EXPLORER_EXTRA + 1;
+                            pClipRect.left = itemRect.left;
+                            pClipRect.right = itemRect.right;
+                            if (columnCount > 0 && hwndHeader !is null) {
+                                HDITEM hdItem;
+                                hdItem.mask = OS.HDI_WIDTH;
+                                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+                                pClipRect.right = Math.min (pClipRect.right, nmcd.nmcd.rc.left + hdItem.cxy);
+                            }
+                        }
+                        RECT pRect;
+                        OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                        if (columnCount > 0 && hwndHeader !is null) {
+                            int totalWidth = 0;
+                            HDITEM hdItem;
+                            hdItem.mask = OS.HDI_WIDTH;
+                            for (int j=0; j<columnCount; j++) {
+                                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
+                                totalWidth += hdItem.cxy;
+                            }
+                            if (totalWidth > clientRect.right - clientRect.left) {
+                                pRect.left = 0;
+                                pRect.right = totalWidth;
+                            } else {
+                                pRect.left = clientRect.left;
+                                pRect.right = clientRect.right;
+                            }
+                        }
+                        draw = false;
+                        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 (draw) fillBackground (hDC, OS.GetBkColor (hDC), &pClipRect);
+                }
+            }
+        }
+        if (x + width > clientRect.left) {
+            RECT* rect = new RECT(), backgroundRect = null;
+            bool drawItem = true, drawText = true, drawImage = true, drawBackground_ = false;
+            if (i is 0) {
+                drawItem = drawImage = drawText = false;
+                if (findImageControl () !is null) {
+                    if (explorerTheme) {
+                        if (OS.IsWindowEnabled (handle) && !hooks (SWT.EraseItem)) {
+                            Image image = null;
+                            if (index is 0) {
+                                image = item.image;
+                            } else {
+                                Image [] images  = item.images;
+                                if (images !is null) image = images [index];
+                            }
+                            if (image !is null) {
+                                Rectangle bounds = image.getBounds ();
+                                if (size is null) size = getImageSize ();
+                                if (!ignoreDrawForeground) {
+                                    GCData data = new GCData();
+                                    data.device = display;
+                                    GC gc = GC.win32_new (hDC, data);
+                                    RECT* iconRect = item.getBounds (index, false, true, false, false, true, hDC);
+                                    gc.setClipping (iconRect.left, iconRect.top, iconRect.right - iconRect.left, iconRect.bottom - iconRect.top);
+                                    gc.drawImage (image, 0, 0, bounds.width, bounds.height, iconRect.left, iconRect.top, size.x, size.y);
+                                    OS.SelectClipRgn (hDC, null);
+                                    gc.dispose ();
+                                }
+                            }
+                        }
+                    } else {
+                        drawItem = drawText = drawBackground_ = true;
+                        rect = item.getBounds (index, true, false, false, false, true, hDC);
+                        if (linesVisible) {
+                            rect.right++;
+                            rect.bottom++;
+                        }
+                    }
+                }
+                if (selected && !ignoreDrawSelection && !ignoreDrawBackground) {
+                    if (!explorerTheme) fillBackground (hDC, OS.GetBkColor (hDC), rect);
+                    drawBackground_ = false;
+                }
+                backgroundRect = rect;
+                if (hooks (SWT.EraseItem)) {
+                    drawItem = drawText = drawImage = true;
+                    rect = item.getBounds (index, true, true, false, false, true, hDC);
+                    if ((style & SWT.FULL_SELECTION) !is 0) {
+                        backgroundRect = rect;
+                    } else {
+                        backgroundRect = item.getBounds (index, true, false, false, false, true, hDC);
+                    }
+                }
+            } else {
+                selectionForeground = -1;
+                ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = false;
+                OS.SetRect (rect, x, nmcd.nmcd.rc.top, x + width, nmcd.nmcd.rc.bottom);
+                backgroundRect = rect;
+            }
+            int clrText = -1, clrTextBk = -1;
+            auto hFont = item.fontHandle (index);
+            if (selectionForeground !is -1) clrText = selectionForeground;
+            if (OS.IsWindowEnabled (handle)) {
+                bool drawForeground = false;
+                if (selected) {
+                    if (i !is 0 && (style & SWT.FULL_SELECTION) is 0) {
+                        OS.SetTextColor (hDC, getForegroundPixel ());
+                        OS.SetBkColor (hDC, getBackgroundPixel ());
+                        drawForeground = drawBackground_ = true;
+                    }
+                } else {
+                    drawForeground = drawBackground_ = true;
+                }
+                if (drawForeground) {
+                    clrText = item.cellForeground !is null ? item.cellForeground [index] : -1;
+                    if (clrText is -1) clrText = item.foreground;
+                }
+                if (drawBackground_) {
+                    clrTextBk = item.cellBackground !is null ? item.cellBackground [index] : -1;
+                    if (clrTextBk is -1) clrTextBk = item.background;
+                    if (clrTextBk is -1 && index is sortIndex) clrTextBk = clrSortBk;
+                }
+            } else {
+                if (clrTextBk is -1 && index is sortIndex) {
+                    drawBackground_ = true;
+                    clrTextBk = clrSortBk;
+                }
+            }
+            if (explorerTheme) {
+                if (selected || (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0) {
+                    if ((style & SWT.FULL_SELECTION) !is 0) {
+                        drawBackground_ = false;
+                    } else {
+                        if (i is 0) {
+                            drawBackground_ = false;
+                            if (!hooks (SWT.EraseItem)) drawText = false;
+                        }
+                    }
+                }
+            }
+            if (drawItem) {
+                if (i !is 0) {
+                    if (hooks (SWT.MeasureItem)) {
+                        sendMeasureItemEvent (item, index, hDC);
+                        if (isDisposed () || item.isDisposed ()) break;
+                    }
+                    if (hooks (SWT.EraseItem)) {
+                        RECT* cellRect = item.getBounds (index, true, true, true, true, true, hDC);
+                        int nSavedDC = OS.SaveDC (hDC);
+                        GCData data = new GCData ();
+                        data.device = display;
+                        data.foreground = OS.GetTextColor (hDC);
+                        data.background = OS.GetBkColor (hDC);
+                        if (!selected || (style & SWT.FULL_SELECTION) is 0) {
+                            if (clrText !is -1) data.foreground = clrText;
+                            if (clrTextBk !is -1) data.background = clrTextBk;
+                        }
+                        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 ();
+                        event.item = item;
+                        event.index = index;
+                        event.gc = gc;
+                        event.detail |= SWT.FOREGROUND;
+                        if (clrTextBk !is -1) event.detail |= SWT.BACKGROUND;
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            if (hot) event.detail |= SWT.HOT;
+                            if (selected) event.detail |= SWT.SELECTED;
+                            if (!explorerTheme) {
+                                //if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+                                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 |= SWT.FOCUSED;
+                                    }
+                                }
+                            }
+                        }
+                        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 (SWT.EraseItem, event);
+                        event.gc = null;
+                        int newTextClr = data.foreground;
+                        gc.dispose ();
+                        OS.RestoreDC (hDC, nSavedDC);
+                        if (isDisposed () || item.isDisposed ()) break;
+                        if (event.doit) {
+                            ignoreDrawForeground = (event.detail & SWT.FOREGROUND) is 0;
+                            ignoreDrawBackground = (event.detail & SWT.BACKGROUND) is 0;
+                            if ((style & SWT.FULL_SELECTION) !is 0) {
+                                ignoreDrawSelection = (event.detail & SWT.SELECTED) is 0;
+                                ignoreDrawFocus = (event.detail & SWT.FOCUSED) is 0;
+                                ignoreDrawHot = (event.detail & SWT.HOT) is 0;
+                            }
+                        } else {
+                            ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+                        }
+                        if (selected && ignoreDrawSelection) ignoreDrawHot = true;
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            if (ignoreDrawSelection) ignoreFullSelection = true;
+                            if (!ignoreDrawSelection || !ignoreDrawHot) {
+                                if (!selected && !hot) {
+                                    selectionForeground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                                } else {
+                                    if (!explorerTheme) {
+                                        drawBackground_ = true;
+                                        ignoreDrawBackground = false;
+                                        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 columnCount - 1) {
+                                            RECT* selectionRect = new RECT ();
+                                            OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom);
+                                            backgroundRect = selectionRect;
+                                        }
+                                    } else {
+                                        RECT pRect;
+                                        OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                                        if (columnCount > 0 && hwndHeader !is null) {
+                                            int totalWidth = 0;
+                                            HDITEM hdItem;
+                                            hdItem.mask = OS.HDI_WIDTH;
+                                            for (int j=0; j<columnCount; j++) {
+                                                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
+                                                totalWidth += hdItem.cxy;
+                                            }
+                                            if (totalWidth > clientRect.right - clientRect.left) {
+                                                pRect.left = 0;
+                                                pRect.right = totalWidth;
+                                            } else {
+                                                pRect.left = clientRect.left;
+                                                pRect.right = clientRect.right;
+                                            }
+                                            if (index is columnCount - 1) {
+                                                RECT* selectionRect = new RECT ();
+                                                OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom);
+                                                backgroundRect = selectionRect;
+                                            }
+                                        }
+                                        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, backgroundRect);
+                                        OS.CloseThemeData (hTheme);
+                                    }
+                                }
+                            } else {
+                                if (selected) {
+                                    selectionForeground = newTextClr;
+                                    if (!explorerTheme) {
+                                        if (clrTextBk is -1 && OS.IsWindowEnabled (handle)) {
+                                            Control control = findBackgroundControl ();
+                                            if (control is null) control = this;
+                                            clrTextBk = control.getBackgroundPixel ();
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    if (selectionForeground !is -1) clrText = selectionForeground;
+                }
+                if (!ignoreDrawBackground) {
+                    if (clrTextBk !is -1) {
+                        if (drawBackground_) fillBackground (hDC, clrTextBk, backgroundRect);
+                    } else {
+                        Control control = findImageControl ();
+                        if (control !is null) {
+                            if (i is 0) {
+                                int right = Math.min (rect.right, width);
+                                OS.SetRect (rect, rect.left, rect.top, right, rect.bottom);
+                                if (drawBackground_) fillImageBackground (hDC, control, rect);
+                            } else {
+                                if (drawBackground_) fillImageBackground (hDC, control, rect);
+                            }
+                        }
+                    }
+                }
+                rect.left += INSET - 1;
+                if (drawImage) {
+                    Image image = null;
+                    if (index is 0) {
+                        image = item.image;
+                    } else {
+                        Image [] images  = item.images;
+                        if (images !is null) image = images [index];
+                    }
+                    int inset = i !is 0 ? INSET : 0;
+                    int offset = i !is 0 ? INSET : INSET + 2;
+                    if (image !is null) {
+                        Rectangle bounds = image.getBounds ();
+                        if (size is null) size = getImageSize ();
+                        if (!ignoreDrawForeground) {
+                            //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);
+                            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);
+                    } else {
+                        if (i is 0) {
+                            if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) !is 0) {
+                                if (size is null) size = getImageSize ();
+                                rect.left = Math.min (rect.left + size.x + offset, rect.right);
+                            }
+                        } else {
+                            OS.SetRect (rect, rect.left + offset, rect.top, rect.right - inset, rect.bottom);
+                        }
+                    }
+                }
+                if (drawText) {
+                    /*
+                    * Bug in Windows.  When DrawText() is used with DT_VCENTER
+                    * and DT_ENDELLIPSIS, the ellipsis can draw outside of the
+                    * rectangle when the rectangle is empty.  The fix is avoid
+                    * all text drawing for empty rectangles.
+                    */
+                    if (rect.left < rect.right) {
+                        String string = null;
+                        if (index is 0) {
+                            string = item.text;
+                        } else {
+                            String [] strings  = item.strings;
+                            if (strings !is null) string = strings [index];
+                        }
+                        if (string !is null) {
+                            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;
+                            if (i !is 0) flags |= OS.DT_ENDELLIPSIS;
+                            TreeColumn column = columns !is null ? columns [index] : null;
+                            if (column !is null) {
+                                if ((column.style & SWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                                if ((column.style & SWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
+                            }
+                            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 = cast(HFONT)OS.SelectObject (hDC, hFont);
+                            if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
+                            if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
+                        }
+                    }
+                }
+            }
+            if (selectionForeground !is -1) clrText = selectionForeground;
+            if (hooks (SWT.PaintItem)) {
+                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);
+                data.foreground = OS.GetTextColor (hDC);
+                data.background = OS.GetBkColor (hDC);
+                if (selected && (style & SWT.FULL_SELECTION) !is 0) {
+                    if (selectionForeground !is -1) data.foreground = selectionForeground;
+                } else {
+                    if (clrText !is -1) data.foreground = clrText;
+                    if (clrTextBk !is -1) data.background = clrTextBk;
+                }
+                data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                GC gc = GC.win32_new (hDC, data);
+                Event event = new Event ();
+                event.item = item;
+                event.index = index;
+                event.gc = gc;
+                event.detail |= SWT.FOREGROUND;
+                if (clrTextBk !is -1) event.detail |= SWT.BACKGROUND;
+                if (hot) event.detail |= SWT.HOT;
+                if (selected && (i is 0 /*nmcd.iSubItem is 0*/ || (style & SWT.FULL_SELECTION) !is 0)) {
+                    event.detail |= SWT.SELECTED;
+                }
+                if (!explorerTheme) {
+                    //if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+                    if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) {
+                        if (i is 0 /*nmcd.iSubItem is 0*/ || (style & SWT.FULL_SELECTION) !is 0) {
+                            if (handle is OS.GetFocus ()) {
+                                int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                                if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= SWT.FOCUSED;
+                            }
+                        }
+                    }
+                }
+                event.x = itemRect.left;
+                event.y = itemRect.top;
+                event.width = itemRect.right - itemRect.left;
+                event.height = itemRect.bottom - itemRect.top;
+                RECT* cellRect = item.getBounds (index, true, true, true, true, true, hDC);
+                int cellWidth = cellRect.right - cellRect.left;
+                int cellHeight = cellRect.bottom - cellRect.top;
+                gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+                sendEvent (SWT.PaintItem, event);
+                if (data.focusDrawn) focusRect = null;
+                event.gc = null;
+                gc.dispose ();
+                OS.RestoreDC (hDC, nSavedDC);
+                if (isDisposed () || item.isDisposed ()) break;
+            }
+        }
+        x += width;
+        if (x > clientRect.right) break;
+    }
+    if (linesVisible) {
+        if ((style & SWT.FULL_SELECTION) !is 0) {
+            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 (!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 & SWT.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);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return new LRESULT (OS.CDRF_DODEFAULT);
+}
+
+LRESULT CDDS_ITEMPREPAINT (NMTVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    /*
+    * Even when custom draw is being ignored, the font needs
+    * to be selected into the HDC so that the item bounds are
+    * measured correctly.
+    */
+    TreeItem item = getItem (nmcd);
+    /*
+    * Feature in Windows.  When a new tree item is inserted
+    * using TVM_INSERTITEM and the tree is using custom draw,
+    * a NM_CUSTOMDRAW is sent before TVM_INSERTITEM returns
+    * and before the item is added to the items array.  The
+    * fix is to check for null.
+    *
+    * NOTE: This only happens on XP with the version 6.00 of
+    * COMCTL32.DLL,
+    */
+    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;
+    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);
+    }
+    RECT* clipRect = null;
+    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;
+    if (OS.IsWindowEnabled (handle)) {
+        clrText = item.cellForeground !is null ? item.cellForeground [index] : -1;
+        if (clrText is -1) clrText = item.foreground;
+        clrTextBk = item.cellBackground !is null ? item.cellBackground [index] : -1;
+        if (clrTextBk is -1) clrTextBk = item.background;
+    }
+    int clrSortBk = -1;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (sortColumn !is null && sortDirection !is SWT.NONE) {
+            if (findImageControl () is null) {
+                if (indexOf (sortColumn) is index) {
+                    clrSortBk = getSortColumnPixel ();
+                    if (clrTextBk is -1) clrTextBk = clrSortBk;
+                }
+            }
+        }
+    }
+    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) {
+            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);
+        }
+        //TODO - BUG - measure and erase sent when first column is clipped
+        Event measureEvent = null;
+        if (hooks (SWT.MeasureItem)) {
+            measureEvent = sendMeasureItemEvent (item, index, hDC);
+            if (isDisposed () || item.isDisposed ()) return null;
+        }
+        selectionForeground = -1;
+        ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false;
+        if (hooks (SWT.EraseItem)) {
+            RECT rect;
+            OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+            RECT* cellRect = item.getBounds (index, true, true, true, true, true, hDC);
+            if (clrSortBk !is -1) {
+                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 ();
+            data.device = display;
+            if (selected && explorerTheme) {
+                data.foreground = OS.GetSysColor (OS.COLOR_WINDOWTEXT);
+            } else {
+                data.foreground = OS.GetTextColor (hDC);
+            }
+            data.background = OS.GetBkColor (hDC);
+            if (!selected) {
+                if (clrText !is -1) data.foreground = clrText;
+                if (clrTextBk !is -1) data.background = clrTextBk;
+            }
+            data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+            data.font = item.getFont (index);
+            GC gc = GC.win32_new (hDC, data);
+            Event event = new Event ();
+            event.index = index;
+            event.item = item;
+            event.gc = gc;
+            event.detail |= SWT.FOREGROUND;
+            if (clrTextBk !is -1) event.detail |= SWT.BACKGROUND;
+            if (hot) event.detail |= SWT.HOT;
+            if (selected) event.detail |= SWT.SELECTED;
+            if (!explorerTheme) {
+                //if ((nmcd.uItemState & OS.CDIS_FOCUS) !is 0) {
+                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) {
+                            focused = true;
+                            event.detail |= SWT.FOCUSED;
+                        }
+                    }
+                }
+            }
+            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 (SWT.EraseItem, event);
+            event.gc = null;
+            int newTextClr = data.foreground;
+            gc.dispose ();
+            OS.RestoreDC (hDC, nSavedDC);
+            if (isDisposed () || item.isDisposed ()) return null;
+            if (event.doit) {
+                ignoreDrawForeground = (event.detail & SWT.FOREGROUND) is 0;
+                ignoreDrawBackground = (event.detail & SWT.BACKGROUND) is 0;
+                ignoreDrawSelection = (event.detail & SWT.SELECTED) is 0;
+                ignoreDrawFocus = (event.detail & SWT.FOCUSED) is 0;
+                ignoreDrawHot = (event.detail & SWT.HOT) is 0;
+            } else {
+                ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = true;
+            }
+            if (selected && ignoreDrawSelection) ignoreDrawHot = true;
+            if (!ignoreDrawBackground && clrTextBk !is -1) {
+                bool draw = !selected && !hot;
+                if (!explorerTheme && selected) draw = !ignoreDrawSelection;
+                if (draw) {
+                    if (columnCount is 0) {
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            fillBackground (hDC, clrTextBk, &rect);
+                        } 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, clrTextBk, textRect);
+                        }
+                    } else {
+                        fillBackground (hDC, clrTextBk, cellRect);
+                    }
+                }
+            }
+            if (ignoreDrawSelection) ignoreFullSelection = true;
+            if (!ignoreDrawSelection || !ignoreDrawHot) {
+                if (!selected && !hot) {
+                    selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
+                }
+                if (explorerTheme) {
+                    if ((style & SWT.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
+                    * 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 & SWT.FULL_SELECTION) !is 0) {
+                        if ((style & SWT.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);
+                    }
+                }
+            } else {
+                if (selected || hot) {
+                    selectionForeground = clrText = newTextClr;
+                    ignoreDrawSelection = ignoreDrawHot = true;
+                }
+                if (explorerTheme) {
+                    nmcd.nmcd.uItemState |= OS.CDIS_DISABLED;
+                    /*
+                    * Feature in Windows.  On Vista only, when the text
+                    * color is unchanged and an item is asked to draw
+                    * disabled, it uses the disabled color.  The fix is
+                    * to modify the color so that is it no longer equal.
+                    */
+                    int newColor = clrText is -1 ? getForegroundPixel () : clrText;
+                    if (nmcd.clrText is newColor) {
+                        nmcd.clrText |= 0x20000000;
+                        if (nmcd.clrText is newColor) nmcd.clrText &= ~0x20000000;
+                    } else {
+                        nmcd.clrText = newColor;
+                    }
+                    OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                }
+            }
+            if (focused && !ignoreDrawFocus && (style & SWT.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);
+                focusRect = textRect;
+            }
+            if (explorerTheme) {
+                if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT;
+                OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+            }
+            RECT* itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+            OS.SaveDC (hDC);
+            OS.SelectClipRgn (hDC, null);
+            if (explorerTheme) {
+                itemRect.left -= EXPLORER_EXTRA;
+                itemRect.right += EXPLORER_EXTRA;
+            }
+            //TODO - bug in Windows selection or SWT itemRect
+            /*if (selected)*/ itemRect.right++;
+            if (linesVisible) itemRect.bottom++;
+            if (clipRect !is null) {
+                OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+            }
+            OS.ExcludeClipRect (hDC, itemRect.left, itemRect.top, itemRect.right, itemRect.bottom);
+            return new LRESULT (OS.CDRF_DODEFAULT | OS.CDRF_NOTIFYPOSTPAINT);
+        }
+        /*
+        * 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 & SWT.FULL_SELECTION) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                RECT rect;
+                OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                if (selected) {
+                    fillBackground (hDC, OS.GetBkColor (hDC), &rect);
+                } else {
+                    if (OS.IsWindowEnabled (handle)) drawBackground (hDC, &rect);
+                }
+                nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+            }
+        }
+    }
+    LRESULT result = null;
+    if (clrText is -1 && clrTextBk is -1 && hFont is cast(HFONT)-1) {
+        result = new LRESULT (OS.CDRF_DODEFAULT | OS.CDRF_NOTIFYPOSTPAINT);
+    } else {
+        result = new LRESULT (OS.CDRF_NEWFONT | OS.CDRF_NOTIFYPOSTPAINT);
+        if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
+        if (OS.IsWindowEnabled (handle) && OS.IsWindowVisible (handle)) {
+            /*
+            * Feature in Windows.  Windows does not fill the entire cell
+            * with the background color when TVS_FULLROWSELECT is not set.
+            * The fix is to fill the cell with the background color.
+            */
+            if (clrTextBk !is -1) {
+                int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                    if (columnCount !is 0 && hwndHeader !is null) {
+                        RECT rect;
+                        HDITEM hdItem;
+                        hdItem.mask = OS.HDI_WIDTH;
+                        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+                        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;
+                            if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)item.handle, &itemRect, true)) {
+                                rect.left = Math.min (itemRect.left, rect.right);
+                            }
+                        }
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            if (!selected) fillBackground (hDC, clrTextBk, &rect);
+                        } else {
+                            if (explorerTheme) {
+                                if (!selected && !hot) fillBackground (hDC, clrTextBk, &rect);
+                            } else {
+                                fillBackground (hDC, clrTextBk, &rect);
+                            }
+                        }
+                    } else {
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            RECT rect;
+                            OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                            if (!selected) fillBackground (hDC, clrTextBk, &rect);
+                        }
+                    }
+                }
+            }
+            if (!selected) {
+                nmcd.clrText = clrText is -1 ? getForegroundPixel () : clrText;
+                nmcd.clrTextBk = clrTextBk is -1 ? getBackgroundPixel () : clrTextBk;
+                OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+            }
+        }
+    }
+    if (OS.IsWindowEnabled (handle)) {
+        /*
+        * On Vista only, when an item is asked to draw disabled,
+        * the background of the text is not filled with the
+        * background color of the tree.  This is true for both
+        * regular and full selection trees.  In order to draw a
+        * background image, mark the item as disabled using
+        * CDIS_DISABLED (when not selected) and set the text
+        * to the regular text color to avoid drawing disabled.
+        */
+        if (explorerTheme) {
+            if (findImageControl () !is  null) {
+                if (!selected && (nmcd.nmcd.uItemState & (OS.CDIS_HOT | OS.CDIS_SELECTED)) is 0) {
+                    nmcd.nmcd.uItemState |= OS.CDIS_DISABLED;
+                    /*
+                    * Feature in Windows.  On Vista only, when the text
+                    * color is unchanged and an item is asked to draw
+                    * disabled, it uses the disabled color.  The fix is
+                    * to modify the color so it is no longer equal.
+                    */
+                    int newColor = clrText is -1 ? getForegroundPixel () : clrText;
+                    if (nmcd.clrText is newColor) {
+                        nmcd.clrText |= 0x20000000;
+                        if (nmcd.clrText is newColor) nmcd.clrText &= ~0x20000000;
+                    } else {
+                        nmcd.clrText = newColor;
+                    }
+                    OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                    if (clrTextBk !is -1) {
+                        if ((style & SWT.FULL_SELECTION) !is 0) {
+                            RECT rect;
+                            if (columnCount !is 0) {
+                                HDITEM hdItem;
+                                hdItem.mask = OS.HDI_WIDTH;
+                                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+                                OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
+                            } else {
+                                OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                            }
+                            fillBackground (hDC, clrTextBk, &rect);
+                        } else {
+                            RECT* textRect = item.getBounds (index, true, false, true, false, true, hDC);
+                            fillBackground (hDC, clrTextBk, textRect);
+                        }
+                    }
+                }
+            }
+        }
+    } else {
+        /*
+        * Feature in Windows.  When the tree is disabled, it draws
+        * with a gray background over the sort column.  The fix is
+        * to fill the background with the sort column color.
+        */
+        if (clrSortBk !is -1) {
+            RECT rect;
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_WIDTH;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
+            fillBackground (hDC, clrSortBk, &rect);
+        }
+    }
+    OS.SaveDC (hDC);
+    if (clipRect !is null) {
+        auto hRgn = OS.CreateRectRgn (clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+        POINT lpPoint;
+        OS.GetWindowOrgEx (hDC, &lpPoint);
+        OS.OffsetRgn (hRgn, -lpPoint.x, -lpPoint.y);
+        OS.SelectClipRgn (hDC, hRgn);
+        OS.DeleteObject (hRgn);
+    }
+    return result;
+}
+
+LRESULT CDDS_POSTPAINT (NMTVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (ignoreCustomDraw) return null;
+    if (OS.IsWindowVisible (handle)) {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            if (sortColumn !is null && sortDirection !is SWT.NONE) {
+                if (findImageControl () is null) {
+                    int index = indexOf (sortColumn);
+                    if (index !is -1) {
+                        int top = nmcd.nmcd.rc.top;
+                        /*
+                        * Bug in Windows.  For some reason, during a collapse,
+                        * when TVM_GETNEXTITEM is sent with TVGN_LASTVISIBLE
+                        * and the collapse causes the item being collapsed
+                        * to become the last visible item in the tree, the
+                        * message takes a long time to process.  In order for
+                        * the slowness to happen, the children of the item
+                        * must have children.  Times of up to 11 seconds have
+                        * been observed with 23 children, each having one
+                        * child.  The fix is to use the bottom partially
+                        * visible item rather than the last possible item
+                        * that could be visible.
+                        *
+                        * NOTE: This problem only happens on Vista during
+                        * WM_NOTIFY with NM_CUSTOMDRAW and CDDS_POSTPAINT.
+                        */
+                        HANDLE hItem;
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            hItem = getBottomItem ();
+                        } else {
+                            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+                        }
+                        if (hItem !is null) {
+                            RECT rect;
+                            if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect, false)) {
+                                top = rect.bottom;
+                            }
+                        }
+                        RECT rect;
+                        OS.SetRect (&rect, nmcd.nmcd.rc.left, top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                        RECT headerRect;
+                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+                        rect.left = headerRect.left;
+                        rect.right = headerRect.right;
+                        fillBackground (nmcd.nmcd.hdc, getSortColumnPixel (), &rect);
+                    }
+                }
+            }
+        }
+        if (linesVisible) {
+            auto hDC = nmcd.nmcd.hdc;
+            if (hwndHeader !is null) {
+                int x = 0;
+                RECT rect;
+                HDITEM hdItem;
+                hdItem.mask = OS.HDI_WIDTH;
+                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);
+                    OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_RIGHT);
+                    x += hdItem.cxy;
+                }
+            }
+            int height = 0;
+            RECT rect;
+            /*
+            * Bug in Windows.  For some reason, during a collapse,
+            * when TVM_GETNEXTITEM is sent with TVGN_LASTVISIBLE
+            * and the collapse causes the item being collapsed
+            * to become the last visible item in the tree, the
+            * message takes a long time to process.  In order for
+            * the slowness to happen, the children of the item
+            * must have children.  Times of up to 11 seconds have
+            * been observed with 23 children, each having one
+            * child.  The fix is to use the bottom partially
+            * visible item rather than the last possible item
+            * that could be visible.
+            *
+            * NOTE: This problem only happens on Vista during
+            * WM_NOTIFY with NM_CUSTOMDRAW and CDDS_POSTPAINT.
+            */
+            HANDLE hItem;
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                hItem = getBottomItem ();
+            } else {
+                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+            }
+            if (hItem !is null) {
+                if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect, false)) {
+                    height = rect.bottom - rect.top;
+                }
+            }
+            if (height is 0) {
+                height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0);
+                OS.GetClientRect (handle, &rect);
+                OS.SetRect (&rect, rect.left, rect.top, rect.right, rect.top + height);
+                OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+            }
+            while (rect.bottom < nmcd.nmcd.rc.bottom) {
+                int top = rect.top + height;
+                OS.SetRect (&rect, rect.left, top, rect.right, top + height);
+                OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
+            }
+        }
+    }
+    return new LRESULT (OS.CDRF_DODEFAULT);
+}
+
+LRESULT CDDS_PREPAINT (NMTVCUSTOMDRAW* nmcd, int wParam, int lParam) {
+    if (explorerTheme) {
+        if ((OS.IsWindowEnabled (handle) && hooks (SWT.EraseItem)) || findImageControl () !is null) {
+            RECT rect;
+            OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+            drawBackground (nmcd.nmcd.hdc, &rect);
+        }
+    }
+    return new LRESULT (OS.CDRF_NOTIFYITEMDRAW | OS.CDRF_NOTIFYPOSTPAINT);
+}
+
+override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (handle is null) return 0;
+    if (hwndParent !is null && hwnd is hwndParent) {
+        return OS.DefWindowProc (hwnd, msg, wParam, lParam);
+    }
+    if (hwndHeader !is null && hwnd is hwndHeader) {
+        return OS.CallWindowProc (HeaderProc, hwnd, msg, wParam, lParam);
+    }
+    switch (msg) {
+        case OS.WM_SETFOCUS: {
+            /*
+            * Feature in Windows.  When a tree control processes WM_SETFOCUS,
+            * if no item is selected, the first item in the tree is selected.
+            * This is unexpected and might clear the previous selection.
+            * The fix is to detect that there is no selection and set it to
+            * the first visible item in the tree.  If the item was not selected,
+            * only the focus is assigned.
+            */
+            if ((style & SWT.SINGLE) !is 0) break;
+            HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+            if (hItem is null) {
+                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                if (hItem !is null) {
+                    TVITEM tvItem;
+                    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                    tvItem.hItem = cast(HTREEITEM)hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    hSelect = hItem;
+                    ignoreDeselect = ignoreSelect = lockSelection = true;
+                    OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hItem);
+                    ignoreDeselect = ignoreSelect = lockSelection = false;
+                    hSelect = null;
+                    if ((tvItem.state & OS.TVIS_SELECTED) is 0) {
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    }
+                }
+            }
+            break;
+        }
+        default:
+    }
+    HANDLE hItem;
+    bool redraw = false;
+    switch (msg) {
+        /* Keyboard messages */
+        case OS.WM_KEYDOWN:
+            if (wParam is OS.VK_CONTROL || wParam is OS.VK_SHIFT) break;
+            //FALL THROUGH
+        case OS.WM_CHAR:
+        case OS.WM_IME_CHAR:
+        case OS.WM_KEYUP:
+        case OS.WM_SYSCHAR:
+        case OS.WM_SYSKEYDOWN:
+        case OS.WM_SYSKEYUP:
+            //FALL THROUGH
+
+        /* Scroll messages */
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL:
+            //FALL THROUGH
+
+        /* Resize messages */
+        case OS.WM_SIZE:
+            redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle);
+            if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            //FALL THROUGH
+
+        /* Mouse messages */
+        case OS.WM_LBUTTONDBLCLK:
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONUP:
+        case OS.WM_MBUTTONDBLCLK:
+        case OS.WM_MBUTTONDOWN:
+        case OS.WM_MBUTTONUP:
+        case OS.WM_MOUSEHOVER:
+        case OS.WM_MOUSELEAVE:
+        case OS.WM_MOUSEMOVE:
+        case OS.WM_MOUSEWHEEL:
+        case OS.WM_RBUTTONDBLCLK:
+        case OS.WM_RBUTTONDOWN:
+        case OS.WM_RBUTTONUP:
+        case OS.WM_XBUTTONDBLCLK:
+        case OS.WM_XBUTTONDOWN:
+        case OS.WM_XBUTTONUP:
+            //FALL THROUGH
+
+        /* Other messages */
+        case OS.WM_SETFONT:
+        case OS.WM_TIMER: {
+            if (findImageControl () !is null) {
+                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+            }
+            break;
+        }
+        default:
+    }
+    int /*long*/ code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
+    switch (msg) {
+        /* Keyboard messages */
+        case OS.WM_KEYDOWN:
+            if (wParam is OS.VK_CONTROL || wParam is OS.VK_SHIFT) break;
+            //FALL THROUGH
+        case OS.WM_CHAR:
+        case OS.WM_IME_CHAR:
+        case OS.WM_KEYUP:
+        case OS.WM_SYSCHAR:
+        case OS.WM_SYSKEYDOWN:
+        case OS.WM_SYSKEYUP:
+            //FALL THROUGH
+
+        /* Scroll messages */
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL:
+            //FALL THROUGH
+
+        /* Resize messages */
+        case OS.WM_SIZE:
+            if (redraw) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.InvalidateRect (handle, null, true);
+                if (hwndHeader !is null) OS.InvalidateRect (hwndHeader, null, true);
+            }
+            //FALL THROUGH
+
+        /* Mouse messages */
+        case OS.WM_LBUTTONDBLCLK:
+        case OS.WM_LBUTTONDOWN:
+        case OS.WM_LBUTTONUP:
+        case OS.WM_MBUTTONDBLCLK:
+        case OS.WM_MBUTTONDOWN:
+        case OS.WM_MBUTTONUP:
+        case OS.WM_MOUSEHOVER:
+        case OS.WM_MOUSELEAVE:
+        case OS.WM_MOUSEMOVE:
+        case OS.WM_MOUSEWHEEL:
+        case OS.WM_RBUTTONDBLCLK:
+        case OS.WM_RBUTTONDOWN:
+        case OS.WM_RBUTTONUP:
+        case OS.WM_XBUTTONDBLCLK:
+        case OS.WM_XBUTTONDOWN:
+        case OS.WM_XBUTTONUP:
+            //FALL THROUGH
+
+        /* Other messages */
+        case OS.WM_SETFONT:
+        case OS.WM_TIMER: {
+            if (findImageControl () !is null) {
+                if (hItem !is cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0)) {
+                    OS.InvalidateRect (handle, null, true);
+                }
+            }
+            updateScrollBar ();
+            break;
+        }
+
+        case OS.WM_PAINT:
+            painted = true;
+            break;
+        default:
+    }
+    return code;
+}
+
+override void checkBuffered () {
+    super.checkBuffered ();
+    if ((style & SWT.VIRTUAL) !is 0) {
+        style |= SWT.DOUBLE_BUFFERED;
+        OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
+    }
+    if (EXPLORER_THEME) {
+        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 |= SWT.DOUBLE_BUFFERED;
+        }
+    }
+}
+
+bool checkData (TreeItem item, bool redraw) {
+    if ((style & SWT.VIRTUAL) is 0) return true;
+    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) {
+    if ((style & SWT.VIRTUAL) is 0) return true;
+    if (!item.cached) {
+        item.cached = true;
+        Event event = new Event ();
+        event.item = item;
+        event.index = index;
+        TreeItem oldItem = currentItem;
+        currentItem = item;
+        sendEvent (SWT.SetData, event);
+        //widget could be disposed at this point
+        currentItem = oldItem;
+        if (isDisposed () || item.isDisposed ()) return false;
+        if (redraw) item.redraw ();
+    }
+    return true;
+}
+
+override bool checkHandle (HWND hwnd) {
+    return hwnd is handle || (hwndParent !is null && hwnd is hwndParent) || (hwndHeader !is null && hwnd is hwndHeader);
+}
+
+bool checkScroll (HANDLE hItem) {
+    /*
+    * Feature in Windows.  If redraw is turned off using WM_SETREDRAW
+    * and a tree item that is not a child of the first root is selected or
+    * scrolled using TVM_SELECTITEM or TVM_ENSUREVISIBLE, then scrolling
+    * does not occur.  The fix is to detect this case, and make sure
+    * that redraw is temporarily enabled.  To avoid flashing, DefWindowProc()
+    * is called to disable redrawing.
+    *
+    * NOTE:  The code that actually works around the problem is in the
+    * callers of this method.
+    */
+    if (drawCount is 0) return false;
+    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);
+    }
+    return hParent is 0;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value.  If the tree was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all <code>true</code> if all child items of the indexed item should be
+ * cleared recursively, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, bool all) {
+    checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    hItem = findItem (hItem, index);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    clear (hItem, &tvItem);
+    if (all) {
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        clearAll (hItem, &tvItem, all);
+    }
+}
+
+void clear (HANDLE hItem, TVITEM* tvItem) {
+    tvItem.hItem = cast(HTREEITEM)hItem;
+    TreeItem item = null;
+    if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) !is 0) {
+        item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
+    }
+    if (item !is null) {
+        if ((style & SWT.VIRTUAL) !is 0 && !item.cached) return;
+        item.clear ();
+        item.redraw ();
+    }
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * tree was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @param all <code>true</code> if all child items should be cleared
+ * recursively, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clearAll (bool all) {
+    checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    if (hItem is null) return;
+    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);
+        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);
+    }
+}
+
+private static extern(Windows) int CompareFunc (int lParam1, int lParam2, int lParamSort) {
+    return sThis.CompareProc( lParam1, lParam2, lParamSort );
+}
+int CompareProc (int lParam1, int lParam2, int lParamSort) {
+    TreeItem item1 = items [lParam1], item2 = items [lParam2];
+    String text1 = item1.getText (lParamSort), text2 = item2.getText (lParamSort);
+    return sortDirection is SWT.UP ? ( text1 < text2 ) : ( text2 < text1 );
+}
+
+override public Point computeSize (int wHint, int hHint, bool changed) {
+    checkWidget ();
+    int width = 0, height = 0;
+    if (hwndHeader !is null) {
+        HDITEM hdItem;
+        hdItem.mask = OS.HDI_WIDTH;
+        for (int i=0; i<columnCount; i++) {
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
+            width += hdItem.cxy;
+        }
+        RECT rect;
+        OS.GetWindowRect (hwndHeader, &rect);
+        height += rect.bottom - rect.top;
+    }
+    RECT rect;
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    while (hItem !is null) {
+        if ((style & SWT.VIRTUAL) is 0 && !painted) {
+            TVITEM tvItem;
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+            tvItem.hItem = cast(HTREEITEM)hItem;
+            tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+            ignoreCustomDraw = true;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            ignoreCustomDraw = false;
+        }
+        if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)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_NEXTVISIBLE, hItem);
+    }
+    if (width is 0) width = DEFAULT_WIDTH;
+    if (height is 0) height = DEFAULT_HEIGHT;
+    if (wHint !is SWT.DEFAULT) width = wHint;
+    if (hHint !is SWT.DEFAULT) height = hHint;
+    int border = getBorderWidth ();
+    width += border * 2;
+    height += border * 2;
+    if ((style & SWT.V_SCROLL) !is 0) {
+        width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
+    }
+    if ((style & SWT.H_SCROLL) !is 0) {
+        height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
+    }
+    return new Point (width, height);
+}
+
+override void createHandle () {
+    super.createHandle ();
+    state &= ~(CANVAS | THEME_BACKGROUND);
+
+    /* Use the Explorer theme */
+    if (EXPLORER_THEME) {
+        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;
+            /*
+            * This code is intentionally commented.
+            */
+//          if ((style & SWT.FULL_SELECTION) is 0) bits |= OS.TVS_EX_AUTOHSCROLL;
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits);
+            /*
+            * Bug in Windows.  When the tree is using the explorer
+            * theme, it does not use COLOR_WINDOW_TEXT for the
+            * default foreground color.  The fix is to explicitly
+            * set the foreground.
+            */
+            setForegroundPixel (-1);
+        }
+    }
+
+    /*
+    * Feature in Windows.  In version 5.8 of COMCTL32.DLL,
+    * if the font is changed for an item, the bounds for the
+    * item are not updated, causing the text to be clipped.
+    * The fix is to detect the version of COMCTL32.DLL, and
+    * if it is one of the versions with the problem, then
+    * use version 5.00 of the control (a version that does
+    * not have the problem).  This is the recommended work
+    * around from the MSDN.
+    */
+    static if (!OS.IsWinCE) {
+        if (OS.COMCTL32_MAJOR < 6) {
+            OS.SendMessage (handle, OS.CCM_SETVERSION, 5, 0);
+        }
+    }
+
+    /* Set the checkbox image list */
+    if ((style & SWT.CHECK) !is 0) setCheckboxImageList ();
+
+    /*
+    * Feature in Windows.  When the control is created,
+    * it does not use the default system font.  A new HFONT
+    * is created and destroyed when the control is destroyed.
+    * This means that a program that queries the font from
+    * this control, uses the font in another control and then
+    * destroys this control will have the font unexpectedly
+    * destroyed in the other control.  The fix is to assign
+    * the font ourselves each time the control is created.
+    * The control will not destroy a font that it did not
+    * create.
+    */
+    HFONT hFont = OS.GetStockObject (OS.SYSTEM_FONT);
+    OS.SendMessage (handle, OS.WM_SETFONT, hFont, 0);
+}
+
+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 & SWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
+    headerToolTipHandle = OS.CreateWindowEx (
+        bits,
+        OS.TOOLTIPS_CLASS.ptr,
+        null,
+        OS.TTS_NOPREFIX,
+        OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+        handle,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (headerToolTipHandle is null) error (SWT.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 (headerToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+}
+
+void createItem (TreeColumn column, int index) {
+    if (hwndHeader is null) createParent ();
+    if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE);
+    if (columnCount is columns.length) {
+        TreeColumn [] newColumns = new TreeColumn [columns.length + 4];
+        System.arraycopy (columns, 0, newColumns, 0, columns.length);
+        columns = newColumns;
+    }
+    for (int i=0; i<items.length; i++) {
+        TreeItem item = items [i];
+        if (item !is null) {
+            String [] strings = item.strings;
+            if (strings !is null) {
+                String [] temp = new String [columnCount + 1];
+                System.arraycopy (strings, 0, temp, 0, index);
+                System.arraycopy (strings, index, temp, index + 1, columnCount - index);
+                item.strings = temp;
+            }
+            Image [] images = item.images;
+            if (images !is null) {
+                Image [] temp = new Image [columnCount + 1];
+                System.arraycopy (images, 0, temp, 0, index);
+                System.arraycopy (images, index, temp, index + 1, columnCount - index);
+                item.images = temp;
+            }
+            if (index is 0) {
+                if (columnCount !is 0) {
+                    if (strings is null) {
+                        item.strings = new String [columnCount + 1];
+                        item.strings [1] = item.text;
+                    }
+                    item.text = "";
+                    if (images is null) {
+                        item.images = new Image [columnCount + 1];
+                        item.images [1] = item.image;
+                    }
+                    item.image = null;
+                }
+            }
+            if (item.cellBackground !is null) {
+                int [] cellBackground = item.cellBackground;
+                int [] temp = new int [columnCount + 1];
+                System.arraycopy (cellBackground, 0, temp, 0, index);
+                System.arraycopy (cellBackground, index, temp, index + 1, columnCount - index);
+                temp [index] = -1;
+                item.cellBackground = temp;
+            }
+            if (item.cellForeground !is null) {
+                int [] cellForeground = item.cellForeground;
+                int [] temp = new int [columnCount + 1];
+                System.arraycopy (cellForeground, 0, temp, 0, index);
+                System.arraycopy (cellForeground, index, temp, index + 1, columnCount - index);
+                temp [index] = -1;
+                item.cellForeground = temp;
+            }
+            if (item.cellFont !is null) {
+                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);
+                item.cellFont = temp;
+            }
+        }
+    }
+    System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
+    columns [index] = column;
+
+    /*
+    * Bug in Windows.  For some reason, when HDM_INSERTITEM
+    * is used to insert an item into a header without text,
+    * if is not possible to set the text at a later time.
+    * The fix is to insert the item with an empty string.
+    */
+    auto hHeap = OS.GetProcessHeap ();
+    auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_TEXT | OS.HDI_FORMAT;
+    hdItem.pszText = pszText;
+    if ((column.style & SWT.LEFT) is SWT.LEFT) hdItem.fmt = OS.HDF_LEFT;
+    if ((column.style & SWT.CENTER) is SWT.CENTER) hdItem.fmt = OS.HDF_CENTER;
+    if ((column.style & SWT.RIGHT) is SWT.RIGHT) hdItem.fmt = OS.HDF_RIGHT;
+    OS.SendMessage (hwndHeader, OS.HDM_INSERTITEM, index, &hdItem);
+    if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+
+    /* When the first column is created, hide the horizontal scroll bar */
+    if (columnCount is 1) {
+        scrollWidth = 0;
+        if ((style & SWT.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
+        * scroll bar.  The fix is to check for this case and
+        * explicitly hide the scroll bar explicitly.
+        */
+        int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+        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 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
+        OS.InvalidateRect (handle, null, true);
+    }
+
+    /* Add the tool tip item for the header */
+    if (headerToolTipHandle !is null) {
+        RECT rect;
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &rect) !is 0) {
+            TOOLINFO lpti;
+            lpti.cbSize = OS.TOOLINFO_sizeof;
+            lpti.uFlags = OS.TTF_SUBCLASS;
+            lpti.hwnd = hwndHeader;
+            lpti.uId = column.id = display.nextToolTipId++;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+            OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, &lpti);
+        }
+    }
+}
+
+void createItem (TreeItem item, HANDLE hParent, HANDLE hInsertAfter, HANDLE hItem) {
+    int id = -1;
+    if (item !is null) {
+        id = lastID < items.length ? lastID : 0;
+        while (id < items.length && items [id] !is null) id++;
+        if (id is items.length) {
+            /*
+            * Grow the array faster when redraw is off or the
+            * table is not visible.  When the table is painted,
+            * the items array is resized to be smaller to reduce
+            * memory usage.
+            */
+            int length = 0;
+            if (drawCount is 0 && OS.IsWindowVisible (handle)) {
+                length = items.length + 4;
+            } else {
+                shrink = true;
+                length = Math.max (4, items.length * 3 / 2);
+            }
+            TreeItem [] newItems = new TreeItem [length];
+            System.arraycopy (items, 0, newItems, 0, items.length);
+            items = newItems;
+        }
+        lastID = id + 1;
+    }
+    HANDLE hNewItem;
+    HANDLE hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
+    bool fixParent = hFirstItem is null;
+    if (hItem is null) {
+        TVINSERTSTRUCT tvInsert;
+        tvInsert.hParent = cast(HTREEITEM)hParent;
+        tvInsert.hInsertAfter = cast(HTREEITEM)hInsertAfter;
+        tvInsert.item.lParam = id;
+        tvInsert.item.pszText = OS.LPSTR_TEXTCALLBACK;
+        tvInsert.item.iImage = tvInsert.item.iSelectedImage = cast(HBITMAP) OS.I_IMAGECALLBACK;
+        tvInsert.item.mask = OS.TVIF_TEXT | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE | OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        if ((style & SWT.CHECK) !is 0) {
+            tvInsert.item.mask = tvInsert.item.mask | OS.TVIF_STATE;
+            tvInsert.item.state = 1 << 12;
+            tvInsert.item.stateMask = OS.TVIS_STATEIMAGEMASK;
+        }
+        ignoreCustomDraw = true;
+        hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert);
+        ignoreCustomDraw = false;
+        if (hNewItem is null) error (SWT.ERROR_ITEM_NOT_ADDED);
+        /*
+        * This code is intentionally commented.
+        */
+//      if (hParent !is 0) {
+//          int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//          bits |= OS.TVS_LINESATROOT;
+//          OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+//      }
+    } else {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        tvItem.hItem = cast(HTREEITEM)( hNewItem = hItem );
+        tvItem.lParam = id;
+        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+    }
+    if (item !is null) {
+        item.handle = hNewItem;
+        items [id] = item;
+    }
+    if (hFirstItem is null) {
+        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++;
+    if (hItem is null) {
+        /*
+        * Bug in Windows.  When a child item is added to a parent item
+        * that has no children outside of WM_NOTIFY with control code
+        * TVN_ITEMEXPANDED, the tree widget does not redraw the + / -
+        * indicator.  The fix is to detect the case when the first
+        * child is added to a visible parent item and redraw the parent.
+        */
+        if (fixParent) {
+            if (drawCount is 0 && OS.IsWindowVisible (handle)) {
+                RECT rect;
+                if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hParent, &rect, false)) {
+                    OS.InvalidateRect (handle, &rect, true);
+                }
+            }
+        }
+        /*
+        * Bug in Windows.  When a new item is added while Windows
+        * is requesting data a tree item using TVN_GETDISPINFO,
+        * outstanding damage for items that are below the new item
+        * is not scrolled.  The fix is to explicitly damage the
+        * new area.
+        */
+        if ((style & SWT.VIRTUAL) !is 0) {
+            if (currentItem !is null) {
+                RECT rect;
+                if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hNewItem, &rect, false)) {
+                    RECT damageRect;
+                    bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true);
+                    if (damaged && damageRect.top < rect.bottom) {
+                        static if (OS.IsWinCE) {
+                            OS.OffsetRect (&damageRect, 0, rect.bottom - rect.top);
+                            OS.InvalidateRect (handle, &damageRect, true);
+                        } else {
+                            HRGN rgn = OS.CreateRectRgn (0, 0, 0, 0);
+                            int result = OS.GetUpdateRgn (handle, rgn, true);
+                            if (result !is OS.NULLREGION) {
+                                OS.OffsetRgn (rgn, 0, rect.bottom - rect.top);
+                                OS.InvalidateRgn (handle, rgn, true);
+                            }
+                            OS.DeleteObject (rgn);
+                        }
+                    }
+                }
+            }
+        }
+        updateScrollBar ();
+    }
+}
+
+void createItemToolTips () {
+    static if (OS.IsWinCE) return;
+    if (itemToolTipHandle !is null) return;
+    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 & SWT.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 (
+        bits2,
+        OS.TOOLTIPS_CLASS.ptr,
+        null,
+        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 (SWT.ERROR_NO_HANDLES);
+    OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
+    TOOLINFO lpti;
+    lpti.cbSize = OS.TOOLINFO_sizeof;
+    lpti.hwnd = handle;
+    lpti.uId = cast(int)handle;
+    lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
+    lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+    OS.SendMessage (itemToolTipHandle, OS.TTM_ADDTOOL, 0, &lpti);
+}
+
+void createParent () {
+    forceResize ();
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    OS.MapWindowPoints (null, parent.handle, cast(POINT*) &rect, 2);
+    int oldStyle = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    int newStyle = super.widgetStyle () & ~OS.WS_VISIBLE;
+    if ((oldStyle & OS.WS_DISABLED) !is 0) newStyle |= OS.WS_DISABLED;
+//  if ((oldStyle & OS.WS_VISIBLE) !is 0) newStyle |= OS.WS_VISIBLE;
+    hwndParent = OS.CreateWindowEx (
+        super.widgetExtStyle (),
+        StrToTCHARz( 0, super.windowClass () ),
+        null,
+        newStyle,
+        rect.left,
+        rect.top,
+        rect.right - rect.left,
+        rect.bottom - rect.top,
+        parent.handle,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (hwndParent is null) error (SWT.ERROR_NO_HANDLES);
+    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;
+        if ((style & SWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
+    hwndHeader = OS.CreateWindowEx (
+        bits,
+        HeaderClass.ptr,
+        null,
+        OS.HDS_BUTTONS | OS.HDS_FULLDRAG | OS.HDS_DRAGDROP | OS.HDS_HIDDEN | OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+        0, 0, 0, 0,
+        hwndParent,
+        null,
+        OS.GetModuleHandle (null),
+        null);
+    if (hwndHeader is null) error (SWT.ERROR_NO_HANDLES);
+    OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, cast(LONG_PTR)hwndHeader);
+    if (OS.IsDBLocale) {
+        auto hIMC = OS.ImmGetContext (handle);
+        OS.ImmAssociateContext (hwndParent, hIMC);
+        OS.ImmAssociateContext (hwndHeader, hIMC);
+        OS.ImmReleaseContext (handle, hIMC);
+    }
+    //This code is intentionally commented
+//  if (!OS.IsPPC) {
+//      if ((style & SWT.BORDER) !is 0) {
+//          int oldExStyle = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+//          oldExStyle &= ~OS.WS_EX_CLIENTEDGE;
+//          OS.SetWindowLong (handle, OS.GWL_EXSTYLE, oldExStyle);
+//      }
+//  }
+    HFONT hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (hFont !is null) OS.SendMessage (hwndHeader, OS.WM_SETFONT, hFont, 0);
+    HANDLE hwndInsertAfter = OS.GetWindow (handle, OS.GW_HWNDPREV);
+    int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
+    SetWindowPos (hwndParent, hwndInsertAfter, 0, 0, 0, 0, flags);
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+    OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
+    info.nPage = info.nMax + 1;
+    OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+    OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
+    info.nPage = info.nMax + 1;
+    OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
+    customDraw = true;
+    deregister ();
+    if ((oldStyle & OS.WS_VISIBLE) !is 0) {
+        OS.ShowWindow (hwndParent, OS.SW_SHOW);
+    }
+    HWND hwndFocus = OS.GetFocus ();
+    if (hwndFocus is handle) OS.SetFocus (hwndParent);
+    OS.SetParent (handle, hwndParent);
+    if (hwndFocus is handle) OS.SetFocus (handle);
+    register ();
+    subclass ();
+}
+
+override void createWidget () {
+    super.createWidget ();
+    items = new TreeItem [4];
+    columns = new TreeColumn [4];
+    itemCount = -1;
+}
+
+override int defaultBackground () {
+    return OS.GetSysColor (OS.COLOR_WINDOW);
+}
+
+override void deregister () {
+    super.deregister ();
+    if (hwndParent !is null) display.removeControl (hwndParent);
+    if (hwndHeader !is null) display.removeControl (hwndHeader);
+}
+
+void deselect (HANDLE hItem, TVITEM* tvItem, HANDLE hIgnoreItem) {
+    while (hItem !is null) {
+        if (hItem !is hIgnoreItem) {
+            tvItem.hItem = cast(HTREEITEM)hItem;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+        }
+        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        deselect (hFirstItem, tvItem, hIgnoreItem);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+    }
+}
+
+/**
+ * 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 SWTException <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 (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    tvItem.hItem = cast(HTREEITEM)item.handle;
+    OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
+}
+
+/**
+ * Deselects all selected items in the receiver.
+ *
+ * @exception SWTException <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 deselectAll () {
+    checkWidget ();
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    if ((style & SWT.SINGLE) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hItem !is null) {
+            tvItem.hItem = cast(HTREEITEM)hItem;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+        }
+    } else {
+        auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+        if ((style & SWT.VIRTUAL) !is 0) {
+            HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+            deselect (hItem, &tvItem, null);
+        } else {
+            for (int i=0; i<items.length; i++) {
+                TreeItem item = items [i];
+                if (item !is null) {
+                    tvItem.hItem = cast(HTREEITEM)item.handle;
+                    OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                }
+            }
+        }
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+    }
+}
+
+void destroyItem (TreeColumn column) {
+    if (hwndHeader is null) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    int index = 0;
+    while (index < columnCount) {
+        if (columns [index] is column) break;
+        index++;
+    }
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr);
+    int orderIndex = 0;
+    while (orderIndex < columnCount) {
+        if (oldOrder [orderIndex] is index) break;
+        orderIndex++;
+    }
+    RECT headerRect;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+    if (OS.SendMessage (hwndHeader, OS.HDM_DELETEITEM, index, 0) is 0) {
+        error (SWT.ERROR_ITEM_NOT_REMOVED);
+    }
+    System.arraycopy (columns, index + 1, columns, index, --columnCount - index);
+    columns [columnCount] = null;
+    for (int i=0; i<items.length; i++) {
+        TreeItem item = items [i];
+        if (item !is null) {
+            if (columnCount is 0) {
+                item.strings = null;
+                item.images = null;
+                item.cellBackground = null;
+                item.cellForeground = null;
+                item.cellFont = null;
+            } else {
+                if (item.strings !is null) {
+                    String [] strings = item.strings;
+                    if (index is 0) {
+                        item.text = strings [1] !is null ? strings [1] : "";
+                    }
+                    String [] temp = new String [columnCount];
+                    System.arraycopy (strings, 0, temp, 0, index);
+                    System.arraycopy (strings, index + 1, temp, index, columnCount - index);
+                    item.strings = temp;
+                } else {
+                    if (index is 0) item.text = "";
+                }
+                if (item.images !is null) {
+                    Image [] images = item.images;
+                    if (index is 0) item.image = images [1];
+                    Image [] temp = new Image [columnCount];
+                    System.arraycopy (images, 0, temp, 0, index);
+                    System.arraycopy (images, index + 1, temp, index, columnCount - index);
+                    item.images = temp;
+                } else {
+                    if (index is 0) item.image = null;
+                }
+                if (item.cellBackground !is null) {
+                    int [] cellBackground = item.cellBackground;
+                    int [] temp = new int [columnCount];
+                    System.arraycopy (cellBackground, 0, temp, 0, index);
+                    System.arraycopy (cellBackground, index + 1, temp, index, columnCount - index);
+                    item.cellBackground = temp;
+                }
+                if (item.cellForeground !is null) {
+                    int [] cellForeground = item.cellForeground;
+                    int [] temp = new int [columnCount];
+                    System.arraycopy (cellForeground, 0, temp, 0, index);
+                    System.arraycopy (cellForeground, index + 1, temp, index, columnCount - index);
+                    item.cellForeground = temp;
+                }
+                if (item.cellFont !is null) {
+                    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;
+                }
+            }
+        }
+    }
+
+    /*
+    * When the last column is deleted, show the horizontal
+    * scroll bar.  Otherwise, left align the first column
+    * and redraw the columns to the right.
+    */
+    if (columnCount is 0) {
+        scrollWidth = 0;
+        if (!hooks (SWT.MeasureItem)) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((style & SWT.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 &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+            columns [0].style |= SWT.LEFT;
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            hdItem.fmt &= ~OS.HDF_JUSTIFYMASK;
+            hdItem.fmt |= OS.HDF_LEFT;
+            OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+        }
+        RECT rect;
+        OS.GetClientRect (handle, &rect);
+        rect.left = headerRect.left;
+        OS.InvalidateRect (handle, &rect, true);
+    }
+    setScrollWidth ();
+    updateImageList ();
+    updateScrollBar ();
+    if (columnCount !is 0) {
+        int [] newOrder = new int [columnCount];
+        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, newOrder.ptr);
+        TreeColumn [] newColumns = new TreeColumn [columnCount - orderIndex];
+        for (int i=orderIndex; i<newOrder.length; i++) {
+            newColumns [i - orderIndex] = columns [newOrder [i]];
+            newColumns [i - orderIndex].updateToolTip (newOrder [i]);
+        }
+        for (int i=0; i<newColumns.length; i++) {
+            if (!newColumns [i].isDisposed ()) {
+                newColumns [i].sendEvent (SWT.Move);
+            }
+        }
+    }
+
+    /* Remove the tool tip item for the header */
+    if (headerToolTipHandle !is null) {
+        TOOLINFO lpti;
+        lpti.cbSize = OS.TOOLINFO_sizeof;
+        lpti.uId = column.id;
+        lpti.hwnd = hwndHeader;
+        OS.SendMessage (headerToolTipHandle, OS.TTM_DELTOOL, 0, &lpti);
+    }
+}
+
+void destroyItem (TreeItem item, HANDLE hItem) {
+    hFirstIndexOf = hLastIndexOf = null;
+    itemCount = -1;
+    /*
+    * Feature in Windows.  When an item is removed that is not
+    * visible in the tree because it belongs to a collapsed branch,
+    * Windows redraws the tree causing a flash for each item that
+    * is removed.  The fix is to detect whether the item is visible,
+    * force the widget to be fully painted, turn off redraw, remove
+    * the item and validate the damage caused by the removing of
+    * the item.
+    *
+    * NOTE: This fix is not necessary when double buffering and
+    * can cause problems for virtual trees due to the call to
+    * UpdateWindow() that flushes outstanding WM_PAINT events,
+    * allowing application code to add or remove items during
+    * this remove operation.
+    */
+    HANDLE hParent;
+    bool fixRedraw = false;
+    if ((style & SWT.DOUBLE_BUFFERED) is 0) {
+        if (drawCount is 0 && OS.IsWindowVisible (handle)) {
+            RECT rect;
+            fixRedraw = !OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect, false);
+        }
+    }
+    if (fixRedraw) {
+        hParent = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+        OS.UpdateWindow (handle);
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        /*
+        * This code is intentionally commented.
+        */
+//      OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    if ((style & SWT.MULTI) !is 0) {
+        ignoreDeselect = ignoreSelect = lockSelection = true;
+    }
+
+    /*
+    * Feature in Windows.  When an item is deleted and a tool tip
+    * is showing, Window requests the new text for the new item
+    * that is under the cursor right away.  This means that when
+    * multiple items are deleted, the tool tip flashes, showing
+    * each new item in the tool tip as it is scrolled into view.
+    * The fix is to hide tool tips when any item is deleted.
+    *
+    * NOTE:  This only happens on Vista.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
+        if (hwndToolTip !is null) OS.SendMessage (hwndToolTip, OS.TTM_POP, 0 ,0);
+    }
+
+    shrink = ignoreShrink = true;
+    OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, hItem);
+    ignoreShrink = false;
+    if ((style & SWT.MULTI) !is 0) {
+        ignoreDeselect = ignoreSelect = lockSelection = false;
+    }
+    if (fixRedraw) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.ValidateRect (handle, null);
+        /*
+        * If the item that was deleted was the last child of a tree item that
+        * is visible, redraw the parent item to force the + / - to be updated.
+        */
+        if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) {
+            RECT rect;
+            if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hParent, &rect, false)) {
+                OS.InvalidateRect (handle, &rect, true);
+            }
+        }
+    }
+    int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+    if (count is 0) {
+        if (imageList !is null) {
+            OS.SendMessage (handle, OS.TVM_SETIMAGELIST, 0, 0);
+            display.releaseImageList (imageList);
+        }
+        imageList = null;
+        if (hwndParent is null && !linesVisible) {
+            if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                customDraw = false;
+            }
+        }
+        items = new TreeItem [4];
+        scrollWidth = 0;
+        setScrollWidth ();
+    }
+    updateScrollBar ();
+}
+
+override void destroyScrollBar (int type) {
+    super.destroyScrollBar (type);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & SWT.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 (SWT.DragDetect)) {
+        bits &= ~OS.TVS_DISABLEDRAGDROP;
+    } else {
+        bits |= OS.TVS_DISABLEDRAGDROP;
+    }
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+}
+
+override void enableWidget (bool enabled) {
+    super.enableWidget (enabled);
+    /*
+    * Feature in Windows.  When a tree is given a background color
+    * using TVM_SETBKCOLOR and the tree is disabled, Windows draws
+    * the tree using the background color rather than the disabled
+    * colors.  This is different from the table which draws grayed.
+    * The fix is to set the default background color while the tree
+    * is disabled and restore it when enabled.
+    */
+    Control control = findBackgroundControl ();
+    /*
+    * Bug in Windows.  On Vista only, Windows does not draw using
+    * the background color when the tree is disabled.  The fix is
+    * to set the default color, even when the color has not been
+    * changed, causing Windows to draw correctly.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (control is null) control = this;
+    }
+    if (control !is null) {
+        if (control.backgroundImage is null) {
+            _setBackgroundPixel (enabled ? control.getBackgroundPixel () : -1);
+        }
+    }
+    if (hwndParent !is null) OS.EnableWindow (hwndParent, enabled);
+
+    /*
+    * 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 the sort column color.  The fix
+    * is to clear TVS_FULLROWSELECT when a their is
+    * as sort column.
+    */
+    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 = 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) {
+        if (hFirstIndexOf is hItem) {
+            hLastIndexOf = hFirstIndexOf;
+            return lastIndexOf = 0;
+        }
+        if (hLastIndexOf is hItem) return lastIndexOf;
+        auto hPrevItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+        if (hPrevItem is hItem) {
+            hLastIndexOf = hPrevItem;
+            return --lastIndexOf;
+        }
+        HANDLE hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+        if (hNextItem is hItem) {
+            hLastIndexOf = hNextItem;
+            return ++lastIndexOf;
+        }
+        int previousIndex = lastIndexOf - 1;
+        while (hPrevItem !is null && hPrevItem !is hItem) {
+            hPrevItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hPrevItem);
+            --previousIndex;
+        }
+        if (hPrevItem is hItem) {
+            hLastIndexOf = hPrevItem;
+            return lastIndexOf = previousIndex;
+        }
+        int nextIndex = lastIndexOf + 1;
+        while (hNextItem !is null && hNextItem !is hItem) {
+            hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+            nextIndex++;
+        }
+        if (hNextItem is hItem) {
+            hLastIndexOf = hNextItem;
+            return lastIndexOf = nextIndex;
+        }
+        return -1;
+    }
+    int index = 0;
+    auto hNextItem = hFirstItem;
+    while (hNextItem !is null && hNextItem !is hItem) {
+        hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+        index++;
+    }
+    if (hNextItem is hItem) {
+        itemCount = -1;
+        hFirstIndexOf = hFirstItem;
+        hLastIndexOf = hNextItem;
+        return lastIndexOf = index;
+    }
+    return -1;
+}
+
+override Widget findItem (HANDLE hItem) {
+    return _getItem (hItem);
+}
+
+HANDLE findItem (HANDLE hFirstItem, int index) {
+    if (hFirstItem is null) return null;
+    if (hFirstItem is hFirstIndexOf) {
+        if (index is 0) {
+            lastIndexOf = 0;
+            return hLastIndexOf = hFirstIndexOf;
+        }
+        if (lastIndexOf is index) return hLastIndexOf;
+        if (lastIndexOf - 1 is index) {
+            --lastIndexOf;
+            return hLastIndexOf = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+        }
+        if (lastIndexOf + 1 is index) {
+            lastIndexOf++;
+            return hLastIndexOf = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+        }
+        if (index < lastIndexOf) {
+            int previousIndex = lastIndexOf - 1;
+            auto hPrevItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hLastIndexOf);
+            while (hPrevItem !is null && index < previousIndex) {
+                hPrevItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUS, hPrevItem);
+                --previousIndex;
+            }
+            if (index is previousIndex) {
+                lastIndexOf = previousIndex;
+                return hLastIndexOf = hPrevItem;
+            }
+        } else {
+            int nextIndex = lastIndexOf + 1;
+            auto hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hLastIndexOf);
+            while (hNextItem !is null && nextIndex < index) {
+                hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+                nextIndex++;
+            }
+            if (index is nextIndex) {
+                lastIndexOf = nextIndex;
+                return hLastIndexOf = hNextItem;
+            }
+        }
+        return null;
+    }
+    int nextIndex = 0;
+    auto hNextItem = hFirstItem;
+    while (hNextItem !is null && nextIndex < index) {
+        hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hNextItem);
+        nextIndex++;
+    }
+    if (index is nextIndex) {
+        itemCount = -1;
+        lastIndexOf = nextIndex;
+        hFirstIndexOf = hFirstItem;
+        return hLastIndexOf = hNextItem;
+    }
+    return null;
+}
+
+TreeItem getFocusItem () {
+//  checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+    return hItem !is null ? _getItem (hItem) : null;
+}
+
+/**
+ * Returns the width in pixels of a grid line.
+ *
+ * @return the width of a grid line in pixels
+ *
+ * @exception SWTException <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.1
+ */
+public int getGridLineWidth () {
+    checkWidget ();
+    return GRID_WIDTH;
+}
+
+/**
+ * Returns the height of the receiver's header
+ *
+ * @return the height of the header or zero if the header is not visible
+ *
+ * @exception SWTException <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.1
+ */
+public int getHeaderHeight () {
+    checkWidget ();
+    if (hwndHeader is null) return 0;
+    RECT rect;
+    OS.GetWindowRect (hwndHeader, &rect);
+    return rect.bottom - rect.top;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's header 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 header's visibility state
+ *
+ * @exception SWTException <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.1
+ */
+public bool getHeaderVisible () {
+    checkWidget ();
+    if (hwndHeader is null) return false;
+    int bits = OS.GetWindowLong (hwndHeader, OS.GWL_STYLE);
+    return (bits & OS.WS_VISIBLE) !is 0;
+}
+
+Point getImageSize () {
+    if (imageList !is null) return imageList.getImageSize ();
+    return new Point (0, getItemHeight ());
+}
+
+HANDLE getBottomItem () {
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+    if (hItem is null) return null;
+    int index = 0, count = OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0);
+    while (index < count) {
+        HANDLE hNextItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+        if (hNextItem is null) return hItem;
+        hItem = hNextItem;
+        index++;
+    }
+    return hItem;
+}
+
+/**
+ * Returns the column at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ * Columns are returned in the order that they were created.
+ * If no <code>TreeColumn</code>s were created by the programmer,
+ * this method will throw <code>ERROR_INVALID_RANGE</code> despite
+ * the fact that a single column of data may be visible in the tree.
+ * This occurs when the programmer uses the tree like a list, adding
+ * items but never creating a column.
+ *
+ * @param index the index of the column to return
+ * @return the column at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn getColumn (int index) {
+    checkWidget ();
+    if (!(0 <= index && index < columnCount)) error (SWT.ERROR_INVALID_RANGE);
+    return columns [index];
+}
+
+/**
+ * Returns the number of columns contained in the receiver.
+ * If no <code>TreeColumn</code>s were created by the programmer,
+ * this value is zero, despite the fact that visually, one column
+ * of items may be visible. This occurs when the programmer uses
+ * the tree like a list, adding items but never creating a column.
+ *
+ * @return the number of columns
+ *
+ * @exception SWTException <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.1
+ */
+public int getColumnCount () {
+    checkWidget ();
+    return columnCount;
+}
+
+/**
+ * Returns an array of zero-relative integers that map
+ * the creation order of the receiver's items to the
+ * order in which they are currently being displayed.
+ * <p>
+ * Specifically, the indices of the returned array represent
+ * the current visual order of the items, and the contents
+ * of the array represent the creation order of the items.
+ * </p><p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the current visual order of the receiver's items
+ *
+ * @exception SWTException <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 Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public int[] getColumnOrder () {
+    checkWidget ();
+    if (columnCount is 0) return null;
+    int [] order = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
+    return order;
+}
+
+/**
+ * Returns an array of <code>TreeColumn</code>s which are the
+ * columns in the receiver. Columns are returned in the order
+ * that they were created.  If no <code>TreeColumn</code>s were
+ * created by the programmer, the array is empty, despite the fact
+ * that visually, one column of items may be visible. This occurs
+ * when the programmer uses the tree like a list, adding items but
+ * never creating a column.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items in the receiver
+ *
+ * @exception SWTException <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 Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.1
+ */
+public TreeColumn [] getColumns () {
+    checkWidget ();
+    TreeColumn [] result = new TreeColumn [columnCount];
+    System.arraycopy (columns, 0, result, 0, columnCount);
+    return result;
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public TreeItem getItem (int index) {
+    checkWidget ();
+    if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+    auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    if (hFirstItem is null) error (SWT.ERROR_INVALID_RANGE);
+    HANDLE hItem = findItem (hFirstItem, index);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    return _getItem (hItem);
+}
+
+TreeItem getItem (NMTVCUSTOMDRAW* nmcd) {
+    /*
+    * Bug in Windows.  If the lParam field of TVITEM
+    * is changed during custom draw using TVM_SETITEM,
+    * the lItemlParam field of the NMTVCUSTOMDRAW struct
+    * is not updated until the next custom draw.  The
+    * fix is to query the field from the item instead
+    * of using the struct.
+    */
+    int id = nmcd.nmcd.lItemlParam;
+    if ((style & SWT.VIRTUAL) !is 0) {
+        if (id is -1) {
+            TVITEM tvItem;
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+            tvItem.hItem = cast(HTREEITEM) nmcd.nmcd.dwItemSpec;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+            id = tvItem.lParam;
+        }
+    }
+    return _getItem (cast(HANDLE) nmcd.nmcd.dwItemSpec, id);
+}
+
+/**
+ * Returns the 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.
+ * <p>
+ * The item that is returned represents an item that could be selected by the user.
+ * For example, if selection only occurs in items in the first column, then null is
+ * returned if the point is outside of the item.
+ * Note that the SWT.FULL_SELECTION style hint, which specifies the selection policy,
+ * determines the extent of the selection.
+ * </p>
+ *
+ * @param point the point used to locate the item
+ * @return the item at the given point, or null if the point is not in a selectable item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <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 TreeItem getItem (Point point) {
+    checkWidget ();
+    if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TVHITTESTINFO lpht;
+    lpht.pt.x = point.x;
+    lpht.pt.y = point.y;
+    OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
+    if (lpht.hItem !is null) {
+        int flags = OS.TVHT_ONITEM;
+        if ((style & SWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (SWT.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;
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.  The
+ * number that is returned is the number of roots in the
+ * tree.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    if (hItem is null) return 0;
+    return getItemCount (hItem);
+}
+
+int getItemCount (HANDLE hItem) {
+    int count = 0;
+    auto hFirstItem = hItem;
+    if (hItem is hFirstIndexOf) {
+        if (itemCount !is -1) return itemCount;
+        hFirstItem = hLastIndexOf;
+        count = lastIndexOf;
+    }
+    while (hFirstItem !is null) {
+        hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hFirstItem);
+        count++;
+    }
+    if (hItem is hFirstIndexOf) itemCount = count;
+    return count;
+}
+
+/**
+ * Returns the height of the area which would be used to
+ * display <em>one</em> of the items in the tree.
+ *
+ * @return the height of one item
+ *
+ * @exception SWTException <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 int getItemHeight () {
+    checkWidget ();
+    return OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0);
+}
+
+/**
+ * Returns a (possibly empty) array of items contained in the
+ * receiver that are direct item children of the receiver.  These
+ * are the roots of the tree.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the items
+ *
+ * @exception SWTException <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 TreeItem [] getItems () {
+    checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    if (hItem is null) return null;
+    return getItems (hItem);
+}
+
+TreeItem [] getItems (HANDLE hTreeItem) {
+    int count = 0;
+    auto hItem = hTreeItem;
+    while (hItem !is null) {
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+        count++;
+    }
+    int index = 0;
+    TreeItem [] result = new TreeItem [count];
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    tvItem.hItem = cast(HTREEITEM)hTreeItem;
+    /*
+    * Feature in Windows.  In some cases an expand or collapse message
+    * can occur from within TVM_DELETEITEM.  When this happens, the item
+    * being destroyed has been removed from the list of items but has not
+    * been deleted from the tree.  The fix is to check for null items and
+    * remove them from the list.
+    */
+    while (tvItem.hItem !is null) {
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        TreeItem item = _getItem (tvItem.hItem, tvItem.lParam);
+        if (item !is null) result [index++] = item;
+        tvItem.hItem = cast(HTREEITEM) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, tvItem.hItem);
+    }
+    if (index !is count) {
+        TreeItem [] newResult = new TreeItem [index];
+        System.arraycopy (result, 0, newResult, 0, index);
+        result = newResult;
+    }
+    return result;
+}
+
+/**
+ * Returns <code>true</code> if the receiver's lines are 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 visibility state of the lines
+ *
+ * @exception SWTException <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.1
+ */
+public bool getLinesVisible () {
+    checkWidget ();
+    return linesVisible;
+}
+
+HANDLE getNextSelection (HANDLE hItem, TVITEM* tvItem) {
+    while (hItem !is null) {
+        int state = 0;
+        static if (OS.IsWinCE) {
+            tvItem.hItem = hItem;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+            state = tvItem.state;
+        } else {
+            state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+        }
+        if ((state & OS.TVIS_SELECTED) !is 0) return hItem;
+        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        auto hSelected = getNextSelection (hFirstItem, tvItem);
+        if (hSelected !is null) return hSelected;
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+    }
+    return null;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>TreeItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException <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 TreeItem getParentItem () {
+    checkWidget ();
+    return null;
+}
+
+int getSelection (HANDLE hItem, TVITEM* tvItem, TreeItem [] selection, int index, int count, bool bigSelection, bool all) {
+    while (hItem !is null) {
+        if (OS.IsWinCE || bigSelection) {
+            tvItem.hItem = cast(HTREEITEM)hItem;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+            if ((tvItem.state & OS.TVIS_SELECTED) !is 0) {
+                if (selection !is null && index < selection.length) {
+                    selection [index] = _getItem (hItem, tvItem.lParam);
+                }
+                index++;
+            }
+        } else {
+            int state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+            if ((state & OS.TVIS_SELECTED) !is 0) {
+                if (tvItem !is null && selection !is null && index < selection.length) {
+                    tvItem.hItem = cast(HTREEITEM)hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                    selection [index] = _getItem (hItem, tvItem.lParam);
+                }
+                index++;
+            }
+        }
+        if (index is count) break;
+        if (all) {
+            auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+            if ((index = getSelection (hFirstItem, tvItem, selection, index, count, bigSelection, all)) is count) {
+                break;
+            }
+            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+        } else {
+            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+        }
+    }
+    return index;
+}
+
+/**
+ * Returns an array of <code>TreeItem</code>s that are currently
+ * selected in the receiver. The order of the items is unspecified.
+ * An empty array indicates that no items are selected.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its selection, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ * @return an array representing the selection
+ *
+ * @exception SWTException <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 TreeItem [] getSelection () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hItem is null) return new TreeItem [0];
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+        tvItem.hItem = cast(HTREEITEM)hItem;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        if ((tvItem.state & OS.TVIS_SELECTED) is 0) return new TreeItem [0];
+        return [_getItem (tvItem.hItem, tvItem.lParam)];
+    }
+    int count = 0;
+    TreeItem [] guess = new TreeItem [(style & SWT.VIRTUAL) !is 0 ? 8 : 1];
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+    if ((style & SWT.VIRTUAL) !is 0) {
+        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);
+        count = getSelection (hItem, &tvItem, guess, 0, -1, false, true);
+    } else {
+        TVITEM tvItem;
+        static if (OS.IsWinCE) {
+            //tvItem = new TVITEM ();
+            tvItem.mask = OS.TVIF_STATE;
+        }
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null) {
+                HANDLE hItem = item.handle;
+                int state = 0;
+                static if (OS.IsWinCE) {
+                    tvItem.hItem = hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    state = tvItem.state;
+                } else {
+                    state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                }
+                if ((state & OS.TVIS_SELECTED) !is 0) {
+                    if (count < guess.length) guess [count] = item;
+                    count++;
+                }
+            }
+        }
+    }
+    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];
+    if (count < guess.length) {
+        System.arraycopy (guess, 0, result, 0, count);
+        return result;
+    }
+    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);
+    int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+    bool bigSelection = result.length > itemCount / 2;
+    if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) {
+        getSelection (hItem, &tvItem, result, 0, count, bigSelection, true);
+    }
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+    return result;
+}
+
+/**
+ * Returns the number of selected items contained in the receiver.
+ *
+ * @return the number of selected items
+ *
+ * @exception SWTException <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 int getSelectionCount () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hItem is null) return 0;
+        int state = 0;
+        static if (OS.IsWinCE) {
+            TVITEM tvItem;
+            tvItem.hItem = hItem;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+            state = tvItem.state;
+        } else {
+            state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+        }
+        return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1;
+    }
+    int count = 0;
+    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.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+    if ((style & SWT.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);
+    } else {
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null) {
+                auto hItem = item.handle;
+                int state = 0;
+                static if (OS.IsWinCE) {
+                    tvItem.hItem = hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                    state = tvItem.state;
+                } else {
+                    state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                }
+                if ((state & OS.TVIS_SELECTED) !is 0) count++;
+            }
+        }
+    }
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+    return count;
+}
+
+/**
+ * Returns the column which shows the sort indicator for
+ * the receiver. The value may be null if no column shows
+ * the sort indicator.
+ *
+ * @return the sort indicator
+ *
+ * @exception SWTException <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 #setSortColumn(TreeColumn)
+ *
+ * @since 3.2
+ */
+public TreeColumn getSortColumn () {
+    checkWidget ();
+    return sortColumn;
+}
+
+int getSortColumnPixel () {
+    int pixel = OS.IsWindowEnabled (handle) ? getBackgroundPixel () : OS.GetSysColor (OS.COLOR_3DFACE);
+    int red = pixel & 0xFF;
+    int green = (pixel & 0xFF00) >> 8;
+    int blue = (pixel & 0xFF0000) >> 16;
+    if (red > 240 && green > 240 && blue > 240) {
+        red -= 8;
+        green -= 8;
+        blue -= 8;
+    } else {
+        red = Math.min (0xFF, (red / 10) + red);
+        green = Math.min (0xFF, (green / 10) + green);
+        blue = Math.min (0xFF, (blue / 10) + blue);
+    }
+    return (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
+}
+
+/**
+ * Returns the direction of the sort indicator for the receiver.
+ * The value will be one of <code>UP</code>, <code>DOWN</code>
+ * or <code>NONE</code>.
+ *
+ * @return the sort direction
+ *
+ * @exception SWTException <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 #setSortDirection(int)
+ *
+ * @since 3.2
+ */
+public int getSortDirection () {
+    checkWidget ();
+    return sortDirection;
+}
+
+/**
+ * Returns the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @return the item at the top of the receiver
+ *
+ * @exception SWTException <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 2.1
+ */
+public TreeItem getTopItem () {
+    checkWidget ();
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+    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 (SWT.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) {
+        Rectangle bounds = image.getBounds ();
+        imageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+    }
+    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) {
+            OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+            updateScrollBar ();
+        }
+    }
+    return imageIndex;
+}
+
+int imageIndexHeader (Image image) {
+    if (image is null) return OS.I_IMAGENONE;
+    if (headerImageList is null) {
+        Rectangle bounds = image.getBounds ();
+        headerImageList = display.getImageList (style & SWT.RIGHT_TO_LEFT, bounds.width, bounds.height);
+        int index = headerImageList.indexOf (image);
+        if (index is -1) index = headerImageList.add (image);
+        auto hImageList = headerImageList.getHandle ();
+        if (hwndHeader !is null) {
+            OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, hImageList);
+        }
+        updateScrollBar ();
+        return index;
+    }
+    int index = headerImageList.indexOf (image);
+    if (index !is -1) return index;
+    return headerImageList.add (image);
+}
+
+/**
+ * Searches the receiver's list starting at the first column
+ * (index 0) until a column is found that is equal to the
+ * argument, and returns the index of that column. If no column
+ * is found, returns -1.
+ *
+ * @param column the search column
+ * @return the index of the column
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the column is null</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public int indexOf (TreeColumn column) {
+    checkWidget ();
+    if (column is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    for (int i=0; i<columnCount; i++) {
+        if (columns [i] is column) return i;
+    }
+    return -1;
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @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 SWTException <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.1
+ */
+public int indexOf (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    return hItem is null ? -1 : findIndex (hItem, item.handle);
+}
+
+bool isCustomToolTip () {
+    return hooks (SWT.MeasureItem);
+}
+
+bool isItemSelected (NMTVCUSTOMDRAW* nmcd) {
+    bool selected = false;
+    if (OS.IsWindowEnabled (handle)) {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+        tvItem.hItem = cast(HTREEITEM)nmcd.nmcd.dwItemSpec;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        if ((tvItem.state & (OS.TVIS_SELECTED | OS.TVIS_DROPHILITED)) !is 0) {
+            selected = true;
+            /*
+            * Feature in Windows.  When the mouse is pressed and the
+            * selection is first drawn for a tree, the previously
+            * selected item is redrawn but the the TVIS_SELECTED bits
+            * are not cleared.  When the user moves the mouse slightly
+            * and a drag and drop operation is not started, the item is
+            * drawn again and this time with TVIS_SELECTED is cleared.
+            * This means that an item that contains colored cells will
+            * not draw with the correct background until the mouse is
+            * moved.  The fix is to test for the selection colors and
+            * guess that the item is not selected.
+            *
+            * NOTE: This code does not work when the foreground and
+            * background of the tree are set to the selection colors
+            * but this does not happen in a regular application.
+            */
+            if (handle is OS.GetFocus ()) {
+                if (OS.GetTextColor (nmcd.nmcd.hdc) !is OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) {
+                    selected = false;
+                } else {
+                    if (OS.GetBkColor (nmcd.nmcd.hdc) !is OS.GetSysColor (OS.COLOR_HIGHLIGHT)) {
+                        selected = false;
+                    }
+                }
+            }
+        } else {
+            if (nmcd.nmcd.dwDrawStage is OS.CDDS_ITEMPOSTPAINT) {
+                /*
+                * Feature in Windows.  When the mouse is pressed and the
+                * selection is first drawn for a tree, the item is drawn
+                * selected, but the TVIS_SELECTED bits for the item are
+                * not set.  When the user moves the mouse slightly and
+                * a drag and drop operation is not started, the item is
+                * drawn again and this time TVIS_SELECTED is set.  This
+                * means that an item that is in a tree that has the style
+                * TVS_FULLROWSELECT and that also contains colored cells
+                * will not draw the entire row selected until the user
+                * moves the mouse.  The fix is to test for the selection
+                * colors and guess that the item is selected.
+                *
+                * NOTE: This code does not work when the foreground and
+                * background of the tree are set to the selection colors
+                * but this does not happen in a regular application.
+                */
+                if (OS.GetTextColor (nmcd.nmcd.hdc) is OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT)) {
+                    if (OS.GetBkColor (nmcd.nmcd.hdc) is OS.GetSysColor (OS.COLOR_HIGHLIGHT)) {
+                        selected = true;
+                    }
+                }
+            }
+        }
+    }
+    return selected;
+}
+
+void redrawSelection () {
+    if ((style & SWT.SINGLE) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hItem !is null) {
+            RECT rect;
+            if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect, false)) {
+                OS.InvalidateRect (handle, &rect, true);
+            }
+        }
+    } else {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+        if (hItem !is null) {
+            TVITEM tvItem;
+            static if (OS.IsWinCE) {
+                //tvItem = new TVITEM ();
+                tvItem.mask = OS.TVIF_STATE;
+            }
+            RECT rect;
+            int index = 0, count = OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0);
+            while (index <= count && hItem !is null) {
+                int state = 0;
+                static if (OS.IsWinCE) {
+                    tvItem.hItem = hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    state = tvItem.state;
+                } else {
+                    state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+                }
+                if ((state & OS.TVIS_SELECTED) !is 0) {
+                    if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect, false)) {
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
+                }
+                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                index++;
+            }
+        }
+    }
+}
+
+override void register () {
+    super.register ();
+    if (hwndParent !is null) display.addControl (hwndParent, this);
+    if (hwndHeader !is null) display.addControl (hwndHeader, this);
+}
+
+void releaseItem (HANDLE hItem, TVITEM* tvItem, bool release) {
+    if (hItem is hAnchor) hAnchor = null;
+    if (hItem is hInsert) hInsert = null;
+    tvItem.hItem = cast(HTREEITEM)hItem;
+    if (OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem) !is 0) {
+        if (tvItem.lParam !is -1) {
+            if (tvItem.lParam < lastID) lastID = tvItem.lParam;
+            if (release) {
+                TreeItem item = items [tvItem.lParam];
+                if (item !is null) item.release (false);
+            }
+            items [tvItem.lParam] = null;
+        }
+    }
+}
+
+void releaseItems (HANDLE hItem, TVITEM* tvItem) {
+    hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+    while (hItem !is null) {
+        releaseItems (hItem, tvItem);
+        releaseItem (hItem, tvItem, true);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+    }
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    hwndParent = hwndHeader = null;
+}
+
+override void releaseChildren (bool destroy) {
+    if (items !is null) {
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null && !item.isDisposed ()) {
+                item.release (false);
+            }
+        }
+        items = null;
+    }
+    if (columns !is null) {
+        for (int i=0; i<columns.length; i++) {
+            TreeColumn column = columns [i];
+            if (column !is null && !column.isDisposed ()) {
+                column.release (false);
+            }
+        }
+        columns = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    /*
+    * Feature in Windows.  For some reason, when TVM_GETIMAGELIST
+    * or TVM_SETIMAGELIST is sent, the tree issues NM_CUSTOMDRAW
+    * messages.  This behavior is unwanted when the tree is being
+    * disposed.  The fix is to ignore NM_CUSTOMDRAW messages by
+    * clearing the custom draw flag.
+    *
+    * NOTE: This only happens on Windows XP.
+    */
+    customDraw = false;
+    if (imageList !is null) {
+        OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, 0);
+        display.releaseImageList (imageList);
+    }
+    if (headerImageList !is null) {
+        if (hwndHeader !is null) {
+            OS.SendMessage (hwndHeader, OS.HDM_SETIMAGELIST, 0, 0);
+        }
+        display.releaseImageList (headerImageList);
+    }
+    imageList = headerImageList = null;
+    auto hStateList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0);
+    OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, 0);
+    if (hStateList !is null) OS.ImageList_Destroy (hStateList);
+    if (itemToolTipHandle !is null) OS.DestroyWindow (itemToolTipHandle);
+    if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle);
+    itemToolTipHandle = headerToolTipHandle = null;
+}
+
+/**
+ * Removes all of the items from the receiver.
+ *
+ * @exception SWTException <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 removeAll () {
+    checkWidget ();
+    hFirstIndexOf = hLastIndexOf = null;
+    itemCount = -1;
+    for (int i=0; i<items.length; i++) {
+        TreeItem item = items [i];
+        if (item !is null && !item.isDisposed ()) {
+            item.release (false);
+        }
+    }
+    ignoreDeselect = ignoreSelect = true;
+    bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+    if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+    shrink = ignoreShrink = true;
+    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);
+        OS.InvalidateRect (handle, null, true);
+    }
+    ignoreDeselect = ignoreSelect = false;
+    if (result is 0) error (SWT.ERROR_ITEM_NOT_REMOVED);
+    if (imageList !is null) {
+        OS.SendMessage (handle, OS.TVM_SETIMAGELIST, 0, 0);
+        display.releaseImageList (imageList);
+    }
+    imageList = null;
+    if (hwndParent is null && !linesVisible) {
+        if (!hooks (SWT.MeasureItem) && !hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+            customDraw = false;
+        }
+    }
+    hAnchor = hInsert = hFirstIndexOf = hLastIndexOf = null;
+    itemCount = -1;
+    items = new TreeItem [4];
+    scrollWidth = 0;
+    setScrollWidth ();
+    updateScrollBar ();
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the user changes the receiver's selection.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when items in the receiver are expanded or collapsed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 TreeListener
+ * @see #addTreeListener
+ */
+public void removeTreeListener(TreeListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Expand, listener);
+    eventTable.unhook (SWT.Collapse, listener);
+}
+
+/**
+ * Display a mark indicating the point at which an item will be inserted.
+ * The drop insert item has a visual hint to show where a dragged item
+ * will be inserted when dropped on the tree.
+ *
+ * @param item the insert item.  Null will clear the insertion mark.
+ * @param before true places the insert mark above 'item'. false places
+ *  the insert mark below 'item'.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 setInsertMark (TreeItem item, bool before) {
+    checkWidget ();
+    HANDLE hItem;
+    if (item !is null) {
+        if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+        hItem = item.handle;
+    }
+    hInsert = hItem;
+    insertAfter = !before;
+    OS.SendMessage (handle, OS.TVM_SETINSERTMARK, insertAfter ? 1 : 0, hInsert);
+}
+
+/**
+ * Sets the number of root-level items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @exception SWTException <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.2
+ */
+public void setItemCount (int count) {
+    checkWidget ();
+    count = Math.max (0, count);
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    setItemCount (count, cast(HANDLE) OS.TVGN_ROOT, hItem);
+}
+
+void setItemCount (int count, HANDLE hParent, HANDLE hItem) {
+    bool redraw = false;
+    if (OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) is 0) {
+        redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    int itemCount = 0;
+    while (hItem !is null && itemCount < count) {
+        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 & SWT.VIRTUAL) !is 0) {
+        if (OS.IsWinCE) {
+            tvItem.hItem = cast(HTREEITEM)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 = cast(HTREEITEM)hItem;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+        TreeItem item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
+        if (item !is null && !item.isDisposed ()) {
+            item.dispose ();
+        } else {
+            releaseItem (tvItem.hItem, &tvItem, false);
+            destroyItem (null, tvItem.hItem);
+        }
+    }
+    if ((style & SWT.VIRTUAL) !is 0) {
+        for (int i=itemCount; i<count; i++) {
+            if (expanded) ignoreShrink = true;
+            createItem (null, hParent, cast(HTREEITEM) OS.TVI_LAST, null);
+            if (expanded) ignoreShrink = false;
+        }
+    } else {
+        shrink = true;
+        int extra = Math.max (4, (count + 3) / 4 * 4);
+        TreeItem [] newItems = new TreeItem [items.length + extra];
+        System.arraycopy (items, 0, newItems, 0, items.length);
+        items = newItems;
+        for (int i=itemCount; i<count; i++) {
+            new TreeItem (this, SWT.NONE, hParent, cast(HTREEITEM) OS.TVI_LAST, null);
+        }
+    }
+    if (redraw) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.InvalidateRect (handle, null, true);
+    }
+}
+
+/**
+ * Sets the height of the area which would be used to
+ * display <em>one</em> of the items in the tree.
+ *
+ * @param itemHeight the height of one item
+ *
+ * @exception SWTException <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.2
+ */
+/*public*/ void setItemHeight (int itemHeight) {
+    checkWidget ();
+    if (itemHeight < -1) error (SWT.ERROR_INVALID_ARGUMENT);
+    OS.SendMessage (handle, OS.TVM_SETITEMHEIGHT, itemHeight, 0);
+}
+
+/**
+ * Marks the receiver's lines 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 show the new visibility state
+ *
+ * @exception SWTException <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.1
+ */
+public void setLinesVisible (bool show) {
+    checkWidget ();
+    if (linesVisible is show) return;
+    linesVisible = show;
+    if (hwndParent is null && linesVisible) customDraw = true;
+    OS.InvalidateRect (handle, null, true);
+}
+
+override HWND scrolledHandle () {
+    if (hwndHeader is null) return handle;
+    return columnCount is 0 && scrollWidth is 0 ? handle : hwndParent;
+}
+
+void select (HANDLE hItem, TVITEM* tvItem) {
+    while (hItem !is null) {
+        tvItem.hItem = cast(HTREEITEM)hItem;
+        OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        select (hFirstItem, tvItem);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+    }
+}
+
+/**
+ * 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 SWTException <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 (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if ((style & SWT.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 & SWT.DOUBLE_BUFFERED) is 0) {
+                int oldStyle = style;
+                style |= SWT.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 = cast(HTREEITEM)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.
+ * </p>
+ *
+ * @exception SWTException <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 selectAll () {
+    checkWidget ();
+    if ((style & SWT.SINGLE) !is 0) return;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.state = OS.TVIS_SELECTED;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+    if ((style & SWT.VIRTUAL) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+        select (hItem, &tvItem);
+    } else {
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null) {
+                tvItem.hItem = cast(HTREEITEM)item.handle;
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            }
+        }
+    }
+    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 |= SWT.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 (SWT.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 (SWT.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 |= SWT.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 (SWT.PaintItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+override void setBackgroundImage (HBITMAP hBitmap) {
+    super.setBackgroundImage (hBitmap);
+    if (hBitmap !is null) {
+        /*
+        * Feature in Windows.  If TVM_SETBKCOLOR is never
+        * used to set the background color of a tree, the
+        * background color of the lines and the plus/minus
+        * will be drawn using the default background color,
+        * not the HBRUSH returned from WM_CTLCOLOR.  The fix
+        * is to set the background color to the default (when
+        * it is already the default) to make Windows use the
+        * brush.
+        */
+        if (OS.SendMessage (handle, OS.TVM_GETBKCOLOR, 0, 0) is -1) {
+            OS.SendMessage (handle, OS.TVM_SETBKCOLOR, 0, -1);
+        }
+        _setBackgroundPixel (-1);
+    } else {
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        if (control.backgroundImage is null) {
+            setBackgroundPixel (control.getBackgroundPixel ());
+        }
+    }
+    /*
+    * 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 the background image.  The fix
+    * is to clear TVS_FULLROWSELECT when a background
+    * image is set.
+    */
+    updateFullSelection ();
+}
+
+override void setBackgroundPixel (int pixel) {
+    Control control = findImageControl ();
+    if (control !is null) {
+        setBackgroundImage (control.backgroundImage);
+        return;
+    }
+    /*
+    * Feature in Windows.  When a tree is given a background color
+    * using TVM_SETBKCOLOR and the tree is disabled, Windows draws
+    * the tree using the background color rather than the disabled
+    * colors.  This is different from the table which draws grayed.
+    * The fix is to set the default background color while the tree
+    * is disabled and restore it when enabled.
+    */
+    if (OS.IsWindowEnabled (handle)) _setBackgroundPixel (pixel);
+
+    /*
+    * 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 the background image.  The fix
+    * is to restore TVS_FULLROWSELECT when a background
+    * color is set.
+    */
+    updateFullSelection ();
+}
+
+override void setCursor () {
+    /*
+    * Bug in Windows.  Under certain circumstances, when WM_SETCURSOR
+    * is sent from SendMessage(), Windows GP's in the window proc for
+    * the tree.  The fix is to avoid calling the tree window proc and
+    * set the cursor for the tree outside of WM_SETCURSOR.
+    *
+    * NOTE:  This code assumes that the default cursor for the tree
+    * is IDC_ARROW.
+    */
+    Cursor cursor = findCursor ();
+    auto hCursor = cursor is null ? OS.LoadCursor (null, cast(TCHAR*) OS.IDC_ARROW) : cursor.handle;
+    OS.SetCursor (hCursor);
+}
+
+/**
+ * Sets the order that the items in the receiver should
+ * be displayed in to the given argument which is described
+ * in terms of the zero-relative ordering of when the items
+ * were added.
+ *
+ * @param order the new order to display the items
+ *
+ * @exception SWTException <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_ARGUMENT - if the item order is not the same length as the number of items</li>
+ * </ul>
+ *
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see TreeColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setColumnOrder (int [] order) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (order is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (columnCount is 0) {
+        if (order.length !is 0) error (SWT.ERROR_INVALID_ARGUMENT);
+        return;
+    }
+    if (order.length !is columnCount) error (SWT.ERROR_INVALID_ARGUMENT);
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr);
+    bool reorder = false;
+    bool [] seen = new bool [columnCount];
+    for (int i=0; i<order.length; i++) {
+        int index = order [i];
+        if (index < 0 || index >= columnCount) error (SWT.ERROR_INVALID_RANGE);
+        if (seen [index]) error (SWT.ERROR_INVALID_ARGUMENT);
+        seen [index] = true;
+        if (index !is oldOrder [i]) reorder = true;
+    }
+    if (reorder) {
+        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 [columnCount];
+        System.arraycopy (columns, 0, newColumns, 0, columnCount);
+        RECT newRect;
+        for (int i=0; i<columnCount; i++) {
+            TreeColumn column = newColumns [i];
+            if (!column.isDisposed ()) {
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect);
+                if (newRect.left !is oldRects [i].left) {
+                    column.updateToolTip (i);
+                    column.sendEvent (SWT.Move);
+                }
+            }
+        }
+    }
+}
+
+void setCheckboxImageList () {
+    if ((style & SWT.CHECK) is 0) return;
+    int count = 5, flags = 0;
+    static if (OS.IsWinCE) {
+        flags |= OS.ILC_COLOR;
+    } else {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            flags |= OS.ILC_COLOR32;
+        } else {
+            auto hDC = OS.GetDC (handle);
+            int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
+            int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
+            OS.ReleaseDC (handle, hDC);
+            int depth = bits * planes;
+            switch (depth) {
+                case 4: flags |= OS.ILC_COLOR4; break;
+                case 8: flags |= OS.ILC_COLOR8; break;
+                case 16: flags |= OS.ILC_COLOR16; break;
+                case 24: flags |= OS.ILC_COLOR24; break;
+                case 32: flags |= OS.ILC_COLOR32; break;
+                default: flags |= OS.ILC_COLOR; break;
+            }
+            flags |= OS.ILC_MASK;
+        }
+    }
+    if ((style & SWT.RIGHT_TO_LEFT) !is 0) flags |= OS.ILC_MIRROR;
+    int height = OS.SendMessage (handle, OS.TVM_GETITEMHEIGHT, 0, 0), width = height;
+    auto hStateList = OS.ImageList_Create (width, height, flags, count, count);
+    auto hDC = OS.GetDC (handle);
+    auto memDC = OS.CreateCompatibleDC (hDC);
+    auto hBitmap = OS.CreateCompatibleBitmap (hDC, width * count, height);
+    auto hOldBitmap = OS.SelectObject (memDC, hBitmap);
+    RECT rect;
+    OS.SetRect (&rect, 0, 0, width * count, height);
+    /*
+    * NOTE: DrawFrameControl() draws a black and white
+    * mask when not drawing a push button.  In order to
+    * make the box surrounding the check mark transparent,
+    * fill it with a color that is neither black or white.
+    */
+    int clrBackground = 0;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        Control control = findBackgroundControl ();
+        if (control is null) control = this;
+        clrBackground = control.getBackgroundPixel ();
+    } else {
+        clrBackground = 0x020000FF;
+        if ((clrBackground & 0xFFFFFF) is OS.GetSysColor (OS.COLOR_WINDOW)) {
+            clrBackground = 0x0200FF00;
+        }
+    }
+    auto hBrush = OS.CreateSolidBrush (clrBackground);
+    OS.FillRect (memDC, &rect, hBrush);
+    OS.DeleteObject (hBrush);
+    auto oldFont = OS.SelectObject (hDC, defaultFont ());
+    TEXTMETRIC tm;
+    OS.GetTextMetrics (hDC, &tm);
+    OS.SelectObject (hDC, oldFont);
+    int itemWidth = Math.min (tm.tmHeight, width);
+    int itemHeight = Math.min (tm.tmHeight, height);
+    int left = (width - itemWidth) / 2, top = (height - itemHeight) / 2 + 1;
+    OS.SetRect (&rect, left + width, top, left + width + itemWidth, top + itemHeight);
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        auto hTheme = display.hButtonTheme ();
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_CHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_UNCHECKEDNORMAL, &rect, null);
+        rect.left += width;  rect.right += width;
+        OS.DrawThemeBackground (hTheme, memDC, OS.BP_CHECKBOX, OS.CBS_MIXEDNORMAL, &rect, null);
+    } else {
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+        rect.left += width;  rect.right += width;
+        OS.DrawFrameControl (memDC, &rect, OS.DFC_BUTTON, OS.DFCS_BUTTONCHECK | OS.DFCS_CHECKED | OS.DFCS_INACTIVE | OS.DFCS_FLAT);
+    }
+    OS.SelectObject (memDC, hOldBitmap);
+    OS.DeleteDC (memDC);
+    OS.ReleaseDC (handle, hDC);
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        OS.ImageList_Add (hStateList, hBitmap, null);
+    } else {
+        OS.ImageList_AddMasked (hStateList, hBitmap, clrBackground);
+    }
+    OS.DeleteObject (hBitmap);
+    auto hOldStateList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_STATE, 0);
+    OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_STATE, hStateList);
+    if (hOldStateList !is null) OS.ImageList_Destroy (hOldStateList);
+}
+
+override public void setFont (Font font) {
+    checkWidget ();
+    super.setFont (font);
+    if ((style & SWT.CHECK) !is 0) setCheckboxImageList ();
+}
+
+override void setForegroundPixel (int pixel) {
+    /*
+    * Bug in Windows.  When the tree is using the explorer
+    * theme, it does not use COLOR_WINDOW_TEXT for the
+    * foreground.  When TVM_SETTEXTCOLOR is called with -1,
+    * it resets the color to black, not COLOR_WINDOW_TEXT.
+    * The fix is to explicitly set the color.
+    */
+    if (explorerTheme) {
+        if (pixel is -1) pixel = defaultForeground ();
+    }
+    OS.SendMessage (handle, OS.TVM_SETTEXTCOLOR, 0, pixel);
+}
+
+/**
+ * Marks the receiver's header 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 show the new visibility state
+ *
+ * @exception SWTException <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.1
+ */
+public void setHeaderVisible (bool show) {
+    checkWidget ();
+    if (hwndHeader is null) {
+        if (!show) return;
+        createParent ();
+    }
+    int bits = OS.GetWindowLong (hwndHeader, OS.GWL_STYLE);
+    if (show) {
+        if ((bits & OS.HDS_HIDDEN) is 0) return;
+        bits &= ~OS.HDS_HIDDEN;
+        OS.SetWindowLong (hwndHeader, OS.GWL_STYLE, bits);
+        OS.ShowWindow (hwndHeader, OS.SW_SHOW);
+    } else {
+        if ((bits & OS.HDS_HIDDEN) !is 0) return;
+        bits |= OS.HDS_HIDDEN;
+        OS.SetWindowLong (hwndHeader, OS.GWL_STYLE, bits);
+        OS.ShowWindow (hwndHeader, OS.SW_HIDE);
+    }
+    setScrollWidth ();
+    updateHeaderToolTips ();
+    updateScrollBar ();
+}
+
+override public void setRedraw (bool redraw) {
+    checkWidget ();
+    /*
+    * Feature in Windows.  When WM_SETREDRAW is used to
+    * turn off redraw, the scroll bars are updated when
+    * items are added and removed.  The fix is to call
+    * the default window proc to stop all drawing.
+    *
+    * Bug in Windows.  For some reason, when WM_SETREDRAW
+    * is used to turn redraw on for a tree and the tree
+    * contains no items, the last item in the tree does
+    * not redraw properly.  If the tree has only one item,
+    * that item is not drawn.  If another window is dragged
+    * on top of the item, parts of the item are redrawn
+    * and erased at random.  The fix is to ensure that this
+    * case doesn't happen by inserting and deleting an item
+    * when redraw is turned on and there are no items in
+    * the tree.
+    */
+    HANDLE hItem;
+    if (redraw) {
+        if (drawCount is 1) {
+            int count = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+            if (count is 0) {
+                TVINSERTSTRUCT tvInsert;
+                tvInsert.hInsertAfter = cast(HTREEITEM) OS.TVI_FIRST;
+                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert);
+            }
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            updateScrollBar ();
+        }
+    }
+    super.setRedraw (redraw);
+    if (!redraw) {
+        if (drawCount is 1) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    if (hItem !is null) {
+        ignoreShrink = true;
+        OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, hItem);
+        ignoreShrink = false;
+    }
+}
+
+void setScrollWidth () {
+    if (hwndHeader is null || hwndParent is null) return;
+    int width = 0;
+    HDITEM hdItem;
+    for (int i=0; i<columnCount; i++) {
+        hdItem.mask = OS.HDI_WIDTH;
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
+        width += hdItem.cxy;
+    }
+    setScrollWidth (Math.max (scrollWidth, width));
+}
+
+void setScrollWidth (int width) {
+    if (hwndHeader is null || hwndParent is null) return;
+    //TEMPORARY CODE
+    //scrollWidth = width;
+    int left = 0;
+    RECT rect;
+    SCROLLINFO info;
+    info.cbSize = SCROLLINFO.sizeof;
+    info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
+    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);
+        OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
+        info.nPage = info.nMax + 1;
+        OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
+    } else {
+        if ((style & SWT.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);
+        horizontalBar.setPageIncrement (info.nPage);
+    }
+    OS.GetClientRect (hwndParent, &rect);
+    HDLAYOUT playout;
+    RECT layoutrect = rect;
+    playout.prc = &layoutrect;
+    WINDOWPOS pos;
+    playout.pwpos = &pos;
+    OS.SendMessage (hwndHeader, OS.HDM_LAYOUT, 0, &playout);
+    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 + (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;
+    SetWindowPos (handle, null, pos.x - left - b, pos.y + pos.cy - b, w + left + b * 2, h + b * 2, OS.SWP_NOACTIVATE | OS.SWP_NOZORDER);
+    ignoreResize = oldIgnore;
+}
+
+void setSelection (HANDLE hItem, TVITEM* tvItem, TreeItem [] selection) {
+    while (hItem !is null) {
+        int index = 0;
+        while (index < selection.length) {
+            TreeItem item = selection [index];
+            if (item !is null && item.handle is hItem) break;
+            index++;
+        }
+        tvItem.hItem = cast(HTREEITEM)hItem;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        if ((tvItem.state & OS.TVIS_SELECTED) !is 0) {
+            if (index is selection.length) {
+                tvItem.state = 0;
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            }
+        } else {
+            if (index !is selection.length) {
+                tvItem.state = OS.TVIS_SELECTED;
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            }
+        }
+        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        setSelection (hFirstItem, tvItem, selection);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+    }
+}
+
+/**
+ * Sets the receiver's selection to the given item.
+ * The current selection is cleared before the new item is selected.
+ * <p>
+ * If the item is not in the receiver, then it is ignored.
+ * </p>
+ *
+ * @param item the item to select
+ *
+ * @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 SWTException <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.2
+ */
+public void setSelection (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    setSelection ([item]);
+}
+
+/**
+ * Sets the receiver's selection to be the given array of items.
+ * The current selection is cleared before the new items are selected.
+ * <p>
+ * Items that are not in the receiver are ignored.
+ * If the receiver is single-select and multiple items are specified,
+ * then all items are ignored.
+ * </p>
+ *
+ * @param items the array of items
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the items has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 Tree#deselectAll()
+ */
+public void setSelection (TreeItem [] items) {
+    checkWidget ();
+    // SWT extension: allow null array
+    //if (items is null) error (SWT.ERROR_NULL_ARGUMENT);
+    int length = items.length;
+    if (length is 0 || ((style & SWT.SINGLE) !is 0 && length > 1)) {
+        deselectAll();
+        return;
+    }
+
+    /* Select/deselect the first item */
+    TreeItem item = items [0];
+    if (item !is null) {
+        if (item.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+        HANDLE hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        HANDLE hNewItem = hAnchor = item.handle;
+
+        /*
+        * Bug in Windows.  When TVM_SELECTITEM is used to select and
+        * scroll an item to be visible and the client area of the tree
+        * is smaller that the size of one item, TVM_SELECTITEM makes
+        * the next item in the tree visible by making it the top item
+        * instead of making the desired item visible.  The fix is to
+        * detect the case when the client area is too small and make
+        * the desired visible item be the top item in the tree.
+        *
+        * Note that TVM_SELECTITEM when called with TVGN_FIRSTVISIBLE
+        * also requires the work around for scrolling.
+        */
+        bool fixScroll = checkScroll (hNewItem);
+        if (fixScroll) {
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+        ignoreSelect = true;
+        OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem);
+        ignoreSelect = false;
+        if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
+            OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, 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) {
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+
+        /*
+        * Feature in Windows.  When the old and new focused item
+        * are the same, Windows does not check to make sure that
+        * the item is actually selected, not just focused.  The
+        * fix is to force the item to draw selected by setting
+        * the state mask, and to ensure that it is visible.
+        */
+        if (hOldItem is hNewItem) {
+            TVITEM tvItem;
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+            tvItem.state = OS.TVIS_SELECTED;
+            tvItem.stateMask = OS.TVIS_SELECTED;
+            tvItem.hItem = cast(HTREEITEM)hNewItem;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            showItem (hNewItem);
+        }
+    }
+    if ((style & SWT.SINGLE) !is 0) return;
+
+    /* Select/deselect the rest of the items */
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+    if ((style & SWT.VIRTUAL) !is 0) {
+        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+        setSelection (hItem, &tvItem, items);
+    } else {
+        for (int i=0; i<this.items.length; i++) {
+            item = this.items [i];
+            if (item !is null) {
+                int index = 0;
+                while (index < length) {
+                    if (items [index] is item) break;
+                    index++;
+                }
+                tvItem.hItem = cast(HTREEITEM)item.handle;
+                OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                if ((tvItem.state & OS.TVIS_SELECTED) !is 0) {
+                    if (index is length) {
+                        tvItem.state = 0;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    }
+                } else {
+                    if (index !is length) {
+                        tvItem.state = OS.TVIS_SELECTED;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    }
+                }
+            }
+        }
+    }
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+}
+
+/**
+ * Sets the column used by the sort indicator for the receiver. A null
+ * value will clear the sort indicator.  The current sort column is cleared
+ * before the new column is set.
+ *
+ * @param column the column used by the sort indicator or <code>null</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the column is disposed</li>
+ * </ul>
+ * @exception SWTException <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.2
+ */
+public void setSortColumn (TreeColumn column) {
+    checkWidget ();
+    if (column !is null && column.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        sortColumn.setSortDirection (SWT.NONE);
+    }
+    sortColumn = column;
+    if (sortColumn !is null && sortDirection !is SWT.NONE) {
+        sortColumn.setSortDirection (sortDirection);
+    }
+}
+
+/**
+ * Sets the direction of the sort indicator for the receiver. The value
+ * can be one of <code>UP</code>, <code>DOWN</code> or <code>NONE</code>.
+ *
+ * @param direction the direction of the sort indicator
+ *
+ * @exception SWTException <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.2
+ */
+public void setSortDirection (int direction) {
+    checkWidget ();
+    if ((direction & (SWT.UP | SWT.DOWN)) is 0 && direction !is SWT.NONE) return;
+    sortDirection = direction;
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        sortColumn.setSortDirection (direction);
+    }
+}
+
+/**
+ * Sets the item which is currently at the top of the receiver.
+ * This item can change when items are expanded, collapsed, scrolled
+ * or new items are added or removed.
+ *
+ * @param item the item to be shown
+ *
+ * @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 SWTException <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 Tree#getTopItem()
+ *
+ * @since 2.1
+ */
+public void setTopItem (TreeItem item) {
+    checkWidget ();
+    if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    HANDLE hItem = item.handle;
+    auto hTopItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+    if (hItem is hTopItem) return;
+    bool fixScroll = checkScroll (hItem), redraw = false;
+    if (fixScroll) {
+        OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+    } else {
+        redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hItem);
+    auto hParent = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+    if (hParent is null) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
+    if (fixScroll) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+    } else {
+        if (redraw) {
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, null, true);
+        }
+    }
+    updateScrollBar ();
+}
+
+void showItem (HANDLE hItem) {
+    /*
+    * Bug in Windows.  When TVM_ENSUREVISIBLE is used to ensure
+    * that an item is visible and the client area of the tree is
+    * smaller that the size of one item, TVM_ENSUREVISIBLE makes
+    * the next item in the tree visible by making it the top item
+    * instead of making the desired item visible.  The fix is to
+    * detect the case when the client area is too small and make
+    * the desired visible item be the top item in the tree.
+    */
+    if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
+        bool fixScroll = checkScroll (hItem);
+        if (fixScroll) {
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+        OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hItem);
+        /* This code is intentionally commented */
+        //int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+        //if (hParent is 0) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
+        OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
+        if (fixScroll) {
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+    } else {
+        bool scroll = true;
+        RECT itemRect;
+        if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &itemRect, true)) {
+            forceResize ();
+            RECT rect;
+            OS.GetClientRect (handle, &rect);
+            POINT pt;
+            pt.x = itemRect.left;
+            pt.y = itemRect.top;
+            if (OS.PtInRect (&rect, pt)) {
+                pt.y = itemRect.bottom;
+                if (OS.PtInRect (&rect, pt)) scroll = false;
+            }
+        }
+        if (scroll) {
+            bool fixScroll = checkScroll (hItem);
+            if (fixScroll) {
+                OS.SendMessage (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            }
+            OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem);
+            if (fixScroll) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
+            }
+        }
+    }
+    if (hwndParent !is null) {
+        RECT itemRect;
+        if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &itemRect, true)) {
+            forceResize ();
+            RECT rect;
+            OS.GetClientRect (hwndParent, &rect);
+            OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
+            POINT pt;
+            pt.x = itemRect.left;
+            pt.y = itemRect.top;
+            if (!OS.PtInRect (&rect, pt)) {
+                pt.y = itemRect.bottom;
+                if (!OS.PtInRect (&rect, pt)) {
+                    SCROLLINFO info;
+                    info.cbSize = SCROLLINFO.sizeof;
+                    info.fMask = OS.SIF_POS;
+                    info.nPos = Math.max (0, pt.x - Tree.INSET / 2);
+                    OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+                    setScrollWidth ();
+                }
+            }
+        }
+    }
+    updateScrollBar ();
+}
+
+/**
+ * Shows the column.  If the column is already showing in the receiver,
+ * this method simply returns.  Otherwise, the columns are scrolled until
+ * the column is visible.
+ *
+ * @param column the column to be shown
+ *
+ * @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 SWTException <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.1
+ */
+public void showColumn (TreeColumn column) {
+    checkWidget ();
+    if (column is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (column.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+    if (column.parent !is this) return;
+    int index = indexOf (column);
+    if (index is -1) return;
+    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 ();
+        }
+    }
+}
+
+/**
+ * Shows the item.  If the item is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled
+ * and expanded until the item is visible.
+ *
+ * @param item the item to be shown
+ *
+ * @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 SWTException <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 Tree#showSelection()
+ */
+public void showItem (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error(SWT.ERROR_INVALID_ARGUMENT);
+    showItem (item.handle);
+}
+
+/**
+ * Shows the selection.  If the selection is already showing in the receiver,
+ * this method simply returns.  Otherwise, the items are scrolled until
+ * the selection is visible.
+ *
+ * @exception SWTException <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 Tree#showItem(TreeItem)
+ */
+public void showSelection () {
+    checkWidget ();
+    HANDLE hItem;
+    if ((style & SWT.SINGLE) !is 0) {
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hItem is null) return;
+        int state = 0;
+        static if (OS.IsWinCE) {
+            TVITEM tvItem;
+            tvItem.hItem = hItem;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+            state = tvItem.state;
+        } else {
+            state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
+        }
+        if ((state & OS.TVIS_SELECTED) is 0) return;
+    } else {
+        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) {
+            tvItem = &tvItem_;
+            tvItem.mask = OS.TVIF_STATE;
+        }
+        if ((style & SWT.VIRTUAL) !is 0) {
+            auto hRoot = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+            hItem = getNextSelection (hRoot, tvItem);
+        } else {
+            //FIXME - this code expands first selected item it finds
+            int index = 0;
+            while (index <items.length) {
+                TreeItem item = items [index];
+                if (item !is null) {
+                    int state = 0;
+                    static if (OS.IsWinCE) {
+                        tvItem.hItem = item.handle;
+                        OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+                        state = tvItem.state;
+                    } else {
+                        state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, item.handle, OS.TVIS_SELECTED);
+                    }
+                    if ((state & OS.TVIS_SELECTED) !is 0) {
+                        hItem = item.handle;
+                        break;
+                    }
+                }
+                index++;
+            }
+        }
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+    }
+    if (hItem !is null) showItem (hItem);
+}
+
+/*public*/ void sort () {
+    checkWidget ();
+    if ((style & SWT.VIRTUAL) !is 0) return;
+    sort ( cast(HTREEITEM) OS.TVI_ROOT, false);
+}
+
+void sort (HANDLE hParent, bool all) {
+    int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+    if (itemCount is 0 || itemCount is 1) return;
+    hFirstIndexOf = hLastIndexOf = null;
+    itemCount = -1;
+    if (sortDirection is SWT.UP || sortDirection is SWT.NONE) {
+        OS.SendMessage (handle, OS.TVM_SORTCHILDREN, all ? 1 : 0, hParent);
+    } else {
+        //Callback compareCallback = new Callback (this, "CompareFunc", 3);
+        //int lpfnCompare = compareCallback.getAddress ();
+        sThis = this;
+        TVSORTCB psort;
+        psort.hParent = cast(HTREEITEM)hParent;
+        psort.lpfnCompare = &CompareFunc;
+        psort.lParam = sortColumn is null ? 0 : indexOf (sortColumn);
+        OS.SendMessage (handle, OS.TVM_SORTCHILDRENCB, all ? 1 : 0, &psort);
+        sThis = null;
+        //compareCallback.dispose ();
+    }
+}
+
+override void subclass () {
+    super.subclass ();
+    if (hwndHeader !is null) {
+        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) {
+        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) {
+        if (toolTipText_ !is null) return "";
+        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);
+}
+
+override HWND topHandle () {
+    return hwndParent !is null ? hwndParent : handle;
+}
+
+void updateFullSelection () {
+    if ((style & SWT.FULL_SELECTION) !is 0) {
+        int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits;
+        if ((newBits & OS.TVS_FULLROWSELECT) !is 0) {
+            if (!OS.IsWindowEnabled (handle) || findImageControl () !is null) {
+                if (!explorerTheme) newBits &= ~OS.TVS_FULLROWSELECT;
+            }
+        } else {
+            if (OS.IsWindowEnabled (handle) && findImageControl () is null) {
+                if (!hooks (SWT.EraseItem) && !hooks (SWT.PaintItem)) {
+                    newBits |= OS.TVS_FULLROWSELECT;
+                }
+            }
+        }
+        if (newBits !is oldBits) {
+            OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+            OS.InvalidateRect (handle, null, true);
+        }
+    }
+}
+
+void updateHeaderToolTips () {
+    if (headerToolTipHandle is null) return;
+    RECT rect;
+    TOOLINFO lpti;
+    lpti.cbSize = OS.TOOLINFO_sizeof;
+    lpti.uFlags = OS.TTF_SUBCLASS;
+    lpti.hwnd = hwndHeader;
+    lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
+    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++;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            OS.SendMessage (headerToolTipHandle, OS.TTM_ADDTOOL, 0, &lpti);
+        }
+    }
+}
+
+void updateImageList () {
+    if (imageList is null) return;
+    if (hwndHeader is null) return;
+    int i = 0, index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+    while (i < items.length) {
+        TreeItem item = items [i];
+        if (item !is null) {
+            Image image = null;
+            if (index is 0) {
+                image = item.image;
+            } else {
+                Image [] images = item.images;
+                if (images !is null) image = images [index];
+            }
+            if (image !is null) break;
+        }
+        i++;
+    }
+    /*
+    * 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.
+    */
+    HBITMAP hImageList = i is items.length ? null : imageList.getHandle ();
+    HANDLE hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+    if (hImageList !is hOldImageList) {
+        OS.SendMessage (handle, OS.TVM_SETIMAGELIST, OS.TVSIL_NORMAL, hImageList);
+    }
+}
+
+override void updateImages () {
+    if (sortColumn !is null && !sortColumn.isDisposed ()) {
+        if (OS.COMCTL32_MAJOR < 6) {
+            switch (sortDirection) {
+                case SWT.UP:
+                case SWT.DOWN:
+                    sortColumn.setImage (display.getSortImage (sortDirection), true, true);
+                    break;
+                default:
+            }
+        }
+    }
+}
+
+void updateScrollBar () {
+    if (hwndParent !is null) {
+        if (columnCount !is 0 || scrollWidth !is 0) {
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_ALL;
+            int itemCount = OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0);
+            if (itemCount is 0) {
+                OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
+                info.nPage = info.nMax + 1;
+                OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
+            } else {
+                OS.GetScrollInfo (handle, OS.SB_VERT, &info);
+                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);
+            }
+        }
+    }
+}
+
+override void unsubclass () {
+    super.unsubclass ();
+    if (hwndHeader !is null) {
+        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) && OS.IsAppThemed ()) {
+        bits |= OS.TVS_TRACKSELECT;
+        if ((style & SWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT;
+    } else {
+        if ((style & SWT.FULL_SELECTION) !is 0) {
+            bits |= OS.TVS_FULLROWSELECT;
+        } else {
+            bits |= OS.TVS_HASLINES;
+        }
+    }
+    if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & SWT.H_SCROLL) is 0) {
+            bits &= ~OS.WS_HSCROLL;
+            bits |= OS.TVS_NOHSCROLL;
+        }
+    }
+//  bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP;
+    return bits | OS.TVS_DISABLEDRAGDROP;
+}
+
+override String windowClass () {
+    return TCHARsToStr(TreeClass);
+}
+
+override int windowProc () {
+    return cast(int) TreeProc;
+}
+
+override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    if (hwndHeader !is null && hwnd is hwndHeader) {
+        switch (msg) {
+            /* This code is intentionally commented */
+//          case OS.WM_CONTEXTMENU: {
+//              LRESULT result = wmContextMenu (hwnd, wParam, lParam);
+//              if (result !is null) return result.value;
+//              break;
+//          }
+            case OS.WM_CAPTURECHANGED: {
+                /*
+                * Bug in Windows.  When the capture changes during a
+                * header drag, Windows does not redraw the header item
+                * such that the header remains pressed.  For example,
+                * when focus is assigned to a push button, the mouse is
+                * pressed (but not released), then the SPACE key is
+                * pressed to activate the button, the capture changes,
+                * the header not notified and NM_RELEASEDCAPTURE is not
+                * sent.  The fix is to redraw the header when the capture
+                * changes to another control.
+                *
+                * This does not happen on XP.
+                */
+                if (OS.COMCTL32_MAJOR < 6) {
+                    if (lParam !is 0 && cast(HANDLE) lParam !is hwndHeader) {
+                        OS.InvalidateRect (hwndHeader, null, true);
+                    }
+                }
+                break;
+            }
+            case OS.WM_MOUSELEAVE: {
+                /*
+                * Bug in Windows.  On XP, when a tooltip is hidden
+                * due to a time out or mouse press, the tooltip
+                * remains active although no longer visible and
+                * won't show again until another tooltip becomes
+                * active.  The fix is to reset the tooltip bounds.
+                */
+                if (OS.COMCTL32_MAJOR >= 6) updateHeaderToolTips ();
+                updateHeaderToolTips ();
+                break;
+            }
+            case OS.WM_NOTIFY: {
+                NMHDR* hdr = cast(NMHDR*)lParam;
+                //OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+                switch (hdr.code) {
+                    case OS.TTN_SHOW:
+                    case OS.TTN_POP:
+                    case OS.TTN_GETDISPINFOA:
+                    case OS.TTN_GETDISPINFOW:
+                        return OS.SendMessage (handle, msg, wParam, lParam);
+                    default:
+                }
+                break;
+            }
+            case OS.WM_SETCURSOR: {
+                if (cast(HWND)wParam is hwnd) {
+                    int hitTest = cast(short) OS.LOWORD (lParam);
+                    if (hitTest is OS.HTCLIENT) {
+                        HDHITTESTINFO pinfo;
+                        int pos = OS.GetMessagePos ();
+                        POINT pt;
+                        OS.POINTSTOPOINT (pt, pos);
+                        OS.ScreenToClient (hwnd, &pt);
+                        pinfo.pt.x = pt.x;
+                        pinfo.pt.y = pt.y;
+                        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) {
+                                OS.SetCursor (OS.LoadCursor (null, cast(TCHAR*) OS.IDC_ARROW));
+                                return 1;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+        }
+        return callWindowProc (hwnd, msg, wParam, lParam);
+    }
+    if (hwndParent !is null && hwnd is hwndParent) {
+        switch (msg) {
+            case OS.WM_MOVE: {
+                sendEvent (SWT.Move);
+                return 0;
+            }
+            case OS.WM_SIZE: {
+                setScrollWidth ();
+                if (ignoreResize) return 0;
+                setResizeChildren (false);
+                int /*long*/ code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
+                sendEvent (SWT.Resize);
+                if (isDisposed ()) return 0;
+                if (layout_ !is null) {
+                    markLayout (false, false);
+                    updateLayout (false, false);
+                }
+                setResizeChildren (true);
+                updateScrollBar ();
+                return code;
+            }
+            case OS.WM_NCPAINT: {
+                LRESULT result = wmNCPaint (hwnd, wParam, lParam);
+                if (result !is null) return result.value;
+                break;
+            }
+            case OS.WM_PRINT: {
+                LRESULT result = wmPrint (hwnd, wParam, lParam);
+                if (result !is null) return result.value;
+                break;
+            }
+            case OS.WM_COMMAND:
+            case OS.WM_NOTIFY:
+            case OS.WM_SYSCOLORCHANGE: {
+                return OS.SendMessage (handle, msg, wParam, lParam);
+            }
+            case OS.WM_HSCROLL: {
+                /*
+                * Bug on WinCE.  lParam should be NULL when the message is not sent
+                * by a scroll bar control, but it contains the handle to the window.
+                * When the message is sent by a scroll bar control, it correctly
+                * contains the handle to the scroll bar.  The fix is to check for
+                * both.
+                */
+                if (horizontalBar !is null && (lParam is 0 || lParam is cast(int)hwndParent)) {
+                    wmScroll (horizontalBar, true, hwndParent, OS.WM_HSCROLL, wParam, lParam);
+                }
+                setScrollWidth ();
+                break;
+            }
+            case OS.WM_VSCROLL: {
+                SCROLLINFO info;
+                info.cbSize = SCROLLINFO.sizeof;
+                info.fMask = OS.SIF_ALL;
+                OS.GetScrollInfo (hwndParent, OS.SB_VERT, &info);
+                /*
+                * Update the nPos field to match the nTrackPos field
+                * so that the tree scrolls when the scroll bar of the
+                * parent is dragged.
+                *
+                * NOTE: For some reason, this code is only necessary
+                * on Windows Vista.
+                */
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                    if (OS.LOWORD (wParam) is OS.SB_THUMBTRACK) {
+                        info.nPos = info.nTrackPos;
+                    }
+                }
+                OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
+                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;
+            }
+            default:
+        }
+        return callWindowProc (hwnd, msg, wParam, lParam);
+    }
+    if (msg is Display.DI_GETDRAGIMAGE) {
+        /*
+        * 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 & SWT.MULTI) !is 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) {
+            auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+            TreeItem [] items = new TreeItem [10];
+            TVITEM tvItem;
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+            int count = getSelection (hItem, &tvItem, items, 0, 10, false, true);
+            if (count is 0) return 0;
+            POINT mousePos;
+            OS.POINTSTOPOINT (mousePos, OS.GetMessagePos ());
+            OS.MapWindowPoints (null, handle, &mousePos, 1);
+            RECT clientRect;
+            OS.GetClientRect(handle, &clientRect);
+            RECT rect = *(items [0].getBounds (0, true, true, false));
+            if ((style & SWT.FULL_SELECTION) !is 0) {
+                int width = DRAG_IMAGE_SIZE;
+                rect.left = Math.max (clientRect.left, mousePos.x - width / 2);
+                if (clientRect.right > rect.left + width) {
+                    rect.right = rect.left + width;
+                } else {
+                    rect.right = clientRect.right;
+                    rect.left = Math.max (clientRect.left, rect.right - width);
+                }
+            }
+            auto hRgn = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+            for (int i = 1; i < count; i++) {
+                if (rect.bottom - rect.top > DRAG_IMAGE_SIZE) break;
+                if (rect.bottom > clientRect.bottom) break;
+                RECT itemRect = *(items[i].getBounds (0, true, true, false));
+                if ((style & SWT.FULL_SELECTION) !is 0) {
+                    itemRect.left = rect.left;
+                    itemRect.right = rect.right;
+                }
+                auto rectRgn = OS.CreateRectRgn (itemRect.left, itemRect.top, itemRect.right, itemRect.bottom);
+                OS.CombineRgn (hRgn, hRgn, rectRgn, OS.RGN_OR);
+                OS.DeleteObject (rectRgn);
+                rect.bottom = itemRect.bottom;
+                
+            }
+            OS.GetRgnBox (hRgn, &rect);
+            
+            /* Create resources */
+            auto hdc = OS.GetDC (handle);
+            auto memHdc = OS.CreateCompatibleDC (hdc);
+            BITMAPINFOHEADER bmiHeader;
+            bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+            bmiHeader.biWidth = rect.right - rect.left;
+            bmiHeader.biHeight = -(rect.bottom - rect.top);
+            bmiHeader.biPlanes = 1;
+            bmiHeader.biBitCount = 32;
+            bmiHeader.biCompression = OS.BI_RGB;
+            byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
+            OS.MoveMemory (bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+            void* [1] pBits;
+            auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*) bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+            if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
+            auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+            int colorKey = 0x0000FD;
+            POINT pt;
+            OS.SetWindowOrgEx (memHdc, rect.left, rect.top, &pt);
+            OS.FillRect (memHdc, &rect, findBrush (colorKey, OS.BS_SOLID));
+            OS.OffsetRgn (hRgn, -rect.left, -rect.top);
+            OS.SelectClipRgn (memHdc, hRgn);
+            OS.PrintWindow (handle, memHdc, 0);
+            OS.SetWindowOrgEx (memHdc, pt.x, pt.y, null);
+            OS.SelectObject (memHdc, oldMemBitmap);
+            OS.DeleteDC (memHdc);
+            OS.ReleaseDC (null, hdc);
+            OS.DeleteObject (hRgn);
+
+            SHDRAGIMAGE shdi;
+            shdi.hbmpDragImage = memDib;
+            shdi.crColorKey = colorKey;
+            shdi.sizeDragImage.cx = bmiHeader.biWidth;
+            shdi.sizeDragImage.cy = -bmiHeader.biHeight;
+            shdi.ptOffset.x = mousePos.x - rect.left;
+            shdi.ptOffset.y = mousePos.y - rect.top;
+            if ((style & SWT.MIRRORED) !is 0) {
+                shdi.ptOffset.x = shdi.sizeDragImage.cx - shdi.ptOffset.x; 
+            }
+            OS.MoveMemory (cast(void*)lParam, &shdi, SHDRAGIMAGE.sizeof);
+            return 1;
+        }
+    }
+    return super.windowProc (hwnd, msg, wParam, 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 tree control beeps
+    * in WM_CHAR when the search for the item that
+    * matches the key stroke fails.  This is the
+    * standard tree behavior but is unexpected when
+    * the key that was typed was ESC, CR or SPACE.
+    * The fix is to avoid calling the tree window
+    * proc in these cases.
+    */
+    switch (wParam) {
+        case ' ': {
+            HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+            if (hItem !is null) {
+                hAnchor = hItem;
+                OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hItem);
+                TVITEM tvItem;
+                tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE | OS.TVIF_PARAM;
+                tvItem.hItem = cast(HTREEITEM)hItem;
+                if ((style & SWT.CHECK) !is 0) {
+                    tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    int state = tvItem.state >> 12;
+                    if ((state & 0x1) !is 0) {
+                        state++;
+                    } else  {
+                        --state;
+                    }
+                    tvItem.state = state << 12;
+                    OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    static if (!OS.IsWinCE) {
+                        int id = cast(int) hItem;
+                        if (OS.COMCTL32_MAJOR >= 6) {
+                            id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, hItem, 0);
+                        }
+                        OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+                    }
+                }
+                tvItem.stateMask = OS.TVIS_SELECTED;
+                OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                if ((style & SWT.MULTI) !is 0 && OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                    if ((tvItem.state & OS.TVIS_SELECTED) !is 0) {
+                        tvItem.state &= ~OS.TVIS_SELECTED;
+                    } else {
+                        tvItem.state |= OS.TVIS_SELECTED;
+                    }
+                } else {
+                    tvItem.state |= OS.TVIS_SELECTED;
+                }
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                TreeItem item = _getItem (hItem, tvItem.lParam);
+                Event event = new Event ();
+                event.item = item;
+                postEvent (SWT.Selection, event);
+                if ((style & SWT.CHECK) !is 0) {
+                    event = new Event ();
+                    event.item = item;
+                    event.detail = SWT.CHECK;
+                    postEvent (SWT.Selection, event);
+                }
+            }
+            return LRESULT.ZERO;
+        }
+        case SWT.CR: {
+            /*
+            * Feature in Windows.  Windows sends NM_RETURN from WM_KEYDOWN
+            * instead of using WM_CHAR.  This means that application code
+            * that expects to consume the key press and therefore avoid a
+            * SWT.DefaultSelection event from WM_CHAR will fail.  The fix
+            * is to implement SWT.DefaultSelection in WM_CHAR instead of
+            * using NM_RETURN.
+            */
+            Event event = new Event ();
+            HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+            if (hItem !is null) event.item = _getItem (hItem);
+            postEvent (SWT.DefaultSelection, event);
+            return LRESULT.ZERO;
+        }
+        case SWT.ESC:
+            return LRESULT.ZERO;
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+    LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+    if ((style & SWT.DOUBLE_BUFFERED) !is 0) return LRESULT.ONE;
+    if (findImageControl () !is null) return LRESULT.ONE;
+    return result;
+}
+
+override LRESULT WM_GETOBJECT (int wParam, int lParam) {
+    /*
+    * Ensure that there is an accessible object created for this
+    * control because support for checked item and tree column
+    * accessibility is temporarily implemented in the accessibility
+    * package.
+    */
+    if ((style & SWT.CHECK) !is 0 || hwndParent !is null) {
+        if (accessible is null) accessible = new_Accessible (this);
+    }
+    return super.WM_GETOBJECT (wParam, lParam);
+}
+
+override LRESULT WM_HSCROLL (int wParam, int lParam) {
+    bool fixScroll = false;
+    if ((style & SWT.DOUBLE_BUFFERED) !is 0) {
+        fixScroll = (style & SWT.VIRTUAL) !is 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem);
+    }
+    if (fixScroll) {
+        style &= ~SWT.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 |= SWT.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) {
+        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_ADD:
+            if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                if (hwndHeader !is null) {
+                    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 ();
+                        }
+                    }
+                }
+            }
+            break;
+        case OS.VK_UP:
+        case OS.VK_DOWN:
+        case OS.VK_PRIOR:
+        case OS.VK_NEXT:
+        case OS.VK_HOME:
+        case OS.VK_END: {
+            OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            if ((style & SWT.SINGLE) !is 0) break;
+            if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+                HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                if (hItem !is null) {
+                    if (hAnchor is null) hAnchor = hItem;
+                    ignoreSelect = ignoreDeselect = true;
+                    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;
+                    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                    tvItem.stateMask = OS.TVIS_SELECTED;
+                    auto hDeselectItem = hItem;
+                    RECT rect1;
+                    if (!OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hAnchor, &rect1, false)) {
+                        hAnchor = hItem;
+                        OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hAnchor, &rect1, false);
+                    }
+                    RECT rect2;
+                    OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hDeselectItem, &rect2, false);
+                    int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+                    while (hDeselectItem !is hAnchor) {
+                        tvItem.hItem = cast(HTREEITEM)hDeselectItem;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        hDeselectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
+                    }
+                    auto hSelectItem = hAnchor;
+                    OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hNewItem, &rect1, false);
+                    OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hSelectItem, &rect2, false);
+                    tvItem.state = OS.TVIS_SELECTED;
+                    flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
+                    while (hSelectItem !is hNewItem) {
+                        tvItem.hItem = cast(HTREEITEM)hSelectItem;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        hSelectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hSelectItem);
+                    }
+                    tvItem.hItem = cast(HTREEITEM)hNewItem;
+                    OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+                    tvItem.hItem = cast(HTREEITEM)hNewItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    Event event = new Event ();
+                    event.item = _getItem (hNewItem, tvItem.lParam);
+                    postEvent (SWT.Selection, event);
+                    return new LRESULT (code);
+                }
+            }
+            if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
+                HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                if (hItem !is null) {
+                    TVITEM tvItem;
+                    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                    tvItem.stateMask = OS.TVIS_SELECTED;
+                    tvItem.hItem = cast(HTREEITEM)hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    bool oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
+                    HANDLE hNewItem;
+                    switch (wParam) {
+                        case OS.VK_UP:
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PREVIOUSVISIBLE, hItem);
+                            break;
+                        case OS.VK_DOWN:
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                            break;
+                        case OS.VK_HOME:
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+                            break;
+                        case OS.VK_PRIOR:
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                            if (hNewItem is hItem) {
+                                OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEUP, 0);
+                                hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                            }
+                            break;
+                        case OS.VK_NEXT:
+                            RECT rect, clientRect;
+                            OS.GetClientRect (handle, &clientRect);
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                            do {
+                                auto hVisible = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
+                                if (hVisible is null) break;
+                                if (!OS.TreeView_GetItemRect (handle, cast(HTREEITEM)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);
+                                }
+                            } while (hNewItem !is null);
+                            break;
+                        case OS.VK_END:
+                            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
+                            break;
+                        default:
+                    }
+                    if (hNewItem !is null) {
+                        OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, hNewItem);
+                        tvItem.hItem = cast(HTREEITEM)hNewItem;
+                        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                        bool newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
+                        bool redraw = !newSelected && drawCount is 0 && OS.IsWindowVisible (handle);
+                        if (redraw) {
+                            OS.UpdateWindow (handle);
+                            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                        }
+                        hSelect = hNewItem;
+                        ignoreSelect = true;
+                        OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, hNewItem);
+                        ignoreSelect = false;
+                        hSelect = null;
+                        if (oldSelected) {
+                            tvItem.state = OS.TVIS_SELECTED;
+                            tvItem.hItem = cast(HTREEITEM)hItem;
+                            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        }
+                        if (!newSelected) {
+                            tvItem.state = 0;
+                            tvItem.hItem = cast(HTREEITEM)hNewItem;
+                            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        }
+                        if (redraw) {
+                            RECT rect1, rect2;
+                            bool fItemRect = (style & SWT.FULL_SELECTION) is 0;
+                            if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) fItemRect = false;
+                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+                            OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hItem, &rect1, fItemRect);
+                            OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hNewItem, &rect2, fItemRect);
+                            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                            OS.InvalidateRect (handle, &rect1, true);
+                            OS.InvalidateRect (handle, &rect2, true);
+                            OS.UpdateWindow (handle);
+                        }
+                        return LRESULT.ZERO;
+                    }
+                }
+            }
+            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);
+        }
+        default:
+    }
+    return result;
+}
+
+override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When a tree item that has an image
+    * with alpha is expanded or collapsed, the area where
+    * the image is drawn is not erased before it is drawn.
+    * This means that the image gets darker each time.
+    * The fix is to redraw the selection.
+    *
+    * Feature in Windows.  When multiple item have
+    * the TVIS_SELECTED state, Windows redraws only
+    * the focused item in the color used to show the
+    * selection when the tree loses or gains focus.
+    * The fix is to force Windows to redraw the
+    * selection when focus is gained or lost.
+    */
+    bool redraw = (style & SWT.MULTI) !is 0;
+    if (!redraw) {
+        if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
+            if (imageList !is null) {
+                int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                    redraw = true;
+                }
+            }
+        }
+    }
+    if (redraw) redrawSelection ();
+    return super.WM_KILLFOCUS (wParam, lParam);
+}
+
+override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+    TVHITTESTINFO lpht;
+    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 & SWT.CHECK) !is 0) {
+            if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) !is 0) {
+                Display display = this.display;
+                display.captureChanged = false;
+                sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+                if (!sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
+                    if (!display.captureChanged && !isDisposed ()) {
+                        if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+                    }
+                    return LRESULT.ZERO;
+                }
+                if (!display.captureChanged && !isDisposed ()) {
+                    if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+                }
+                OS.SetFocus (handle);
+                TVITEM tvItem;
+                tvItem.hItem = lpht.hItem;
+                tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+                tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+                OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                int state = tvItem.state >> 12;
+                if ((state & 0x1) !is 0) {
+                    state++;
+                } else  {
+                    --state;
+                }
+                tvItem.state = state << 12;
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                static if (!OS.IsWinCE) {
+                    int id = cast(int) tvItem.hItem;
+                    if (OS.COMCTL32_MAJOR >= 6) {
+                        id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+                    }
+                    OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+                }
+                Event event = new Event ();
+                event.item = _getItem (tvItem.hItem, tvItem.lParam);
+                event.detail = SWT.CHECK;
+                postEvent (SWT.Selection, event);
+                return LRESULT.ZERO;
+            }
+        }
+    }
+    LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
+    if (result is LRESULT.ZERO) return result;
+    if (lpht.hItem !is null) {
+        int flags = OS.TVHT_ONITEM;
+        if ((style & SWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (SWT.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 (SWT.DefaultSelection, event);
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * In a multi-select tree, if the user is collapsing a subtree that
+    * contains selected items, clear the selection from these items and
+    * issue a selection event.  Only items that are selected and visible
+    * are cleared.  This code also runs in the case when the white space
+    * below the last item is selected.
+    */
+    TVHITTESTINFO lpht;
+    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;
+        display.captureChanged = false;
+        if (!sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
+            if (!display.captureChanged && !isDisposed ()) {
+                if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+            }
+            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 & SWT.MULTI) !is 0) {
+            if (hOldSelection !is null) {
+                TVITEM tvItem;
+                tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+                tvItem.hItem = lpht.hItem;
+                OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                if ((tvItem.state & OS.TVIS_EXPANDED) !is 0) {
+                    fixSelection = true;
+                    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 = cast(HTREEITEM)hNext;
+                        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                        if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true;
+                        tvItem.state = 0;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        HANDLE hItem = hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNext);
+                        while (hItem !is null && hItem !is lpht.hItem) {
+                            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+                        }
+                        if (hItem is null) break;
+                    }
+                }
+            }
+        }
+        dragStarted = gestureCompleted = false;
+        if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true;
+        int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            if (OS.GetFocus () !is handle) OS.SetFocus (handle);
+        }
+        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, cast(HTREEITEM)hItem, &rect, false)) {
+                            OS.InvalidateRect (handle, &rect, true);
+                        }
+                    }
+                }
+            }
+        }
+        if (deselected) {
+            Event event = new Event ();
+            event.item = _getItem (lpht.hItem);
+            postEvent (SWT.Selection, event);
+        }
+        return new LRESULT (code);
+    }
+
+    /* Look for check/uncheck */
+    if ((style & SWT.CHECK) !is 0) {
+        if ((lpht.flags & OS.TVHT_ONITEMSTATEICON) !is 0) {
+            Display display = this.display;
+            display.captureChanged = false;
+            if (!sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
+                if (!display.captureChanged && !isDisposed ()) {
+                    if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+                }
+                return LRESULT.ZERO;
+            }
+            if (!display.captureChanged && !isDisposed ()) {
+                if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+            }
+            OS.SetFocus (handle);
+            TVITEM tvItem;
+            tvItem.hItem = lpht.hItem;
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
+            tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+            int state = tvItem.state >> 12;
+            if ((state & 0x1) !is 0) {
+                state++;
+            } else  {
+                --state;
+            }
+            tvItem.state = state << 12;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+            static if (!OS.IsWinCE) {
+                int id = cast(int) tvItem.hItem;
+                if (OS.COMCTL32_MAJOR >= 6) {
+                    id = OS.SendMessage (handle, OS.TVM_MAPHTREEITEMTOACCID, tvItem.hItem, 0);
+                }
+                OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, handle, OS.OBJID_CLIENT, id);
+            }
+            Event event = new Event ();
+            event.item = _getItem (tvItem.hItem, tvItem.lParam);
+            event.detail = SWT.CHECK;
+            postEvent (SWT.Selection, event);
+            return LRESULT.ZERO;
+        }
+    }
+
+    /*
+    * 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 & SWT.FULL_SELECTION) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) fakeSelection = true;
+        } else {
+            if (hooks (SWT.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 (!selected && (style & SWT.FULL_SELECTION) is 0) {
+        if ((lpht.flags & OS.TVHT_ONITEM) is 0) {
+            Display display = this.display;
+            display.captureChanged = false;
+            if (!sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
+                if (!display.captureChanged && !isDisposed ()) {
+                    if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+                }
+                return LRESULT.ZERO;
+            }
+            int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if (OS.GetFocus () !is handle) OS.SetFocus (handle);
+            }
+            if (!display.captureChanged && !isDisposed ()) {
+                if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+            }
+            return new LRESULT (code);
+        }
+    }
+
+    /* Get the selected state of the item under the mouse */
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    bool hittestSelected = false;
+    if ((style & SWT.MULTI) !is 0) {
+        tvItem.hItem = lpht.hItem;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
+    }
+
+    /* Get the selected state of the last selected item */
+    auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+    if ((style & SWT.MULTI) !is 0) {
+        tvItem.hItem = cast(HTREEITEM)hOldItem;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+
+        /* Check for CONTROL or drag selection */
+        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 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
+            * delivered during WM_LBUTTONDOWN.  When WM_SETREDRAW is used
+            * to disable drawing for the tree and a WM_PAINT happens for
+            * a parent of the tree (or a sibling that overlaps), the parent
+            * will draw on top of the tree.  If WM_SETREDRAW is turned back
+            * 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
+            * 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 SWT, 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) {
+                OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            }
+            OS.UpdateWindow (handle);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        } else {
+            deselectAll ();
+        }
+    }
+
+    /* Do the selection */
+    Display display = this.display;
+    display.captureChanged = false;
+    if (!sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam)) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+        return LRESULT.ZERO;
+    }
+    hSelect = lpht.hItem;
+    dragStarted = gestureCompleted = false;
+    ignoreDeselect = ignoreSelect = true;
+    int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (OS.GetFocus () !is handle) OS.SetFocus (handle);
+    }
+    auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+    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 (SWT.DragDetect)) {
+            dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
+        }
+    }
+    ignoreDeselect = ignoreSelect = false;
+    hSelect = null;
+    if (dragStarted) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+    }
+
+    /*
+    * Feature in Windows.  When the old and new focused item
+    * are the same, Windows does not check to make sure that
+    * the item is actually selected, not just focused.  The
+    * fix is to force the item to draw selected by setting
+    * the state mask.  This is only necessary when the tree
+    * is single select.
+    */
+    if ((style & SWT.SINGLE) !is 0) {
+        if (hOldItem is hNewItem) {
+            tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+            tvItem.state = OS.TVIS_SELECTED;
+            tvItem.stateMask = OS.TVIS_SELECTED;
+            tvItem.hItem = cast(HTREEITEM)hNewItem;
+            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+        }
+    }
+
+    /* Reselect the last item that was unselected */
+    if ((style & SWT.MULTI) !is 0) {
+
+        /* Check for CONTROL and reselect the last item */
+        if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) {
+            if (hOldItem is hNewItem && hOldItem is lpht.hItem) {
+                if ((wParam & OS.MK_CONTROL) !is 0) {
+                    tvItem.state ^= OS.TVIS_SELECTED;
+                    if (dragStarted) tvItem.state = OS.TVIS_SELECTED;
+                    OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                }
+            } else {
+                if ((tvItem.state & OS.TVIS_SELECTED) !is 0) {
+                    tvItem.state = OS.TVIS_SELECTED;
+                    OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                }
+                if ((wParam & OS.MK_CONTROL) !is 0 && !dragStarted) {
+                    if (hittestSelected) {
+                        tvItem.state = 0;
+                        tvItem.hItem = lpht.hItem;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    }
+                }
+            }
+            RECT rect1, rect2;
+            bool fItemRect = (style & SWT.FULL_SELECTION) is 0;
+            if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) fItemRect = false;
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+            OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hOldItem, &rect1, fItemRect);
+            OS.TreeView_GetItemRect (handle, cast(HTREEITEM)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;
+                auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
+                if ((style & SWT.VIRTUAL) !is 0) {
+                    HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+                    deselect (hItem, &tvItem, hNewItem);
+                } else {
+                    for (int i=0; i<items.length; i++) {
+                        TreeItem item = items [i];
+                        if (item !is null && item.handle !is hNewItem) {
+                            tvItem.hItem = cast(HTREEITEM)item.handle;
+                            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                        }
+                    }
+                }
+                tvItem.hItem = cast(HTREEITEM)hNewItem;
+                tvItem.state = OS.TVIS_SELECTED;
+                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+                if ((wParam & OS.MK_SHIFT) !is 0) {
+                    RECT rect1;
+                    if (hAnchor is null) hAnchor = hNewItem;
+                    if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hAnchor, &rect1, false)) {
+                        RECT rect2;
+                        if (OS.TreeView_GetItemRect (handle, cast(HTREEITEM)hNewItem, &rect2, false)) {
+                            int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
+                            tvItem.state = OS.TVIS_SELECTED;
+                            auto hItem = tvItem.hItem = cast(HTREEITEM)hAnchor;
+                            OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                            while (hItem !is hNewItem) {
+                                tvItem.hItem = hItem;
+                                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                                hItem = cast(HTREEITEM) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if ((wParam & OS.MK_SHIFT) is 0) hAnchor = hNewItem;
+
+    /* Issue notification */
+    if (!gestureCompleted) {
+        tvItem.hItem = cast(HTREEITEM)hNewItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+        Event event = new Event ();
+        event.item = _getItem (tvItem.hItem, tvItem.lParam);
+        postEvent (SWT.Selection, event);
+    }
+    gestureCompleted = false;
+
+    /*
+    * Feature in Windows.  Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN,
+    * the widget starts a modal loop to determine if the user wants
+    * to begin a drag/drop operation or marquee select.  Unfortunately,
+    * this modal loop eats the corresponding mouse up.  The fix is to
+    * detect the cases when the modal loop has eaten the mouse up and
+    * issue a fake mouse up.
+    */
+    if (dragStarted) {
+        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) {
+            sendMouseEvent (SWT.MouseUp, 1, handle, OS.WM_LBUTTONUP, wParam, lParam);
+        }
+    }
+    dragStarted = false;
+    return new LRESULT (code);
+}
+
+override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
+    if (result !is null) return result;
+    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,
+        * causing mouse capture to become stuck.  The fix is to test
+        * for the extra buttons only when they exist.
+        */
+        int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+        if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+        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);
+                    }
+                }
+                TOOLINFO lpti;
+                lpti.cbSize = OS.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);
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_MOVE (int wParam, int lParam) {
+    if (ignoreResize) return null;
+    return super.WM_MOVE (wParam, lParam);
+}
+
+override LRESULT WM_RBUTTONDOWN (int wParam, int lParam) {
+    /*
+    * Feature in Windows.  The receiver uses WM_RBUTTONDOWN
+    * to initiate a drag/drop operation depending on how the
+    * user moves the mouse.  If the user clicks the right button,
+    * without moving the mouse, the tree consumes the corresponding
+    * WM_RBUTTONUP.  The fix is to avoid calling the window proc for
+    * the tree.
+    */
+    Display display = this.display;
+    display.captureChanged = false;
+    if (!sendMouseEvent (SWT.MouseDown, 3, handle, OS.WM_RBUTTONDOWN, wParam, lParam)) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+        return LRESULT.ZERO;
+    }
+    /*
+    * This code is intentionally commented.
+    */
+//  if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+    if (OS.GetFocus () !is handle) OS.SetFocus (handle);
+
+    /*
+    * Feature in Windows.  When the user selects a tree item
+    * with the right mouse button, the item remains selected
+    * only as long as the user does not release or move the
+    * mouse.  As soon as this happens, the selection snaps
+    * back to the previous selection.  This behavior can be
+    * observed in the Explorer but is not instantly apparent
+    * because the Explorer explicitly sets the selection when
+    * the user chooses a menu item.  If the user cancels the
+    * menu, the selection snaps back.  The fix is to avoid
+    * calling the window proc and do the selection ourselves.
+    * This behavior is consistent with the table.
+    */
+    TVHITTESTINFO lpht;
+    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) {
+        bool fakeSelection = (style & SWT.FULL_SELECTION) !is 0;
+        if (!fakeSelection) {
+            if (hooks (SWT.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;
+                tvItem.stateMask = OS.TVIS_SELECTED;
+                tvItem.hItem = lpht.hItem;
+                OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                if ((tvItem.state & OS.TVIS_SELECTED) is 0) {
+                    ignoreSelect = true;
+                    OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, 0);
+                    ignoreSelect = false;
+                    OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
+                }
+            }
+        }
+    }
+    return LRESULT.ZERO;
+}
+
+override LRESULT WM_PAINT (int wParam, int lParam) {
+    if (shrink && !ignoreShrink) {
+        /* Resize the item array to fit the last item */
+        int count = items.length - 1;
+        while (count >= 0) {
+            if (items [count] !is null) break;
+            --count;
+        }
+        count++;
+        if (items.length > 4 && items.length - count > 3) {
+            int length = Math.max (4, (count + 3) / 4 * 4);
+            TreeItem [] newItems = new TreeItem [length];
+            System.arraycopy (items, 0, newItems, 0, count);
+            items = newItems;
+        }
+        shrink = false;
+    }
+    if ((style & SWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) {
+        bool doubleBuffer = true;
+        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;
+            HDC paintDC;
+            PAINTSTRUCT ps;
+            bool hooksPaint = hooks (SWT.Paint);
+            if (hooksPaint) {
+                GCData data = new GCData ();
+                data.ps = &ps;
+                data.hwnd = handle;
+                gc = GC.win32_new (this, data);
+                paintDC = gc.handle;
+            } else {
+                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);
+                callWindowProc (handle, OS.WM_PAINT, cast(int) hDC, 0);
+                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);
+                if (hooksPaint) {
+                    Event event = new Event ();
+                    event.gc = gc;
+                    event.x = ps.rcPaint.left;
+                    event.y = ps.rcPaint.top;
+                    event.width = ps.rcPaint.right - ps.rcPaint.left;
+                    event.height = ps.rcPaint.bottom - ps.rcPaint.top;
+                    sendEvent (SWT.Paint, event);
+                    // widget could be disposed at this point
+                    event.gc = null;
+                }
+            }
+            if (hooksPaint) {
+                gc.dispose ();
+            } else {
+                OS.EndPaint (handle, &ps);
+            }
+            return LRESULT.ZERO;
+        }
+    }
+    return super.WM_PAINT (wParam, lParam);
+}
+
+override LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+    LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  For some reason, when WM_PRINT is used
+    * to capture an image of a hierarchy that contains a tree with
+    * columns, the clipping that is used to stop the first column
+    * from drawing on top of subsequent columns stops the first
+    * column and the tree lines from drawing.  This does not happen
+    * during WM_PAINT.  The fix is to draw without clipping and
+    * then draw the rest of the columns on top.  Since the drawing
+    * is happening in WM_PRINTCLIENT, the redrawing is not visible.
+    */
+    printClient = true;
+    int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+    printClient = false;
+    return new LRESULT (code);
+}
+
+override LRESULT WM_SETFOCUS (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When a tree item that has an image
+    * with alpha is expanded or collapsed, the area where
+    * the image is drawn is not erased before it is drawn.
+    * This means that the image gets darker each time.
+    * The fix is to redraw the selection.
+    *
+    * Feature in Windows.  When multiple item have
+    * the TVIS_SELECTED state, Windows redraws only
+    * the focused item in the color used to show the
+    * selection when the tree loses or gains focus.
+    * The fix is to force Windows to redraw the
+    * selection when focus is gained or lost.
+    */
+    bool redraw = (style & SWT.MULTI) !is 0;
+    if (!redraw) {
+        if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
+            if (imageList !is null) {
+                int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+                if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                    redraw = true;
+                }
+            }
+        }
+    }
+    if (redraw) redrawSelection ();
+    return super.WM_SETFOCUS (wParam, lParam);
+}
+
+override LRESULT WM_SETFONT (int wParam, int lParam) {
+    LRESULT result = super.WM_SETFONT (wParam, lParam);
+    if (result !is null) return result;
+    if (hwndHeader !is null) {
+        /*
+        * Bug in Windows.  When a header has a sort indicator
+        * triangle, Windows resizes the indicator based on the
+        * size of the n-1th font.  The fix is to always make
+        * the n-1th font be the default.  This makes the sort
+        * indicator always be the default size.
+        */
+        OS.SendMessage (hwndHeader, OS.WM_SETFONT, 0, lParam);
+        OS.SendMessage (hwndHeader, OS.WM_SETFONT, wParam, lParam);
+    }
+    if (itemToolTipHandle !is null) {
+        OS.SendMessage (itemToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+    }
+    if (headerToolTipHandle !is null) {
+        OS.SendMessage (headerToolTipHandle, OS.WM_SETFONT, wParam, lParam);
+    }
+    return result;
+}
+
+override LRESULT WM_SETREDRAW (int wParam, int lParam) {
+    LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  Under certain circumstances, when
+    * WM_SETREDRAW is used to turn off drawing and then
+    * TVM_GETITEMRECT is sent to get the bounds of an item
+    * that is not inside the client area, Windows segment
+    * faults.  The fix is to call the default window proc
+    * rather than the default tree proc.
+    *
+    * NOTE:  This problem is intermittent and happens on
+    * Windows Vista running under the theme manager.
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+        return code is 0 ? LRESULT.ZERO : new LRESULT (code);
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When TVS_NOHSCROLL is set when the
+    * size of the tree is zero, the scroll bar is shown the
+    * next time the tree resizes.  The fix is to hide the
+    * scroll bar every time the tree is resized.
+    */
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.TVS_NOHSCROLL) !is 0) {
+        static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false);
+    }
+    /*
+    * Bug in Windows.  On Vista, when the Explorer theme
+    * is used with a full selection tree, when the tree
+    * is resized to be smaller, the rounded right edge
+    * of the selected items is not drawn.  The fix is the
+    * redraw the entire tree.
+    */
+    if (explorerTheme && (style & SWT.FULL_SELECTION) !is 0) {
+        OS.InvalidateRect (handle, null, false);
+    }
+    if (ignoreResize) return null;
+    return super.WM_SIZE (wParam, lParam);
+}
+
+override LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+    LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  When the tree is using the explorer
+    * theme, it does not use COLOR_WINDOW_TEXT for the
+    * default foreground color.  The fix is to explicitly
+    * set the foreground.
+    */
+    if (explorerTheme) {
+        if (foreground is -1) setForegroundPixel (-1);
+    }
+    if ((style & SWT.CHECK) !is 0) setCheckboxImageList ();
+    return result;
+}
+
+override LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
+    bool fixScroll = false;
+    if ((style & SWT.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 & SWT.VIRTUAL) !is 0 || hooks (SWT.EraseItem) || hooks (SWT.PaintItem);
+                break;
+            default:
+        }
+    }
+    if (fixScroll) {
+        style &= ~SWT.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 |= SWT.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) {
+            return super.wmColorChild (wParam, lParam);
+        }
+        return new LRESULT ( cast(int) OS.GetStockObject (OS.NULL_BRUSH));
+    }
+    /*
+    * Feature in Windows.  Tree controls send WM_CTLCOLOREDIT
+    * to allow application code to change the default colors.
+    * This is undocumented and conflicts with TVM_SETTEXTCOLOR
+    * and TVM_SETBKCOLOR, the documented way to do this.  The
+    * fix is to ignore WM_CTLCOLOREDIT messages from trees.
+    */
+    return null;
+}
+
+override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
+    if (hdr.hwndFrom is itemToolTipHandle) {
+        LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+        if (result !is null) return result;
+    }
+    if (hdr.hwndFrom is hwndHeader) {
+        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) {
+    switch (hdr.code) {
+        case OS.TVN_GETDISPINFOA:
+        case OS.TVN_GETDISPINFOW: {
+            NMTVDISPINFO* lptvdi = cast(NMTVDISPINFO*)lParam;
+            //OS.MoveMemory (lptvdi, lParam, NMTVDISPINFO.sizeof);
+            if ((style & SWT.VIRTUAL) !is 0) {
+                /*
+                * Feature in Windows.  When a new tree item is inserted
+                * using TVM_INSERTITEM, a TVN_GETDISPINFO is sent before
+                * TVM_INSERTITEM returns and before the item is added to
+                * the items array.  The fix is to check for null.
+                *
+                * NOTE: This only happens on XP with the version 6.00 of
+                * COMCTL32.DLL.
+                */
+                bool checkVisible = true;
+                /*
+                * When an item is being deleted from a virtual tree, do not
+                * allow the application to provide data for a new item that
+                * becomes visible until the item has been removed from the
+                * items array.  Because arbitrary application code can run
+                * during the callback, the items array might be accessed
+                * in an inconsistent state.  Rather than answering the data
+                * right away, queue a redraw for later.
+                */
+                if (!ignoreShrink) {
+                    if (items !is null && lptvdi.item.lParam !is -1) {
+                        if (items [lptvdi.item.lParam] !is null && items [lptvdi.item.lParam].cached) {
+                            checkVisible = false;
+                        }
+                    }
+                }
+                if (checkVisible) {
+                    if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break;
+                    RECT itemRect;
+                    if (!OS.TreeView_GetItemRect (handle, lptvdi.item.hItem, &itemRect, false)) {
+                        break;
+                    }
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    if (!OS.IntersectRect (&rect, &rect, &itemRect)) break;
+                    if (ignoreShrink) {
+                        OS.InvalidateRect (handle, &rect, true);
+                        break;
+                    }
+                }
+            }
+            if (items is null) break;
+            /*
+            * Bug in Windows.  If the lParam field of TVITEM
+            * is changed during custom draw using TVM_SETITEM,
+            * the lItemlParam field of the NMTVCUSTOMDRAW struct
+            * is not updated until the next custom draw.  The
+            * fix is to query the field from the item instead
+            * of using the struct.
+            */
+            int id = lptvdi.item.lParam;
+            if ((style & SWT.VIRTUAL) !is 0) {
+                if (id is -1) {
+                    TVITEM tvItem;
+                    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+                    tvItem.hItem = lptvdi.item.hItem;
+                    OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
+                    id = tvItem.lParam;
+                }
+            }
+            TreeItem item = _getItem (lptvdi.item.hItem, id);
+            /*
+            * Feature in Windows.  When a new tree item is inserted
+            * using TVM_INSERTITEM, a TVN_GETDISPINFO is sent before
+            * TVM_INSERTITEM returns and before the item is added to
+            * the items array.  The fix is to check for null.
+            *
+            * NOTE: This only happens on XP with the version 6.00 of
+            * COMCTL32.DLL.
+            *
+            * Feature in Windows.  When TVM_DELETEITEM is called with
+            * TVI_ROOT to remove all items from a tree, under certain
+            * circumstances, the tree sends TVN_GETDISPINFO for items
+            * that are about to be disposed.  The fix is to check for
+            * disposed items.
+            */
+            if (item is null) break;
+            if (item.isDisposed ()) break;
+            if (!item.cached) {
+                if ((style & SWT.VIRTUAL) !is 0) {
+                    if (!checkData (item, false)) break;
+                }
+                if (painted) item.cached = true;
+            }
+            int index = 0;
+            if (hwndHeader !is null) {
+                index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+            }
+            if ((lptvdi.item.mask & OS.TVIF_TEXT) !is 0) {
+                String string = null;
+                if (index is 0) {
+                    string = item.text;
+                } else {
+                    String [] strings  = item.strings;
+                    if (strings !is null) string = strings [index];
+                }
+                if (string !is null) {
+                    TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
+                    int byteCount = Math.min (buffer.length, lptvdi.item.cchTextMax - 1) * TCHAR.sizeof;
+                    OS.MoveMemory (lptvdi.item.pszText, buffer.ptr, byteCount);
+                    int st = byteCount/TCHAR.sizeof;
+                    lptvdi.item.pszText[ st .. st+1 ] = 0;
+                    //OS.MoveMemory (lptvdi.pszText + byteCount, new byte [TCHAR.sizeof], TCHAR.sizeof);
+                    lptvdi.item.cchTextMax = Math.min (lptvdi.item.cchTextMax, string.length + 1);
+                }
+            }
+            if ((lptvdi.item.mask & (OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE)) !is 0) {
+                Image image = null;
+                if (index is 0) {
+                    image = item.image;
+                } else {
+                    Image [] images  = item.images;
+                    if (images !is null) image = images [index];
+                }
+                lptvdi.item.iImage = lptvdi.item.iSelectedImage = OS.I_IMAGENONE;
+                if (image !is null) {
+                    lptvdi.item.iImage = lptvdi.item.iSelectedImage = imageIndex (image, index);
+                }
+                if (explorerTheme && OS.IsWindowEnabled (handle)) {
+                    if (findImageControl () !is null) {
+                        lptvdi.item.iImage = lptvdi.item.iSelectedImage = OS.I_IMAGENONE;
+                    }
+                }
+            }
+            //OS.MoveMemory (cast(void*)lParam, lptvdi, NMTVDISPINFO.sizeof);
+            break;
+        }
+        case OS.NM_CUSTOMDRAW: {
+            if (hdr.hwndFrom is hwndHeader) break;
+            if (hooks (SWT.MeasureItem)) {
+                if (hwndHeader is null) createParent ();
+            }
+            if (!customDraw && findImageControl () is null) {
+                if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                    if (sortColumn is null || sortDirection is SWT.NONE) {
+                        break;
+                    }
+                }
+            }
+            NMTVCUSTOMDRAW* nmcd = cast(NMTVCUSTOMDRAW*)lParam;
+            //OS.MoveMemory (nmcd, lParam, NMTVCUSTOMDRAW.sizeof);
+            switch (nmcd.nmcd.dwDrawStage) {
+                case OS.CDDS_PREPAINT: return CDDS_PREPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_ITEMPREPAINT: return CDDS_ITEMPREPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_ITEMPOSTPAINT: return CDDS_ITEMPOSTPAINT (nmcd, wParam, lParam);
+                case OS.CDDS_POSTPAINT: return CDDS_POSTPAINT (nmcd, wParam, lParam);
+                default:
+            }
+            break;
+        }
+        case OS.NM_DBLCLK: {
+            /*
+            * When the user double clicks on a tree item
+            * or a line beside the item, the window proc
+            * for the tree collapses or expand the branch.
+            * When application code associates an action
+            * with double clicking, then the tree expand
+            * is unexpected and unwanted.  The fix is to
+            * avoid the operation by testing to see whether
+            * the mouse was inside a tree item.
+            */
+            if (hooks (SWT.MeasureItem)) return LRESULT.ONE;
+            if (hooks (SWT.DefaultSelection)) {
+                POINT pt;
+                int pos = OS.GetMessagePos ();
+                OS.POINTSTOPOINT (pt, pos);
+                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 && (lpht.flags & OS.TVHT_ONITEM) !is 0) {
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        }
+        /*
+        * Bug in Windows.  On Vista, when TVM_SELECTITEM is called
+        * with TVGN_CARET in order to set the selection, for some
+        * reason, Windows deselects the previous two items that
+        * were selected.  The fix is to stop the selection from
+        * changing on all but the item that is supposed to be
+        * selected.
+        */
+        case OS.TVN_ITEMCHANGINGA:
+        case OS.TVN_ITEMCHANGINGW: {
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if ((style & SWT.MULTI) !is 0) {
+                    if (hSelect !is null) {
+                        NMTVITEMCHANGE* pnm = cast(NMTVITEMCHANGE*)lParam;
+                        //OS.MoveMemory (pnm, lParam, NMTVITEMCHANGE.sizeof);
+                        if (hSelect is pnm.hItem) break;
+                        return LRESULT.ONE;
+                    }
+                }
+            }
+            break;
+        }
+        case OS.TVN_SELCHANGINGA:
+        case OS.TVN_SELCHANGINGW: {
+            if ((style & SWT.MULTI) !is 0) {
+                if (lockSelection) {
+                    /* Save the old selection state for both items */
+                    auto treeView = cast(NMTREEVIEW*)lParam;
+                    TVITEM* tvItem = &treeView.itemOld;
+                    oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
+                    tvItem = &treeView.itemNew;
+                    newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
+                }
+            }
+            if (!ignoreSelect && !ignoreDeselect) {
+                hAnchor = null;
+                if ((style & SWT.MULTI) !is 0) deselectAll ();
+            }
+            break;
+        }
+        case OS.TVN_SELCHANGEDA:
+        case OS.TVN_SELCHANGEDW: {
+            NMTREEVIEW* treeView = null;
+            if ((style & SWT.MULTI) !is 0) {
+                if (lockSelection) {
+                    /* Restore the old selection state of both items */
+                    if (oldSelected) {
+                        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) {
+                        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;
+                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                    }
+                }
+            }
+            if (!ignoreSelect) {
+                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);
+                postEvent (SWT.Selection, event);
+            }
+            updateScrollBar ();
+            break;
+        }
+        case OS.TVN_ITEMEXPANDINGA:
+        case OS.TVN_ITEMEXPANDINGW: {
+            bool runExpanded = false;
+            if ((style & SWT.VIRTUAL) !is 0) style &= ~SWT.DOUBLE_BUFFERED;
+            if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) style &= ~SWT.DOUBLE_BUFFERED;
+            if (findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle)) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            }
+            /*
+            * Bug in Windows.  When TVM_SETINSERTMARK is used to set
+            * an insert mark for a tree and an item is expanded or
+            * collapsed near the insert mark, the tree does not redraw
+            * the insert mark properly.  The fix is to hide and show
+            * the insert mark whenever an item is expanded or collapsed.
+            */
+            if (hInsert !is null) {
+                OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0);
+            }
+            if (!ignoreExpand) {
+                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
+                * being destroyed.  By the time the message is sent,
+                * the item has already been removed from the list of
+                * items.  The fix is to check for null.
+                */
+                if (items is null) break;
+                TreeItem item = _getItem (tvItem.hItem, tvItem.lParam);
+                if (item is null) break;
+                Event event = new Event ();
+                event.item = item;
+                switch (treeView.action) {
+                    case OS.TVE_EXPAND:
+                        /*
+                        * Bug in Windows.  When the numeric keypad asterisk
+                        * key is used to expand every item in the tree, Windows
+                        * sends TVN_ITEMEXPANDING to items in the tree that
+                        * have already been expanded.  The fix is to detect
+                        * that the item is already expanded and ignore the
+                        * notification.
+                        */
+                        if ((tvItem.state & OS.TVIS_EXPANDED) is 0) {
+                            sendEvent (SWT.Expand, event);
+                            if (isDisposed ()) return LRESULT.ZERO;
+                        }
+                        break;
+                    case OS.TVE_COLLAPSE:
+                        sendEvent (SWT.Collapse, event);
+                        if (isDisposed ()) return LRESULT.ZERO;
+                        break;
+                    default:
+                }
+                /*
+                * Bug in Windows.  When all of the items are deleted during
+                * TVN_ITEMEXPANDING, Windows does not send TVN_ITEMEXPANDED.
+                * The fix is to detect this case and run the TVN_ITEMEXPANDED
+                * code in this method.
+                */
+                auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, tvItem.hItem);
+                runExpanded = hFirstItem is null;
+            }
+            if (!runExpanded) break;
+            //FALL THROUGH
+        }
+        case OS.TVN_ITEMEXPANDEDA:
+        case OS.TVN_ITEMEXPANDEDW: {
+            if ((style & SWT.VIRTUAL) !is 0) style |= SWT.DOUBLE_BUFFERED;
+            if (hooks (SWT.EraseItem) || hooks (SWT.PaintItem)) style |= SWT.DOUBLE_BUFFERED;
+            if (findImageControl () !is null && drawCount is 0 /*&& OS.IsWindowVisible (handle)*/) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.InvalidateRect (handle, null, true);
+            }
+            /*
+            * Bug in Windows.  When TVM_SETINSERTMARK is used to set
+            * an insert mark for a tree and an item is expanded or
+            * collapsed near the insert mark, the tree does not redraw
+            * the insert mark properly.  The fix is to hide and show
+            * the insert mark whenever an item is expanded or collapsed.
+            */
+            if (hInsert !is null) {
+                OS.SendMessage (handle, OS.TVM_SETINSERTMARK, insertAfter ? 1 : 0, hInsert);
+            }
+            /*
+            * Bug in Windows.  When a tree item that has an image
+            * with alpha is expanded or collapsed, the area where
+            * the image is drawn is not erased before it is drawn.
+            * This means that the image gets darker each time.
+            * The fix is to redraw the item.
+            */
+            if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
+                if (imageList !is null) {
+                    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;
+                            if (OS.TreeView_GetItemRect (handle, tvItem.hItem, &rect, false)) {
+                                OS.InvalidateRect (handle, &rect, true);
+                            }
+                        }
+                    }
+                }
+            }
+            updateScrollBar ();
+            break;
+        }
+        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: {
+            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;
+                OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, tvItem.hItem);
+                ignoreSelect = ignoreDeselect = false;
+                hSelect = null;
+            }
+            break;
+        }
+        case OS.NM_RECOGNIZEGESTURE: {
+            /*
+            * Feature in Pocket PC.  The tree and table controls detect the tap
+            * and hold gesture by default. They send a GN_CONTEXTMENU message to show
+            * the popup menu.  This default behaviour is unwanted on Pocket PC 2002
+            * when no menu has been set, as it still draws a red circle.  The fix
+            * is to disable this default behaviour when no menu is set by returning
+            * TRUE when receiving the Pocket PC 2002 specific NM_RECOGNIZEGESTURE
+            * message.
+            */
+            if (OS.IsPPC) {
+                bool hasMenu = menu !is null && !menu.isDisposed ();
+                if (!hasMenu && !hooks (SWT.MenuDetect)) return LRESULT.ONE;
+            }
+            break;
+        }
+        case OS.GN_CONTEXTMENU: {
+            if (OS.IsPPC) {
+                bool hasMenu = menu !is null && !menu.isDisposed ();
+                if (hasMenu || hooks (SWT.MenuDetect)) {
+                    NMRGINFO* nmrg = cast(NMRGINFO*)lParam;
+                    //OS.MoveMemory (nmrg, lParam, NMRGINFO.sizeof);
+                    showMenu (nmrg.x, nmrg.y);
+                    gestureCompleted = true;
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        }
+        default:
+    }
+    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 ();
+                default:
+            }
+            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 (SWT.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 (SWT.MeasureItem) || hooks (SWT.EraseItem) || hooks (SWT.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 & SWT.DOUBLE_BUFFERED) is 0) {
+                                int oldStyle = style;
+                                style |= SWT.DOUBLE_BUFFERED;
+                                OS.UpdateWindow (handle);
+                                style = oldStyle;
+                            }
+                        }
+                    }
+                    TreeColumn column = columns [phdn.iItem];
+                    if (column !is null) {
+                        column.updateToolTip (phdn.iItem);
+                        column.sendEvent (SWT.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 (SWT.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 (SWT.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 (SWT.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: {
+            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;
+        }
+        default:
+    }
+    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 = OS.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 (SWT.EraseItem)) {
+                            Event event = sendEraseItemEvent (item, nmcd, index, cellRect);
+                            if (isDisposed () || item.isDisposed ()) break;
+                            if (event.doit) {
+                                drawForeground = (event.detail & SWT.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 & SWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                                    if ((column.style & SWT.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 (SWT.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;
+        }
+        default:
+    }
+    return null;
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TreeColumn.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,767 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TreeColumn;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.TypedListener;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a column in a tree widget.
+ * <p><dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>LEFT, RIGHT, CENTER</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd> Move, Resize, Selection</dd>
+ * </dl>
+ * </p><p>
+ * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
+ * </p><p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ * 
+ * @since 3.1
+ */
+public class TreeColumn : Item {
+    Tree parent;
+    bool resizable, moveable;
+    String toolTipText;
+    int id;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code>) and a style value
+ * describing its behavior and appearance. The item is added
+ * to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Tree parent, int style) {
+    super (parent, checkStyle (style));
+    resizable = true;
+    this.parent = parent;
+    parent.createItem (this, parent.getColumnCount ());
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code>), a style value
+ * describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</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>
+ * 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT#LEFT
+ * @see SWT#RIGHT
+ * @see SWT#CENTER
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Tree parent, int style, int index) {
+    super (parent, checkStyle (style));
+    resizable = true;
+    this.parent = parent;
+    parent.createItem (this, index);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is moved or resized, by sending
+ * it one of the messages defined in the <code>ControlListener</code>
+ * interface.
+ *
+ * @param listener the listener which should be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #removeControlListener
+ */
+public void addControlListener(ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Resize,typedListener);
+    addListener (SWT.Move,typedListener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the control is selected by the user, by sending
+ * it one of the messages defined in the <code>SelectionListener</code>
+ * interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the column header is selected.
+ * <code>widgetDefaultSelected</code> is not called.
+ * </p>
+ *
+ * @param listener the listener which should be notified when the control is selected by the user
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #removeSelectionListener
+ * @see SelectionEvent
+ */
+public void addSelectionListener (SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Selection,typedListener);
+    addListener (SWT.DefaultSelection,typedListener);
+}
+
+static int checkStyle (int style) {
+    return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+override void destroyWidget () {
+    parent.destroyItem (this);
+    releaseHandle ();
+}
+
+/**
+ * Returns a value which describes the position of the
+ * text or image in the receiver. The value will be one of
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
+ *
+ * @return the alignment
+ *
+ * @exception SWTException <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 int getAlignment () {
+    checkWidget ();
+    if ((style & SWT.LEFT) !is 0) return SWT.LEFT;
+    if ((style & SWT.CENTER) !is 0) return SWT.CENTER;
+    if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT;
+    return SWT.LEFT;
+}
+
+/**
+ * Gets the moveable attribute. A column that is
+ * not moveable cannot be reordered by the user
+ * by dragging the header but may be reordered
+ * by the programmer.
+ *
+ * @return the moveable attribute
+ *
+ * @exception SWTException <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 Tree#getColumnOrder()
+ * @see Tree#setColumnOrder(int[])
+ * @see TreeColumn#setMoveable(bool)
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public bool getMoveable () {
+    checkWidget ();
+    return moveable;
+}
+
+override String getNameText () {
+    return getText ();
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tree</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Tree getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Gets the resizable attribute. A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @return the resizable attribute
+ *
+ * @exception SWTException <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 getResizable () {
+    checkWidget ();
+    return resizable;
+}
+
+/**
+ * Returns the receiver's tool tip text, or null if it has
+ * not been set.
+ *
+ * @return the receiver's tool tip text
+ *
+ * @exception SWTException <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.2
+ */
+public String getToolTipText () {
+    checkWidget();
+    return toolTipText;
+}
+
+/**
+ * Gets the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <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 int getWidth () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return 0;
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader is null) return 0;
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_WIDTH;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+    return hdItem.cxy;
+}
+
+/**
+ * Causes the receiver to be resized to its preferred size.
+ * For a composite, this involves computing the preferred size
+ * from its layout, if there is one.
+ *
+ * @exception SWTException <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 pack () {
+    checkWidget ();
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    int columnWidth = 0;
+    auto hwnd = parent.handle;
+    auto hwndHeader = parent.hwndHeader;
+    RECT headerRect;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+    auto hDC = OS.GetDC (hwnd);
+    HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    while (tvItem.hItem !is null) {
+        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) {
+            int itemRight = 0;
+            if (parent.hooks (SWT.MeasureItem)) {
+                Event event = parent.sendMeasureItemEvent (item, index, hDC);
+                if (isDisposed () || parent.isDisposed ()) break;
+                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, itemRight - headerRect.left);
+        }
+        tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, tvItem.hItem);
+    }
+    RECT rect;
+    int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), text, false);
+    OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
+    int headerWidth = rect.right - rect.left + Tree.HEADER_MARGIN;
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) headerWidth += Tree.HEADER_EXTRA;
+    if (image !is null || parent.sortColumn is this) {
+        Image headerImage = null;
+        if (parent.sortColumn is this && parent.sortDirection !is SWT.NONE) {
+            if (OS.COMCTL32_MAJOR < 6) {
+                headerImage = display.getSortImage (parent.sortDirection);
+            } else {
+                headerWidth += Tree.SORT_WIDTH;
+            }
+        } else {
+            headerImage = image;
+        }
+        if (headerImage !is null) {
+            Rectangle bounds = headerImage.getBounds ();
+            headerWidth += bounds.width;
+        }
+        int margin = 0;
+        if (hwndHeader !is null && OS.COMCTL32_VERSION >= OS.VERSION (5, 80)) {
+            margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
+        } else {
+            margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3;
+        }
+        headerWidth += margin * 2;
+    }
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (hwnd, hDC);
+    int gridWidth = parent.linesVisible ? Tree.GRID_WIDTH : 0;
+    setWidth (Math.max (headerWidth, columnWidth + gridWidth));
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    parent = null;
+}
+
+override void releaseParent () {
+    super.releaseParent ();
+    if (parent.sortColumn is this) {
+        parent.sortColumn = null;
+    }
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is moved or resized.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 ControlListener
+ * @see #addControlListener
+ */
+public void removeControlListener (ControlListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Move, listener);
+    eventTable.unhook (SWT.Resize, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the control is selected by the user.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SelectionListener
+ * @see #addSelectionListener
+ */
+public void removeSelectionListener(SelectionListener listener) {
+    checkWidget ();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Selection, listener);
+    eventTable.unhook (SWT.DefaultSelection,listener);
+}
+
+/**
+ * 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 SWTException <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 setAlignment (int alignment) {
+    checkWidget ();
+    if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return;
+    int index = parent.indexOf (this);
+    if (index is -1 || index is 0) return;
+    style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader is null) return;
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_FORMAT;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+    hdItem.fmt &= ~OS.HDF_JUSTIFYMASK;
+    if ((style & SWT.LEFT) is SWT.LEFT) hdItem.fmt |= OS.HDF_LEFT;
+    if ((style & SWT.CENTER) is SWT.CENTER) hdItem.fmt |= OS.HDF_CENTER;
+    if ((style & SWT.RIGHT) is SWT.RIGHT) hdItem.fmt |= OS.HDF_RIGHT;
+    OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+    if (index !is 0) {
+        auto hwnd = parent.handle;
+        parent.forceResize ();
+        RECT rect, headerRect;
+        OS.GetClientRect (hwnd, &rect);
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+        rect.left = headerRect.left;
+        rect.right = headerRect.right;
+        OS.InvalidateRect (hwnd, &rect, true);
+    }
+}
+
+override public void setImage (Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    super.setImage (image);
+    if (parent.sortColumn !is this || parent.sortDirection !is SWT.NONE) {
+        setImage (image, false, false);
+    }
+}
+
+void setImage (Image image, bool sort, bool right) {
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader is null) return;
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE | OS.HDI_BITMAP;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+    hdItem.fmt &= ~OS.HDF_BITMAP_ON_RIGHT;
+    if (image !is null) {
+        if (sort) {
+            hdItem.mask &= ~OS.HDI_IMAGE;
+            hdItem.fmt &= ~OS.HDF_IMAGE;
+            hdItem.fmt |= OS.HDF_BITMAP;
+            hdItem.hbm = image.handle;
+        } else {
+            hdItem.mask &= ~OS.HDI_BITMAP;
+            hdItem.fmt &= ~OS.HDF_BITMAP;
+            hdItem.fmt |= OS.HDF_IMAGE;
+            hdItem.iImage = parent.imageIndexHeader (image);
+        }
+        if (right) hdItem.fmt |= OS.HDF_BITMAP_ON_RIGHT;
+    } else {
+        hdItem.mask &= ~(OS.HDI_IMAGE | OS.HDI_BITMAP);
+        hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_BITMAP);
+    }
+    OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+}
+
+/**
+ * Sets the moveable attribute.  A column that is
+ * moveable can be reordered by the user by dragging
+ * the header. A column that is not moveable cannot be
+ * dragged by the user but may be reordered
+ * by the programmer.
+ *
+ * @param moveable the moveable attribute
+ *
+ * @exception SWTException <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 Tree#setColumnOrder(int[])
+ * @see Tree#getColumnOrder()
+ * @see TreeColumn#getMoveable()
+ * @see SWT#Move
+ *
+ * @since 3.2
+ */
+public void setMoveable (bool moveable) {
+    checkWidget ();
+    this.moveable = moveable;
+}
+
+/**
+ * Sets the resizable attribute.  A column that is
+ * not resizable cannot be dragged by the user but
+ * may be resized by the programmer.
+ *
+ * @param resizable the resize attribute
+ *
+ * @exception SWTException <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 setResizable (bool resizable) {
+    checkWidget ();
+    this.resizable = resizable;
+}
+
+void setSortDirection (int direction) {
+    if (OS.COMCTL32_MAJOR >= 6) {
+        auto hwndHeader = parent.hwndHeader;
+        if (hwndHeader !is null) {
+            int index = parent.indexOf (this);
+            if (index is -1) return;
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            switch (direction) {
+                case SWT.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 SWT.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 SWT.NONE:
+                    hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
+                    if (image !is null) {
+                        hdItem.fmt |= OS.HDF_IMAGE;
+                        hdItem.iImage = parent.imageIndexHeader (image);
+                    } else {
+                        hdItem.fmt &= ~OS.HDF_IMAGE;
+                        hdItem.mask &= ~OS.HDI_IMAGE;
+                    }
+                    break;
+                default:
+            }
+            OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                auto hwnd = parent.handle;
+                parent.forceResize ();
+                RECT rect, headerRect;
+                OS.GetClientRect (hwnd, &rect);
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+                rect.left = headerRect.left;
+                rect.right = headerRect.right;
+                OS.InvalidateRect (hwnd, &rect, true);
+            }
+        }
+    } else {
+        switch (direction) {
+            case SWT.UP:
+            case SWT.DOWN:
+                setImage (display.getSortImage (direction), true, true);
+                break;
+            case SWT.NONE:
+                setImage (image, false, false);
+                break;
+            default:
+        }
+    }
+}
+
+override public void setText (String string) {
+    checkWidget ();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (string.equals (text)) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    super.setText (string);
+    /*
+    * Bug in Windows.  When a column header contains a
+    * mnemonic character, Windows does not measure the
+    * text properly.  This causes '...' to always appear
+    * at the end of the text.  The fix is to remove
+    * mnemonic characters and replace doubled mnemonics
+    * with spaces.
+    */
+    auto hHeap = OS.GetProcessHeap ();
+    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);
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader is null) return;
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_TEXT;
+    hdItem.pszText = pszText;
+    int result = OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+    if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+    if (result is 0) error (SWT.ERROR_CANNOT_SET_TEXT);
+}
+
+/**
+ * Sets the receiver's tool tip text to the argument, which
+ * may be null indicating that no tool tip text should be shown.
+ *
+ * @param string the new tool tip text (or null)
+ *
+ * @exception SWTException <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.2
+ */
+public void setToolTipText (String string) {
+    checkWidget();
+    toolTipText = string;
+    auto hwndHeaderToolTip = parent.headerToolTipHandle;
+    if (hwndHeaderToolTip is null) {
+        parent.createHeaderToolTips ();
+        parent.updateHeaderToolTips ();
+    }
+}
+
+/**
+ * Sets the width of the receiver.
+ *
+ * @param width the new width
+ *
+ * @exception SWTException <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 setWidth (int width) {
+    checkWidget ();
+    if (width < 0) return;
+    int index = parent.indexOf (this);
+    if (index is -1) return;
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader is null) return;
+    HDITEM hdItem;
+    hdItem.mask = OS.HDI_WIDTH;
+    hdItem.cxy = width;
+    OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
+    RECT headerRect;
+    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+    parent.forceResize ();
+    auto hwnd = parent.handle;
+    RECT rect;
+    OS.GetClientRect (hwnd, &rect);
+    rect.left = headerRect.left;
+    OS.InvalidateRect (hwnd, &rect, true);
+    parent.setScrollWidth ();
+}
+
+void updateToolTip (int index) {
+    auto hwndHeaderToolTip = parent.headerToolTipHandle;
+    if (hwndHeaderToolTip !is null) {
+        auto hwndHeader = parent.hwndHeader;
+        RECT rect;
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &rect) !is 0) {
+            TOOLINFO lpti;
+            lpti.cbSize = TOOLINFO.sizeof;
+            lpti.hwnd = hwndHeader;
+            lpti.uId = id;
+            lpti.rect.left = rect.left;
+            lpti.rect.top = rect.top;
+            lpti.rect.right = rect.right;
+            lpti.rect.bottom = rect.bottom;
+            OS.SendMessage (hwndHeaderToolTip, OS.TTM_NEWTOOLRECT, 0, cast(int) &lpti);
+        }
+    }
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TreeItem.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,1832 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TreeItem;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.win32.OS;
+
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Event;
+
+import java.lang.all;
+
+/**
+ * Instances of this class represent a selectable user interface object
+ * that represents a hierarchy of tree items in a tree widget.
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ * </p>
+ *
+ * @see <a href="http://www.eclipse.org/swt/snippets/#tree">Tree, TreeItem, TreeColumn snippets</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public class TreeItem : Item {
+    /**
+     * the handle to the OS resource
+     * (Warning: This field is platform dependent)
+     * <p>
+     * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+     * public API. It is marked public only so that it can be shared
+     * within the packages provided by SWT. It is not available on all
+     * platforms and should never be accessed from application code.
+     * </p>
+     */
+    public HANDLE handle;
+    Tree parent;
+    String [] strings;
+    Image [] images;
+    Font font;
+    Font [] cellFont;
+    bool cached;
+    int background = -1, foreground = -1;
+    int [] cellBackground, cellForeground;
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Tree parent, int style) {
+    this (parent, style, cast(HANDLE)OS.TVGN_ROOT, cast(HANDLE)OS.TVI_LAST, null);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a tree 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (Tree parent, int style, int index) {
+    this (parent, style, cast(HANDLE) OS.TVGN_ROOT, findPrevious (parent, index), null);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>)
+ * and a style value describing its behavior and appearance.
+ * The item is added to the end of the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parentItem a tree control which will be the parent of the new instance (cannot be null)
+ * @param style the style of control to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (TreeItem parentItem, int style) {
+    this (checkNull (parentItem).parent, style, parentItem.handle, cast(HANDLE)OS.TVI_LAST, null);
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * (which must be a <code>Tree</code> or a <code>TreeItem</code>),
+ * a style value describing its behavior and appearance, and the index
+ * at which to place it in the items maintained by its parent.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parentItem a tree 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
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see Widget#checkSubclass
+ * @see Widget#getStyle
+ */
+public this (TreeItem parentItem, int style, int index) {
+    this (checkNull (parentItem).parent, style, parentItem.handle, findPrevious (parentItem, index), null);
+}
+
+this (Tree parent, int style, HANDLE hParent, HANDLE hInsertAfter, HANDLE hItem) {
+    super (parent, style);
+    this.parent = parent;
+    parent.createItem (this, hParent, hInsertAfter, hItem);
+}
+
+static TreeItem checkNull (TreeItem item) {
+    if (item is null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+    return item;
+}
+
+static HANDLE findPrevious (Tree parent, int index) {
+    if (parent is null) return null;
+    if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
+    if (index is 0) return cast(HANDLE) OS.TVI_FIRST;
+    auto hwnd = parent.handle;
+    HANDLE hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    HANDLE hItem = parent.findItem (hFirstItem, index - 1);
+    if (hItem is null) SWT.error (SWT.ERROR_INVALID_RANGE);
+    return hItem;
+}
+
+static HANDLE findPrevious (TreeItem parentItem, int index) {
+    if (parentItem is null) return null;
+    if (index < 0) SWT.error (SWT.ERROR_INVALID_RANGE);
+    if (index is 0) return cast(HANDLE) OS.TVI_FIRST;
+    Tree parent = parentItem.parent;
+    auto hwnd = parent.handle;
+    auto hParent = parentItem.handle;
+    HANDLE hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent);
+    HANDLE hItem = parent.findItem (hFirstItem, index - 1);
+    if (hItem is null) SWT.error (SWT.ERROR_INVALID_RANGE);
+    return hItem;
+}
+
+override protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+void clear () {
+    text = "";
+    image = null;
+    strings = null;
+    images = null;
+    if ((parent.style & SWT.CHECK) !is 0) {
+        auto hwnd = parent.handle;
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+        tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+        tvItem.state = 1 << 12;
+        tvItem.hItem = cast(HTREEITEM)handle;
+        OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    }
+    background = foreground = -1;
+    font = null;
+    cellBackground = cellForeground = null;
+    cellFont = null;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = false;
+}
+
+/**
+ * Clears the item at the given zero-relative index in the receiver.
+ * The text, icon and other attributes of the item are set to the default
+ * value.  If the tree was created with the <code>SWT.VIRTUAL</code> style,
+ * these attributes are requested again as needed.
+ *
+ * @param index the index of the item to clear
+ * @param all <code>true</code> if all child items of the indexed item should be
+ * cleared recursively, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clear (int index, bool all) {
+    checkWidget ();
+    auto hwnd = parent.handle;
+    HANDLE hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    hItem = parent.findItem (hItem, index);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    parent.clear (hItem, &tvItem);
+    if (all) {
+        hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+        parent.clearAll (hItem, &tvItem, all);
+    }
+}
+
+/**
+ * Clears all the items in the receiver. The text, icon and other
+ * attributes of the items are set to their default values. If the
+ * tree was created with the <code>SWT.VIRTUAL</code> style, these
+ * attributes are requested again as needed.
+ *
+ * @param all <code>true</code> if all child items should be cleared
+ * recursively, and <code>false</code> otherwise
+ *
+ * @exception SWTException <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 SWT#VIRTUAL
+ * @see SWT#SetData
+ *
+ * @since 3.2
+ */
+public void clearAll (bool all) {
+    checkWidget ();
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    if (hItem is null) return;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    parent.clearAll (hItem, &tvItem, all);
+}
+
+override void destroyWidget () {
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    parent.releaseItem (handle, &tvItem, false);
+    parent.destroyItem (this, handle);
+    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.
+ *
+ * @return the background color
+ *
+ * @exception SWTException <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 2.0
+ *
+ */
+public Color getBackground () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (background is -1) return parent.getBackground ();
+    return Color.win32_new (display, background);
+}
+
+/**
+ * Returns the background color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the background color
+ *
+ * @exception SWTException <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.1
+ */
+public Color getBackground (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return getBackground ();
+    int pixel = cellBackground !is null ? cellBackground [index] : -1;
+    return pixel is -1 ? getBackground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception SWTException <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 Rectangle getBounds () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    RECT* rect = getBounds (0, true, false, false);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent at a column in the tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding column rectangle
+ *
+ * @exception SWTException <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.1
+ */
+public Rectangle getBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    RECT* rect = getBounds (index, true, true, true);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+RECT* getBounds (int index, bool getText, bool getImage, bool fullText) {
+    return getBounds (index, getText, getImage, fullText, false, true, null);
+}
+
+//TODO - take into account grid (add bool arg) to damage less during redraw
+RECT* getBounds (int index, bool getText, bool getImage, bool fullText, bool fullImage, bool clip, HDC hDC) {
+    if (!getText && !getImage) return new RECT();
+    auto hwnd = parent.handle;
+    if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+        tvItem.hItem = cast(HTREEITEM)handle;
+        tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+        parent.ignoreCustomDraw = true;
+        OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+        parent.ignoreCustomDraw = false;
+    }
+    bool firstColumn = index is 0;
+    int columnCount = 0;
+    auto hwndHeader = parent.hwndHeader;
+    if (hwndHeader !is null) {
+        columnCount = parent.columnCount;
+        firstColumn = index is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+    }
+    RECT* rect = new RECT();
+    if (firstColumn) {
+        bool full = columnCount is 0 && getText && getImage && fullText && fullImage;
+        if (!OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, rect, !full)) {
+            return new RECT();
+        }
+        if (getImage && !fullImage) {
+            if (OS.SendMessage (hwnd, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) !is 0) {
+                Point size = parent.getImageSize ();
+                rect.left -= size.x + Tree.INSET;
+                if (!getText) rect.right = rect.left + size.x;
+            } else {
+                if (!getText) rect.right = rect.left;
+            }
+        }
+        if (fullText || fullImage || clip) {
+            if (hwndHeader !is null) {
+                RECT* headerRect = new RECT();
+                if (columnCount !is 0) {
+                    if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) headerRect) is 0) {
+                        return new RECT();
+                    }
+                } else {
+                    headerRect.right = parent.scrollWidth;
+                    if (headerRect.right is 0) headerRect = rect;
+                }
+                if (fullText && clip) rect.right = headerRect.right;
+                if (fullImage) rect.left = headerRect.left;
+                if (clip && headerRect.right < rect.right) {
+                    rect.right = headerRect.right;
+                }
+            }
+        }
+    } else {
+        if (!(0 <= index && index < columnCount)) return new RECT();
+        RECT* headerRect = new RECT();
+        if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) headerRect) is 0) {
+            return new RECT();
+        }
+        if (!OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, rect, false)) {
+            return new RECT();
+        }
+        rect.left = headerRect.left;
+        if (fullText && getImage && clip) {
+            rect.right = headerRect.right;
+        } else {
+            rect.right = headerRect.left;
+            Image image = null;
+            if (index is 0) {
+                image = this.image;
+            } else {
+                if (images !is null) image = images [index];
+            }
+            if (image !is null) {
+                Point size = parent.getImageSize ();
+                rect.right += size.x;
+            }
+            if (getText) {
+                if (fullText && clip) {
+                    rect.left = rect.right + Tree.INSET;
+                    rect.right = headerRect.right;
+                } else {
+                    String string = index is 0 ? text : strings !is null ? strings [index] : null;
+                    if (string !is null) {
+                        RECT* textRect = new RECT();
+                        TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), string, false);
+                        int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_CALCRECT;
+                        auto hNewDC = hDC;
+                        HFONT hFont;
+                        if (hDC is null) {
+                            hNewDC = OS.GetDC (hwnd);
+                            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);
+                        }
+                        OS.DrawText (hNewDC, buffer.ptr, buffer.length, textRect, flags);
+                        if (hDC is null) {
+                            OS.SelectObject (hNewDC, hFont);
+                            OS.ReleaseDC (hwnd, hNewDC);
+                        }
+                        if (getImage) {
+                            rect.right += textRect.right - textRect.left + Tree.INSET * 3;
+                        } else {
+                            rect.left = rect.right + Tree.INSET;
+                            rect.right = rect.left + (textRect.right - textRect.left) + Tree.INSET;
+                        }
+                    }
+                }
+            }
+            if (clip && headerRect.right < rect.right) {
+                rect.right = headerRect.right;
+            }
+        }
+    }
+    int gridWidth = parent.linesVisible && columnCount !is 0 ? Tree.GRID_WIDTH : 0;
+    if (getText || !getImage) {
+        rect.right = Math.max (rect.left, rect.right - gridWidth);
+    }
+    rect.bottom = Math.max (rect.top, rect.bottom - gridWidth);
+    return rect;
+}
+
+/**
+ * Returns <code>true</code> if the receiver is checked,
+ * and false otherwise.  When the parent does not have
+ * the <code>CHECK style, return false.
+ * <p>
+ *
+ * @return the checked state
+ *
+ * @exception SWTException <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 getChecked () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if ((parent.style & SWT.CHECK) is 0) return false;
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+    tvItem.hItem = cast(HTREEITEM)handle;
+    int result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+    return (result !is 0) && (((tvItem.state >> 12) & 1) is 0);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is expanded,
+ * and false otherwise.
+ * <p>
+ *
+ * @return the expanded state
+ *
+ * @exception SWTException <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 getExpanded () {
+    checkWidget ();
+    auto hwnd = parent.handle;
+    int state = 0;
+    static if (OS.IsWinCE) {
+        TVITEM tvItem;
+        tvItem.hItem = handle;
+        tvItem.mask = OS.TVIF_STATE;
+        OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+        state = tvItem.state;
+    } 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.
+        */
+        state = OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
+    }
+    return (state & OS.TVIS_EXPANDED) !is 0;
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information for this item.
+ *
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.0
+ */
+public Font getFont () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return font !is null ? font : parent.getFont ();
+}
+
+/**
+ * Returns the font that the receiver will use to paint textual information
+ * for the specified cell in this item.
+ *
+ * @param index the column index
+ * @return the receiver's font
+ *
+ * @exception SWTException <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.1
+ */
+public Font getFont (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count -1) return getFont ();
+    if (cellFont is null || cellFont [index] is null) return getFont ();
+    return cellFont [index];
+}
+
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ *
+ * @exception SWTException <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 2.0
+ *
+ */
+public Color getForeground () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (foreground is -1) return parent.getForeground ();
+    return Color.win32_new (display, foreground);
+}
+
+/**
+ *
+ * Returns the foreground color at the given column index in the receiver.
+ *
+ * @param index the column index
+ * @return the foreground color
+ *
+ * @exception SWTException <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.1
+ */
+public Color getForeground (int index) {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count -1) return getForeground ();
+    int pixel = cellForeground !is null ? cellForeground [index] : -1;
+    return pixel is -1 ? getForeground () : Color.win32_new (display, pixel);
+}
+
+/**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the parent does not have
+ * the <code>CHECK style, return false.
+ * <p>
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception SWTException <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 (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if ((parent.style & SWT.CHECK) is 0) return false;
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+    tvItem.hItem = cast(HTREEITEM)handle;
+    int result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+    return (result !is 0) && ((tvItem.state >> 12) > 2);
+}
+
+/**
+ * Returns the item at the given, zero-relative index in the
+ * receiver. Throws an exception if the index is out of range.
+ *
+ * @param index the index of the item to return
+ * @return the item at the given index
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public TreeItem getItem (int index) {
+    checkWidget ();
+    if (index < 0) error (SWT.ERROR_INVALID_RANGE);
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    auto hwnd = parent.handle;
+    auto hFirstItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    if (hFirstItem is null) error (SWT.ERROR_INVALID_RANGE);
+    auto hItem = parent.findItem (hFirstItem, index);
+    if (hItem is null) error (SWT.ERROR_INVALID_RANGE);
+    return parent._getItem (hItem);
+}
+
+/**
+ * Returns the number of items contained in the receiver
+ * that are direct item children of the receiver.
+ *
+ * @return the number of items
+ *
+ * @exception SWTException <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 int getItemCount () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    if (hItem is null) return 0;
+    return parent.getItemCount (hItem);
+}
+
+/**
+ * Returns a (possibly empty) array of <code>TreeItem</code>s which
+ * are the direct item children of the receiver.
+ * <p>
+ * Note: This is not the actual structure used by the receiver
+ * to maintain its list of items, so modifying the array will
+ * not affect the receiver.
+ * </p>
+ *
+ * @return the receiver's items
+ *
+ * @exception SWTException <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 TreeItem [] getItems () {
+    checkWidget ();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    if (hItem is null) return null;
+    return parent.getItems (hItem);
+}
+
+override public Image getImage () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return super.getImage ();
+}
+
+/**
+ * Returns the image stored at the given column index in the receiver,
+ * or null if the image has not been set or if the column does not exist.
+ *
+ * @param index the column index
+ * @return the image stored at the given column index in the receiver
+ *
+ * @exception SWTException <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.1
+ */
+public Image getImage (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (index is 0) return getImage ();
+    if (images !is null) {
+        if (0 <= index && index < images.length) return images [index];
+    }
+    return null;
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of an image at a column in the
+ * tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding image rectangle
+ *
+ * @exception SWTException <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.1
+ */
+public Rectangle getImageBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    RECT* rect = getBounds (index, false, true, false);
+    int width = rect.right - rect.left, height = rect.bottom - rect.top;
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Returns the receiver's parent, which must be a <code>Tree</code>.
+ *
+ * @return the receiver's parent
+ *
+ * @exception SWTException <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 Tree getParent () {
+    checkWidget ();
+    return parent;
+}
+
+/**
+ * Returns the receiver's parent item, which must be a
+ * <code>TreeItem</code> or null when the receiver is a
+ * root.
+ *
+ * @return the receiver's parent item
+ *
+ * @exception SWTException <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 TreeItem getParentItem () {
+    checkWidget ();
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, handle);
+    return hItem !is null ? parent._getItem (hItem) : null;
+}
+
+override public String getText () {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    return super.getText ();
+}
+
+/**
+ * Returns the text stored at the given column index in the receiver,
+ * or empty string if the text has not been set.
+ *
+ * @param index the column index
+ * @return the text stored at the given column index in the receiver
+ *
+ * @exception SWTException <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.1
+ */
+public String getText (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    if (index is 0) return getText ();
+    if (strings !is null) {
+        if (0 <= index && index < strings.length) {
+            String string = strings [index];
+            return string !is null ? string : "";
+        }
+    }
+    return "";
+}
+
+/**
+ * Returns a rectangle describing the size and location
+ * relative to its parent of the text at a column in the
+ * tree.
+ *
+ * @param index the index that specifies the column
+ * @return the receiver's bounding text rectangle
+ *
+ * @exception SWTException <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 Rectangle getTextBounds (int index) {
+    checkWidget();
+    if (!parent.checkData (this, true)) error (SWT.ERROR_WIDGET_DISPOSED);
+    RECT* rect = getBounds (index, true, false, true);
+    if (index is 0) rect.left += Tree.INSET - 1;
+    rect.left = Math.min (rect.left, rect.right);
+    rect.right = rect.right - Tree.INSET;
+    int width = Math.max (0, rect.right - rect.left);
+    int height = Math.max (0, rect.bottom - rect.top);
+    return new Rectangle (rect.left, rect.top, width, height);
+}
+
+/**
+ * Searches the receiver's list starting at the first item
+ * (index 0) until an item is found that is equal to the
+ * argument, and returns the index of that item. If no item
+ * is found, returns -1.
+ *
+ * @param item the search item
+ * @return the index of the item
+ *
+ * @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 SWTException <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.1
+ */
+public int indexOf (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    return hItem is null ? -1 : parent.findIndex (hItem, item.handle);
+}
+
+void redraw () {
+    if (parent.currentItem is this || parent.drawCount !is 0) return;
+    auto hwnd = parent.handle;
+    if (!OS.IsWindowVisible (hwnd)) return;
+    /*
+    * When there are no columns and the tree is not
+    * full selection, redraw only the text.  This is
+    * an optimization to reduce flashing.
+    */
+    bool full = (parent.style & (SWT.FULL_SELECTION | SWT.VIRTUAL)) !is 0;
+    if (!full) {
+        full = parent.columnCount !is 0;
+        if (!full) {
+            if (parent.hooks (SWT.EraseItem) || parent.hooks (SWT.PaintItem)) {
+                full = true;
+            }
+        }
+    }
+    RECT rect;
+    if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, !full)) {
+        OS.InvalidateRect (hwnd, &rect, true);
+    }
+}
+
+void redraw (int column, bool drawText, bool drawImage) {
+    if (parent.currentItem is this || parent.drawCount !is 0) return;
+    auto hwnd = parent.handle;
+    if (!OS.IsWindowVisible (hwnd)) return;
+    bool fullImage = column is 0 && drawText && drawImage;
+    RECT* rect = getBounds (column, drawText, drawImage, true, fullImage, true, null);
+    OS.InvalidateRect (hwnd, rect, true);
+}
+
+override void releaseChildren (bool destroy) {
+    if (destroy) {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        parent.releaseItems (handle, &tvItem);
+    }
+    super.releaseChildren (destroy);
+}
+
+override void releaseHandle () {
+    super.releaseHandle ();
+    handle = null;
+    parent = null;
+}
+
+override void releaseWidget () {
+    super.releaseWidget ();
+    strings = null;
+    images = null;
+    cellBackground = cellForeground = null;
+    cellFont = null;
+}
+
+/**
+ * Removes all of the items from the receiver.
+ * <p>
+ * @exception SWTException <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.1
+ */
+public void removeAll () {
+    checkWidget ();
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, cast(int)handle);
+    while (tvItem.hItem !is null) {
+        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 && !item.isDisposed ()) {
+            item.dispose ();
+        } else {
+            parent.releaseItem (tvItem.hItem, &tvItem, false);
+            parent.destroyItem (null, tvItem.hItem);
+        }
+        tvItem.hItem = cast(HTREEITEM) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, cast(int)handle);
+    }
+}
+
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ *
+ */
+public void setBackground (Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int pixel = -1;
+    if (color !is null) {
+        parent.customDraw = true;
+        pixel = color.handle;
+    }
+    if (background is pixel) return;
+    background = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw ();
+}
+
+/**
+ * Sets the background color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.1
+ *
+ */
+public void setBackground (int index, Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    int pixel = -1;
+    if (color !is null) {
+        parent.customDraw = true;
+        pixel = color.handle;
+    }
+    if (cellBackground is null) {
+        cellBackground = new int [count];
+        for (int i = 0; i < count; i++) {
+            cellBackground [i] = -1;
+        }
+    }
+    if (cellBackground [index] is pixel) return;
+    cellBackground [index] = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw (index, true, true);
+}
+
+/**
+ * Sets the checked state of the receiver.
+ * <p>
+ *
+ * @param checked the new checked state
+ *
+ * @exception SWTException <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 setChecked (bool checked) {
+    checkWidget ();
+    if ((parent.style & SWT.CHECK) is 0) return;
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+    tvItem.hItem = cast(HTREEITEM)handle;
+    OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+    int state = tvItem.state >> 12;
+    if (checked) {
+        if ((state & 0x1) !is 0) state++;
+    } else {
+        if ((state & 0x1) is 0) --state;
+    }
+    state <<= 12;
+    if (tvItem.state is state) return;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    tvItem.state = state;
+    OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    /*
+    * Bug in Windows.  When TVM_SETITEM is used to set
+    * the state image of an item inside TVN_GETDISPINFO,
+    * the new state is not redrawn.  The fix is to force
+    * a redraw.
+    */
+    if ((parent.style & SWT.VIRTUAL) !is 0) {
+        if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
+            RECT rect;
+            if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, false)) {
+                OS.InvalidateRect (hwnd, &rect, true);
+            }
+        }
+    }
+}
+
+/**
+ * Sets the expanded state of the receiver.
+ * <p>
+ *
+ * @param expanded the new expanded state
+ *
+ * @exception SWTException <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 setExpanded (bool expanded) {
+    checkWidget ();
+
+    /* Do nothing when the item is a leaf or already expanded */
+    auto hwnd = parent.handle;
+    if (OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle) is 0) {
+        return;
+    }
+    int state = 0;
+    static if (OS.IsWinCE) {
+        TVITEM tvItem;
+        tvItem.hItem = handle;
+        tvItem.mask = OS.TVIF_STATE;
+        OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+        state = tvItem.state;
+    } 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.
+        */
+        state = OS.SendMessage (hwnd, OS.TVM_GETITEMSTATE, handle, OS.TVIS_EXPANDED);
+    }
+    if (((state & OS.TVIS_EXPANDED) !is 0) is expanded) return;
+
+    /*
+    * Feature in Windows.  When TVM_EXPAND is used to expand
+    * an item, the widget scrolls to show the item and the
+    * newly expanded items.  While not strictly incorrect,
+    * this means that application code that expands tree items
+    * in a background thread can scroll the widget while the
+    * user is interacting with it.  The fix is to remember
+    * the top item and the bounds of every tree item, turn
+    * redraw off, expand the item, scroll back to the top
+    * item.  If none of the rectangles have moved, then
+    * it is safe to turn redraw back on without redrawing
+    * the control.
+    */
+    RECT oldRect;
+    RECT [] rects = null;
+    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 ();
+        oldInfo.cbSize = SCROLLINFO.sizeof;
+        oldInfo.fMask = OS.SIF_ALL;
+        if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) {
+            oldInfo = null;
+        }
+        if (parent.drawCount is 0 && OS.IsWindowVisible (hwnd)) {
+            bool noAnimate = true;
+            count = OS.SendMessage (hwnd, OS.TVM_GETVISIBLECOUNT, 0, 0);
+            rects = new RECT [count + 1];
+            HANDLE hItem = hTopItem;
+            int index = 0;
+            while (hItem !is null && (noAnimate || hItem !is handle) && index < count) {
+                RECT rect;
+                if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hItem, &rect, true)) {
+                    rects [index++] = rect;
+                }
+                hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, cast(int) &hItem);
+            }
+            if (noAnimate || hItem !is handle) {
+                redraw = true;
+                count = index;
+                hBottomItem = hItem;
+                //oldRect = new RECT ();
+                OS.GetClientRect (hwnd, &oldRect);
+                auto topHandle = parent.topHandle ();
+                OS.UpdateWindow (topHandle);
+                OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
+                if (hwnd !is topHandle) {
+                    OS.UpdateWindow (hwnd);
+                    OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 0, 0);
+                }
+                /*
+                * This code is intentionally commented.
+                */
+//              OS.SendMessage (hwnd, OS.WM_SETREDRAW, 0, 0);
+            }
+        }
+    }
+
+    /*
+    * Feature in Windows.  When the user collapses the root
+    * of a subtree that has the focus item, Windows moves
+    * the selection to the root of the subtree and issues
+    * a TVN_SELCHANGED to inform the programmer that the
+    * selection has changed.  When the programmer collapses
+    * the same subtree using TVM_EXPAND, Windows does not
+    * send the selection changed notification.  This is not
+    * strictly wrong but is inconsistent.  The fix is to
+    * check whether the selection has changed and issue
+    * the event.
+    */
+    auto hOldItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+
+    /* Expand or collapse the item */
+    parent.ignoreExpand = true;
+    OS.SendMessage (hwnd, OS.TVM_EXPAND, expanded ? OS.TVE_EXPAND : OS.TVE_COLLAPSE, handle);
+    parent.ignoreExpand = false;
+
+    /* Scroll back to the top item */
+    if (noScroll && hTopItem !is null) {
+        bool collapsed = false;
+        if (!expanded) {
+            RECT rect;
+            while (hTopItem !is null && !OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hTopItem, &rect, false)) {
+                hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
+                collapsed = true;
+            }
+        }
+        bool scrolled = true;
+        if (hTopItem !is null) {
+            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 && 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 /*long*/ lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos);
+                    OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0);
+                }
+            }
+        }
+        if (redraw) {
+            bool fixScroll = false;
+            if (!collapsed && !scrolled) {
+                RECT newRect;
+                OS.GetClientRect (hwnd, &newRect);
+                if (OS.EqualRect (&oldRect, &newRect)) {
+                    HANDLE hItem = hTopItem;
+                    int index = 0;
+                    while (hItem !is null && index < count) {
+                        RECT rect;
+                        if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hItem, &rect, true)) {
+                            if (!OS.EqualRect (&rect, & rects [index])) {
+                                break;
+                            }
+                        }
+                        hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
+                        index++;
+                    }
+                    fixScroll = index is count && hItem is hBottomItem;
+                }
+            }
+            auto topHandle = parent.topHandle ();
+            OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0);
+            if (hwnd !is topHandle) {
+                OS.DefWindowProc (hwnd, OS.WM_SETREDRAW, 1, 0);
+            }
+            /*
+            * This code is intentionally commented.
+            */
+//          OS.SendMessage (hwnd, OS.WM_SETREDRAW, 1, 0);
+            if (fixScroll) {
+                parent.updateScrollBar ();
+                SCROLLINFO info;
+                info.cbSize = SCROLLINFO.sizeof;
+                info.fMask = OS.SIF_ALL;
+                if (OS.GetScrollInfo (hwnd, OS.SB_VERT, &info)) {
+                    OS.SetScrollInfo (hwnd, OS.SB_VERT, &info, true);
+                }
+                if (handle is hBottomItem) {
+                    RECT rect;
+                    if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)hBottomItem, &rect, false)) {
+                        OS.InvalidateRect (hwnd, &rect, true);
+                    }
+                }
+            } else {
+                static if (OS.IsWinCE) {
+                    OS.InvalidateRect (topHandle, null, true);
+                    if (hwnd !is topHandle) OS.InvalidateRect (hwnd, null, true);
+                } else {
+                    int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                    OS.RedrawWindow (topHandle, null, null, flags);
+                }
+            }
+        }
+    }
+
+    /* Check for a selection event */
+    auto hNewItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+    if (hNewItem !is hOldItem) {
+        Event event = new Event ();
+        if (hNewItem !is null) {
+            event.item = parent._getItem (hNewItem);
+            parent.hAnchor = hNewItem;
+        }
+        parent.sendEvent (SWT.Selection, event);
+    }
+}
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for this item to the font specified by the argument, or to the default font
+ * for that kind of control if the argument is null.
+ *
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.0
+ */
+public void setFont (Font font){
+    checkWidget ();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    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 & SWT.VIRTUAL) !is 0) cached = true;
+    /*
+    * Bug in Windows.  When the font is changed for an item,
+    * the bounds for the item are not updated, causing the text
+    * to be clipped.  The fix is to reset the text, causing
+    * Windows to compute the new bounds using the new font.
+    */
+    if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
+        return;
+    }
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+    tvItem.hItem = cast(HTREEITEM)handle;
+    tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+    OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+}
+
+
+/**
+ * Sets the font that the receiver will use to paint textual information
+ * for the specified cell in this item to the font specified by the
+ * argument, or to the default font for that kind of control if the
+ * argument is null.
+ *
+ * @param index the column index
+ * @param font the new font (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void setFont (int index, Font font) {
+    checkWidget ();
+    if (font !is null && font.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (cellFont is null) {
+        if (font is null) return;
+        cellFont = new Font [count];
+    }
+    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 & SWT.VIRTUAL) !is 0) cached = true;
+    /*
+    * Bug in Windows.  When the font is changed for an item,
+    * the bounds for the item are not updated, causing the text
+    * to be clipped.  The fix is to reset the text, causing
+    * Windows to compute the new bounds using the new font.
+    */
+    if (index is 0) {
+        if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
+            return;
+        }
+        auto hwnd = parent.handle;
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+        tvItem.hItem = cast(HTREEITEM)handle;
+        tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+        OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    } else {
+        redraw (index, true, false);
+    }
+}
+
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param color the new color (or null)
+ *
+ * @since 2.0
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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 2.0
+ *
+ */
+public void setForeground (Color color) {
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int pixel = -1;
+    if (color !is null) {
+        parent.customDraw = true;
+        pixel = color.handle;
+    }
+    if (foreground is pixel) return;
+    foreground = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw ();
+}
+
+/**
+ * Sets the foreground color at the given column index in the receiver
+ * to the color specified by the argument, or to the default system color for the item
+ * if the argument is null.
+ *
+ * @param index the column index
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.1
+ *
+ */
+public void setForeground (int index, Color color){
+    checkWidget ();
+    if (color !is null && color.isDisposed ()) {
+        SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    int pixel = -1;
+    if (color !is null) {
+        parent.customDraw = true;
+        pixel = color.handle;
+    }
+    if (cellForeground is null) {
+        cellForeground = new int [count];
+        for (int i = 0; i < count; i++) {
+            cellForeground [i] = -1;
+        }
+    }
+    if (cellForeground [index] is pixel) return;
+    cellForeground [index] = pixel;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    redraw (index, true, false);
+}
+
+/**
+ * Sets the grayed state of the checkbox for this item.  This state change
+ * only applies if the Tree was created with the SWT.CHECK style.
+ *
+ * @param grayed the new grayed state of the checkbox
+ *
+ * @exception SWTException <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 ((parent.style & SWT.CHECK) is 0) return;
+    auto hwnd = parent.handle;
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
+    tvItem.hItem = cast(HTREEITEM)handle;
+    OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
+    int state = tvItem.state >> 12;
+    if (grayed) {
+        if (state <= 2) state +=2;
+    } else {
+        if (state > 2) state -=2;
+    }
+    state <<= 12;
+    if (tvItem.state is state) return;
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    tvItem.state = state;
+    OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    /*
+    * Bug in Windows.  When TVM_SETITEM is used to set
+    * the state image of an item inside TVN_GETDISPINFO,
+    * the new state is not redrawn.  The fix is to force
+    * a redraw.
+    */
+    if ((parent.style & SWT.VIRTUAL) !is 0) {
+        if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
+            RECT rect;
+            if (OS.TreeView_GetItemRect (hwnd, cast(HTREEITEM)handle, &rect, false)) {
+                OS.InvalidateRect (hwnd, &rect, true);
+            }
+        }
+    }
+}
+
+/**
+ * Sets the image for multiple columns in the tree.
+ *
+ * @param images the array of new images
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if one of the images has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void setImage (Image [] images) {
+    checkWidget();
+    // SWT extension; allow null array
+    //if (images is null) error (SWT.ERROR_NULL_ARGUMENT);
+    for (int i=0; i<images.length; i++) {
+        setImage (i, images [i]);
+    }
+}
+
+/**
+ * Sets the receiver's image at a column.
+ *
+ * @param index the column index
+ * @param image the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <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.1
+ */
+public void setImage (int index, Image image) {
+    checkWidget();
+    if (image !is null && image.isDisposed ()) {
+        error(SWT.ERROR_INVALID_ARGUMENT);
+    }
+    Image oldImage = null;
+    if (index is 0) {
+        if (image !is null && image.type is SWT.ICON) {
+            if (image==/*eq*/this.image) return;
+        }
+        oldImage = this.image;
+        super.setImage (image);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (images is null && index !is 0) {
+        images = new Image [count];
+        images [0] = image;
+    }
+    if (images !is null) {
+        if (image !is null && image.type is SWT.ICON) {
+            if (image==/*eq*/images [index]) return;
+        }
+        oldImage = images [index];
+        images [index] = image;
+    }
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+
+    /* Ensure that the image list is created */
+    //TODO - items that are not in column zero don't need to be in the image list
+    parent.imageIndex (image, index);
+
+    if (index is 0) {
+        if ((parent.style & SWT.VIRTUAL) is 0 &&!cached && !parent.painted) {
+            return;
+        }
+        auto hwnd = parent.handle;
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_IMAGE | OS.TVIF_SELECTEDIMAGE;
+        tvItem.hItem = cast(HTREEITEM)handle;
+        tvItem.iImage = tvItem.iSelectedImage = OS.I_IMAGECALLBACK;
+        /*
+        * Bug in Windows.  When I_IMAGECALLBACK is used with TVM_SETITEM
+        * to indicate that an image has changed, Windows does not draw
+        * the new image.  The fix is to use LPSTR_TEXTCALLBACK to force
+        * Windows to ask for the text, causing Windows to ask for both.
+        */
+        tvItem.mask |= OS.TVIF_TEXT;
+        tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+        OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    } else {
+        bool drawText = (image is null && oldImage !is null) || (image !is null && oldImage is null);
+        redraw (index, drawText, true);
+    }
+}
+
+override public void setImage (Image image) {
+    checkWidget ();
+    setImage (0, image);
+}
+
+/**
+ * Sets the number of child items contained in the receiver.
+ *
+ * @param count the number of items
+ *
+ * @exception SWTException <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.2
+ */
+public void setItemCount (int count) {
+    checkWidget ();
+    count = Math.max (0, count);
+    auto hwnd = parent.handle;
+    auto hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, handle);
+    parent.setItemCount (count, handle, hItem);
+}
+
+/**
+ * Sets the text for multiple columns in the tree.
+ *
+ * @param strings the array of new strings
+ *
+ * @exception SWTException <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.1
+ */
+public void setText (String[] strings) {
+    checkWidget();
+    // SWT extension: allow null array
+    //if (strings is null) error (SWT.ERROR_NULL_ARGUMENT);
+    for (int i=0; i<strings.length; i++) {
+        String string = strings [i];
+        if (string !is null) setText (i, string);
+    }
+}
+
+/**
+ * Sets the receiver's text at a column
+ *
+ * @param index the column index
+ * @param string the new text
+ *
+ * @exception SWTException <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.1
+ */
+public void setText (int index, String string) {
+    checkWidget();
+    // SWT extension: allow null string
+    //if (string is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (index is 0) {
+        if (string==/*eq*/text) return;
+        super.setText (string);
+    }
+    int count = Math.max (1, parent.getColumnCount ());
+    if (0 > index || index > count - 1) return;
+    if (strings is null && index !is 0) {
+        strings = new String [count];
+        strings [0] = text;
+    }
+    if (strings !is null) {
+        if (string==/*eq*/strings [index]) return;
+        strings [index] = string;
+    }
+    if ((parent.style & SWT.VIRTUAL) !is 0) cached = true;
+    if (index is 0) {
+        if ((parent.style & SWT.VIRTUAL) is 0 && !cached && !parent.painted) {
+            return;
+        }
+        auto hwnd = parent.handle;
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_TEXT;
+        tvItem.hItem = cast(HTREEITEM)handle;
+        tvItem.pszText = OS.LPSTR_TEXTCALLBACK;
+        OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
+    } else {
+        redraw (index, true, false);
+    }
+}
+
+override public void setText (String string) {
+    checkWidget();
+    setText (0, string);
+}
+
+/*public*/ void sort () {
+    checkWidget ();
+    if ((parent.style & SWT.VIRTUAL) !is 0) return;
+    parent.sort (handle, false);
+}
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/TypedListener.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.TypedListener;
+
+
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.events.ArmEvent;
+import org.eclipse.swt.events.ArmListener;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.DragDetectEvent;
+import org.eclipse.swt.events.DragDetectListener;
+import org.eclipse.swt.events.ExpandEvent;
+import org.eclipse.swt.events.ExpandListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.HelpEvent;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MenuDetectListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.MouseWheelListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.events.ShellListener;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.GC;
+
+
+/**
+ * Instances of this class are <em>internal SWT implementation</em>
+ * objects which provide a mapping between the typed and untyped
+ * listener mechanisms that SWT supports.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @see Listener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+public class TypedListener : Listener {
+
+    /**
+     * The receiver's event listener
+     */
+    protected SWTEventListener eventListener;
+
+/**
+ * Constructs a new instance of this class for the given event listener.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @param listener the event listener to store in the receiver
+ */
+public this (SWTEventListener listener) {
+    eventListener = listener;
+}
+
+/**
+ * Returns the receiver's event listener.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @return the receiver's event listener
+ */
+public SWTEventListener getEventListener () {
+    return eventListener;
+}
+
+/**
+ * Handles the given event.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ * @param e the event to handle
+ */
+public void handleEvent (Event e) {
+    switch (e.type) {
+        case SWT.Activate: {
+            (cast(ShellListener) eventListener).shellActivated(new ShellEvent(e));
+            break;
+        }
+        case SWT.Arm: {
+            (cast(ArmListener) eventListener).widgetArmed (new ArmEvent (e));
+            break;
+        }
+        case SWT.Close: {
+            /* Fields set by Decorations */
+            ShellEvent event = new ShellEvent (e);
+            (cast(ShellListener) eventListener).shellClosed(event);
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.Collapse: {
+            if ( auto l = cast(TreeListener)eventListener ) {
+                l.treeCollapsed(new TreeEvent(e));
+            } else {
+                (cast(ExpandListener) eventListener).itemCollapsed(new ExpandEvent(e));
+            }
+            break;
+        }
+        case SWT.Deactivate: {
+            (cast(ShellListener) eventListener).shellDeactivated(new ShellEvent(e));
+            break;
+        }
+        case SWT.Deiconify: {
+            (cast(ShellListener) eventListener).shellDeiconified(new ShellEvent(e));
+            break;
+        }
+        case SWT.DefaultSelection: {
+            (cast(SelectionListener)eventListener).widgetDefaultSelected(new SelectionEvent(e));
+            break;
+        }
+        case SWT.Dispose: {
+            (cast(DisposeListener) eventListener).widgetDisposed(new DisposeEvent(e));
+            break;
+        }
+        case SWT.DragDetect: {
+            (cast(DragDetectListener) eventListener).dragDetected(new DragDetectEvent(e));
+            break;
+        }
+        case SWT.Expand: {
+            if (auto l = cast(TreeListener)eventListener ) {
+                l.treeExpanded(new TreeEvent(e));
+            } else {
+                (cast(ExpandListener) eventListener).itemExpanded(new ExpandEvent(e));
+            }
+            break;
+        }
+        case SWT.FocusIn: {
+            (cast(FocusListener) eventListener).focusGained(new FocusEvent(e));
+            break;
+        }
+        case SWT.FocusOut: {
+            (cast(FocusListener) eventListener).focusLost(new FocusEvent(e));
+            break;
+        }
+        case SWT.Help: {
+            (cast(HelpListener) eventListener).helpRequested (new HelpEvent (e));
+            break;
+        }
+        case SWT.Hide: {
+            (cast(MenuListener) eventListener).menuHidden(new MenuEvent(e));
+            break;
+        }
+        case SWT.Iconify: {
+            (cast(ShellListener) eventListener).shellIconified(new ShellEvent(e));
+            break;
+        }
+        case SWT.KeyDown: {
+            /* Fields set by Control */
+            KeyEvent event = new KeyEvent(e);
+            (cast(KeyListener) eventListener).keyPressed(event);
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.KeyUp: {
+            /* Fields set by Control */
+            KeyEvent event = new KeyEvent(e);
+            (cast(KeyListener) eventListener).keyReleased(event);
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.Modify: {
+            (cast(ModifyListener) eventListener).modifyText(new ModifyEvent(e));
+            break;
+        }
+        case SWT.MenuDetect: {
+            MenuDetectEvent event = new MenuDetectEvent(e);
+            (cast(MenuDetectListener) eventListener).menuDetected(event);
+            e.x = event.x;
+            e.y = event.y;
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.MouseDown: {
+            (cast(MouseListener) eventListener).mouseDown(new MouseEvent(e));
+            break;
+        }
+        case SWT.MouseDoubleClick: {
+            (cast(MouseListener) eventListener).mouseDoubleClick(new MouseEvent(e));
+            break;
+        }
+        case SWT.MouseEnter: {
+            (cast(MouseTrackListener) eventListener).mouseEnter (new MouseEvent (e));
+            break;
+        }
+        case SWT.MouseExit: {
+            (cast(MouseTrackListener) eventListener).mouseExit (new MouseEvent (e));
+            break;
+        }
+        case SWT.MouseHover: {
+            (cast(MouseTrackListener) eventListener).mouseHover (new MouseEvent (e));
+            break;
+        }
+        case SWT.MouseMove: {
+            (cast(MouseMoveListener) eventListener).mouseMove(new MouseEvent(e));
+            return;
+        }
+        case SWT.MouseWheel: {
+            (cast(MouseWheelListener) eventListener).mouseScrolled(new MouseEvent(e));
+            return;
+        }
+        case SWT.MouseUp: {
+            (cast(MouseListener) eventListener).mouseUp(new MouseEvent(e));
+            break;
+        }
+        case SWT.Move: {
+            (cast(ControlListener) eventListener).controlMoved(new ControlEvent(e));
+            break;
+        }
+        case SWT.Paint: {
+            /* Fields set by Control */
+            PaintEvent event = new PaintEvent (e);
+            (cast(PaintListener) eventListener).paintControl (event);
+            e.gc = event.gc;
+            break;
+        }
+        case SWT.Resize: {
+            (cast(ControlListener) eventListener).controlResized(new ControlEvent(e));
+            break;
+        }
+        case SWT.Selection: {
+            /* Fields set by Sash */
+            SelectionEvent event = new SelectionEvent (e);
+            (cast(SelectionListener) eventListener).widgetSelected (event);
+            e.x = event.x;
+            e.y = event.y;
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.Show: {
+            (cast(MenuListener) eventListener).menuShown(new MenuEvent(e));
+            break;
+        }
+        case SWT.Traverse: {
+            /* Fields set by Control */
+            TraverseEvent event = new TraverseEvent (e);
+            (cast(TraverseListener) eventListener).keyTraversed (event);
+            e.detail = event.detail;
+            e.doit = event.doit;
+            break;
+        }
+        case SWT.Verify: {
+            /* Fields set by Text, RichText */
+            VerifyEvent event = new VerifyEvent (e);
+            (cast(VerifyListener) eventListener).verifyText (event);
+            e.text = event.text;
+            e.doit = event.doit;
+            break;
+        }
+        default:
+    }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Widget.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,2554 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.internal.SWTEventListener;
+import org.eclipse.swt.internal.win32.OS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.EventTable;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.TypedListener;
+
+import tango.text.convert.Format;
+import tango.io.Stdout;
+import tango.core.Thread;
+import java.lang.all;
+
+/**
+ * This class is the abstract superclass of all user interface objects.
+ * Widgets are created, disposed and issue notification to listeners
+ * when events occur which affect them.
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>Dispose</dd>
+ * </dl>
+ * <p>
+ * IMPORTANT: This class is intended to be subclassed <em>only</em>
+ * within the SWT implementation. However, it has not been marked
+ * final to allow those outside of the SWT development team to implement
+ * patched versions of the class in order to get around specific
+ * limitations in advance of when those limitations can be addressed
+ * by the team.  Any class built using subclassing to access the internals
+ * of this class will likely fail to compile or run between releases and
+ * may be strongly platform specific. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the workings of the
+ * hierarchy. No support is provided for user-written classes which are
+ * implemented as subclasses of this class.
+ * </p>
+ *
+ * @see #checkSubclass
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ */
+
+public abstract class Widget {
+
+    int style, state;
+    Display display;
+    EventTable eventTable;
+    Object data;
+
+    public alias org.eclipse.swt.internal.win32.OS.LDWTRESULT LRESULT;
+
+    /* Global state flags */
+    static const int DISPOSED       = 1<<0;
+    static const int CANVAS         = 1<<1;
+    static const int KEYED_DATA     = 1<<2;
+    static const int DISABLED       = 1<<3;
+    static const int HIDDEN         = 1<<4;
+
+    /* A layout was requested on this widget */
+    static const int LAYOUT_NEEDED  = 1<<5;
+
+    /* The preferred size of a child has changed */
+    static const int LAYOUT_CHANGED = 1<<6;
+
+    /* A layout was requested in this widget hierarchy */
+    static const int LAYOUT_CHILD = 1<<7;
+
+    /* Background flags */
+    static const int THEME_BACKGROUND = 1<<8;
+    static const int DRAW_BACKGROUND = 1<<9;
+    static const int PARENT_BACKGROUND = 1<<10;
+
+    /* Dispose and release flags */
+    static const int RELEASED       = 1<<11;
+    static const int DISPOSE_SENT   = 1<<12;
+
+    /* More global widget state flags */
+    static const int TRACK_MOUSE    = 1<<13;
+    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;
+
+    /* Check and initialize the Common Controls DLL */
+    static const int MAJOR = 5, MINOR = 80;
+
+    private static bool static_this_completed = false;
+    private static void static_this() {
+        if( static_this_completed ){
+            return;
+        }
+        synchronized {
+            if( static_this_completed ){
+                return;
+            }
+            static if (!OS.IsWinCE) {
+                if (OS.COMCTL32_VERSION < OS.VERSION (MAJOR, MINOR)) {
+                    Stdout.formatln ("***WARNING: SWT requires comctl32.dll version {}.{} or greater", MAJOR, MINOR); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                    Stdout.formatln ("***WARNING: Detected: {}.{}", OS.COMCTL32_MAJOR, OS.COMCTL32_MINOR); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+            }
+            OS.InitCommonControls ();
+            static_this_completed = true;
+        }
+    }
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+    static_this();
+}
+
+/**
+ * Constructs a new instance of this class given its parent
+ * and a style value describing its behavior and appearance.
+ * <p>
+ * The style value is either one of the style constants defined in
+ * class <code>SWT</code> which is applicable to instances of this
+ * class, or must be built by <em>bitwise OR</em>'ing together
+ * (that is, using the <code>int</code> "|" operator) two or more
+ * of those <code>SWT</code> style constants. The class description
+ * lists the style constants that are applicable to the class.
+ * Style bits are also inherited from superclasses.
+ * </p>
+ *
+ * @param parent a widget which will be the parent of the new instance (cannot be null)
+ * @param style the style of widget to construct
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ *
+ * @see SWT
+ * @see #checkSubclass
+ * @see #getStyle
+ */
+public this (Widget parent, int style) {
+    static_this();
+    checkSubclass ();
+    checkParent (parent);
+    this.style = style;
+    display = parent.display;
+}
+
+void _addListener (int eventType, Listener listener) {
+    if (eventTable is null) eventTable = new EventTable ();
+    eventTable.hook (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when an event of the given type occurs. When the
+ * event does occur in the widget, the listener is notified by
+ * sending it the <code>handleEvent()</code> message. The event
+ * type is one of the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SWT
+ * @see #getListeners(int)
+ * @see #removeListener(int, Listener)
+ * @see #notifyListeners
+ */
+public void addListener (int eventType, Listener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    _addListener (eventType, listener);
+}
+
+/**
+ * Adds the listener to the collection of listeners who will
+ * be notified when the widget is disposed. When the widget is
+ * disposed, the listener is notified by sending it the
+ * <code>widgetDisposed()</code> message.
+ *
+ * @param listener the listener which should be notified when the receiver is disposed
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 DisposeListener
+ * @see #removeDisposeListener
+ */
+public void addDisposeListener (DisposeListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    TypedListener typedListener = new TypedListener (listener);
+    addListener (SWT.Dispose, typedListener);
+}
+
+int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
+    return 0;
+}
+
+/**
+ * Returns a style with exactly one style bit set out of
+ * the specified set of exclusive style bits. All other
+ * possible bits are cleared when the first matching bit
+ * is found. Bits that are not part of the possible set
+ * are untouched.
+ *
+ * @param style the original style bits
+ * @param int0 the 0th possible style bit
+ * @param int1 the 1st possible style bit
+ * @param int2 the 2nd possible style bit
+ * @param int3 the 3rd possible style bit
+ * @param int4 the 4th possible style bit
+ * @param int5 the 5th possible style bit
+ *
+ * @return the new style bits
+ */
+static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) {
+    int mask = int0 | int1 | int2 | int3 | int4 | int5;
+    if ((style & mask) is 0) style |= int0;
+    if ((style & int0) !is 0) style = (style & ~mask) | int0;
+    if ((style & int1) !is 0) style = (style & ~mask) | int1;
+    if ((style & int2) !is 0) style = (style & ~mask) | int2;
+    if ((style & int3) !is 0) style = (style & ~mask) | int3;
+    if ((style & int4) !is 0) style = (style & ~mask) | int4;
+    if ((style & int5) !is 0) style = (style & ~mask) | int5;
+    return style;
+}
+
+void checkOrientation (Widget parent) {
+    style &= ~SWT.MIRRORED;
+    if ((style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT)) is 0) {
+        if (parent !is null) {
+            if ((parent.style & SWT.LEFT_TO_RIGHT) !is 0) style |= SWT.LEFT_TO_RIGHT;
+            if ((parent.style & SWT.RIGHT_TO_LEFT) !is 0) style |= SWT.RIGHT_TO_LEFT;
+        }
+    }
+    style = checkBits (style, SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
+void checkOpened () {
+    /* Do nothing */
+}
+
+/**
+ * Throws an exception if the specified widget can not be
+ * used as a parent for the receiver.
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
+ * </ul>
+ */
+void checkParent (Widget parent) {
+    if (parent is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (parent.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+    parent.checkWidget ();
+    parent.checkOpened ();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ * <p>
+ * The SWT class library is intended to be subclassed
+ * only at specific, controlled points (most notably,
+ * <code>Composite</code> and <code>Canvas</code> when
+ * implementing new widgets). This method enforces this
+ * rule unless it is overridden.
+ * </p><p>
+ * <em>IMPORTANT:</em> By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between SWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ * </p><p>
+ * The ability to subclass outside of the allowed SWT classes
+ * is intended purely to enable those not on the SWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
+ * </ul>
+ */
+protected void checkSubclass () {
+    if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * widget implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code>) on a widget that has had its
+ * <code>dispose()</code> method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * </p>
+ *
+ * @exception SWTException <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>
+ */
+void checkWidget () {
+    Display display = this.display;
+    if (display is null) error (SWT.ERROR_WIDGET_DISPOSED);
+    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 not been
+        * observed in all places where it is called. 
+        */
+        if (display.threadId !is OS.GetCurrentThreadId ()) {
+            error (SWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+    }
+    if ((state & DISPOSED) !is 0) error (SWT.ERROR_WIDGET_DISPOSED);
+}
+
+/**
+ * Destroys the widget in the operating system and releases
+ * the widget's handle.  If the widget does not have a handle,
+ * this method may hide the widget, mark the widget as destroyed
+ * or do nothing, depending on the widget.
+ * <p>
+ * When a widget is destroyed in the operating system, its
+ * descendants are also destroyed by the operating system.
+ * This means that it is only necessary to call <code>destroyWidget</code>
+ * on the root of the widget tree.
+ * </p><p>
+ * This method is called after <code>releaseWidget()</code>.
+ * </p><p>
+ * See also <code>releaseChild()</code>, <code>releaseWidget()</code>
+ * and <code>releaseHandle()</code>.
+ * </p>
+ *
+ * @see #dispose
+ */
+void destroyWidget () {
+    releaseHandle ();
+}
+
+HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags){
+    static if (OS.IsWinCE) {
+        /*
+        * Feature in Windows.  On Windows CE, DeferWindowPos always causes
+        * a WM_SIZE message, even when the new size is the same as the old
+        * size.  The fix is to detect that the size has not changed and set
+        * SWP_NOSIZE.
+        */
+        if ((uFlags & OS.SWP_NOSIZE) is 0) {
+            RECT lpRect;
+            OS.GetWindowRect (hWnd, &lpRect);
+            if (cy is lpRect.bottom - lpRect.top && cx is lpRect.right - lpRect.left) {
+                /*
+                * Feature in Windows.  On Windows CE, DeferWindowPos when called
+                * with SWP_DRAWFRAME always causes a WM_SIZE message, even
+                * when SWP_NOSIZE is set and when the new size is the same as the
+                * old size.  The fix is to clear SWP_DRAWFRAME when the size is
+                * the same.
+                */
+                uFlags &= ~OS.SWP_DRAWFRAME;
+                uFlags |= OS.SWP_NOSIZE;
+            }
+        }
+    }
+    return OS.DeferWindowPos (hWinPosInfo, hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver and all its descendants. After this method has
+ * been invoked, the receiver and all descendants will answer
+ * <code>true</code> when sent the message <code>isDisposed()</code>.
+ * Any internal connections between the widgets in the tree will
+ * have been removed to facilitate garbage collection.
+ * <p>
+ * NOTE: This method is not called recursively on the descendants
+ * of the receiver. This means that, widget implementers can not
+ * detect when a widget is being disposed of by re-implementing
+ * this method, but should instead listen for the <code>Dispose</code>
+ * event.
+ * </p>
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #addDisposeListener
+ * @see #removeDisposeListener
+ * @see #checkWidget
+ */
+public void dispose () {
+    /*
+    * Note:  It is valid to attempt to dispose a widget
+    * more than once.  If this happens, fail silently.
+    */
+    if (isDisposed ()) return;
+    if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
+    release (true);
+}
+
+bool dragDetect (HWND hwnd, int x, int y, bool filter, bool [] detect, bool [] consume) {
+    if (consume !is null) consume [0] = false;
+    if (detect !is null) detect [0] = true;
+    POINT pt;
+    pt.x = x;
+    pt.y = y;
+    OS.ClientToScreen (hwnd, &pt);
+    return cast(bool) OS.DragDetect (hwnd, pt);
+}
+
+/**
+ * Does whatever widget specific cleanup is required, and then
+ * uses the code in <code>SWTError.error</code> to handle the error.
+ *
+ * @param code the descriptive error code
+ *
+ * @see SWT#error(int)
+ */
+void error (int code) {
+    SWT.error(code);
+}
+
+bool filters (int eventType) {
+    return display.filters (eventType);
+}
+
+Widget findItem (HANDLE id) {
+    return null;
+}
+
+char [] fixMnemonic (String string) {
+    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 '&') {
+                if (spaces) buffer [j] = ' ';
+                j++;
+                i++;
+            }
+            i++;
+        } else {
+            buffer [j++] = buffer [i++];
+        }
+    }
+    while (j < buffer.length) buffer [j++] = 0;
+    return buffer;
+}
+
+/**
+ * Returns the application defined widget data associated
+ * with the receiver, or null if it has not been set. The
+ * <em>widget data</em> is a single, unnamed field that is
+ * stored with every widget.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ * </p>
+ *
+ * @return the widget data
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
+ * </ul>
+ *
+ * @see #setData(Object)
+ */
+public Object getData () {
+    checkWidget();
+    return (state & KEYED_DATA) !is 0 ? (cast(ArrayWrapperObject) data).array [0] : data;
+}
+public String getDataStr () {
+    return stringcast(getData());
+}
+
+/**
+ * Returns the application defined property of the receiver
+ * with the specified name, or null if it has not been set.
+ * <p>
+ * Applications may have associated arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ * </p>
+ *
+ * @param   key the name of the property
+ * @return the value of the property or null if it has not been set
+ *
+ * @exception SWTException <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 #setData(String, Object)
+ */
+public Object getData (String key) {
+    checkWidget();
+    // SWT extension: allow null key
+    //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if ((state & KEYED_DATA) !is 0) {
+        Object [] table = (cast(ArrayWrapperObject) data).array;
+        for (int i=1; i<table.length; i+=2) {
+            String tablekey = (cast(ArrayWrapperString) table[i]).array;
+            if (key ==/*eq*/ tablekey ) return table [i+1];
+        }
+    }
+    return null;
+}
+public String getDataStr (String key) {
+    return stringcast(getData(key));
+}
+
+/**
+ * Returns the <code>Display</code> that is associated with
+ * the receiver.
+ * <p>
+ * A widget's display is either provided when it is created
+ * (for example, top level <code>Shell</code>s) or is the
+ * same as its parent's display.
+ * </p>
+ *
+ * @return the receiver's display
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Display getDisplay () {
+    Display display = this.display;
+    if (display is null) error (SWT.ERROR_WIDGET_DISPOSED);
+    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>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @return an array of listeners that will be notified when the event occurs
+ *
+ * @exception SWTException <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 SWT
+ * @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;
+}
+
+/**
+ * Returns the name of the widget. This is the name of
+ * the class without the package name.
+ *
+ * @return the name of the widget
+ */
+String getName () {
+    String str = this.classinfo.name;
+    int index = str.length;
+    while ((--index > 0) && (str[index] !is '.')) {}
+    return str[index + 1 .. $ ];
+}
+
+/*
+ * Returns a short printable representation for the contents
+ * of a widget. For example, a button may answer the label
+ * text. This is used by <code>toString</code> to provide a
+ * more meaningful description of the widget.
+ *
+ * @return the contents string for the widget
+ *
+ * @see #toString
+ */
+String getNameText () {
+    return ""; //$NON-NLS-1$
+}
+
+/**
+ * Returns the receiver's style information.
+ * <p>
+ * Note that the value which is returned by this method <em>may
+ * not match</em> the value which was provided to the constructor
+ * when the receiver was created. This can occur when the underlying
+ * operating system does not support a particular combination of
+ * requested styles. For example, if the platform widget used to
+ * implement a particular SWT widget always has scroll bars, the
+ * result of calling this method would always have the
+ * <code>SWT.H_SCROLL</code> and <code>SWT.V_SCROLL</code> bits set.
+ * </p>
+ *
+ * @return the style bits
+ *
+ * @exception SWTException <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 int getStyle () {
+    checkWidget();
+    return style;
+}
+
+/*
+ * Returns <code>true</code> if the specified eventType is
+ * hooked, and <code>false</code> otherwise. Implementations
+ * of SWT can avoid creating objects and sending events
+ * when an event happens in the operating system but
+ * there are no listeners hooked for the event.
+ *
+ * @param eventType the event to be checked
+ *
+ * @return <code>true</code> when the eventType is hooked and <code>false</code> otherwise
+ *
+ * @see #isListening
+ */
+bool hooks (int eventType) {
+    if (eventTable is null) return false;
+    return eventTable.hooks (eventType);
+}
+
+/**
+ * Returns <code>true</code> if the widget has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the widget.
+ * When a widget has been disposed, it is an error to
+ * invoke any other method using the widget.
+ * </p>
+ *
+ * @return <code>true</code> when the widget is disposed and <code>false</code> otherwise
+ */
+public bool isDisposed () {
+    return (state & DISPOSED) !is 0;
+}
+
+/**
+ * Returns <code>true</code> if there are any listeners
+ * for the specified event type associated with the receiver,
+ * and <code>false</code> otherwise. The event type is one of
+ * the event constants defined in class <code>SWT</code>.
+ *
+ * @param eventType the type of event
+ * @return true if the event is hooked
+ *
+ * @exception SWTException <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 SWT
+ */
+public bool isListening (int eventType) {
+    checkWidget();
+    return hooks (eventType);
+}
+
+/*
+ * Returns <code>true</code> when subclassing is
+ * allowed and <code>false</code> otherwise
+ *
+ * @return <code>true</code> when subclassing is allowed and <code>false</code> otherwise
+ */
+bool isValidSubclass () {
+    return true;//Display.isValidClass (getClass ());
+}
+
+/*
+ * Returns <code>true</code> when the current thread is
+ * the thread that created the widget and <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> when the current thread is the thread that created the widget and <code>false</code> otherwise
+ */
+bool isValidThread () {
+    return getDisplay ().isValidThread ();
+}
+
+void mapEvent (HWND hwnd, Event event) {
+}
+
+GC new_GC (GCData data) {
+    return null;
+}
+
+/**
+ * Notifies all of the receiver's listeners for events
+ * of the given type that one such event has occurred by
+ * invoking their <code>handleEvent()</code> method.  The
+ * event type is one of the event constants defined in class
+ * <code>SWT</code>.
+ *
+ * @param eventType the type of event which has occurred
+ * @param event the event data
+ *
+ * @exception SWTException <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 SWT
+ * @see #addListener
+ * @see #getListeners(int)
+ * @see #removeListener(int, Listener)
+ */
+public void notifyListeners (int eventType, Event event) {
+    checkWidget();
+    if (event is null) event = new Event ();
+    sendEvent (eventType, event);
+}
+
+void postEvent (int eventType) {
+    sendEvent (eventType, null, false);
+}
+
+void postEvent (int eventType, Event event) {
+    sendEvent (eventType, event, false);
+}
+
+/*
+ * Releases the widget hierarchy and optionally destroys
+ * the receiver.
+ * <p>
+ * Typically, a widget with children will broadcast this
+ * message to all children so that they too can release their
+ * resources.  The <code>releaseHandle</code> method is used
+ * as part of this broadcast to zero the handle fields of the
+ * children without calling <code>destroyWidget</code>.  In
+ * this scenario, the children are actually destroyed later,
+ * when the operating system destroys the widget tree.
+ * </p>
+ *
+ * @param destroy indicates that the receiver should be destroyed
+ *
+ * @see #dispose
+ * @see #releaseHandle
+ * @see #releaseParent
+ * @see #releaseWidget
+*/
+void release (bool destroy) {
+    if ((state & DISPOSE_SENT) is 0) {
+        state |= DISPOSE_SENT;
+        sendEvent (SWT.Dispose);
+    }
+    if ((state & DISPOSED) is 0) {
+        releaseChildren (destroy);
+    }
+    if ((state & RELEASED) is 0) {
+        state |= RELEASED;
+        if (destroy) {
+            releaseParent ();
+            releaseWidget ();
+            destroyWidget ();
+        } else {
+            releaseWidget ();
+            releaseHandle ();
+        }
+    }
+}
+
+void releaseChildren (bool destroy) {
+}
+
+/*
+ * Releases the widget's handle by zero'ing it out.
+ * Does not destroy or release any operating system
+ * resources.
+ * <p>
+ * This method is called after <code>releaseWidget</code>
+ * or from <code>destroyWidget</code> when a widget is being
+ * destroyed to ensure that the widget is marked as destroyed
+ * in case the act of destroying the widget in the operating
+ * system causes application code to run in callback that
+ * could access the widget.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseParent
+ * @see #releaseWidget
+ */
+void releaseHandle () {
+    state |= DISPOSED;
+    display = null;
+}
+
+/*
+ * Releases the receiver, a child in a widget hierarchy,
+ * from its parent.
+ * <p>
+ * When a widget is destroyed, it may be necessary to remove
+ * it from an internal data structure of the parent. When
+ * a widget has no handle, it may also be necessary for the
+ * parent to hide the widget or otherwise indicate that the
+ * widget has been disposed. For example, disposing a menu
+ * bar requires that the menu bar first be released from the
+ * shell when the menu bar is active.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseWidget
+ * @see #releaseHandle
+ */
+void releaseParent () {
+}
+
+/*
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the widget handle.
+ * <p>
+ * When a widget is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system.  For example, if the widget made a
+ * copy of an icon, supplied by the programmer, this copy
+ * would be freed in <code>releaseWidget</code>.  Also,
+ * to assist the garbage collector and minimize the amount
+ * of memory that is not reclaimed when the programmer keeps
+ * a reference to a disposed widget, all fields except the
+ * handle are zero'd.  The handle is needed by <code>destroyWidget</code>.
+ * </p>
+ *
+ * @see #dispose
+ * @see #releaseChildren
+ * @see #releaseHandle
+ * @see #releaseParent
+ */
+void releaseWidget () {
+    eventTable = null;
+    data = null;
+}
+
+/**
+ * Removes the listener from the collection 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>SWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 SWT
+ * @see #addListener
+ * @see #getListeners(int)
+ * @see #notifyListeners
+ */
+public void removeListener (int eventType, Listener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when an event of the given type occurs.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the SWT
+ * public API. It is marked public only so that it can be shared
+ * within the packages provided by SWT. It should never be
+ * referenced from application code.
+ * </p>
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 #addListener
+ */
+protected void removeListener (int eventType, SWTEventListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (eventType, listener);
+}
+
+/**
+ * Removes the listener from the collection of listeners who will
+ * be notified when the widget is disposed.
+ *
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
+ * </ul>
+ * @exception SWTException <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 DisposeListener
+ * @see #addDisposeListener
+ */
+public void removeDisposeListener (DisposeListener listener) {
+    checkWidget();
+    if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
+    if (eventTable is null) return;
+    eventTable.unhook (SWT.Dispose, listener);
+}
+
+bool sendDragEvent (int button, int x, int y) {
+    Event event = new Event ();
+    event.button = button;
+    event.x = x;
+    event.y = y;
+    setInputState (event, SWT.DragDetect);
+    postEvent (SWT.DragDetect, event);
+    if (isDisposed ()) return false;
+    return event.doit;
+}
+
+bool sendDragEvent (int button, int stateMask, int x, int y) {
+    Event event = new Event ();
+    event.button = button;
+    event.x = x;
+    event.y = y;
+    event.stateMask = stateMask;
+    postEvent (SWT.DragDetect, event);
+    if (isDisposed ()) return false;
+    return event.doit;
+}
+
+void sendEvent (Event event) {
+    Display display = event.display;
+    if (!display.filterEvent (event)) {
+        if (eventTable !is null) eventTable.sendEvent (event);
+    }
+}
+
+void sendEvent (int eventType) {
+    sendEvent (eventType, null, true);
+}
+
+void sendEvent (int eventType, Event event) {
+    sendEvent (eventType, event, true);
+}
+
+void sendEvent (int eventType, Event event, bool send) {
+    if (eventTable is null && !display.filters (eventType)) {
+        return;
+    }
+    if (event is null) event = new Event ();
+    event.type = eventType;
+    event.display = display;
+    event.widget = this;
+    if (event.time is 0) {
+        event.time = display.getLastEventTime ();
+    }
+    if (send) {
+        sendEvent (event);
+    } else {
+        display.postEvent (event);
+    }
+}
+
+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 /*long*/ wParam, int /*long*/ lParam, Event event) {
+    sendEvent (type, event);
+    if (isDisposed ()) return false;
+    return event.doit;
+}
+
+bool sendMouseEvent (int type, int button, HWND hwnd, int msg, int wParam, int lParam) {
+    return sendMouseEvent (type, button, display.getClickCount (type, button, hwnd, lParam), 0, false, hwnd, msg, wParam, lParam);
+}
+
+bool sendMouseEvent (int type, int button, int count, int detail, bool send, HWND hwnd, int msg, int wParam, int lParam) {
+    if (!hooks (type) && !filters (type)) return true;
+    Event event = new Event ();
+    event.button = button;
+    event.detail = detail;
+    event.count = count;
+    event.x = OS.GET_X_LPARAM (lParam);
+    event.y = OS.GET_Y_LPARAM (lParam);
+    setInputState (event, type);
+    mapEvent (hwnd, event);
+    if (send) {
+        sendEvent (type, event);
+        if (isDisposed ()) return false;
+    } else {
+        postEvent (type, event);
+    }
+    return event.doit;
+}
+
+/**
+ * Sets the application defined widget data associated
+ * with the receiver to be the argument. The <em>widget
+ * data</em> is a single, unnamed field that is stored
+ * with every widget.
+ * <p>
+ * Applications may put arbitrary objects in this field. If
+ * the object stored in the widget data needs to be notified
+ * when the widget is disposed of, it is the application's
+ * responsibility to hook the Dispose event on the widget and
+ * do so.
+ * </p>
+ *
+ * @param data the widget data
+ *
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - when the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - when called from the wrong thread</li>
+ * </ul>
+ *
+ * @see #getData()
+ */
+public void setData (Object data) {
+    checkWidget();
+    if ((state & KEYED_DATA) !is 0) {
+        (cast(ArrayWrapperObject) this.data).array [0] = data;
+    } else {
+        this.data = data;
+    }
+}
+/// SWT extension
+public void setDataStr (String data) {
+    setData(stringcast(data));
+}
+
+/**
+ * Sets the application defined property of the receiver
+ * with the specified name to the given value.
+ * <p>
+ * Applications may associate arbitrary objects with the
+ * receiver in this fashion. If the objects stored in the
+ * properties need to be notified when the widget is disposed
+ * of, it is the application's responsibility to hook the
+ * Dispose event on the widget and do so.
+ * </p>
+ *
+ * @param key the name of the property
+ * @param value the new value for the property
+ *
+ * @exception SWTException <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 #getData(String)
+ */
+public void setData (String key, Object value) {
+    checkWidget();
+    // SWT extension: allow null key
+    //if (key.length is 0) error (SWT.ERROR_NULL_ARGUMENT);
+    int index = 1;
+    Object [] table = null;
+    if ((state & KEYED_DATA) !is 0) {
+        table = (cast(ArrayWrapperObject) data).array;
+        while (index < table.length) {
+            String tablekey = (cast(ArrayWrapperString)table[index]).array;
+            if (key ==/*eq*/ tablekey ) break;
+            index += 2;
+        }
+    }
+    if (value !is null) {
+        if ((state & KEYED_DATA) !is 0) {
+            if (index is table.length) {
+                Object [] newTable = new Object [table.length + 2];
+                System.arraycopy (table, 0, newTable, 0, table.length);
+                table = newTable;
+                data = new ArrayWrapperObject( table );
+            }
+        } else {
+            table = new Object [3];
+            table [0] = data;
+            data = new ArrayWrapperObject( table );
+            state |= KEYED_DATA;
+        }
+        table [index] = new ArrayWrapperString( key );
+        table [index + 1] = value;
+    } else {
+        if ((state & KEYED_DATA) !is 0) {
+            if (index !is table.length) {
+                int len = table.length - 2;
+                if (len is 1) {
+                    data = table [0];
+                    state &= ~KEYED_DATA;
+                } else {
+                    Object [] newTable = new Object [len];
+                    System.arraycopy (table, 0, newTable, 0, index);
+                    System.arraycopy (table, index + 2, newTable, index, len - index);
+                    data = new ArrayWrapperObject( newTable );
+                }
+            }
+        }
+    }
+}
+/// SWT extension
+public void setDataStr (String key, String value) {
+    setData( key, stringcast(value));
+}
+
+bool sendFocusEvent (int type) {
+    sendEvent (type);
+    // widget could be disposed at this point
+    return true;
+}
+
+bool setInputState (Event event, int type) {
+    if (OS.GetKeyState (OS.VK_MENU) < 0) event.stateMask |= SWT.ALT;
+    if (OS.GetKeyState (OS.VK_SHIFT) < 0) event.stateMask |= SWT.SHIFT;
+    if (OS.GetKeyState (OS.VK_CONTROL) < 0) event.stateMask |= SWT.CONTROL;
+    if (OS.GetKeyState (OS.VK_LBUTTON) < 0) event.stateMask |= SWT.BUTTON1;
+    if (OS.GetKeyState (OS.VK_MBUTTON) < 0) event.stateMask |= SWT.BUTTON2;
+    if (OS.GetKeyState (OS.VK_RBUTTON) < 0) event.stateMask |= SWT.BUTTON3;
+    if (display.xMouse) {
+        if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= SWT.BUTTON4;
+        if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= SWT.BUTTON5;
+    }
+    switch (type) {
+        case SWT.MouseDown:
+        case SWT.MouseDoubleClick:
+            if (event.button is 1) event.stateMask &= ~SWT.BUTTON1;
+            if (event.button is 2) event.stateMask &= ~SWT.BUTTON2;
+            if (event.button is 3) event.stateMask &= ~SWT.BUTTON3;
+            if (event.button is 4) event.stateMask &= ~SWT.BUTTON4;
+            if (event.button is 5) event.stateMask &= ~SWT.BUTTON5;
+            break;
+        case SWT.MouseUp:
+            if (event.button is 1) event.stateMask |= SWT.BUTTON1;
+            if (event.button is 2) event.stateMask |= SWT.BUTTON2;
+            if (event.button is 3) event.stateMask |= SWT.BUTTON3;
+            if (event.button is 4) event.stateMask |= SWT.BUTTON4;
+            if (event.button is 5) event.stateMask |= SWT.BUTTON5;
+            break;
+        case SWT.KeyDown:
+        case SWT.Traverse:
+            if (event.keyCode is SWT.ALT) event.stateMask &= ~SWT.ALT;
+            if (event.keyCode is SWT.SHIFT) event.stateMask &= ~SWT.SHIFT;
+            if (event.keyCode is SWT.CONTROL) event.stateMask &= ~SWT.CONTROL;
+            break;
+        case SWT.KeyUp:
+            if (event.keyCode is SWT.ALT) event.stateMask |= SWT.ALT;
+            if (event.keyCode is SWT.SHIFT) event.stateMask |= SWT.SHIFT;
+            if (event.keyCode is SWT.CONTROL) event.stateMask |= SWT.CONTROL;
+            break;
+        default:
+    }
+    return true;
+}
+
+bool setKeyState (Event event, int type, int /*long*/ wParam, int /*long*/ lParam) {
+
+    /*
+    * Feature in Windows.  When the user presses Ctrl+Backspace
+    * or Ctrl+Enter, Windows sends a WM_CHAR with Delete (0x7F)
+    * and '\n' instead of '\b' and '\r'.  This is the correct
+    * platform behavior but is not portable.  The fix is to detect
+    * these cases and convert the character.
+    */
+    switch (display.lastAscii) {
+        case SWT.DEL:
+            if (display.lastKey is SWT.BS) display.lastAscii = SWT.BS;
+            break;
+        case SWT.LF:
+            if (display.lastKey is SWT.CR) display.lastAscii = SWT.CR;
+            break;
+        default:
+    }
+
+    /*
+    * Feature in Windows.  When the user presses either the Enter
+    * key or the numeric keypad Enter key, Windows sends a WM_KEYDOWN
+    * with wParam=VK_RETURN in both cases.  In order to distinguish
+    * between the keys, the extended key bit is tested. If the bit
+    * is set, assume that the numeric keypad Enter was pressed.
+    */
+    if (display.lastKey is SWT.CR && display.lastAscii is SWT.CR) {
+        if ((lParam & 0x1000000) !is 0) display.lastKey = SWT.KEYPAD_CR;
+    }
+
+    if (display.lastVirtual) {
+        /*
+        * Feature in Windows.  The virtual key VK_DELETE is not
+        * treated as both a virtual key and an ASCII key by Windows.
+        * Therefore, we will not receive a WM_CHAR for this key.
+        * The fix is to treat VK_DELETE as a special case and map
+        * the ASCII value explicitly (Delete is 0x7F).
+        */
+        if (display.lastKey is OS.VK_DELETE) display.lastAscii = 0x7F;
+
+        /*
+        * Feature in Windows.  When the user presses Ctrl+Pause, the
+        * VK_CANCEL key is generated and a WM_CHAR is sent with 0x03,
+        * possibly to allow an application to look for Ctrl+C and the
+        * the Break key at the same time.  This is unexpected and
+        * unwanted.  The fix is to detect the case and set the character
+        * to zero.
+        */
+        if (display.lastKey is OS.VK_CANCEL) display.lastAscii = 0x0;
+
+        event.keyCode = Display.translateKey (display.lastKey);
+    } else {
+        event.keyCode = display.lastKey;
+    }
+    if (display.lastAscii !is 0 || display.lastNull) {
+        event.character = Display.mbcsToWcs (cast(wchar) display.lastAscii);
+    }
+    if (event.keyCode is 0 && event.character is 0) {
+        if (!display.lastNull) return false;
+    }
+    return setInputState (event, type);
+}
+
+bool SetWindowPos (HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags) {
+    static if (OS.IsWinCE) {
+        /*
+        * Feature in Windows.  On Windows CE, SetWindowPos() always causes
+        * a WM_SIZE message, even when the new size is the same as the old
+        * size.  The fix is to detect that the size has not changed and set
+        * SWP_NOSIZE.
+        */
+        if ((uFlags & OS.SWP_NOSIZE) is 0) {
+            RECT lpRect;
+            OS.GetWindowRect (hWnd, &lpRect);
+            if (cy is lpRect.bottom - lpRect.top && cx is lpRect.right - lpRect.left) {
+                /*
+                * Feature in Windows.  On Windows CE, SetWindowPos() when called
+                * with SWP_DRAWFRAME always causes a WM_SIZE message, even
+                * when SWP_NOSIZE is set and when the new size is the same as the
+                * old size.  The fix is to clear SWP_DRAWFRAME when the size is
+                * the same.
+                */
+                uFlags &= ~OS.SWP_DRAWFRAME;
+                uFlags |= OS.SWP_NOSIZE;
+            }
+        }
+    }
+    return cast(bool) OS.SetWindowPos (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
+}
+
+bool showMenu (int x, int y) {
+    Event event = new Event ();
+    event.x = x;
+    event.y = y;
+    sendEvent (SWT.MenuDetect, event);
+    if (!event.doit) return true;
+    Menu menu = getMenu ();
+    if (menu !is null && !menu.isDisposed ()) {
+        if (x !is event.x || y !is event.y) {
+            menu.setLocation (event.x, event.y);
+        }
+        menu.setVisible (true);
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+override public String toString () {
+    String string = "*Disposed*"; //$NON-NLS-1$
+    if (!isDisposed ()) {
+        string = "*Wrong Thread*"; //$NON-NLS-1$
+        if (isValidThread ()) string = getNameText ();
+    }
+    return Format( "{} {{{}}", getName (), string ); //$NON-NLS-1$ //$NON-NLS-2$
+}
+
+LRESULT wmCaptureChanged (HWND hwnd, int wParam, int lParam) {
+    display.captureChanged = true;
+    return null;
+}
+
+LRESULT wmChar (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Do not report a lead byte as a key pressed.
+    */
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        byte lead = cast(byte) (wParam & 0xFF);
+        if (OS.IsDBCSLeadByte (lead)) return null;
+    }
+    display.lastAscii = wParam;
+    display.lastNull = wParam is 0;
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_CHAR, wParam, lParam)) {
+        return LRESULT.ONE;
+    }
+    // widget could be disposed at this point
+    return null;
+}
+
+LRESULT wmContextMenu (HWND hwnd, int wParam, int lParam) {
+    if (wParam !is cast(int)hwnd) return null;
+
+    /*
+    * Feature in Windows.  SHRecognizeGesture() sends an undocumented
+    * WM_CONTEXTMENU notification when the flag SHRG_NOTIFY_PARENT is
+    * not set.  This causes the context menu to be displayed twice,
+    * once by the caller of SHRecognizeGesture() and once from this
+    * method.  The fix is to ignore WM_CONTEXTMENU notifications on
+    * all WinCE platforms.
+    *
+    * NOTE: This only happens on WM2003.  Previous WinCE versions did
+    * not support WM_CONTEXTMENU.
+    */
+    static if (OS.IsWinCE) return null;
+
+    /*
+    * Feature in Windows.  When the user presses  WM_NCRBUTTONUP,
+    * a WM_CONTEXTMENU message is generated.  This happens when
+    * the user releases the mouse over a scroll bar.  Normally,
+    * window displays the default scrolling menu but applications
+    * can process WM_CONTEXTMENU to display a different menu.
+    * Typically, an application does not want to supply a special
+    * scroll menu.  The fix is to look for a WM_CONTEXTMENU that
+    * originated from a mouse event and display the menu when the
+    * mouse was released in the client area.
+    */
+    int x = 0, y = 0;
+    if (lParam !is -1) {
+        POINT pt;
+        OS.POINTSTOPOINT (pt, lParam);
+        x = pt.x;
+        y = pt.y;
+        OS.ScreenToClient (hwnd, &pt);
+        RECT rect;
+        OS.GetClientRect (hwnd, &rect);
+        if (!OS.PtInRect (&rect, pt)) return null;
+    } else {
+        int pos = OS.GetMessagePos ();
+        x = OS.GET_X_LPARAM (pos);
+        y = OS.GET_Y_LPARAM (pos);
+    }
+
+    /* Show the menu */
+    return showMenu (x, y) ? LRESULT.ZERO : null;
+}
+
+LRESULT wmIMEChar (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    display.lastKey = 0;
+    display.lastAscii = wParam;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
+        return LRESULT.ONE;
+    }
+    sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
+    // widget could be disposed at this point
+    display.lastKey = display.lastAscii = 0;
+    return LRESULT.ONE;
+}
+
+LRESULT wmKeyDown (HWND hwnd, int wParam, int lParam) {
+
+    /* Ignore repeating modifier keys by testing key down state */
+    switch (wParam) {
+        case OS.VK_SHIFT:
+        case OS.VK_MENU:
+        case OS.VK_CONTROL:
+        case OS.VK_CAPITAL:
+        case OS.VK_NUMLOCK:
+        case OS.VK_SCROLL:
+            if ((lParam & 0x40000000) !is 0) return null;
+        default:
+    }
+
+    /* Clear last key and last ascii because a new key has been typed */
+    display.lastAscii = display.lastKey = 0;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+
+    /*
+    * Do not report a lead byte as a key pressed.
+    */
+    if (!OS.IsUnicode && OS.IsDBLocale) {
+        byte lead = cast(byte) (wParam & 0xFF);
+        if (OS.IsDBCSLeadByte (lead)) return null;
+    }
+
+    /* Map the virtual key */
+    /*
+    * Bug in WinCE.  MapVirtualKey() returns incorrect values.
+    * The fix is to rely on a key mappings table to determine
+    * whether the key event must be sent now or if a WM_CHAR
+    * event will follow.  The key mappings table maps virtual
+    * keys to SWT key codes and does not contain mappings for
+    * Windows virtual keys like VK_A.  Virtual keys that are
+    * both virtual and ASCII are a special case.
+    */
+    int mapKey = 0;
+    static if (OS.IsWinCE) {
+        switch (wParam) {
+            case OS.VK_BACK: mapKey = SWT.BS; break;
+            case OS.VK_RETURN: mapKey = SWT.CR; break;
+            case OS.VK_DELETE: mapKey = SWT.DEL; break;
+            case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+            case OS.VK_TAB: mapKey = SWT.TAB; break;
+            default:
+        }
+    } else {
+        /*
+        * 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);
+        }
+    }
+
+    /*
+    * Bug in Windows 95 and NT.  When the user types an accent key such
+    * as ^ to get an accented character on a German keyboard, the accent
+    * key should be ignored and the next key that the user types is the
+    * accented key.  The fix is to detect the accent key stroke (called
+    * a dead key) by testing the high bit of the value returned by
+    * MapVirtualKey().  A further problem is that the high bit on
+    * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+    * They should both be bit 32.
+    *
+    * When the user types an accent key that does not correspond to a
+    * virtual key, MapVirtualKey() won't set the high bit to indicate
+    * a dead key.  This happens when an accent key, such as '^' is the
+    * result of a modifier such as Shift key and MapVirtualKey() always
+    * returns the unshifted key.  The fix is to peek for a WM_DEADCHAR
+    * and avoid issuing the event.
+    */
+    if (OS.IsWinNT) {
+        if ((mapKey & 0x80000000) !is 0) return null;
+    } else {
+        if ((mapKey & 0x8000) !is 0) return null;
+    }
+    MSG msg;
+    int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+    if (OS.PeekMessage (&msg, hwnd, OS.WM_DEADCHAR, OS.WM_DEADCHAR, flags)) {
+        display.lastDead = true;
+        display.lastVirtual = mapKey is 0;
+        display.lastKey = display.lastVirtual ? wParam : mapKey;
+        return null;
+    }
+
+    /*
+    *  Bug in Windows.  Somehow, the widget is becoming disposed after
+    *  calling PeekMessage().  In rare circumstances, it seems that
+    *  PeekMessage() can allow SWT listeners to run that might contain
+    *  application code that disposes the widget.  It is not exactly
+    *  clear how this can happen.  PeekMessage() is only looking for
+    *  WM_DEADCHAR.  It is not dispatching any message that it finds
+    *  or removing any message from the queue.  Cross-thread messages
+    *  are disabled.  The fix is to check for a disposed widget and
+    *  return without calling the window proc.
+    */
+    if (isDisposed ()) return LRESULT.ONE;
+
+    /*
+    * If we are going to get a WM_CHAR, ensure that last key has
+    * the correct character value for the key down and key up
+    * events.  It is not sufficient to ignore the WM_KEYDOWN
+    * (when we know we are going to get a WM_CHAR) and compute
+    * the key in WM_CHAR because there is not enough information
+    * by the time we get the WM_CHAR.  For example, when the user
+    * types Ctrl+Shift+6 on a US keyboard, we get a WM_CHAR with
+    * wParam=30.  When the user types Ctrl+Shift+6 on a German
+    * keyboard, we also get a WM_CHAR with wParam=30.  On the US
+    * keyboard Shift+6 is ^, on the German keyboard Shift+6 is &.
+    * There is no way to map wParam=30 in WM_CHAR to the correct
+    * value.  Also, on international keyboards, the control key
+    * may be down when the user has not entered a control character.
+    *
+    * NOTE: On Windows 98, keypad keys are virtual despite the
+    * fact that a WM_CHAR is issued.  On Windows 2000 and XP,
+    * they are not virtual.  Therefore it is necessary to force
+    * numeric keypad keys to be virtual.
+    */
+    display.lastVirtual = mapKey is 0 || display.numpadKey (wParam) !is 0;
+    if (display.lastVirtual) {
+        display.lastKey = wParam;
+        /*
+        * Feature in Windows.  The virtual key VK_DELETE is not
+        * treated as both a virtual key and an ASCII key by Windows.
+        * Therefore, we will not receive a WM_CHAR for this key.
+        * The fix is to treat VK_DELETE as a special case and map
+        * the ASCII value explicitly (Delete is 0x7F).
+        */
+        if (display.lastKey is OS.VK_DELETE) display.lastAscii = 0x7F;
+
+        /*
+        * It is possible to get a WM_CHAR for a virtual key when
+        * Num Lock is on.  If the user types Home while Num Lock
+        * is down, a WM_CHAR is issued with WPARM=55 (for the
+        * character 7).  If we are going to get a WM_CHAR we need
+        * to ensure that the last key has the correct value.  Note
+        * that Ctrl+Home does not issue a WM_CHAR when Num Lock is
+        * down.
+        */
+        if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) {
+            /*
+            * Feature in Windows.  Calling to ToAscii() or ToUnicode(), clears
+            * the accented state such that the next WM_CHAR loses the accent.
+            * This makes is critical that the accent key is detected.  Also,
+            * these functions clear the character that is entered using the
+            * special Windows keypad sequence when NumLock is down (ie. typing
+            * ALT+0231 should gives 'c' with a cedilla when NumLock is down).
+            */
+            if (display.asciiKey (display.lastKey) !is 0) return null;
+            display.lastAscii = display.numpadKey (display.lastKey);
+        }
+    } else {
+        /*
+        * Convert LastKey to lower case because Windows non-virtual
+        * keys that are also ASCII keys, such as like VK_A, are have
+        * upper case values in WM_KEYDOWN despite the fact that the
+        * Shift was not pressed.
+        */
+        display.lastKey = cast(int) OS.CharLower (cast(wchar*) mapKey);
+
+        /*
+        * Feature in Windows. The virtual key VK_CANCEL is treated
+        * as both a virtual key and ASCII key by Windows.  This
+        * means that a WM_CHAR with WPARAM=3 will be issued for
+        * this key.  In order to distinguish between this key and
+        * Ctrl+C, mark the key as virtual.
+        */
+        if (wParam is OS.VK_CANCEL) display.lastVirtual = true;
+
+        /*
+        * Some key combinations map to Windows ASCII keys depending
+        * on the keyboard.  For example, Ctrl+Alt+Q maps to @ on a
+        * German keyboard.  If the current key combination is special,
+        * the correct character is placed in wParam for processing in
+        * WM_CHAR.  If this is the case, issue the key down event from
+        * inside WM_CHAR.
+        */
+        dchar asciiKey = display.asciiKey (wParam);
+        if (asciiKey !is 0) {
+            /*
+            * When the user types Ctrl+Space, ToAscii () maps this to
+            * Space.  Normally, ToAscii () maps a key to a different
+            * key if both a WM_KEYDOWN and a WM_CHAR will be issued.
+            * To avoid the extra SWT.KeyDown, look for a space and
+            * issue the event from WM_CHAR.
+            */
+            if (asciiKey is ' ') return null;
+            if (asciiKey !is wParam) return null;
+            /*
+            * Feature in Windows. The virtual key VK_CANCEL is treated
+            * as both a virtual key and ASCII key by Windows.  This
+            * means that a WM_CHAR with WPARAM=3 will be issued for
+            * this key. To avoid the extra SWT.KeyDown, look for
+            * VK_CANCEL and issue the event from WM_CHAR.
+            */
+            if (wParam is OS.VK_CANCEL) return null;
+        }
+
+        /*
+        * If the control key is not down at this point, then
+        * the key that was pressed was an accent key or a regular
+        * key such as 'A' or Shift+A.  In that case, issue the
+        * key event from WM_CHAR.
+        */
+        if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return null;
+
+        /*
+        * Get the shifted state or convert to lower case if necessary.
+        * If the user types Ctrl+A, LastAscii should be 'a', not 'A'.
+        * If the user types Ctrl+Shift+A, LastAscii should be 'A'.
+        * If the user types Ctrl+Shift+6, the value of LastAscii will
+        * depend on the international keyboard.
+        */
+        if (OS.GetKeyState (OS.VK_SHIFT) < 0) {
+            display.lastAscii = display.shiftedKey (wParam);
+            if (display.lastAscii is 0) display.lastAscii = mapKey;
+        } else {
+            display.lastAscii = cast(int)OS.CharLower (cast(wchar*) mapKey);
+        }
+
+        /* Note that Ctrl+'@' is ASCII NUL and is delivered in WM_CHAR */
+        if (display.lastAscii is '@') return null;
+        display.lastAscii = display.controlKey (display.lastAscii);
+    }
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_KEYDOWN, wParam, lParam)) {
+        return LRESULT.ONE;
+    }
+    // widget could be disposed at this point
+    return null;
+}
+
+LRESULT wmKeyUp (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+
+    /* Check for hardware keys */
+    static if (OS.IsWinCE) {
+        if (OS.VK_APP1 <= wParam && wParam <= OS.VK_APP6) {
+            display.lastKey = display.lastAscii = 0;
+            display.lastVirtual = display.lastNull = display.lastDead = false;
+            Event event = new Event ();
+            event.detail = wParam - OS.VK_APP1 + 1;
+            /* Check the bit 30 to get the key state */
+            int type = (lParam & 0x40000000) !is 0 ? SWT.HardKeyUp : SWT.HardKeyDown;
+            if (setInputState (event, type)) sendEvent (type, event);
+            // widget could be disposed at this point
+            return null;
+        }
+    }
+
+    /*
+    * If the key up is not hooked, reset last key
+    * and last ascii in case the key down is hooked.
+    */
+    if (!hooks (SWT.KeyUp) && !display.filters (SWT.KeyUp)) {
+        display.lastKey = display.lastAscii = 0;
+        display.lastVirtual = display.lastNull = display.lastDead = false;
+        return null;
+    }
+
+    /* Map the virtual key. */
+    /*
+    * Bug in WinCE.  MapVirtualKey() returns incorrect values.
+    * The fix is to rely on a key mappings table to determine
+    * whether the key event must be sent now or if a WM_CHAR
+    * event will follow.  The key mappings table maps virtual
+    * keys to SWT key codes and does not contain mappings for
+    * Windows virtual keys like VK_A.  Virtual keys that are
+    * both virtual and ASCII are a special case.
+    */
+    int mapKey = 0;
+    static if (OS.IsWinCE) {
+        switch (wParam) {
+            case OS.VK_BACK: mapKey = SWT.BS; break;
+            case OS.VK_RETURN: mapKey = SWT.CR; break;
+            case OS.VK_DELETE: mapKey = SWT.DEL; break;
+            case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+            case OS.VK_TAB: mapKey = SWT.TAB; break;
+            default:
+        }
+    } else {
+        mapKey = OS.MapVirtualKey (wParam, 2);
+    }
+
+    /*
+    * Bug in Windows 95 and NT.  When the user types an accent key such
+    * as ^ to get an accented character on a German keyboard, the accent
+    * key should be ignored and the next key that the user types is the
+    * accented key. The fix is to detect the accent key stroke (called
+    * a dead key) by testing the high bit of the value returned by
+    * MapVirtualKey ().  A further problem is that the high bit on
+    * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
+    * They should both be bit 32.
+    */
+    if (OS.IsWinNT) {
+        if ((mapKey & 0x80000000) !is 0) return null;
+    } else {
+        if ((mapKey & 0x8000) !is 0) return null;
+    }
+    if (display.lastDead) return null;
+
+    /*
+    * NOTE: On Windows 98, keypad keys are virtual despite the
+    * fact that a WM_CHAR is issued.  On Windows 2000 and XP,
+    * they are not virtual.  Therefore it is necessary to force
+    * numeric keypad keys to be virtual.
+    */
+    display.lastVirtual = mapKey is 0 || display.numpadKey (wParam) !is 0;
+    if (display.lastVirtual) {
+        display.lastKey = wParam;
+    } else {
+        /*
+        * Feature in Windows. The virtual key VK_CANCEL is treated
+        * as both a virtual key and ASCII key by Windows.  This
+        * means that a WM_CHAR with WPARAM=3 will be issued for
+        * this key.  In order to distinguish between this key and
+        * Ctrl+C, mark the key as virtual.
+        */
+        if (wParam is OS.VK_CANCEL) display.lastVirtual = true;
+        if (display.lastKey is 0) {
+            display.lastAscii = 0;
+            display.lastNull = display.lastDead = false;
+            return null;
+        }
+    }
+    LRESULT result = null;
+    if (!sendKeyEvent (SWT.KeyUp, OS.WM_KEYUP, wParam, lParam)) {
+        result = LRESULT.ONE;
+    }
+    // widget could be disposed at this point
+    display.lastKey = display.lastAscii = 0;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+    return result;
+}
+
+LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) {
+    display.scrollRemainder = 0;
+    int code = callWindowProc (hwnd, OS.WM_KILLFOCUS, wParam, lParam);
+    sendFocusEvent (SWT.FocusOut);
+    // widget could be disposed at this point
+
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the focus
+    * or deactivate events.  If this happens, end the
+    * processing of the Windows message by returning
+    * zero as the result of the window proc.
+    */
+    if (isDisposed ()) return LRESULT.ZERO;
+    if (code is 0) return LRESULT.ZERO;
+    return new LRESULT(code);
+}
+
+LRESULT wmLButtonDblClk (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows. Windows sends the following
+    * messages when the user double clicks the mouse:
+    *
+    *   WM_LBUTTONDOWN      - mouse down
+    *   WM_LBUTTONUP        - mouse up
+    *   WM_LBUTTONDBLCLK    - double click
+    *   WM_LBUTTONUP        - mouse up
+    *
+    * Applications that expect matching mouse down/up
+    * pairs will not see the second mouse down.  The
+    * fix is to send a mouse down event.
+    */
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    sendMouseEvent (SWT.MouseDown, 1, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (sendMouseEvent (SWT.MouseDoubleClick, 1, hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
+        result = new LRESULT( callWindowProc (hwnd, OS.WM_LBUTTONDBLCLK, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmLButtonDown (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = null;
+    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 (SWT.MouseDown, 1, hwnd, lParam);
+    if (count is 1 && (state & DRAG_DETECT) !is 0 && hooks (SWT.DragDetect)) {
+        static if (!OS.IsWinCE) {
+            /*
+            * Feature in Windows.  It's possible that the drag
+            * operation will not be started while the mouse is
+            * down, meaning that the mouse should be captured.
+            * This can happen when the user types the ESC key
+            * to cancel the drag.  The fix is to query the state
+            * of the mouse and capture the mouse accordingly.
+            */
+            detect = new bool [1];
+            consume = new bool [1];
+            dragging = dragDetect (hwnd, x, y, true, detect, consume);
+            if (isDisposed ()) return LRESULT.ZERO;
+            mouseDown = OS.GetKeyState (OS.VK_LBUTTON) < 0;
+        }
+    }
+    display.captureChanged = false;
+    bool dispatch = sendMouseEvent (SWT.MouseDown, 1, count, 0, false, hwnd, OS.WM_LBUTTONDOWN, wParam, lParam);
+    if (dispatch && (consume is null || !consume [0])) {
+        result = new LRESULT( callWindowProc (hwnd, OS.WM_LBUTTONDOWN, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    static if( OS.IsWinCE ){
+        if (OS.IsPPC) {
+            /*
+            * Note: On WinCE PPC, only attempt to recognize the gesture for
+            * a context menu when the control contains a valid menu or there
+            * are listeners for the MenuDetect event.
+            */
+            Menu menu = getMenu ();
+            bool hasMenu = menu !is null && !menu.isDisposed ();
+            if (hasMenu || hooks (SWT.MenuDetect)) {
+                SHRGINFO shrg;
+                shrg.cbSize = SHRGINFO.sizeof;
+                shrg.hwndClient = hwnd;
+                shrg.ptDown.x = x;
+                shrg.ptDown.y = y;
+                shrg.dwFlags = OS.SHRG_RETURNCMD;
+                int type = OS.SHRecognizeGesture (&shrg);
+                if (type is OS.GN_CONTEXTMENU) showMenu (x, y);
+            }
+        }
+    }
+    if (mouseDown) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+        }
+    }
+    if (dragging) {
+        sendDragEvent (1, x, y);
+    } else {
+        if (detect !is null && detect [0]) {
+            /*
+            * Feature in Windows.  DragDetect() captures the mouse
+            * and tracks its movement until the user releases the
+            * left mouse button, presses the ESC key, or moves the
+            * mouse outside the drag rectangle.  If the user moves
+            * the mouse outside of the drag rectangle, DragDetect()
+            * returns true and a drag and drop operation can be
+            * started.  When the left mouse button is released or
+            * the ESC key is pressed, these events are consumed by
+            * DragDetect() so that application code that matches
+            * mouse down/up pairs or looks for the ESC key will not
+            * function properly.  The fix is to send the missing
+            * events when the drag has not started.
+            *
+            * NOTE: For now, don't send a fake WM_KEYDOWN/WM_KEYUP
+            * events for the ESC key.  This would require computing
+            * wParam (the key) and lParam (the repeat count, scan code,
+            * extended-key flag, context code, previous key-state flag,
+            * and transition-state flag) which is non-trivial.
+            */
+            if (OS.GetKeyState (OS.VK_ESCAPE) >= 0) {
+                OS.SendMessage (hwnd, OS.WM_LBUTTONUP, wParam, lParam);
+            }
+        }
+    }
+    return result;
+}
+
+LRESULT wmLButtonUp (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = null;
+    if (sendMouseEvent (SWT.MouseUp, 1, hwnd, OS.WM_LBUTTONUP, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_LBUTTONUP, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    /*
+    * Bug in Windows.  On some machines that do not have XBUTTONs,
+    * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+    * causing mouse capture to become stuck.  The fix is to test
+    * for the extra buttons only when they exist.
+    */
+    int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+    if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+    if ((wParam & mask) is 0) {
+        if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
+    }
+    return result;
+}
+
+LRESULT wmMButtonDblClk (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows. Windows sends the following
+    * messages when the user double clicks the mouse:
+    *
+    *   WM_MBUTTONDOWN      - mouse down
+    *   WM_MBUTTONUP        - mouse up
+    *   WM_MLBUTTONDBLCLK   - double click
+    *   WM_MBUTTONUP        - mouse up
+    *
+    * Applications that expect matching mouse down/up
+    * pairs will not see the second mouse down.  The
+    * fix is to send a mouse down event.
+    */
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam);
+    if (sendMouseEvent (SWT.MouseDoubleClick, 2, hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_MBUTTONDBLCLK, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmMButtonDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    if (sendMouseEvent (SWT.MouseDown, 2, hwnd, OS.WM_MBUTTONDOWN, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_MBUTTONDOWN, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmMButtonUp (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = null;
+    if (sendMouseEvent (SWT.MouseUp, 2, hwnd, OS.WM_MBUTTONUP, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_MBUTTONUP, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    /*
+    * Bug in Windows.  On some machines that do not have XBUTTONs,
+    * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+    * causing mouse capture to become stuck.  The fix is to test
+    * for the extra buttons only when they exist.
+    */
+    int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+    if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+    if ((wParam & mask) is 0) {
+        if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
+    }
+    return result;
+}
+
+LRESULT wmMouseHover (HWND hwnd, int wParam, int lParam) {
+    if (!sendMouseEvent (SWT.MouseHover, 0, hwnd, OS.WM_MOUSEHOVER, wParam, lParam)) {
+        return LRESULT.ZERO;
+    }
+    return null;
+}
+
+LRESULT wmMouseLeave (HWND hwnd, int wParam, int lParam) {
+    if (!hooks (SWT.MouseExit) && !filters (SWT.MouseExit)) return null;
+    int pos = OS.GetMessagePos ();
+    POINT pt;
+    OS.POINTSTOPOINT (pt, pos);
+    OS.ScreenToClient (hwnd, &pt);
+    lParam = OS.MAKELPARAM (pt.x, pt.y);
+    if (!sendMouseEvent (SWT.MouseExit, 0, hwnd, OS.WM_MOUSELEAVE, wParam, lParam)) {
+        return LRESULT.ZERO;
+    }
+    return null;
+}
+
+LRESULT wmMouseMove (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = null;
+    Display display = this.display;
+    int pos = OS.GetMessagePos ();
+    if (pos !is display.lastMouse || display.captureChanged) {
+        static if (!OS.IsWinCE) {
+            bool trackMouse = (state & TRACK_MOUSE) !is 0;
+            bool mouseEnter = hooks (SWT.MouseEnter) || display.filters (SWT.MouseEnter);
+            bool mouseExit = hooks (SWT.MouseExit) || display.filters (SWT.MouseExit);
+            bool mouseHover = hooks (SWT.MouseHover) || display.filters (SWT.MouseHover);
+            if (trackMouse || mouseEnter || mouseExit || mouseHover) {
+                TRACKMOUSEEVENT lpEventTrack;
+                lpEventTrack.cbSize = TRACKMOUSEEVENT.sizeof;
+                lpEventTrack.dwFlags = OS.TME_QUERY;
+                lpEventTrack.hwndTrack = hwnd;
+                OS.TrackMouseEvent (&lpEventTrack);
+                if (lpEventTrack.dwFlags is 0) {
+                    lpEventTrack.dwFlags = OS.TME_LEAVE | OS.TME_HOVER;
+                    lpEventTrack.hwndTrack = hwnd;
+                    OS.TrackMouseEvent (&lpEventTrack);
+                    if (mouseEnter) {
+                        /*
+                        * Force all outstanding WM_MOUSELEAVE messages to be dispatched before
+                        * issuing a mouse enter.  This causes mouse exit events to be processed
+                        * before mouse enter events.  Note that WM_MOUSELEAVE is posted to the
+                        * event queue by TrackMouseEvent().
+                        */
+                        MSG msg;
+                        int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
+                        while (OS.PeekMessage (&msg, null, OS.WM_MOUSELEAVE, OS.WM_MOUSELEAVE, flags)) {
+                            OS.TranslateMessage (&msg);
+                            OS.DispatchMessage (&msg);
+                        }
+                        sendMouseEvent (SWT.MouseEnter, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam);
+                    }
+                } else {
+                    lpEventTrack.dwFlags = OS.TME_HOVER;
+                    OS.TrackMouseEvent (&lpEventTrack);
+                }
+            }
+        }
+        if (pos !is display.lastMouse) {
+            display.lastMouse = pos;
+            if (!sendMouseEvent (SWT.MouseMove, 0, hwnd, OS.WM_MOUSEMOVE, wParam, lParam)) {
+                result = LRESULT.ZERO;
+            }
+        }
+    }
+    display.captureChanged = false;
+    return result;
+}
+
+LRESULT wmMouseWheel (HWND hwnd, int wParam, int lParam) {
+    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 = SWT.SCROLL_PAGE;
+    } else {
+        detail = SWT.SCROLL_LINE;
+        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 (SWT.MouseWheel) && !filters (SWT.MouseWheel)) return null;
+    int count = delta / OS.WHEEL_DELTA;
+    POINT pt;
+    OS.POINTSTOPOINT (pt, lParam);
+    OS.ScreenToClient (hwnd, &pt);
+    lParam = OS.MAKELPARAM (pt.x, pt.y);
+    if (!sendMouseEvent (SWT.MouseWheel, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam)) {
+        return LRESULT.ZERO;
+    }
+    return null;
+}
+
+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 (SWT.Paint) && !filters (SWT.Paint)) {
+        return null;
+    }
+
+    /* Issue a paint event */
+    int /*long*/ result = 0;
+    static if (OS.IsWinCE) {
+        RECT rect;
+        OS.GetUpdateRect (hwnd, &rect, false);
+        result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam);
+        /*
+        * Bug in Windows.  When InvalidateRgn(), InvalidateRect()
+        * or RedrawWindow() with RDW_INVALIDATE is called from
+        * within WM_PAINT to invalidate a region for a further
+        * BeginPaint(), the caret is not properly erased causing
+        * pixel corruption.  The fix is to hide and show the
+        * caret.
+        */
+        OS.HideCaret (hwnd);
+        OS.InvalidateRect (hwnd, &rect, false);
+        OS.ShowCaret (hwnd);
+        PAINTSTRUCT* ps = new PAINTSTRUCT;
+        GCData data = new GCData ();
+        data.ps = ps;
+        data.hwnd = hwnd;
+        GC gc = new_GC (data);
+        if (gc !is null) {
+            int width = ps.rcPaint.right - ps.rcPaint.left;
+            int height = ps.rcPaint.bottom - ps.rcPaint.top;
+            if (width !is 0 && height !is 0) {
+                Event event = new Event ();
+                event.gc = gc;
+                event.x = ps.rcPaint.left;
+                event.y = ps.rcPaint.top;
+                event.width = width;
+                event.height = height;
+                sendEvent (SWT.Paint, event);
+                // widget could be disposed at this point
+                event.gc = null;
+            }
+            gc.dispose ();
+        }
+    } else {
+        auto rgn = OS.CreateRectRgn (0, 0, 0, 0);
+        OS.GetUpdateRgn (hwnd, rgn, false);
+        result = callWindowProc (hwnd, OS.WM_PAINT, wParam, lParam);
+        GCData data = new GCData ();
+        data.hwnd = hwnd;
+        GC gc = new_GC (data);
+        if (gc !is null) {
+            OS.HideCaret (hwnd);
+            RECT rect;
+            OS.GetRgnBox (rgn, &rect);
+            int width = rect.right - rect.left;
+            int height = rect.bottom - rect.top;
+            if (width !is 0 && height !is 0) {
+                auto hDC = gc.handle;
+                OS.SelectClipRgn (hDC, rgn);
+                OS.SetMetaRgn (hDC);
+                Event event = new Event ();
+                event.gc = gc;
+                event.x = rect.left;
+                event.y = rect.top;
+                event.width = width;
+                event.height = height;
+                sendEvent (SWT.Paint, event);
+                // widget could be disposed at this point
+                event.gc = null;
+            }
+            gc.dispose ();
+            OS.ShowCaret (hwnd);
+        }
+        OS.DeleteObject (rgn);
+    }
+    if (result is 0) return LRESULT.ZERO;
+    return new LRESULT (result);
+}
+
+LRESULT wmPrint (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Bug in Windows.  When WM_PRINT is used to print the contents
+    * of a control that has WS_EX_CLIENTEDGE, the old 3D border is
+    * drawn instead of the theme border.  The fix is to call the
+    * default window proc and then draw the theme border on top.
+    */
+    if ((lParam & OS.PRF_NONCLIENT) !is 0) {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+            if ((bits & OS.WS_EX_CLIENTEDGE) !is 0) {
+                int /*long*/ code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam);
+                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 ( cast(void*)wParam, border, border, rect.right - border, rect.bottom - border);
+                OS.DrawThemeBackground (display.hEditTheme (), cast(HDC)wParam, OS.EP_EDITTEXT, OS.ETS_NORMAL, &rect, null);
+                return new LRESULT (code);
+            }
+        }
+    }
+    return null;
+}
+
+LRESULT wmRButtonDblClk (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows. Windows sends the following
+    * messages when the user double clicks the mouse:
+    *
+    *   WM_RBUTTONDOWN      - mouse down
+    *   WM_RBUTTONUP        - mouse up
+    *   WM_RBUTTONDBLCLK    - double click
+    *   WM_LBUTTONUP        - mouse up
+    *
+    * Applications that expect matching mouse down/up
+    * pairs will not see the second mouse down.  The
+    * fix is to send a mouse down event.
+    */
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam);
+    if (sendMouseEvent (SWT.MouseDoubleClick, 3, hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_RBUTTONDBLCLK, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmRButtonDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    if (sendMouseEvent (SWT.MouseDown, 3, hwnd, OS.WM_RBUTTONDOWN, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_RBUTTONDOWN, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmRButtonUp (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = null;
+    if (sendMouseEvent (SWT.MouseUp, 3, hwnd, OS.WM_RBUTTONUP, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_RBUTTONUP, wParam, lParam));
+    } else {
+        /* Call the DefWindowProc() to support WM_CONTEXTMENU */
+        OS.DefWindowProc (hwnd, OS.WM_RBUTTONUP, wParam, lParam);
+        result = LRESULT.ZERO;
+    }
+    /*
+    * Bug in Windows.  On some machines that do not have XBUTTONs,
+    * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+    * causing mouse capture to become stuck.  The fix is to test
+    * for the extra buttons only when they exist.
+    */
+    int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+    if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+    if ((wParam & mask) is 0) {
+        if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
+    }
+    return result;
+}
+
+LRESULT wmSetFocus (HWND hwnd, int wParam, int lParam) {
+    int /*long*/ code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam);
+    sendFocusEvent (SWT.FocusIn);
+    // widget could be disposed at this point
+
+    /*
+    * It is possible (but unlikely), that application
+    * code could have disposed the widget in the focus
+    * or activate events.  If this happens, end the
+    * processing of the Windows message by returning
+    * zero as the result of the window proc.
+    */
+    if (isDisposed ()) return LRESULT.ZERO;
+    if (code is 0) return LRESULT.ZERO;
+    return new LRESULT (code);
+}
+
+LRESULT wmSysChar (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    display.lastAscii = wParam;
+    display.lastNull = wParam is 0;
+
+    /* Do not issue a key down if a menu bar mnemonic was invoked */
+    if (!hooks (SWT.KeyDown) && !display.filters (SWT.KeyDown)) {
+        return null;
+    }
+
+    /* Call the window proc to determine whether it is a system key or mnemonic */
+    bool oldKeyHit = display.mnemonicKeyHit;
+    display.mnemonicKeyHit = true;
+    int /*long*/ result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam);
+    bool consumed = false;
+    if (!display.mnemonicKeyHit) {
+        consumed = !sendKeyEvent (SWT.KeyDown, OS.WM_SYSCHAR, wParam, lParam);
+        // widget could be disposed at this point
+    }
+    consumed |= display.mnemonicKeyHit;
+    display.mnemonicKeyHit = oldKeyHit;
+    return consumed ? LRESULT.ONE : new LRESULT (result);
+}
+
+LRESULT wmSysKeyDown (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows.  When WM_SYSKEYDOWN is sent,
+    * the user pressed ALT+<key> or F10 to get to the
+    * menu bar.  In order to issue events for F10 but
+    * ignore other key presses when the ALT is not down,
+    * make sure that either F10 was pressed or that ALT
+    * is pressed.
+    */
+    if (wParam !is OS.VK_F10) {
+        /* Make sure WM_SYSKEYDOWN was sent by ALT-<aKey>. */
+        if ((lParam & 0x20000000) is 0) return null;
+    }
+
+    /* Ignore well known system keys */
+    switch (wParam) {
+        case OS.VK_F4: {
+            HWND hwndShell = hwnd;
+            while (OS.GetParent (hwndShell) !is null) {
+                if (OS.GetWindow (hwndShell, OS.GW_OWNER) !is null) break;
+                hwndShell = OS.GetParent (hwndShell);
+            }
+            int bits = OS.GetWindowLong (hwndShell, OS.GWL_STYLE);
+            if ((bits & OS.WS_SYSMENU) !is 0) return null;
+        }
+        default:
+    }
+
+    /* Ignore repeating modifier keys by testing key down state */
+    switch (wParam) {
+        case OS.VK_SHIFT:
+        case OS.VK_MENU:
+        case OS.VK_CONTROL:
+        case OS.VK_CAPITAL:
+        case OS.VK_NUMLOCK:
+        case OS.VK_SCROLL:
+            if ((lParam & 0x40000000) !is 0) return null;
+        default:
+    }
+
+    /* Clear last key and last ascii because a new key has been typed */
+    display.lastAscii = display.lastKey = 0;
+    display.lastVirtual = display.lastNull = display.lastDead = false;
+
+    /* If are going to get a WM_SYSCHAR, ignore this message. */
+    /*
+    * Bug in WinCE.  MapVirtualKey() returns incorrect values.
+    * The fix is to rely on a key mappings table to determine
+    * whether the key event must be sent now or if a WM_CHAR
+    * event will follow.  The key mappings table maps virtual
+    * keys to SWT key codes and does not contain mappings for
+    * Windows virtual keys like VK_A.  Virtual keys that are
+    * both virtual and ASCII are a special case.
+    */
+    int mapKey = 0;
+    static if (OS.IsWinCE) {
+        switch (wParam) {
+            case OS.VK_BACK: mapKey = SWT.BS; break;
+            case OS.VK_RETURN: mapKey = SWT.CR; break;
+            case OS.VK_DELETE: mapKey = SWT.DEL; break;
+            case OS.VK_ESCAPE: mapKey = SWT.ESC; break;
+            case OS.VK_TAB: mapKey = SWT.TAB; break;
+            default:
+        }
+    } else {
+        mapKey = OS.MapVirtualKey (wParam, 2);
+    }
+    display.lastVirtual = mapKey is 0 || display.numpadKey (wParam) !is 0;
+    if (display.lastVirtual) {
+        display.lastKey = wParam;
+        /*
+        * Feature in Windows.  The virtual key VK_DELETE is not
+        * treated as both a virtual key and an ASCII key by Windows.
+        * Therefore, we will not receive a WM_SYSCHAR for this key.
+        * The fix is to treat VK_DELETE as a special case and map
+        * the ASCII value explicitly (Delete is 0x7F).
+        */
+        if (display.lastKey is OS.VK_DELETE) display.lastAscii = 0x7F;
+
+        /* When a keypad key is typed, a WM_SYSCHAR is not issued */
+        if (OS.VK_NUMPAD0 <= display.lastKey && display.lastKey <= OS.VK_DIVIDE) {
+            /*
+            * A WM_SYSCHAR will be issued for '*', '+', '-', '.' and '/'
+            * on the numeric keypad.  Avoid issuing the key event twice
+            * by checking for these keys.  Note that calling to ToAscii()
+            * or ToUnicode(), clear the character that is entered using
+            * the special Windows keypad sequence when NumLock is down
+            * (ie. typing ALT+0231 should gives 'c' with a cedilla when
+            * NumLock is down).  Do not call either of these from here.
+            */
+            switch (display.lastKey) {
+                case OS.VK_MULTIPLY:
+                case OS.VK_ADD:
+                case OS.VK_SUBTRACT:
+                case OS.VK_DECIMAL:
+                case OS.VK_DIVIDE: return null;
+                default:
+            }
+            display.lastAscii = display.numpadKey (display.lastKey);
+        }
+    } else {
+        /*
+        * Convert LastKey to lower case because Windows non-virtual
+        * keys that are also ASCII keys, such as like VK_A, are have
+        * upper case values in WM_SYSKEYDOWN despite the fact that the
+        * Shift was not pressed.
+        */
+        display.lastKey = cast(int) OS.CharLower (cast(wchar*) mapKey);
+
+        /*
+        * Feature in Windows 98.  MapVirtualKey() indicates that
+        * a WM_SYSCHAR message will occur for Alt+Enter but
+        * this message never happens.  The fix is to issue the
+        * event from WM_SYSKEYDOWN and map VK_RETURN to '\r'.
+        */
+        if (OS.IsWinNT) return null;
+        if (wParam !is OS.VK_RETURN) return null;
+        display.lastAscii = '\r';
+    }
+
+    if (!sendKeyEvent (SWT.KeyDown, OS.WM_SYSKEYDOWN, wParam, lParam)) {
+        return LRESULT.ONE;
+    }
+    // widget could be disposed at this point
+    return null;
+}
+
+LRESULT wmSysKeyUp (HWND hwnd, int wParam, int lParam) {
+    return wmKeyUp (hwnd, wParam, lParam);
+}
+
+LRESULT wmXButtonDblClk (HWND hwnd, int wParam, int lParam) {
+    /*
+    * Feature in Windows. Windows sends the following
+    * messages when the user double clicks the mouse:
+    *
+    *   WM_XBUTTONDOWN      - mouse down
+    *   WM_XBUTTONUP        - mouse up
+    *   WM_XLBUTTONDBLCLK   - double click
+    *   WM_XBUTTONUP        - mouse up
+    *
+    * Applications that expect matching mouse down/up
+    * pairs will not see the second mouse down.  The
+    * fix is to send a mouse down event.
+    */
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
+    sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam);
+    if (sendMouseEvent (SWT.MouseDoubleClick, button, hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmXButtonDown (HWND hwnd, int wParam, int lParam) {
+    LRESULT result = null;
+    Display display = this.display;
+    display.captureChanged = false;
+    display.xMouse = true;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
+    if (sendMouseEvent (SWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDOWN, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    if (!display.captureChanged && !isDisposed ()) {
+        if (OS.GetCapture () !is hwnd) OS.SetCapture (hwnd);
+    }
+    return result;
+}
+
+LRESULT wmXButtonUp (HWND hwnd, int wParam, int lParam) {
+    Display display = this.display;
+    LRESULT result = null;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
+    if (sendMouseEvent (SWT.MouseUp, button, hwnd, OS.WM_XBUTTONUP, wParam, lParam)) {
+        result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONUP, wParam, lParam));
+    } else {
+        result = LRESULT.ZERO;
+    }
+    /*
+    * Bug in Windows.  On some machines that do not have XBUTTONs,
+    * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
+    * causing mouse capture to become stuck.  The fix is to test
+    * for the extra buttons only when they exist.
+    */
+    int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
+    if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
+    if ((wParam & mask) is 0) {
+        if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
+    }
+    return result;
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/all.d	Mon Mar 02 14:44:16 2009 +0100
@@ -0,0 +1,63 @@
+module org.eclipse.swt.widgets.all;
+
+public import org.eclipse.swt.widgets.Button;
+public import org.eclipse.swt.widgets.Canvas;
+public import org.eclipse.swt.widgets.Caret;
+public import org.eclipse.swt.widgets.ColorDialog;
+public import org.eclipse.swt.widgets.Combo;
+public import org.eclipse.swt.widgets.Composite;
+public import org.eclipse.swt.widgets.Control;
+public import org.eclipse.swt.widgets.CoolBar;
+public import org.eclipse.swt.widgets.CoolItem;
+public import org.eclipse.swt.widgets.DateTime;
+public import org.eclipse.swt.widgets.Decorations;
+public import org.eclipse.swt.widgets.Dialog;
+public import org.eclipse.swt.widgets.DirectoryDialog;
+public import org.eclipse.swt.widgets.Display;
+public import org.eclipse.swt.widgets.Event;
+public import org.eclipse.swt.widgets.EventTable;
+public import org.eclipse.swt.widgets.ExpandBar;
+public import org.eclipse.swt.widgets.ExpandItem;
+public import org.eclipse.swt.widgets.FileDialog;
+public import org.eclipse.swt.widgets.FontDialog;
+public import org.eclipse.swt.widgets.Group;
+public import org.eclipse.swt.widgets.IME;
+public import org.eclipse.swt.widgets.Item;
+public import org.eclipse.swt.widgets.Label;
+public import org.eclipse.swt.widgets.Layout;
+public import org.eclipse.swt.widgets.Link;
+public import org.eclipse.swt.widgets.List;
+public import org.eclipse.swt.widgets.Listener;
+public import org.eclipse.swt.widgets.Menu;
+public import org.eclipse.swt.widgets.MenuItem;
+public import org.eclipse.swt.widgets.MessageBox;
+public import org.eclipse.swt.widgets.Monitor;
+public import org.eclipse.swt.widgets.ProgressBar;
+public import org.eclipse.swt.widgets.RunnableLock;
+public import org.eclipse.swt.widgets.Sash;
+public import org.eclipse.swt.widgets.Scale;
+public import org.eclipse.swt.widgets.ScrollBar;
+public import org.eclipse.swt.widgets.Scrollable;
+public import org.eclipse.swt.widgets.Shell;
+public import org.eclipse.swt.widgets.Slider;
+public import org.eclipse.swt.widgets.Spinner;
+public import org.eclipse.swt.widgets.Synchronizer;
+public import org.eclipse.swt.widgets.TabFolder;
+public import org.eclipse.swt.widgets.TabItem;
+public import org.eclipse.swt.widgets.Table;
+public import org.eclipse.swt.widgets.TableColumn;
+public import org.eclipse.swt.widgets.TableItem;
+public import org.eclipse.swt.widgets.Text;
+public import org.eclipse.swt.widgets.ToolBar;
+public import org.eclipse.swt.widgets.ToolItem;
+public import org.eclipse.swt.widgets.ToolTip;
+public import org.eclipse.swt.widgets.Tracker;
+public import org.eclipse.swt.widgets.Tray;
+public import org.eclipse.swt.widgets.TrayItem;
+public import org.eclipse.swt.widgets.Tree;
+public import org.eclipse.swt.widgets.TreeColumn;
+public import org.eclipse.swt.widgets.TreeItem;
+public import org.eclipse.swt.widgets.TypedListener;
+public import org.eclipse.swt.widgets.Widget;
+
+